古いPHPでHTTPヘッダインジェクションを再現
はじめに
HTTPヘッダインジェクションの理解を深めるために普段使っているPHPで動きを再現しようとしたのですが、思うように動かず、、。
調べてみると、バージョン5台で対策されており、現在メンテナンスされてるバージョンでは再現しないようです。
PHPにおけるHTTPヘッダインジェクションの対応は、以下のページを参考にしていただくと良いかと思います。
修正によってheader()を使用して、1回の呼び出しで複数の応答ヘッダーを送信できなくなっているようです。
本記事ではバージョン5以前のPHPを用意してHTTPヘッダインジェクションを再現してみます。
そもそもHTTPヘッダインジェクションとは
HTTPヘッダインジェクションの概要は以下のページなどがわかりやすいです。
HTTPヘッダ・インジェクションの脆弱性とは、任意のレスポンスヘッダフィールドやレスポンスボディを作成する罠が仕掛けられ、この罠を踏んだ利用者のブラウザで偽のページが表示されたり、スクリプトが実行したり、任意のCookieを保存させられたりする可能性があります。
リクエストに対して出力するHTTPレスポンスヘッダのフィールド値を、外部から渡されるパラメータの値等を利用して動的に生成するケースがあります。PHPではheader関数を利用した場合でしょう。
たとえば、HTTPリダイレクトの実装として、パラメータから取得したジャンプ先のURL情報を、Locationヘッダのフィールド値に使用する場合や、掲示板等において入力された名前等をSet-Cookieヘッダのフィールド値に使用する場合等が挙げられる。
その渡されたパラメーターを利用してたページにおいて、HTTPレスポンスヘッダの出力処理に問題があることが原因です。具体的には改行コードの扱いです。
改行コードはHTTPヘッダにおいて特殊文字にあたります。各HTTPヘッダ行は改行で区切られ、それ以降は新たなヘッダ行として処理されます。つまり改行コードが挿入できると意図しないレスポンスヘッダが追加できてしまいます。
再現していく
いにしえのPHPを召喚
古いPHP環境を用意していくにあたって、以下のDockerイメージにお世話になりました。(ありがたい、、。)
環境は以下です。
- PHP 4.4.0
- Apache 2.2
PHP 4.4.0のリリースは11 Jul 2005
のようです。歴史を感じますね^^。
状況
パラメーターの値をもとに新しいURLへリダイレクトするという状況を想定します。
たとえば、http://localhost?url=sample.html
にアクセスするとhttp://localhost/sample.html
にリダイレクトされるという仕様です。
上記を踏まえて、ドキュメントルート下に以下のようなファイルを設置しました。
<?php
if(isset($_GET['url'])){
header('Location: ' . $_GET['url']);
}
?>
<div>Render Cookies</div>
<?php
if (isset($_COOKIE)){
echo('<pre>');
var_dump($_COOKIE);
echo('</pre>');
}
?>
header('Location: ' . $_GET['url']);
とあり、header()で'Location
を設定することでリダイレクトを実現しています。
(このケース、オープンリダイレクトの脆弱性も含まれてしまってますが、、、。)
やり方
Set-Cookie
ヘスポンスヘッダを追加することで、Cookieをセットしていきましょう。
そのために、以下のURLにアクセスします。
http://localhost/?url=http://localhost/%0d%0aSet-Cookie:+PHPSESSID%3Dhogehoge
アクセスすると、%0d%0a
が改行として読み込まれ追加されるHTTPレスポンスヘッダは以下のようになりCookieが書き換えられるわけです。
Location: http://localhost
Set-Cookie: PHPSESSID=hogehoge
デモ
それでは実際に動きをみていきましょう。
開発者コンソールからSet-Cookie: PHPSESSID=hogehoge
という内容のレスポンスヘッダも確認できました!!
以上になりますmm
Discussion