ブラインドSQLi:沈黙するデータベースからの「問いかけ」を封じ込める技術
現場でインシデント対応をしていると、「うちはエラー表示をオフにしているからSQLインジェクションは大丈夫」という、非常に危険な慢心に出くわすことがある。はっきり言おう。エラーメッセージが表示されないことと、データが守られていることは全くの別次元の話だ。
攻撃者は、あなたのデータベースが「静かに沈黙している」ことすら情報として利用する。これが、今回解説する「ブラインドSQLi(Blind SQL Injection)」の恐ろしさだ。
1. ブラインドSQLiのメカニズム:応答の「差」を見抜く
ブラインドSQLiは、サーバーがエラーを返さない場合に、以下の2つのアプローチでデータを1文字ずつ抽出する。
- Boolean-based(真偽値ベース):
「このクエリが真ならページを正常表示し、偽なら何も表示しない」という挙動の差から、条件分岐を繰り返して情報を確定させる。
- Time-based(時間差ベース):
「もしデータが正しければ、SLEEP(5)を実行せよ」という命令を投げ、レスポンスが5秒遅延するかどうかで、推測が正しいかを判定する。
攻撃のPoC(概念実証)のイメージ
例えば、ユーザーIDを検索するクエリにおいて、以下のようなペイロードを投げる。
' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE username='admin')='a'--
この時、レスポンスのHTMLサイズやHTTPステータスコードが変化すれば、「管理者のパスワードの1文字目は ‘a’ である」と確定できる。これをスクリプトで自動化すれば、数万行のデータも数十分で抜き取られる。
2. 「防御の鉄則」:静的プレースホルダによる完全分離
ブラインドSQLiを防ぐために、エスケープ処理やバリデーションだけに頼るのは「ザルで水を汲む」ようなものだ。SQLコマンドとユーザー入力値を物理的に分離する「プリペアドステートメント(静的プレースホルダ)」を、何があっても守ってほしい。
PHP (PDO) でのセキュアな実装例
PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false, // 重要:真のプリペアドステートメントを使用する
]);
// ユーザー入力:決して文字列結合しない
$username = $_GET[‘user_id’];
// SQLテンプレートを用意し、値をバインドする
$stmt = $pdo->prepare(“SELECT email FROM users WHERE username = :username”);
$stmt->execute([‘username’ => $username]);
// 結果の取得
$user = $stmt->fetch();
?>
3. インフラ・WAFによる多層防御
アプリケーションコードが完璧であっても、万が一の脆弱性混入に備えてインフラ側でガードを固めるのがプロの流儀だ。
Nginx + ModSecurity (WAF) での防御ルール
WAFは「SQLのパターン」を検知する。sleep() や substring() などのキーワードが連続してリクエストに含まれる場合、即座に遮断する設定を適用しておく。
WAFの設定例(概念)
SQLインジェクションのシグネチャを検知して403を返す
SecRule ARGS “@detectSQLi” \
“id:1001,phase:2,deny,status:403,log,msg:’SQLi detected'”
4. 現場のシニアエンジニアからの忠告
最後に、運用フェーズで必ず守ってほしい「盲点」を2つ伝える。
1. DBユーザー権限の最小化:
Webアプリケーションから接続するDBユーザーには、SELECT, INSERT, UPDATEのみを許可し、DROP TABLEやシステム関数(SLEEP()やBENCHMARK()など)の実行権限は徹底して剥奪せよ。万が一インジェクションが成功しても、被害を最小限に抑えられる。
2. ログ監視の徹底:
ブラインドSQLiの自動化ツールは、短時間に数百回、数千回のリクエストを投げる。WAFのログやWebサーバーのアクセスログで、「同一IPからの異常なリクエスト頻度」をアラート検知できる体制を構築してほしい。
セキュリティは「ツールを導入すれば終わり」ではない。「データは常に外部からの悪意に晒されている」という前提で、コードの1行1行に疑いを持つこと。それが、君たちを一流のエンジニアにする唯一の近道だ。
何か実装で迷ったら、いつでも聞きに来てくれ。理論と現場の板挟みの中で、一緒に最適解を探そう。
コメント