PHPのセキュリティメモ

PHP

PHPを使用する時に考えなくてはいけないセキュリティ。いろいろあって何をどうすればよいのか分かりづらいので調べてみました。

まとめたというよりは自分が再度調べる時へのメモ用に箇条書きレベルです。

また調べた他にもあると思うので、これを対応すれば完璧というわけではありません。参考程度でお願いします。またコードが間違っていてもいけないので、具体的なコードは別で調べていただければと思います。

クロスサイトスクリプティング(XSS)

原因

ユーザーから入力されたデータをそのまま返すとおこる

対策

htmlspecialchars()を使ってエスケープする。
echo htmlspecialchars($val, ENT_QUOTES);
「style href src onclick onload」などの危険な属性に対してユーザー入力を用いない
cookieを使う際の、HttpOnlyを指定(クッキーを、HTTPからのみアクセスできるようにし、JavaScriptからクッキーを読み込まれないようにする)
ini_set('session.cookie_httponly', true);

クロスサイトリクエストフォージェリ(CSRF)

原因

攻撃対象となる脆弱サイトへ意図しないデータを送って処理させる

対策

トークンを使う
トークンに値がなければエラーにする empty()を使う

トークンの比較にはhash_equalsを使うよい。
→「===」は文字列の長さで処理にかかる時間がほんのわずかに違く、その時間の違いからパスワードが推定される。

SQLインジェクション

原因

意図しないSQL文が実行されデータベースを不正に操作する

対策

特殊文字をエスケープする
プレースホルダを使用する

クリックジャッキング

原因

クリックするボタンを隠蔽・偽装してクリックさせる

対策

他のページのiframe内に表示されないようにする
.htaccess →Header set X-FRAME-OPTIONS "DENY"
PHP →header('X-FRAME-OPTIONS:DENY')

HTTPレスポンス分割攻撃

対策

HTTP レスポンスヘッダで読み込む変数に悪意のあるデータを入力する

対策

PHPを最新(ある程度)のバージョンにするとheaderが2つ以上認識しないのでよいらしい
HTTPヘッダとして出力する箇所に「%0d%0a」改行文字(CR/LF)を入れないようにする。
ユーザ入力文字列をHTTPヘッダとして利用する際に無害化(文字列から削除する)

Nullバイト攻撃

原因

NULLバイト文字(\x00 , \0)を正しく扱えないバイナリセーフでない関数を使ったセキュリティーチェックをくぐり抜ける攻撃

対策

Nullバイト文字を消す
$filename =str_replace( "\0", "",$filename );
preg_matchで使用可能な文字列のみ許可する。

Email ヘッダ・インジェクション

原因

ユーザーから入力されたデータをそのまま使った場合、意図しないヘッダ情報を追加される恐れがある。
改行文字を使ってメールヘッダや本文を追加・変更できる。

対策

正規表現をつかってメールアドレスのデータだけなのかどうかをチェックする
入力された値を、レスポンスヘッダの値へ設定する場合は、「改行コード」をエスケープする

ディレクトリトラバーサル

原因

意図しないファイルや階層にアクセスされる。

対策

外部から受け取った値を、エスケープせずにファイル名を取得するために発生。
basename関数を用いる
ファイル名にディレクトリ名が含まれないようにする
ファイル名の妥当性チェックをする(単純なのは英数字に限定かつ拡張子は固定)
外部からファイル名を直接指定できないようにする

セッションハイジャック

原因

セッションを推測され、なりすまされる。

対策

推測されにくいセッションIDを生成する
アクセス毎に変更 session_regenerate_id(TRUE);

参考ページ