Web アプリを動かしている限り、セキュリティの脅威は避けて通れません。一度でも侵害されると、サービス停止・データ漏えい・信用失墜と被害が一気に広がります。
本記事では、Web アプリ開発で 必ず押さえておきたい代表的なセキュリティ脅威 を15件ピックアップし、それぞれの仕組みと対策をまとめます。チェックリストとしても使えるようにできるだけ網羅的に解説しているので、設計・実装・レビューの場面で振り返ってもらえると嬉しいです。
1. SQL インジェクション
ユーザー入力を SQL に直接連結することで、攻撃者が任意のクエリを実行できてしまう脆弱性。最悪の場合 全テーブルの中身が抜かれる / 改ざんされる という致命的被害につながります。
# 危険: 入力を文字列連結している
sql = "SELECT * FROM users WHERE name = '" + name + "'"
# 安全: プレースホルダ + バインド変数
cursor.execute("SELECT * FROM users WHERE name = %s", (name,))- プリペアドステートメント / バインドパラメータを必ず使う
- 動的に SQL を組み立てる必要があるときは 許可リスト方式(カラム名・テーブル名を定数照合)
- DB ユーザーの権限を 必要最小限 に絞る(参照系と更新系のロール分離)
2. XSS(クロスサイトスクリプティング)
ユーザー入力が HTML/JS としてそのまま表示され、攻撃者の用意したスクリプトがブラウザで実行されてしまう脆弱性。セッションクッキーの窃取や 画面の改ざん に直結します。
- テンプレートエンジンの 自動エスケープ を必ず有効にする(React/Vue は基本的にデフォルトで安全だが、
dangerouslySetInnerHTMLやv-htmlは要注意) - HTML を許容する場合は DOMPurify などのサニタイザ を必須化
- Content-Security-Policy (CSP) ヘッダを設定して、許可していないインラインスクリプトの実行をブロック
- Cookie は
HttpOnly+Secure+SameSite=Lax/Strictを必ず付与
3. CSRF(クロスサイトリクエストフォージェリ)
ログイン済みユーザーのブラウザを利用して、攻撃者が意図しないリクエストを送信させる攻撃。送金や設定変更など 状態変更を伴う操作 が標的になります。
- CSRF トークン をフォーム・POSTリクエストに含めて検証する
- SameSite Cookie(Lax 以上)で、クロスサイトでクッキーが自動送信されない設定にする
- 状態変更は POST / PUT / DELETE を使い、GET ではやらない
4. CORS の設定ミス
CORS(Cross-Origin Resource Sharing)はブラウザの同一オリジンポリシーを緩和する仕組みですが、緩めすぎると認証付き API が他オリジンから叩き放題 になります。
Access-Control-Allow-Origin: *とAccess-Control-Allow-Credentials: trueを 同時に使わない(ブラウザが拒否するが、認証情報を許可しているつもりで誤設定するケースが多い)- 許可オリジンは ホワイトリスト方式 でハードコード or 設定ファイル管理
- 動的にエコーバックする実装(リクエストの Origin をそのまま返す)は絶対にしない
5. SSRF(サーバーサイドリクエストフォージェリ)
ユーザーから受け取った URL をサーバ側でそのままリクエストすることで、内部ネットワークやクラウドのメタデータエンドポイント(例: 169.254.169.254)にアクセスされてしまう攻撃。AWS の IAM 認証情報を抜かれた事例で有名になりました。
- 外部 URL を fetch する処理は ホワイトリスト方式 で制限
- プライベート IP / 169.254.x.x / メタデータエンドポイントは 明示的に拒否
- EC2 なら IMDSv2 を強制(トークン必須にしてメタデータ盗難リスクを下げる)
6. パストラバーサル
ファイル名にユーザー入力を含めると、../../etc/passwd のような相対パスを使ってサーバ内の任意ファイルが読まれる可能性があります。
- ファイル名・パスをそのまま入力に使わず、ID から内部マッピングでパスを解決する
- どうしても文字列を受け取るなら、
realpath()で ベースディレクトリ配下に正規化 してから検証 ../や URL エンコードされた%2e%2e%2fも含めて検査
7. コマンドインジェクション
サーバ上で system() や exec() 系を使うとき、ユーザー入力をシェル経由で渡すと 任意コマンドを実行 できてしまう脆弱性です。
- シェル経由ではなく 引数配列形式 で実行(
subprocess.run([cmd, arg1, arg2])) - そもそもシェル呼び出しを避け、ライブラリで実現できないか を先に検討
- 必要なら入力を 許可リストで厳格にバリデーション(英数のみ、長さ制限)
8. オープンリダイレクト
リダイレクト先 URL をパラメータで受け取る実装で、攻撃者の用意した外部サイトに飛ばされてしまう脆弱性。フィッシングと組み合わせて悪用されます。
- リダイレクト先は 自サイトのホワイトリスト or 相対パス限定
- 外部ドメインを許可せざるを得ないときは、確認画面を挟む
9. 認証・セッションの不備
ログイン処理やセッション管理の作りが甘いと、ブルートフォース・セッション固定・トークン漏えい など多面的な攻撃に晒されます。
- パスワードは bcrypt / argon2 / scrypt でハッシュ化(MD5/SHA1 はNG)
- ログイン試行に レート制限 + 連続失敗時のアカウントロック
- セッション ID は ログイン成功時に再発行(セッション固定対策)
- 多要素認証(MFA)を可能な限り導入
- JWT を使うなら 有効期限を短く + 署名検証を必ず行う(
alg: none受け入れは厳禁)
10. 認可の不備(IDOR)
「ログインさえしていれば誰でも他人のデータを参照できる」というパターン。URL の ID を書き換えるだけで他人の請求書が見えてしまうような事例は枚挙にいとまがありません。
- すべてのリソース取得・更新で 「リクエスト元ユーザーがそのリソースの所有者か」 をサーバ側で必ず検証
- UUID にすれば防げるという誤解は捨てる(推測不可能なだけで認可ではない)
- 権限制御は 共通モジュール(ポリシー / ガード) に集約し、コードレビューで漏れを検知
11. ファイルアップロードの脆弱性
アップロードされたファイルがそのまま実行可能な場所に保存されると、Web シェルを設置されてサーバを乗っ取られる 危険があります。
- 拡張子・MIME タイプ・実際のファイルヘッダ(マジックバイト)の3点で検証
- 保存先は Web 配信ディレクトリ外 または S3 などの別ストレージ
- ファイル名はサーバ側で ランダム名に書き換え(パストラバーサル防止も兼ねる)
- 画像なら 再エンコード して保存すれば、埋め込みスクリプトも無効化できる
12. 機密情報の露出
エラーメッセージにスタックトレースや内部 SQL を出す、デバッグモードで本番運用する、API のレスポンスに不要なフィールドを混ぜる…。地味ですが現場でいちばん多い穴です。
- 本番では 詳細なエラー出力を OFF。ユーザー向けには汎用メッセージを返す
- シークレットは 環境変数 or シークレットマネージャ。リポジトリ・ログに残さない
- API レスポンスは 明示的に必要なフィールドだけ 返す(モデルをそのままシリアライズしない)
- S3 バケットや GitHub リポジトリの 公開設定 を定期的に棚卸し
13. クリックジャッキング
透明な iframe で自サイトを攻撃者ページ上に重ね、ユーザーに意図しないボタンを押させる攻撃。
- X-Frame-Options: DENY(または
SAMEORIGIN)を設定 - あわせて Content-Security-Policy の
frame-ancestorsディレクティブで防御
14. 依存ライブラリの脆弱性(サプライチェーン)
自前コードよりも、利用している npm / pip / Maven などのライブラリ経由で侵害される事例が増えています。
- Dependabot / Renovate などで脆弱性アラートを自動化
- CI に SCA ツール(Snyk / GitHub Advanced Security / Trivy など)を組み込む
- 未知の作者・ダウンロード数が極端に少ないライブラリは利用前にレビュー
15. セキュリティヘッダの不足
ブラウザ側の防御機構を有効化する HTTP レスポンスヘッダ群。アプリ修正なしで効くものも多いので、最低限まとめて設定しておきます。
Strict-Transport-Security— HTTPS を強制Content-Security-Policy— スクリプト実行元を制限X-Content-Type-Options: nosniff— MIME スニッフィング無効化X-Frame-Options— クリックジャッキング対策Referrer-Policy— 他サイトへの URL 漏えい制御Permissions-Policy— カメラ・マイク等の権限制御
横断的な備え
個別の脆弱性対策に加えて、運用面の備え も同じくらい重要です。
- WAF(AWS WAF / Cloudflare WAF)でアプリ前段に共通防御を入れる
- レート制限 / Bot 対策(API Gateway / Cloudflare Turnstile など)
- 監査ログ + 異常検知(ログイン失敗、権限昇格、機密 API へのアクセスを記録・通知)
- 脆弱性診断 / ペネトレーションテスト を定期的に実施
- インシデント対応プレイブックを平時から準備(連絡フロー、ログ保全、影響範囲調査の手順)
まとめ
Web アプリのセキュリティは 「単一の銀の弾丸」では守れない 領域です。今回紹介した 15 の脅威に対して、対策が複数レイヤで効いている状態(多層防御)を目指すのが現実解です。
最後にチェックリストとして要点をまとめておきます。
- 入力は 必ずバリデーション、出力は 必ずエスケープ
- 認証は強く、認可は サーバ側で必ず再検証
- シークレットは コード・ログに残さない
- ヘッダ・CORS・CSP など ブラウザ側の防御も使い倒す
- 依存ライブラリは 自動更新+脆弱性スキャン
- WAF・ログ・監視で 気付ける仕組み を整える
本記事は一覧として継続的に更新していく予定です。「これも入れて」というネタがあればぜひ教えてください。
