【検索フォーム編】入力欄から考えるXSS・SQLiの入口と守り方|CTF思考フレームワーク #04
こんにちは、アンペンです!
前回は、パスワード再設定機能で「画面の返事」と「リセットリンクの作り」の両方を整える話をしました。
今回は、誰もが毎日使う検索フォームを見ていきます。「ただ検索するだけ」の入力欄が、なぜ攻撃の入口になってしまうのかを学びましょう。

検索フォームに文字を打ち込むだけだよね?何が危ないの?

入力した文字が、画面とサーバーにそのまま渡される場面が多いから、扱い方を間違えるとXSSやSQLiの入口になるんだ。
検索ボックスって、たぶんネットで一番よく使う入力欄ですよね。『調べたい言葉を打つだけ』のあの何気ない欄が、実はWebセキュリティの超重要テーマ——XSSやSQLインジェクション——の入口になりやすいんです。今日は「なぜそんなことになるのか」を、むずかしい用語をかみくだきながら一歩ずつ追いかけていきます。身構えずに読んでくださいね。
検索フォームは入力をそのまま画面やデータベースに使う場面が多く、出力時のエスケープや入力検証を忘れるとXSS・SQLi・オープンリダイレクトの典型的な入口になります。
この記事で分かること
- 検索フォームで、入力がどんな経路で使われるか
- XSS・SQLi・オープンリダイレクトなど、検索から狙われる代表的な攻撃
- 演習環境での観察方法と、守る側の基本対策
📖 はじめてのWebセキュリティ #04|検索フォーム編
身近な検索ボックスを題材に、入力が「画面」と「サーバー」のどこに渡るかを追いかけて、攻撃の入口になる仕組みを学びます。 シリーズ一覧を見る →
⚠️ 大事なお約束
この記事の確認は、CTF・公式ラボ・自分で作った検証環境だけで行ってください。実在するサイトの検索フォームで、攻撃を試みる文字列を入力する行為は絶対にしないでください。
検索フォームは「入力の通り道」が短い場所
検索フォームでキーワードを入力して送信すると、入力した文字は2つの場所に渡されます。
- 画面:「『キーワード』の検索結果」のように、入力をそのまま表示することが多い
- サーバー:データベース検索や外部APIに、入力を渡して結果を取り出す
この「画面」と「サーバー」の両方で、入力をどう扱うかが安全性を決めます。何も処理せずに使うと、入力に混ざった攻撃文字列がそのまま動いてしまいます。
検索フォームがちょっと特別なのは、打ち込んだ言葉が“すぐ目の前に返ってくる”ところです。「『ねこ』の検索結果」のように、入力がそのまま画面に表示されますよね。この『入力 → そのまま出力』という最短ルートこそ、攻撃者にとって一番おいしいポイント。自分が送った文字が画面に出るなら、そこに“ただの文字”じゃないものを混ぜたらどうなる?——そう考えるのが攻撃者の発想なんです。
図解:検索キーワードが画面に表示されるまで

普通のキーワード(「ねこ」)と、HTMLタグ入りのキーワード(「<b>test</b>」)を比べてみると、扱いの差がはっきり見えます。

宅配伝票の「備考欄」に「玄関先に置いてください」と書けば、配達員はその通りに動きます。もし「他の荷物も全部一緒に置いてください」と書いたら、伝票通りに動く仕組みでは、それも実行されてしまいます。検索キーワードも、サーバーにそのまま渡せば「文字」ではなく「命令」として解釈されることがあります。
ここで覚える用語:エスケープ
入力された文字を「ただの文字」として表示・処理できるように、特別な意味を持つ記号(<, >, ‘, ” など)を安全な形に書き換えることです。検索結果を表示するときも、データベースに渡すときも、それぞれ別のエスケープが必要になります。
『エスケープ』という言葉、ここで一度しっかり押さえておきましょう。むずかしく聞こえますが、やっていることは“記号の牙を抜く”だけ。たとえば「<」をそのまま出すとブラウザはタグの始まりだと勘違いしますが、これを安全な表記に置き換えてあげれば、ただの「小なり記号」として表示されます。料理でいう『下ごしらえ』みたいなもので、危ない部分をあらかじめ無害にしておく作業だと思ってください。
検索フォームから狙われる代表的な攻撃
検索フォームから狙われる攻撃は1つではありません。画面表示・データベース・リダイレクトなど、それぞれの経路で別の攻撃が成立します。
『攻撃が3つもあるの?覚えるの大変そう…』と思うかもしれません。でも安心してください。この3つは、根っこがぜんぶ同じなんです。すなわち「入力をそのまま使ってしまう」こと。表示で悪さをすればXSS、データベースで悪さをすればSQLi、転送先で悪さをすればオープンリダイレクト——出口が違うだけで、原因は一つ。だから対策も『出口ごとにちゃんと処理する』という一本の筋でつながっていきます。
代表的な3つの攻撃パターン

- XSS(クロスサイトスクリプティング):キーワードに混ぜたスクリプトが、検索結果画面でそのまま動いてしまう
- SQLi(SQLインジェクション):キーワードに混ぜた文字が、データベース命令の一部として解釈されてしまう
- オープンリダイレクト:「検索後に飛ばす先」のURLパラメータに、外部の悪意あるサイトを入れられる
OWASP Top 10では、これらは「インジェクション」「クロスサイトスクリプティング」として長く上位に登場し続けている、Webセキュリティの中心テーマです。

XSSって名前はよく聞くけど、結局なにが起きるの?

ざっくり言うと『他人のブラウザで、攻撃者が書いたプログラムが動いてしまう』ことだよ。たとえば検索結果に紛れ込ませたスクリプトが、その画面を見た人のログイン情報をこっそり盗む——なんてことが起きうる。検索欄が“他人のパソコンを操る遠隔スイッチ”に変わってしまうイメージだね。
ここまで読んで『じゃあ自分の目で確かめてみたい』と思ったら、いい流れです。ただし大前提として、試すのは必ず自分の演習環境かCTFだけ。本物のサイトで攻撃文字列を打ち込むのは、たとえ出来心でも法律に触れます。安全な砂場の中で、入力がどう扱われるかをじっくり観察してみましょう。
CTFでやってみよう:検索結果を観察する
検索キーワードに「文字」と「タグ」を入れて、表示と挙動を比べよう
目的は攻撃を成立させることではなく、「入力がどう扱われているか」に気づくことです。
- CTFや自分の検証環境にある検索フォームを開く
- 普通のキーワード(例:「ねこ」)で検索し、結果画面に入力がどう表示されるか確認する
- HTMLタグ入りのキーワード(例:「<b>test</b>」)で同じことをする
- 結果が太字になったら、入力がHTMLとして解釈されている合図
- URLバーを見て、検索キーワードがそのまま
q=...の形で入っているか確認する
<script> タグや、SQL文を本物のサービスで試すのは絶対にやめてください。CTFや自分のラボでは、講義の指示に沿って安全に確認できます。記録してみよう
| 入力したキーワード | 結果画面の表示 | 気づいたこと |
|---|---|---|
| 普通の単語(例:ねこ) | 自分で記録 | 自分で記録 |
| HTMLタグ入り(例:<b>test</b>) | 自分で記録 | 自分で記録 |
| 記号入り(例:’や”) | 自分で記録 | 自分で記録 |
演習をやってみると、『普通の文字はそのまま、タグを入れると太字になっちゃった!』という瞬間に出会えるはずです。その一瞬こそ、入力が“文字”ではなく“命令”として扱われた証拠。怖がる必要はなくて、ここが腹落ちすれば守り方もスッと入ってきます。キーワードはたった一つ、『出力するその瞬間に処理する』です。
守る側なら、出力先ごとに正しく処理しよう
検索フォームを守るときは、「入力を信用しない」ではなく、「出力するときに、出力先に合わせた処理を必ずする」と覚えるのがコツです。
- 画面に検索キーワードを表示するときは、HTMLエスケープ(<, >, “, & などの変換)を必ず通す
- データベースに渡すときは、文字列連結ではなく、プリペアドステートメント(パラメータ化クエリ)を使う
- 外部APIに渡すときは、そのAPIに合わせた処理(JSON文字列化、URLエンコードなど)を行う
- リダイレクト先URLは、ホワイトリストや自サイト内に限定する
- Content Security Policy(CSP)を設定し、想定外のスクリプト実行を抑止する

「入力をチェックする」より「出力で処理する」の方が確実なんだね。

そう。入力チェックも大事だけど、最終的な防御は『出力するその瞬間』の処理だと覚えておくと安心だよ。
もう一つだけ大事なコツを。守りは“多重”にするのが基本です。出力エスケープをしていても、CSP(決められた場所のスクリプトしか動かさない仕組み)をかけておけば、万一エスケープ漏れがあっても被害を食い止められます。鍵を一つではなく二つ三つかけておく感覚ですね。「ここさえやれば100点」という単一の対策はない、と覚えておくと安心です。
まとめ:検索フォームは「画面」と「サーバー」の両方を守る
- 検索フォームは入力を画面とサーバーの両方にそのまま渡すことが多い
- 処理を忘れると、XSS・SQLi・オープンリダイレクトの入口になる
- CTFでは、普通のキーワードとHTMLタグ入りキーワードを比べて、扱いの差に気づく
- 守る側は、出力先ごとに正しい処理(HTMLエスケープ・プリペアドステートメント・URL検証)を必ず通す
今日の持ち帰りは『入力は信じず、出力で守る』。入り口でがんばって怪しい文字をはじくより、出ていくその瞬間に、出力先(画面・データベース・転送先)に合った処理をするほうが、ずっと確実で漏れがありません。しかもこの考え方は検索フォームに限らず、コメント欄でもプロフィール欄でも、入力を扱うあらゆる場所でそのまま使えます。
検索フォームは便利な機能ですが、入力を「ただの文字」として正しく扱わないと、画面とサーバーの両方が攻撃の踏み台になります。次回は、もう一歩進んで利用者と運営者が直接やりとりするお問い合わせフォームを題材にします。
