入力サニタイズとは、SQLインジェクションやクロスサイトスクリプティング(XSS)などのWebベースの攻撃を防ぐために、ユーザーが入力した潜在的に有害なデータを変更または削除するプロセスです。セキュリティツールにどれだけ投資していても、コードベースは組織のサイバーセキュリティにおける最も弱い部分になり得ます。
入力のサニタイズと検証は、通常、防御の第一層です。適切な形式で安全な入力だけが処理されるようにすることで、開発者は悪意のあるコードの実行、データ漏えい、アプリケーション障害のリスクを低減できます。
ここでは、Webフォームを効果的に保護するため、入力のサニタイズと検証に加え、サーバー設定などの重要な要素についても説明します。
入力サニタイズでWeb攻撃を防ぐ手順
サイバー犯罪者は今も一般的な脆弱性を悪用し、SQLインジェクション、クロスサイトスクリプティング(XSS)、リモートファイルインクルージョン(RFI)、ディレクトリトラバーサルなどのサイバー攻撃を仕掛けています。敵対的機械学習、高度な難読化、ゼロデイ攻撃など、より高度な脅威も存在しますが、古典的な攻撃は依然として広く見られ、今もセキュリティ侵害の大半を占めています。こうしたリスクを防ぐには、開発者はデータを処理または保存する前に、正しくサニタイズして検証しなければなりません。

- ユーザー入力を特定:アプリケーション内でユーザーがデータを送信できるフォームや検索バーなど、すべての入力ポイントを確認します。GETリクエストとPOSTリクエスト、Cookie、その他ユーザーが送信するあらゆる入力も対象です。
- 入力検証を実装:ユーザー入力が、データ型、長さ、使用可能な文字について定められた厳格なルールに従っていることを確認します。たとえば数値を想定している場合、入力が本当に数値かどうかを確認します。PHPの
filter_var()などの検証関数や、JavaScriptの正規表現パターンを使用します。 - 入力をサニタイズ:検証後、潜在的に悪意のある文字を削除またはエンコードして入力をサニタイズします。PHPでは、
htmlspecialchars()やhtmlentities()などの関数を試すことができます。JavaScriptでは、encodeURIComponent(). - データベースクエリにはプリペアドステートメントを使用:ユーザー入力をSQLクエリに直接挿入するのは避けます。代わりに、バインドパラメーターを使ったプリペアドステートメントを使用して、SQLインジェクション攻撃を防ぎます。こうすることで、入力は実行可能なコードではなく、データとして扱われます。
- 安全な出力エンコードを確認:ユーザー入力を表示する際は、XSSを防ぐために適切にエスケープされていることを確認します。これは、HTML、JavaScript、URLパラメーターに出力されるデータで特に重要です。
- 入力検証とサニタイズをテスト:自動化されたセキュリティツールと手動のペネトレーションテストを使い、すべての入力フィールドに脆弱性がないか定期的にテストします。有害な入力が検証やサニタイズの手順をすり抜けられないことを確認します。
サニタイズと入力検証の違いとは?
サニタイズはユーザー入力から安全でない文字を削除する処理であるのに対し、検証はデータが想定された形式と型になっているかを確認する処理です。サニタイズでは、表示時またはデータベースへの挿入前に有効な形式になるよう入力を変更します。

一方、検証では、Webフォームなどの入力が特定のポリシーや制約(単一引用符など)に準拠しているかを確認します。たとえば、次の入力を考えてみましょう。
<input id="num" name="num" type="number" />
検証がなければ、想定された数値の代わりに予期しない入力を送信して、攻撃者がフォームを悪用するのを防ぐものはありません。また、送信されたフォームがデータベースに保存される一般的な構成では、攻撃者がコードを直接実行しようとする可能性もあります。
このような事態を防ぐため、開発者は処理を続行する前にデータを検査する検証ステップを追加する必要があります。たとえばPHPのような一般的な言語を使えば、データ型や長さ、その他多くの条件を確認できます。
入力のサニタイズと検証が必要な理由
入力のサニタイズと検証は、攻撃者が脆弱な入力フィールドを悪用して悪意のあるコードを注入したり、データベースを操作したり、ユーザーデータを侵害したりするのを防ぐために必要です。これらのセキュリティ対策により、安全で想定どおりのデータだけがアプリケーションで処理され、セキュリティリスクが低減されます。
脆弱な入力に対して使われる最も一般的な手法はXSS攻撃です。これは、攻撃者が本来は信頼できるWebサイトに悪意のあるスクリプトを注入する攻撃です。
XSS攻撃には、他のものより分かりやすいものもあります。入力のサニタイズと検証に時間をかけても、熟練した攻撃者は特定の条件下で悪意のあるコードを注入する方法を見つける可能性があります。
典型的な攻撃デモでは、脆弱な入力に次のスクリプトを注入します。プレースホルダーの「XSS」は任意のJavaScriptです。
<script>alert('XSS')</script>
入力内容がページに表示される場合、攻撃者は標的のWebサイト上で任意のJavaScriptを実行できます。典型的な例は、検索語をページに表示する脆弱な検索入力です。
https://mysite.com/?s=<script>alert('XSS')</script>
悪意のある入力がデータベースに保存されると、事態はさらに深刻になります。デモコードは遊びで試すには面白そうに見えるかもしれませんが、現実の環境では攻撃者がJavaScriptを使ってさまざまなことを実行でき、Cookieを盗むことさえあります。
サニタイズを使うべきでない場合
サニタイズはあらゆる攻撃を防ぐものではなく、必要なデータを意図せず削除する可能性もあるため、唯一のセキュリティ対策として使うべきではありません。
サニタイズの最大の問題は、ネットワークセキュリティが確保されたという誤った印象を与える可能性があることです。不要な文字やHTMLタグを除去するのは、チェックの一層にすぎません。実装が不十分なことも多く、正当な引用符や特殊文字などの情報を削除しすぎる一方で、あらゆる攻撃経路をカバーできるわけではありません。汎用的なルールを無批判に適用することはできません。
重要なのはコンテキストであり、使用しているプログラミング言語もその一部です。データが使われる正確なコンテキストが分かるため、「遅い段階でエスケープする」(たとえば出力直前)という原則に従うことが重要です。
私の経験では、最も難しいのは、生の入力やその他の緩やかな設定を許可する必要がある場合です。そのようなケースでは、データを正しくサニタイズするのが難しくなり、使用を許可する文字のカスタムホワイトリストを維持したり、悪意のあるパターンを手動でブラックリスト化したりする必要があります。
代わりに、堅牢なライブラリやフレームワークを使うことが推奨されます。
より一般的には、開発者は推測や修正に頼るのではなく、不正な入力に対してエラーを返すことをためらってはいけません。推測や修正はエラーや欠陥につながりやすいためです。
ベストプラクティス:入力のサニタイズ、検証、遅い段階でのエスケープ
開発チームが従うことで、可能な限り最良の結果を得られる原則やベストプラクティスがいくつかあります。ここでは、注意すべき具体例とともに、主なカテゴリーを取り上げます。
ユーザー入力を信用しない
ユーザー入力のチェックを行わないWebサイトもあり、アプリケーションを最大レベルの危険にさらしています。幸い、セキュリティ意識の向上とコード解析により、そうしたサイトは減少しています。しかし、不完全なサニタイズも優れた解決策とはいえません。
検討すべき攻撃経路をいくつか紹介します。
GETリクエスト
開発者が文字列を正しくサニタイズしないと、攻撃者は次のようなXSSの欠陥を悪用できます。
https://mysite.com/?s=<script>console.log('you are in trouble!');</script>
一般的なサイバーセキュリティの啓発では、上の例を単純なconsole.logやalertで示すことが多いでしょう。しかしこれは、悪意のあるURLを短縮したバージョンを何も知らない被害者に送るだけで、誰でもそのページ上で任意のJavaScriptを実行できることを示しています。
XSSの欠陥には永続的なもの(たとえばデータベースに保存されるもの)もあり、攻撃者は被害者に何かをクリックさせる手間をかけずに、悪意のあるペイロードを自動的に配信してWebサイトのユーザーを攻撃できます。
Cookie
Webサイトでは、セッション管理、カスタマイズ、トラッキングにHTTP Cookieがよく使われます。たとえば開発者は、ユーザーをログインさせたり、設定を記憶したり、行動を分析したりできます。
サーバーはCookie、つまりデータの一種を生成し、後で使えるようブラウザーに送信して保存させます。そのためCookieを盗めば、攻撃者はログインなしですぐに標的アカウントへアクセスし、被害者になりすますことができます。
さらに、ハッカーは被害者のコンピューターを侵害する必要もありません。HTTP Cookieはすべてのリクエストとともに送信されるため、たとえば中間者(MITM)攻撃でリクエストを傍受し、データを盗むことができます。
より高度な手法では、XSS攻撃を使って標的のWebサイトに悪意のあるコードを挿入し、最終的にユーザーのCookieをコピーして、ユーザーになり代わって有害な操作を実行できます。
Googleは2025年にChromeブラウザーでCookieを段階的に廃止する計画を立てていますが、サイバーセキュリティのベストプラクティスを策定することは依然として重要です。たとえばSSL(Secure Sockets Layer)は、もはや任意のレイヤーではありません。しかし、コードが非SSLリクエストを送信するとCookieは平文で送られるため、どこでもSSLを使用するようにしてください。
もう1つの優れたプラクティスは、JavaScriptによるハイジャックを防ぐため、常にhttpOnly属性SameSiteも推奨されます。
Cookieはユーザーや開発者にとって便利ですが、最新の認証方式やAPIを使えば、より優れたアプローチが可能です。クライアント側のデータベースにデータを保存すると、安全性とプライバシーに関する多くの脆弱性が生じるため、代わりに、より安全な方法を実装する方がよいでしょう。
POSTリクエスト
POSTリクエストはサーバー側のリクエストであるため、たとえばオンラインアカウントに画像をアップロードしたり、次のような問い合わせフォームを送信したりする場合でも、URLにデータが露出しません。
<form action="https://my-website.com/contact" method="POST">
POSTリクエストはGETリクエストより安全だというのは、よくある誤解です。しかし、せいぜいPOSTリクエストは「見えにくさによるセキュリティ」にすぎません。ユーザーによる変更にはPOSTリクエストを使う方がよいものの、セキュリティ関連の目的には適しておらず、それだけでセキュリティが強化されるわけでもありません。
PHPで入力からPOSTデータをサニタイズする簡単な方法の1つは、次のコマンドを使うことです。
filter_var($_POST['message'], FILTER_SANITIZE_STRING);filter_var('bobby.fisher@chess.com', FILTER_VALIDATE_EMAIL)
PHPでのもう1つの優れたプラクティスは、文字列内の不要なHTML文字をエスケープするためにhtmlentities()を使うことです。
Cookieと同様に、データの暗号化には常にSSLを使い、暗号化されずに残るのがTCP/IP情報だけになるようにします。
ディレクトリトラバーサル
コードベースに、次のような画像タグが含まれている場合、
<img src="/getImages?filename=image12.png" />
ハッカーは次のようなものを使おうとする可能性があります。
https://yourwebsite.com/getImages?filename=../../../etc/passwd
これにより、ユーザーの情報にアクセスできます。
ただし、サーバーが正しく設定されていれば、このような機密情報の開示を試みる行為はブロックされます。また、ユーザー入力をフィルタリングし、想定された形式とデータ型だけが送信されるようにする必要があります。
クライアント側の検証を信用しない
特に初心者に多い誤解は、フォームデータの検証をHTMLとJavaScriptだけに頼ることです。HTMLでは、文字数制限の設定や特定フィールドの入力必須化など、パターンや必須フィールドを定義できます。しかし、クライアント側で変更できないHTML属性やJavaScriptコードは存在しません。
ハッカーはcURLや任意のHTTPクライアントを使ってフォームを送信することもできるため、クライアント側はフォームを検証する安全なレイヤーではありません。
厳格モードを有効にする
可能な場合は、PHP、JavaScript、SQLなど、どの言語でも厳格モードを有効にしてください。ただし、厳格モードでは便利な構文の多くが使えなくなるため、技術的負債やレガシーコードが大量にある場合は有効化が難しいことがあります。
しかし、厳格モードでコーディングしないと、エンジンが推測を始め、コードを動作させるために値を自動的に変更することさえあります。これにより、ハッカーが悪意のあるコマンドを注入するために利用できる脆弱性が生じます。
たとえば2015年、WordPressの主要な貢献者であるAndrew Nacinは、SQLで厳格モードを有効にするだけで重大なセキュリティバグを回避できた可能性があることを説明しました。4バイト文字を使ってMySQLを切り詰めさせ、その後データベースに悪意のあるコードを注入することで、ハッカーが重大な脆弱性を悪用できることを実演したのです。
この攻撃を防ぐ単純な解決策は、コマンドSET SESSION sql_mode = "STRICT_ALL_TABLES"を実行することですが、これを有効にするとWordPressで動作するすべてのWebサイトが壊れてしまうため、不可能です。
OWASP Web Testing Guideを参照する
OWASP(Open Web Application Security Project)は、Web Security Testing Guide(WTSG)という包括的なドキュメントを管理しており、そこには入力検証が含まれています。
このガイドでは、入力に対するさまざまなインジェクションやその他の巧妙な攻撃をテストする方法を説明しています。内容は頻繁に更新され、さまざまなシナリオについて詳しい解説が掲載されています。
たとえば、永続的なXSSの仕組みとエクスプロイトの再現方法を学ぶには、保存型クロスサイトスクリプティングのテストに関するページを確認するとよいでしょう。

結論:サニタイズし、検証し、遅い段階でエスケープする
入力をサニタイズするとセキュリティリスクの低減に役立ちますが、それだけを防御の第一線にしてはいけません。潜在的な攻撃を防ぐため、保存前には必ず入力を検証し、表示前には出力をエスケープしてください。
入力サニタイズだけに頼ると脆弱性につながる可能性があるため、特定のコンテキストに適したセキュリティライブラリやフレームワークを使用しましょう。これらの方法を組み合わせることでセキュリティを強化し、アプリケーションをサイバー攻撃から守ることができます。
全体的なセキュリティ体制の改善に役立つ主要なセキュリティツールを知るには、コードデバッグとコードセキュリティツールやWebアプリケーションファイアウォール(WAF)ソリューションに関するガイドをご覧ください。
Liz Ticongは2025年2月にこの記事を更新しました。





