Webアプリケーション:最も露出した攻撃面
T1190 公開アプリケーションの悪用インターネットに公開された Web アプリケーションは、企業のファイアウォールを迂回して内部のデータベースやビジネスロジックに直接アクセスできる、世界最大の攻撃面です。企業がどんなに境界防御を固めても、HTTPSポート(443)は正規のトラフィックとして常に開放されています。
非営利団体 OWASP が数年ごとに更新する**OWASP Top 10**は、開発者が知っておくべき重大な脆弱性のランキングです。20年以上にわたり、以下の3つの脆弱性が形を変えながら上位に居続けています。これは「古い問題が解決されていない」というより、「Webが進化するたびに同じ構造的欠陥が新しい文脈で現れる」ことを意味しています。
本レッスンで解説するエクスプロイト手法は、防御アーキテクチャの設計に必要な「攻撃者の視点」を学ぶためのものです。所有権または明示的な許可のないシステムへの攻撃試行は、いかなる理由であれ不正アクセス禁止法違反となります。
SQLインジェクション(SQLi):データソースの完全陥落
データベースへの問い合わせを行うSQL文に、**「データの一部として見せかけた悪意のあるコマンド」**を混入させ、強制的に実行させる攻撃です。一度成立すれば、顧客情報の全件ダンプ(情報漏洩)から、データベースサーバー自体のコード実行(RCE)まで至る、最も破壊的な脆弱性の一つです。
脆弱な実装とインジェクションの成立
// 脆弱なコード(レガシーシステムで頻出する文字列の直接結合)
$username = $_POST['username'];
$query = "SELECT * FROM users WHERE username = '" . $username . "'";
攻撃者が $username に ' OR '1'='1 を入力すると、バックエンドで以下のSQLが構築・実行されます。WHERE句の条件が常に「真(True)」になるため、全ユーザーのデータが漏洩します。
SELECT * FROM users WHERE username = '' OR '1'='1'
ポイントは、これが「バグ」ではなく「SQLの仕様どおりの動作」である点です。文字列結合でSQLを組み立てると、ユーザー入力がデータではなくコマンドとして解釈される余地が生まれます。
現代のWebアプリはエラー画面にSQL文法エラーをそのまま表示しません。しかし攻撃者は、クエリに SLEEP(10) などの遅延コマンドを忍ばせ、「レスポンスが10秒遅れたからこの推測はTrueだ」と1文字ずつデータを抜き出す時間ベースのブラインド攻撃を、SQLmap などの自動化ツールで実行します。エラーが出なくても安全ではありません。
根本的な防衛策:プリペアドステートメント
WAFによるシグネチャ検知は「既知のパターン」を弾くだけで、難読化された攻撃は通過します。唯一の根本的な解決策は、コードレベルでの**プリペアドステートメント(パラメータ化クエリ)**の確実な実装です。
// プリペアドステートメント:SQLの「構文」と「データ」を完全に分離する $stmt = $pdo->prepare(“SELECT * FROM users WHERE username = :username”);
// ユーザー入力は純粋な「データ」としてのみバインドされ、決してSQLコマンドとして解釈されない $stmt->execute([‘username’ => $username]); $user = $stmt->fetch();
クロスサイトスクリプティング(XSS):ブラウザのハイジャック
SQLi が「サーバー(データベース)」への攻撃であるのに対し、XSS は「他のユーザーのブラウザ(クライアント側)」への攻撃です。攻撃者が仕込んだ悪意のある JavaScript が、被害者のブラウザ上で「正規のサイトの一部」として実行されます。これにより、セッションCookieの窃取、偽ログイン画面の表示、ユーザーの権限を使った不正操作が可能になります。
XSSの3つの主要カテゴリ
| カテゴリ | 攻撃のメカニズム | 主な発生箇所 |
|---|---|---|
| 反射型(Reflected) | 攻撃者がスクリプトを埋め込んだ罠URLを被害者に踏ませ、サーバーがそれをそのまま画面に「反射」して出力することで発火する。 | 検索結果ページ、エラーメッセージ表示画面。 |
| 蓄積型(Stored) | 攻撃者がDBにスクリプトを保存(投稿)し、そのページを閲覧した全員のブラウザで被害が連鎖的に発火する。最も危険。 | コメント欄、プロフィール画面、掲示板。 |
| DOMベース | サーバーを介さず、フロントエンドのJavaScript内でのDOM操作の欠陥(innerHTML への直接代入など)によって、ブラウザ内だけで完結して発火する。 | SPA(Single Page Application)のURLフラグメント処理など。 |
蓄積型は「一度仕込めば閲覧した全ユーザーが被害を受ける」ため、特に危険度が高いカテゴリです。大規模なコメントサイトやECサービスで発生すると、被害が数万〜数十万ユーザーに及ぶことがあります。
現代のXSS防御アーキテクチャ
- コンテキストに応じた出力エスケープ: ユーザー入力をHTMLとして出力する際、
<や>などの特殊文字を無害化します。React、Vue などの現代のフレームワークは標準でエスケープ処理を行いますが、dangerouslySetInnerHTMLなどの抜け穴の使用には最大限の警戒が必要です。 - CSP(Content Security Policy): 「このドメインからロードされたスクリプト以外はブラウザで実行させない」と HTTP ヘッダーでブラウザに強制する、最も強力な XSS の防波堤です。コード側に脆弱性があっても、スクリプトの発火をブラウザレベルでブロックできます。
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-cdn.com;
CSRF(クロスサイトリクエストフォージェリ):権限の「無断借用」
CSRFは、被害者が「あるサービス(例:銀行サイト)にログインした状態」で別の悪意のあるサイトを開いた瞬間、背後で勝手に「銀行への送金リクエスト」を送信させる攻撃です。
仕組みを理解するカギはブラウザの仕様にあります。ブラウザは「同じドメイン宛てのリクエストには、そのドメインの Cookie(セッション情報)を自動で付与する」という動作をします。攻撃者はこれを逆手に取り、悪意のあるサイトから銀行のAPIに向けたリクエストを被害者のブラウザに送らせます。被害者の Cookie が自動で付与されるため、銀行側には「正規のユーザーからのリクエスト」に見えてしまいます。
CSRFを無効化する2つのアプローチ
かつては「推測不可能なワンタイムトークン(CSRFトークン)」を隠しフィールドに埋め込む手法が主流でした。現在ではブラウザの Cookie 仕様の進化により、より根本的な防衛線が使えるようになっています。
Set-Cookie: session_id=abc123xyz; Secure; HttpOnly; SameSite=Lax
// SameSite=Lax(現在のブラウザのデフォルト): 外部サイトからのPOSTリクエスト等にはCookieを付与しない。 // SameSite=Strict: 外部サイトからのいかなるリンク遷移でもCookieを付与しない(最も強力)。
SameSite=Lax でほとんどの CSRF は防げますが、レガシーブラウザのサポートや複雑な認証フローを持つシステムでは、CSRFトークンも組み合わせた多層防御が推奨されます。
【確認問題】Webフロントエンド開発において、第三者が注入した悪意のある JavaScript がブラウザ上で実行される「XSS(クロスサイトスクリプティング)」を根本的に防ぐための、HTTPレスポンスヘッダー設定として最も強力なものはどれですか?