SQLインジェクション,XSS対策
SQLインジェクション
今夜分かるSQLインジェクション対策:Security&Trust ウォッチ(42) - @IT
クロスサイトスクリプティング(XSS)
第1回 悪意のJavaScriptで情報が漏えい | 日経 xTECH(クロステック)
- クライアント(ユーザー)からのリクエストは信頼しない
- 悪意のあるコードが含まれている前提でコーディングする
- 規則性のあるコーディングで処理の漏れ・バグをふせぐ
- 統一させることでコードの可読性もあがる
リクエストデータのバリデーション(正当性検証)
- クライアント側(JavaScript)での正当性チェックは効果がない (ユーザビリティのみ)
- selectボックスなどからのリクエストも検証する (引数にはどんなデータでも含ませることができる)
- メールアドレスや文字数制限などの検証も行うことでDBに行く前にチェック (負荷対策にも)
対策:クライアントからリクエストを受け取った時点ですべてのデータの正当性を検証する
例:
if (preg_match('/^[0-9]{,11}$/D', $_GET['id'])) { $id = $_GET['id']; } else { //エラー }
正規表現修飾子のDがないと改行が含まれる場合にチェック漏れがあるらしい
(via:第5回 まだまだ残っているSQLインジェクション:なぜPHPアプリにセキュリティホールが多いのか?|gihyo.jp … 技術評論社)
小文字のdのような気もする。
if (preg_match('/^[A-Z]{2}[0-9]{8}$/D', trim(mb_convert_kana($_GET['id'], "as")))) { $id = trim(mb_convert_kana($_GET['id'], "as")); }
全角英数スペースを半角に変換してtrimするとユーザビリティもUP(全角変換はやりすぎ?)
SQL発行時
対策:適切に文字コード変換をしてpear DBなどのバインド(プレースホルダ)機能を使用する
(addslashesだとmagic_quote_gpc onの時に2重エスケープされてしまう)
例:
$db = DB::connect($dsn); $name = mb_convert_encoding($name, "UTF-8", "auto"); $sql = "SELECT * from user WHERE user_id = ? AND user_name = ?"; $result = $DB->query($sql, array($id, $name));
出力時
対策:出力する直前でhtmlspecialchars (DBからのデータにはstripslashes)
例:
<dl> <dt>名前</dt> <dd><?= htmlspecialchars(stripslashes($res['name']), ENT_QUOTES, "UTF-8") ?></dd> </dl>
ENT_QUOTESでシングルクォーテーションも実体参照になる (文字コード指定はDB登録時にチェックしてるのでいらないかも)
(via:htmlspecialchars/htmlentitiesの正しい使い方 – yohgaki's blog)
備考:
※リクエスト元のページが正しいかcrumbなどを埋め込んでチェックとか
※DB側の設定とか
※他にもファイルを開く際やCookieの取り扱いなど気をつけないといけないところはたくさん
※漏れている部分やよりよい方法があればご指摘お願いします
参考URL:
- Webアプリケーションを作る前に知るべき10の脆弱性
- Webアプリケーションを作る前に知るべき10の脆弱性:Security&Trust ウォッチ(47) - @IT
- 知っていますか?脆弱性 (ぜいじゃくせい)
- 知っていますか?脆弱性 (ぜいじゃくせい):IPA 独立行政法人 情報処理推進機構
- より良いWebアプリケーション設計のヒント(たとえば、PHPを避ける)
- IPA ISEC セキュア・プログラミング講座:Webアプリケーション編 第1章 総論:より良いWebアプリケーション設計のヒント