エクスプロイト&脆弱性
Apache HTTP サーバに存在する脆弱性「OptionsBleed」
2017 年 9 月 18 日、Apache HTTP サーバに新しく確認された脆弱性「CVE-2017-9798」が公開されました。この脆弱性は、Apache HTTP サーバが設定ファイル “.htaccess” 内の特定の設定を処理する方法に起因し、結果としてメモリ情報が流出する恐れがあります。この脆弱性に対する更新プログラムは既に公開されています。
2017 年 9 月 18 日、Apache HTTP サーバに新しく確認された脆弱性「CVE-2017-9798」が公開されました。この脆弱性は、Apache HTTP サーバが設定ファイル “.htaccess” 内の特定の設定を処理する方法に起因し、結果としてメモリ情報が流出する恐れがあります。メモリ上の情報が流出するという点が脆弱性「Heartbleed」と類似していることから、CVE-2017-9798 は「OptionsBleed」と名付けられました。この脆弱性に対する更新プログラムは既に公開されています。
■「OptionsBleed 」の概要
OptionsBleed は、Apache HTTP サーバが ".htaccess" に記述された特定の設定を処理する際に「Use After Free(解放済みメモリの使用)」が可能になる脆弱性です。この脆弱性を持つ Apache HTTP サーバに対して、OPTIONS または非対応のメソッドでHTTP リクエストを送信すると、サーバからの応答にメモリ上の情報が含まれます。
図 1 は、脆弱な Apache HTTP サーバが OPTIONS リクエストに対して返信する典型的な HTTP レスポンスです。赤線で囲んだ部分にメモリから漏えいした情報が含まれています。
OptionsBleed を発見したリサーチャ Hanno Böck 氏と Apache の開発者 Jacob Champion氏によると、Apache HTTP サーバは利用可能な HTTP メソッドをユーザごとに制限する「Limit ディレクティブ」をサポートしています。しかし、サーバの主設定ファイルでグローバルに定義されていない HTTP メソッドを ".htaccess" の Limit ディレクティブに記述すると不具合が生じます。トレンドマイクロは、不正なあるいは非標準のメソッドを ".htaccess" の Limit ディレクティブに設定することにより、この脆弱性による不具合を再現しました。
デバッグによる解析を進める中で、この不具合を再現するためには、必ずしも OPTIONS メソッドを使用する必要が無いことが判明しました。サーバが返す HTTP レスポンスのヘッダに Allow フィールドを含むような HTTP リクエストであれば、この不具合を再現することが可能です。
典型的な例として、ステータスコード 「501(Method Not Implemented)」が挙げられます。501 は、未知の HTTP メソッドを含む HTTP リクエストに対して返信されるステータスコードです。図 2 のように、脆弱性を持たない Apache HTTP サーバは、未知のメソッドを含む HTTP リクエストに対してステータスコード 501 を返します。その際、Allow フィールドにはそのサーバが対応している HTTP メソッドの一覧が表示されます。
".htaccess" に未知の HTTP メソッドを記述した脆弱な Apache HTTP サーバに対して同様のリクエストを送信すると、図 3 のように、レスポンスの Allow フィールドにプロセスメモリ情報の一部が含まれます。
■技術的な詳細
Apache HTTP サーバ(実行ファイルやプロセスの名称は「httpd」)には、ヒープ領域のメモリを管理する独自のライブラリ「Apache Portable Runtime(APR)API」が実装されています。APR は、メモリプールと呼ばれる領域をあらかじめ一括で確保しておき、その中でメモリの確保および解放を行います。
httpd は、グローバルプールや接続ごとのプールのように内部的に複数のプールを維持します。同時に、HTTP メソッドの一覧を管理するために「METHOD_REGISTRY」という名前のグローバル変数を維持します。この変数は、実際には APR ライブラリの「apr_hash_t 型」の変数です。図 4 は、httpd のバージョン 2.4.26 で、METHOD_REGISTRYに登録されているすべての HTTP メソッドです。
ここで、図 4 の「ap_method_regisry_init() 関数」がプールを引数に取っていることに留意してください。起動時に httpd が受け取るこのプールはグローバルプールで、このプールにはすべての定義済み HTTP メソッドが登録された METHOD_REGISTRYが割り当てられています。
".htaccess" で Limit ディレクティブを定義することにより、httpd の起動後に新しい HTTP メソッドを追加することが可能です。図 5 の 2275 行目で、".htaccess" から読み込んだメソッドによって登録済みメソッドを更新しています。
ソースコードを注意深く読んでいくと、2256 行目の変数「method」は、".htaccess" ファイルから読み込んで「cmd->temp_pool」に割り当てたメソッドであることが分かります。その後、この 2256 行目の変数「method」は 2276 行目で「cmd->pool」にコピーされます。2275 行目で「ap_method_register() 関数」が呼ばれると、グローバルプールの METHODS_REGISTRY が更新されます。もし、グローバルプールに cmd->pool が存在しない場合は、別のプールに存在するメソッドが cmd->pool に関連付けられます。cmd->pool が解放されると、メソッドを指すポインタは空き領域を参照するようになります。以後、解放された領域を参照する METHODS_REGISTRY に関する処理は空き領域からデータを読み込むようになります。
■メモリ情報の流出
httpd が Allow フィールドを含む HTTP レスポンスを作成すると、メモリ上の情報流出が発生します。Allow フィールドは図 6 の関数で作成されます。
1056 行目の「apr_array_pstrcat() 関数」の戻り値は、METHODS_REGISTRYから取得したすべてのメソッドを連結した文字列であることに留意してください。この時、METHODS_REGISTRY が参照する空き領域の既存データが戻り値に含まれることでメモリ情報が流出します。apr_array_pstrcat() 関数の内部では、「strlen() 関数」が各メソッドの文字列長を計算します。strlen() 関数は NULL の位置によって文字列の終端を判定するため、流出する情報のサイズは strlen() 関数が呼ばれた際の NULL の位置によって決まります。
例えば、”.htaccess” の Limit ディレクティブを以下のように定義したとします。
<Limit DDDDD> </Limit> |
サーバに「curl -sI -X OPTIONS http://<IP アドレス>/test/index.html」というリクエストを送信すると、図7(上)のようにメソッドの一覧を取得できます。下方に Limit ディレクティブで定義した「DDDDD メソッド」を確認することができます。
このリクエストを再度送信すると、図 8(上)のように、メソッドの一覧に「\xd0}」が追加されました。これが解放済み領域の既存データです。図 8(下)の HTTP レスポンスでも、Allow フィールドの 7 番目に追加されていることを確認できます。
DDDDD メソッドが追加された仕組みを再度確認してみましょう。最初のメモリが破壊された場合、httpd は実行時にもう一度メソッドを追加します。これにより、DDDDD メソッドが追加されました。このような仕組みにより、再度リクエストを送信すると、さらに情報流出が発生します。
このような操作を複数回繰り返すと、以下のような結果となります。
- DDDDD メソッドが割り当てられたメモリは破壊されず、改めてメソッドが追加されることもありません。なぜなら、httpd はメソッドの新規追加時に登録の有無を確認するためです。
- ある時点で、METHODS_REGISTRY に登録したメソッド数が、「METHOD_NUMBER_LAST = 62」として定義された最大値に達し、それ以上メソッドを追加することができなくなります。しかし、実際は、最大値に達することはほぼありません。
■情報流出の発生条件
“.htaccess” は、メソッドの種類に関わらず、リクエストごとに読み込まれます。サーバが Allow フィールドを返すようなリクエストである場合、そのリクエストが不正かどうかに関わらず、どのようなメソッドでもメモリ情報の流出が発生する条件を満たします。例えば、以下のように、存在しないメソッドを利用した不正なリクエストでも同様に情報流出が発生します。
curl -sI -X ANYANY http://192.168.93.207/test/index.html |
■流出する情報のサイズ
流出するメモリ情報のサイズは以下のように複数の要因で決まります。
- 破壊されたメモリからメソッドを読み込む際の NULL の位置
- 漏えいするメソッドの数、最大でも 62 個
- Allow フィールドの長さ
2 番目の要因には上限がありますが、1 番目と 3 番目にはありません。つまり、理論的には流出する情報のサイズに上限は無いということです。実際は、1 番目の要因のように NULL 文字によってサイズが決まる場合が多いと考えられますが、他にも考慮すべき要素があります。Apache HTTP サーバはクライアントにレスポンスを返す前に、Allow フィールドを確認し、不正な値だった場合送信を中止します。具体的には、HTTPプロトコルにおけるメッセージの構文とルーティングを定めた仕様「RFC 7230」のセクション 3.2 で定義されているように、ASCII 制御文字に到達するまで文字列を調べます。コードは図 11 の通りです。
最初に HT(水平タブ)以外の ASCII 制御文字が見つかった箇所に、図 12 のコードが適用されます。
結論として、最初に見つかった HT 以外の ASCII 制御文字が、廃用された行折り返し(※1)だった場合、Allow フィールドをクライアントに送信しません。
※1:CR(キャリッジリターン)+ LF(ラインフィード)+ 空白または HT のいずれか
■更新プログラムの詳細
更新プログラムは、Limit ディレクティブの利用を主設定ファイル "http.conf" に制限し、".htaccess" による Limit ディレクティブのサポートを停止します。cmd->pool は METHODS_REGISTRY が作成された際のプールと等しいという想定から、新しいメソッドは、cmd->temp_pool が cmd->pool と等しい場合にのみ追加されます。これは Web サーバの起動時も同様です。図 13 の 35~42 行が、修正のために追加されたコードです。
本記事で解説した脆弱性「OptionsBleed」 に関しては、不正確な意見も見受けられます。その 1 つに、メモリ情報の流出が複数回の OPTIONS リクエストの送信後に発生するというものがありますが、情報流出は 1 度目のリクエストから発生します。また、メソッドは必ずしも OPTIONS である必要はありません。
■OptionsBleed の深刻度
一般的に、".htaccess" ファイルは、サーバの主設定にディレクトリごとの設定を追加するために使用されます。
公式の「Apache チュートリアル:.htaccess ファイル」では以下のように説明されています。
一般的に、サーバの主設定ファイルにアクセスできない場合を除いて、".htaccess" ファイルの使用は極力避けてください。".htaccess" ファイルの使用はサーバの性能を低下させます。普通は可能であれば ".htaccess" ファイルの使用は避けてください。".htaccess" ファイルに書こうと考えるようなすべての設定は、サーバの主設定ファイルの<Directory>セクションで同じように行なうことができます。 |
上述のガイドラインを踏まえ、OptionsBleed を狙った攻撃には ".htaccess" の Limit ディレクティブが必要であることを考慮すると、この脆弱性は致命的な不具合ではないと考える向きもあるかもしれません。
しかし、ユーザがサーバの主設定ファイルにアクセスできない場合は、".htaccess" で自身の Web サイトの設定を変更することになります。ISP(インターネットサービスプロバイダ)がサーバおよび主設定ファイルのルート権限をユーザに付与しない共有 Web ホスティング環境では、このような状況は一般的です。
攻撃者は、共有 Web ホスティング環境で Web サイトをホストし、自身の Web サイトの ".htaccess" を改ざんし、OptionsBleed を利用してメモリ情報を流出させることが可能です。このメモリ情報には、共有環境にホストされている他の Webサイトの機密情報が含まれている可能性があります。多くの Web サイト管理者が共有 Web ホスティングを利用しており、OptionsBleed はそのようなユーザを情報流出の危険にさらします。
影響を受ける Apache HTTP サーバのバージョンは、2.2.34 以下の2.2.x、2.4.27 以下の2.4.x です。この脆弱性に対する更新プログラムは、多くの Linux ディストリビューションで既に公開されています。
■被害に遭わないためには
システム管理者は Apache HTTP サーバに更新プログラムを直ちに適用してください。また、".htaccess"の無効化によってもこの脆弱性に対応することが可能です。ISP のホスティングサービスを利用するサイト管理者は、更新プログラムの適用状況を ISP に確認してください。
サーバ向け総合セキュリティ製品「Trend Micro Deep Security™」をご利用のお客様は、利用可能な HTTP メソッドを設定し、未知のHTTPメソッドによるメモリ情報の流出を制限する以下の DPI ルールによってこの脆弱性を利用する脅威から保護されています。また CVE-2017-9798 専用のルールもリリースされています。
- 1002593 – Allow HTTP (Including WebDAV) Methods
- 1008618 – Apache HTTP OPTIONS Information Disclosure Vulnerability(CVE-2017-9798)
ネットワークセキュリティ対策製品「TippingPoint」では、以下の Custom Shield Writer(CSW)により今回の脅威をブロックします。
- C1000002: HTTP: Apache Server Options Information Disclosure Vulnerability
参考記事:
- 「OptionsBleed – The Apache HTTP Server Now Bleeds」
by Pavan Thorat and William Gamazo Sanchez
翻訳:澤山 高士(Core Technology Marketing, TrendLabs)