GETで渡す情報にユーザーの身元が特定できるものを不必要につけてはいけない。GETにするのは参照するときのみでデータの更新にはPOSTを使う。同じ情報をPOSTにしてもHTTPヘッダーモニターツール(LiveHttpHeaders)などでいくらでも改ざんできるのでログイン以後はセッションを利用すべきである。
CookieもHTTPヘッダーにて送られるので改竄は容易。Cookieを使うのであれば、平分で保存するのではなく、サーバ側が保持しているIDをCookieに持たせ、さらにそのIDを可逆暗号化して、毎回サーバ側で照合すべき。もちろんニックネームなどの流出しても個人情報特定につながらないものであれば対策は不要。http_only属性をつけるとJavaScriptから読み出しができなくなる。つけといて損はないのでデフォルトでセットするようにすべし。
言語標準でセッション管理が備わっている場合はあまり意識しなくていい。ただし携帯開発などではCOOKIEが使えないので、GETパラメータに加えるように変更する必要がある。スタティックなページでもセッションを維持できる方法がある。それは上位ディレクトリにセッションIDを埋め込んでおいて、mod_rewriteで書き換えるのである。
http://rutake.com/9803/index.php →index.php?session=9803
セッションIDを盗んで他人のログイン後の画面に侵入するものである。漏洩パターン配下のとおり
PHPではデフォルト完全な乱数を使っていないので、php.iniに以下の設定を入れることによりさらに安全になる
[Session] session.entropy_file = /dev/urandom sessoin.entropy_length = 32
eregなどの関数はバイナリセーフではないので%00を入れてしまうと、それ以後のチェックをすり抜けてしまう。制御文字を除去してしまうのが良い。行全体を^$で表すと行末の改行コード%0aがすり抜けるので代わりに\A\zを使う。
preg_match('/\A[\r\n\t[:^cntrl:]]{1,400}\z/u', $comment)
汚染文字列の危険性のチェックをしてくれるモード
perl -T
HTMLタグをそのまま表示するというもの。攻撃手法としてはもっとも単純だが、これの防御ができていないサイトだと、他の脆弱性も間違いなく存在する。JavaScriptを仕込んで任意のページに飛ばしたりできてしまうので、他のユーザにも影響がある。対策としてはHTMLタグを無効化することであり、各言語にはその関数が用意されているはず。ユーザの入力値、データベースの値、現在のアクセスURL($_SERVER['self'])などがタグ無効化対象となる。
入力値に不正なSQLを入れる攻撃。PreparedStatementなどを使っていれば防げる。その場合でも入力値を使ってSQLを組み立てるときは必ず入力チェックを行うこと。
正規なログイン認証を経たユーザーに対して、意図せずして更新などを行わせてしまう脆弱性。対策としてはリファラーチェックやトークンが考えられる。更新対象となる画面を抽出しCSRF対策として対応工数を見積もること。徳丸本ではワンタイムトークンよりもセッションIDでチェックする方法を推奨している。
\0を間に挟むことによりファイルの拡張子チェックなどをすり抜ける攻撃。たとえばdatファイルのみを読み込ませるコードでindex.php\0datとすれば、拡張子チェックは抜けることができる。リクエストパラメータで不正文字は除去する関数を作成しておけば次のディレクトリトラバーサル攻撃も防げる。
JavaScriptのエスケープルールは複雑なので動的生成を避けるのが一番。全部UNICODEにするかHIDDENから動的パラメータを取得するかがおすすめ。
安全なWebアプリケーションの作り方
.co.jpのようなありえない範囲にまかれるCookieが生成できてしまうというブラウザのバグ。
1.攻撃者がメールで自サイトに誘導し、セッション固定のIDを送付。そのリンク先はショッピングサイト 2.頃合いを見て攻撃者がショッピングサイトに同じセッションIDでログイン。 ※セッション固定対策がされていればこの脆弱性の影響はない。
バグではないが地域型ドメインはname.city.prefecture.jpのようなドメインでありながら、上位レベルのprefecture.jpに対してのCookieが発行できてしまうという問題がある。