2013年6月18日火曜日

PostgreSQL と SSRF

お疲れ様です。稲垣です。

今回は、PostgreSQL と SSRF についてご紹介します。

SSRF とは Server Side Request Forgery (サーバ側のリクエスト偽造) の事です。Web アプリケーションに詳しい方なら CSRF (Cross Site Request Forgery サイトをまたがったリクエスト偽造) のサーバ版である、と説明すると分り易いと思います。

ここ数年、セキュリティ研究者は企業内ネットワークに存在する産業システムネットワークなどを攻撃する手法を研究しています。SSRF は企業内ネットワークの奥深くまで侵入する為によく利用される攻撃テクニックです。

今回は PostgreSQL と SSRF について解説します。


■ SSRF 攻撃とは

SSRF 攻撃は比較的単純で分り易い攻撃方法です。直接の攻撃対象となったサーバやサービスの権限を利用して、他のサーバやサービスを攻撃する手法をSSRF攻撃と言います。SSRF 攻撃は新しい攻撃手法ではなく古くから知られた攻撃手法です。

直接攻撃が可能となったサーバ・サービス以外のサーバ・サービスを攻撃する SSRF 攻撃の手法には、次のような物があります。

  • OS コマンドインジェクション
  • プログラム・スクリプト実行
  • XXE 攻撃 (XML External Entity 攻撃)
  • SQL インジェクション

OS コマンドインジェクションやプログラム・スクリプト実行が SSRF 攻撃に利用可能であることは容易に想像できます。

PCクライアントと異なり、サーバには特別なアクセス権限が与えられてる事が多くあります。代表的な例はバックアップサーバへのアクセスです。サーバマシンからは他のシステムバックアップにもアクセスできてしまうシステム構成は少なくありません。

XXE 攻撃やオープンリダイレクターは他のサービスをスキャンしたり、攻撃したりする為に利用されます。XXE とは XML 文書の外部参照を自動的に読み込む仕様を利用して、ネットワークをスキャンしたり攻撃します。

SQL インジェクションも SSRF 攻撃に利用されます。
データベースによっては他のデータベースへのクエリが可能だったり、ユーザ定義関数を利用した任意コードの実行が可能であったり、システムが元々コマンド実行をサポート (SQL Server にはコマンドを実行する xp_cmd_shell() が実装されている) するシステムもあります。これらが SSRF 攻撃に利用されます。


■ PostgreSQL の SQL インジェクションが引き起こす脅威

SQL インジェクションは致命的なセキュリティ上の脆弱性です。
幾つか条件はありますが、テーブル名やフィールド名などのデータベースの構造を知らなくても、外部からデータベース構造を解析する「ブラインド SQL インジェクション」と呼ばれる手法も存在しています。

カスタムシステムでテーブル名やフィールド名が知られていなくても、データベース構造を解析され、任意のデータを盗まれる可能性は十分にあります。データベースに書き込み権限がある場合、データを改ざんする事も可能です。

SQLインジェクションはデータベース内の情報を盗めるだけではありません。
データベースシステムが稼働するサーバでアクセス可能なファイルを盗む事も容易です。

例:/etc/hosts をデータベーステーブルに保存する

# CREATE TABLE t1 (t text);
# COPY t1(t) FROM '/etc/hosts' with CSV
# SELECT * FROM t1;

出力:

                                     t                                      
----------------------------------------------------------------------------
 127.0.0.1       dev.inter.es-i.jp dev localhost.localdomain localhost
 ::1             dev6.inter.es-i.jp dev6 localhost6.localdomain6 localhost6

詳しい解説は省略しますが、SQL インジェクションを利用して、ファイルシステムへの書き込みを行う事も可能です。

例:PostgreSQL を利用し、ファイルシステムに書き込みを行う

# CREATE TABLE footable(data text);
# INSERT INTO footable(data) VALUES ('TVqQ…');
# UPDATE footable SET data=data||'U8pp…vgDw';
  […]
# SELECT lo_create(47);
# UPDATE pg_largeobject SET data=(DECODE((SELECT data FROM footable), 'base64')) WHERE loid=47;
# SELECT lo_export(47, 'C:/WINDOWS/Temp/nc.exe');

この例は Windows システム上に任意のネットワークパケットを送信する NetCat コマンドを一時ディレクトリにインストールしています。

https://www.owasp.org/images/d/dc/AppsecEU09-Damele-A-G-Advanced-SQL-injection-slides.pdf
(p.12)


PostgreSQL の拡張ライブラリを保存するディレクトリに書き込み可能な場合、ユーザ定義関数のライブラリファイルを書き込み、その関数を利用して任意コード・コマンド実行も可能になります。

https://www.owasp.org/images/d/dc/AppsecEU09-Damele-A-G-Advanced-SQL-injection-slides.pdf
(p.18~)


PostgreSQL には dblink と呼ばれる他の PostgreSQL データベースに接続可能な Contrib 機能があります。この機能が有効な場合、サーバを超えて SQL インジェクションが可能になります。

  • 名前
  • dblink -- リモートデータベースで問い合わせを実行します

  • 概要
  • dblink(text connname, text sql [, bool fail_on_error]) returns setof record
    dblink(text connstr, text sql [, bool fail_on_error]) returns setof record
    dblink(text sql [, bool fail_on_error]) returns setof record

  • 説明
  • dblink はリモートデータベースで問い合わせ (通常は SELECT ですが行を返す任意の SQL コマンドを行うことができます) を実行します。

    2 つの text 型の引数が与えられた場合、一番目の引数はまず永続接続の名前を検索するために使われます。
    もし見つかれば、コマンドがその接続上で実行されます。 見つからなければ、一番目の引数は dblink_connect 用の接続情報文字列として扱われ、このコマンド実行時と同様に指定された接続が開きます。

  • 引数
    • conname
    • 使用する接続の名前です。 無名の接続を使用する場合はこのパラメータを省略します。

    • connstr
    • 上でdblink_connectで説明した接続情報文字列です。

    • sql
    • 例えば select * from foo といった、リモートデータベースで実行させるSQL問い合わせです。

    • fail_on_error
    • 真 (省略時のデフォルト) の場合、接続のリモート側で発生したエラーによりローカル側でもエラーが発生します。 偽の場合リモート側のエラーはローカル側には NOTICE として報告され、この関数は行を返しません。

http://www.postgresql.jp/document/9.2/html/contrib-dblink-function.html

conname は libpq の接続文字列に使える項目であればどれでも利用できます。

http://www.postgresql.jp/document/9.2/html/libpq-connect.html#LIBPQ-CONNSTRING

つまり、ネットワーク上のアクセス可能な PostgreSQL サーバに自由にアクセスできます。この仕様は SSRF 攻撃には非常に便利です。


■ サーバと SSRF 攻撃

一般的にサーバはクライアントより多くの権限が与えられている事が多いです。

例えば、データベースにデータを記録する為に制御機器用のネットワークへのアクセスが許可されている、ERP システムと連携するためにクライアントには開放されていない ERP システム API へのアクセスが許可されている、リモートログインが許可されている、などが許されている場合があります。

通常のインストールでは、データベースにアクセスしているユーザと PostgreSQL の実行ファイルなどをインストールしているユーザは異なる (例えば、Red Hat Linux では実行ファイルやライブラリ類は root 権限でインストールされ、サーバは postgres 権限で実行される) ので、SQL インジェクション攻撃により任意コード・コマンドを実行されるリスクは多くないでしょう。

SQL インジェクションでデータベースから Web サーバのファイルを書き換えれる場合、Web サーバ権限で任意のスクリプトやコマンドを実行されるリスクが発生します。

PostgreSQL の dblink が利用されている場合、IP アドレスで他の PostgreSQL サーバからの読み書きアクセスを許している事も多いと思います。このようなシステムの構成の場合、直接 SQL インジェクション攻撃を行われたサーバから SSRF 攻撃を行い、さらなる SQL インジェクション攻撃が可能になります。


■ まとめ

サーバシステムの安全は確保されており、クライアント PC などと異なりサーバシステムは無条件または大幅に信頼できる事を前提として設計されているシステムが多いと思います。

サーバシステムを信頼せざるを得ない場合も多いと思いますが、不必要な権限や機能を与えるとリスクはどんどん大きくなります。企業内部のファイアーウォールで 2 重 3 重に守っているはずのシステムが外部から攻撃されてしまうという事があり得る、認識しながらシステム開発と運用は行わなければなりません。

近年、インターネットから企業内ネットワーク奥深くまで侵入する様々な攻撃手法が考案されています。

SQL インジェクションは完全に無くす事が簡単に行える脆弱性ですが、一度発生すると攻撃対象のデータベースのみではありません。コマンドの実行や他のサーバの攻撃に利用される可能性がある、非常にリスクの高いセキュリティ問題です。SQL インジェクション対策は簡単です。確実に対策し、対策が取られている事を確認しましょう。

0 件のコメント:

コメントを投稿