セキュリティ(PerfectPHP 9章 後編)
HTTPヘッダインジェクション(HTTPレスポンス分割攻撃)
ブラウザに対して不正なHTTPレスポンスヘッダを送りつけること。
任意のURLにリダイレクトさせたり不正なクッキーをセットさせたりする攻撃方法。
※ただしPHP側で4.4.2、5.1.2で対応済み。つまり古いPHPで動く場合は注意。
そもそもレスポンスヘッダがわからないので下記
と思ったら結構ここも詳しく書いてあった。
下記は公開禁止コード
$url = 'http://example.com/';
if(isset($_GET['page']) === true && $_GET['page'] !== ''){
$url .= $_GET['page'];
header('Location: ' . $url);
exit();
}else{
echo 'ページ指定がありません。';
}
これに対して
?page=1をすると/1のとこに飛ぶ仕様。
だが
?page=dummy%0d%0aLocation%3a%20http%3a%2f%2fgihyo%2ejp%2fbook
アクセスするとリダイレクトされる。
この時にヘッダみるとLocation:◉◉が2行になってるのがわかると思う。
chromeの場合は下記にアクセスしてフィルタでtype:URLとかにすると見やすい。
chrome://net-internals/#events
あとは%0D%0ASet-Cookie:SID=12345とかでクッキーIDを固定されたり。
対策方法
・PHPのバージョンを上記以上にする。→勝手にチェックしてWarningとして実行されなくなる。
・プログラム側で改行コードをチェックする。
メールの第三者中継
説明不要、名前のまま。自分も攻撃者になってしまう。
危険パターン1 メール宛先にリクエストからの値を利用してる時。
例
POSTメソッドでリクエスト→お問い合わせフォーム、hiddenでtoにしてる→admin@aaaa.comに送信というプログラムがあったとする。
↓
htmlでフォームに飛ばすようにしてtoを設定するとか、phpでtoに値を設置してPOSTするとかどちらでもメールがそのまま実行されて、踏み台にされてしまうため危険。
最悪の場合、カンマ区切りで沢山POSTされて不正に一斉送信の踏み台にされてしまう。
一斉送信仕様ならテキストエリアで1行1アドレスずつ入力してもらい、1行ごと入力されてるメアドが妥当かチェックすること。
対策
そもそもリクエストからの値を利用しない。
どうしても使うしかないならカンマ区切りのメアド不正挿入、メールヘッダインジェクションに対応しておく必要あり。
危険パターン2 メールヘッダインジェクション
メールヘッダに改行コードを含めた文字列を挿入して送信メールの改ざんをする攻撃方法。
メールヘッダ追加やメール本文の改ざんが可能。
例
脆弱性のあるコード内に$_POST['from']とかあって、Fromアドレスを取得している場合。
mb_send_mail()やmail()関数第四引数にCCやBCC等のヘッダ情報を指定できるので、
使っていた場合は攻撃用のHTMLで<textarea name="from">foo@hoge.com\r\n
Bcc:bar@hoge.com,buz@hoge.com</textarea>
などと改行コードを含んで指定するとBCCのアドレスに送られてしまう。。
対策
・リクエストからの値を使用しない。
どうしても仕様上使う必要がある場合、カンマ区切りのメアド不正挿入やメールヘッダインジェクションに対応する必要がある。
↓
メアド不正挿入対応
・メアドの形式が妥当か。
・メアドドメインが妥当か。
・メアドのローカルが有効か。
ただしRFCに準拠しないアドレスも存在している(日本の携帯電話など)、RFC準拠でも”で囲まれてればどんな文字でも許容される事を考えると確実に有効かどうかの判定は厳しいというのが現実。
メアドの形式として正しいと思われるレベルで問題ないと思われる。
メールヘッダインジェクション対応
改行コードが含まれないことをチェックするプログラムにする。
変数汚染攻撃
変数を改ざんされてしまう危険な攻撃。
恐怖
グローバルスコープ変数、スーパーグローバル変数、環境変数までも改ざんされる。
・権限の不正取得
・コマンド攻撃(これは後述)
等が実行可能となる。
PHP4.4.0より前のWEBアプリケーションだとregister_globalsをよくつかっていた。
有効な場合、GETやPOSTなどの値が自動的に変数として展開される。
そこでセキュリティ上の観点から、PHP4.2.0からは初期値として無効にされている。
このような背景から初期値が無効な場合の対応としてプログラムの最初に変数展開をさせる方法が普及した。
これが脆弱性につながってる。
//register_globalsが無効な場合、GET変数を展開する
foreach($_GET as $key => $value) {
$$key = $value;
}
//GETを使った処理~~~~
echo 'IPアドレスは:' . $_SERVER['REMOTE_ADDR'] . '"です。';
例
?_SERVER[REMOTE_ADDR]=1234をURLに付与すると。。。
本来変更不可の環境変数が改ざんされる。
とにかく
・register_globalsが有効
・何らかの方法でスーパーグローバル変数展開、GET,POST,Cookie変数の配列展開をしている
・parse_str()でクエリ文字列の変数展開
の場合は脆弱性がある可能性あり。
対策
register_globalsを無効にした上で次の対応を行う。
・スーパーグローバル変数に対する変数汚染チェック
・扱う変数以外は展開しない
・foreach,extract()による展開自体しない
スーパーグローバル変数に対する変数汚染チェック
どこからでも参照可能なので狙われやすい。
リクエストのキーがスーパーグローバル変数名かどうかチェック。違ったらOKとする。
つづきはじかい