今、PHPであるアプリを作っていて、セキュリティを固めている途中。
今回は、XSSがテーマ。SQLインジェクションもあとでやります。
XSSは一応知っていたけど、復習&実践&メモ。
こちらと
こちらと
こちらを参考にした。
とりあえず、実践。
<script>alert("XSS");</script>
↑をフォームに入力、実行してみる。
うむ。見事に実行可能。何されるか分からん。
○XSSとは
--------------------------------
XSSが問題になるのは、「ブラウザに出力する」処理の部分でプログラムミスがある場合に起こる。
HTTPおよびHTML中において、特別な意味を持つ文字として定義されている文字がいくつかある。有名なところで「<」と「>」は、HTMLの構成を記述するためのタグの開始と終了を表すための区切り文字として使用する、という特別な意味を持っている。
--------------------------------
と言うことで、さっそく対策。
まず、基本から復習しよう。
○フォームの基本
入力値を受取る → それを処理 → 出力する
↑ ↑
[入力チェック] [サジタイニング]
この流れを忘れてはいけない。
・[入力チェック]
これは、「OSコマンドインジェクション」「SQLインジェクション」「バッファオーバーフロー」といったXSS以外のセキュリティホールの対策となる場合がほとんどなので、とっても重要。
* 入力値として許可する値かどうかチェック
* 入力文字数のチェック
基本中の基本なので、まずはしっかり行う。
※注意点
* サーバ側で行う
javascript とかでチェックしたつもりにならないように!
* すべてのパラメータに対して行う
ラジオボタンとか、チェックボックスとかも同じだよ!
* 毎回行う
たとえば、 入力→確認→完了 というフォームの流れがあったとする。
確認ページでhiddenフィールドにフォームの入力を保存したりする場合、
入力→確認 はチェックしたけど、 確認→完了 はチェックしていないのではなんの意味もない!
○特殊文字のサニタイジング(無害化)
上記の、入力チェックを行っていれば、入力チェックを確実に行っていれば、かなりセキュリティレベルの高いアプリケーションが出来上がっているはず。でも、まだ完璧ではない。
サジタイニング(無害化)する文字列は、実は、アプリごとに違うのである。
たとえば、最終的に「,(カンマ)」で区切られるCSVにデータが保存される場合、「,(カンマ)」がフォームに入力され、そのまま登録されると困るだろう。
このように、サジタイニング(無害化)する文字列は、各自考えることになる。
以下は、代表的なものを示す。
・HTML
* 本文の場合
本文で特殊文字となる文字は、「<」「>」「&」の3つである。
* タグの場合
まず、属性値は必ず「"(ダブルクオーテーション)」または「'(シングルクオーテーション)」で囲む。これはW3Cが推奨しているのと同時に、サニタイジングが必要な特殊文字を限定することになるので、忘れずに行ってほしい。「"」で囲った場合の特殊文字は「"」だけとなる。同様に「'」で囲った場合は「'」だけとなる。それぞれ、「"」と「'」に変換することでサニタイジング完了となる。
要するに、特殊文字が含まれなければよいということである。
具体的に、PHPで言うとhtmlのソースに、
htmlspecialchars( 変数 )
と行えばよい。
※htmlspecialchars() で 「'」の無害化はオプションである。なので、「"」で囲ったほうが良い。
・HTTP
ここまではHTMLに入力値を出力する話だったが、ちょっと視野を広げてHTTPまで踏み込んでみよう。
こちらには、Set-Cookie ヘッダについて書いてある。HTTPヘッダに入力値を含む場合にもサニタイジングが必要になると言うことです。
Set-Cookie ヘッダの場合は「;」が属性の区切りを表す特殊文字であるなど、ヘッダによってさまざまな特殊文字が存在するので、それらの処理も忘れずに行う必要がある。
以上のようなことに、気を付けてXSS対策を行おう!