【実務・中級編】 SQLインジェクションにおけるブラインド型(Boolean-based/Time-based)の検知と防御 – オフェンシブセキュリティ & リバースエンジニアリング防御ガイド

画面に何も出ないから「安全」?ブラインドSQLiという静かなる脅威

「エラーメッセージを非表示にしているから、うちのWebアプリはSQLインジェクションに対して安全だ」。もし君がそう思っているなら、今日でその甘い考えは捨ててくれ。

攻撃者は、画面に表示される派手なエラーメッセージなど必要としていない。彼らが求めているのは、システムが「イエス」か「ノー」を答えてくれるたった一つの真実だ。今日は、防御側の盲点を突く「ブラインドSQLインジェクション」の残酷な現実と、それをシステム設計レベルで無力化する方法を叩き込む。

—

1. ブラインドSQLiの真髄:0か1かの尋問

ブラインドSQLi(Boolean-based)の本質は「尋問」だ。攻撃者はデータベースに対して「ユーザーIDが1のパスワードの1文字目は ‘a’ か?」と問いかける。

  • 真の場合:正常なページが表示される(HTTP 200)
  • 偽の場合:コンテンツが消える、またはカスタムエラーページが表示される

この反応の違いを自動化ツールで数千回繰り返せば、パスワードや機密データがまるで辞書をめくるように抽出される。また、エラーメッセージすら出ない場合は「Time-based(時間差攻撃)」を使う。SLEEP(5) をクエリに仕込み、サーバーの応答が5秒遅延すれば「条件が真だった」と判断する。画面上の見た目は変わらなくても、通信のレスポンスタイムが雄弁に語ってしまうのだ。

攻撃のPoC(概念実証)の裏側

攻撃者が行うのは、以下のようなクエリの注入だ。

-- 攻撃者が投げ込むクエリの断片
' AND (SELECT SUBSTRING(password,1,1) FROM users WHERE id=1) = 'a'--

このクエリが投げられた時、もし条件が合致すればページは正常に読み込まれる。この「レスポンスの差」を見逃さないツール群が、今のセキュリティの最前線では脅威となっている。

—

2. 根本的防御:プレースホルダによる「分断」

脆弱性を修正する際、「入力値をサニタイズ(フィルタリング)すればいい」と考えるのは古い。記号のエスケープ漏れは必ずどこかで起きる。

防御の要諦は、「SQL文」と「データ」を物理的に分断することだ。これを実現するのがプリペアドステートメント(プレースホルダ)である。

セキュアな実装例(PHP/PDO)

多くの現場で、mysql_query といった古い関数や、生の文字列結合を見かける。今すぐ廃止してほしい。

// 悪い例:文字列結合によるSQL構築(絶対NG)
// $sql = "SELECT * FROM users WHERE id = " . $_GET['id'];

// 良い例:プリペアドステートメントの使用
$id = $_GET['id']; // 入力値はそのまま扱う
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");

// 実行時に値をバインドする(ここで初めてデータとして扱われる)
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
$user = $stmt->fetch();

この実装であれば、たとえ $id に 1 OR 1=1 といった悪意ある文字列が入力されても、DBはそれを「数値の1」としてしか処理しない。SQLクエリの構造そのものを書き換えることは不可能になるのだ。

—

3. インフラ層での防衛:WAFとログ監視

コードの改修が間に合わないレガシーなシステムを抱えている場合、インフラ層での遮断が最後の砦となる。

WAF(AWS WAF等)の設定指針

SQLiの兆候を検知するには、シグネチャベースの防御が有効だ。特に UNION SELECT や SLEEP()、BENCHMARK() といった関数をキーワードとして正規表現でブロックする。

Nginxでのアクセスログ監視

ブラインドSQLiは短時間に大量のリクエストを送る必要がある。異常なリクエスト頻度を検知し、IP単位で制限をかける設定を入れておくべきだ。

# nginx.conf: 1秒間に送れるリクエスト数を制限(レートリミット)
limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;

server {
    location /login {
        limit_req zone=one burst=10; # 攻撃ツールによる高速な試行を抑制する
        proxy_pass http://backend;
    }
}

—

現場のエンジニアへ送るアドバイス

セキュリティは「チェックボックスを埋める作業」ではない。攻撃者の視点に立ち、「このクエリがもし操作できたら、自分ならどうやってデータを引き出すか?」と常に想像することだ。

1. プレースホルダを信仰せよ:文字列結合は「バグの種」ではなく「脆弱性の種」だ。
2. ログに異常を見る:データベースの遅延クエリログや、WAFのブロックログは、攻撃者が「試行錯誤している足跡」そのものだ。
3. 最小権限の原則:もしWebアプリが DROP TABLE 権限を持っていたら、それは設計ミスだ。アプリ用DBユーザーには、必要なテーブルへの SELECT/INSERT/UPDATE 権限しか与えるな。

システムが完璧である必要はない。だが、攻撃を「効率的」にさせてはならない。今日のこの知識を、君たちのプロジェクトの防御壁として積み上げてほしい。健闘を祈る。

コメント

タイトルとURLをコピーしました