Webアプリケーション・システム開発と運用で押さえておくべきセキュリティ対策をまとめたチェックリスト兼ガイドです。
目次
- 基本原則
- 認証・パスワード
- 認可・アクセス制御
- 入力検証と出力エスケープ
- 機密情報・シークレット管理
- 暗号化
- セッション・Cookie
- Webセキュリティヘッダー
- API セキュリティ
- 依存関係・サプライチェーン
- インフラ・クラウド
- ログ・監視
- 開発プロセス(DevSecOps)
- インシデント対応・バックアップ
- 個人・組織の基本対策
- 参考資料
1. 基本原則
| 原則 | 内容 |
|---|---|
| 最小権限 | ユーザー・サービス・プロセスには必要最小限の権限だけを与える |
| 多層防御 | 単一の対策に依存せず、複数の層で防御する |
| デフォルトで安全(Secure by Default) | 初期設定が安全側になるよう設計する。危険な機能は明示的に有効化させる |
| フェイルセーフ | エラー時はアクセスを拒否する方向に倒す |
| ゼロトラスト | 社内ネットワークであっても無条件に信頼せず、毎回検証する |
| 攻撃対象領域の最小化 | 不要な機能・ポート・エンドポイント・依存関係は削除する |
| 独自の暗号を作らない | 実績のある標準ライブラリ・アルゴリズムを使う |
2. 認証・パスワード
- 多要素認証(MFA) を提供し、管理者アカウントでは必須にする
- 可能であれば パスキー(WebAuthn/FIDO2) を優先。SMS認証は最終手段
- パスワードは 専用のハッシュ関数 で保存する
- 推奨:
Argon2id>scrypt>bcrypt - ❌ MD5 / SHA-1 / SHA-256 の単純ハッシュは不可
- 推奨:
- パスワードポリシーは長さ重視(最低8文字、推奨12〜15文字以上、最大64文字以上を許容)
- 定期的な強制変更や複雑な文字種ルールより、漏洩済みパスワードリストとの照合 が有効
- ログイン試行に レート制限・段階的遅延・アカウントロック を設ける
- ログイン失敗時のメッセージで「ユーザーが存在するか」を漏らさない
- パスワードリセットトークンは ランダム・短寿命・1回限り
- 自前実装より、実績のある認証基盤(IdP / OIDC)の利用を検討する
3. 認可・アクセス制御
- 認可チェックは 必ずサーバー側 で行う(フロントエンドの非表示は対策ではない)
- すべてのリクエストでリソースの 所有者・権限を検証 する(IDOR対策)
❌ GET /api/orders/123 → IDだけで取得 ✅ GET /api/orders/123 → 「ログインユーザーが注文123の所有者か」を確認 - デフォルトは「拒否」とし、許可を明示的に定義する
- 権限モデル(RBAC / ABAC)を一元化し、各所に散らばらせない
- 管理画面は別経路・IP制限・追加認証で保護する
- 権限変更や重要操作は監査ログに残す
4. 入力検証と出力エスケープ
基本方針
- すべての外部入力は信頼しない(フォーム、URL、ヘッダー、Cookie、ファイル、外部API応答、LLM出力も含む)
- 入力検証は 許可リスト(allowlist)方式 で型・長さ・形式・範囲をチェック
- 出力時は 出力先のコンテキストに応じたエスケープ を行う
主な脆弱性と対策
| 脆弱性 | 対策 |
|---|---|
| SQLインジェクション | プレースホルダ(プリペアドステートメント)/ ORM を使用。文字列連結でSQLを組まない |
| XSS | テンプレートエンジンの自動エスケープ、innerHTML 等の回避、CSP の導入 |
| OSコマンドインジェクション | シェル経由の実行を避け、引数配列で渡す API を使う |
| パストラバーサル | ユーザー入力をファイルパスに直接使わない。正規化後に許可ディレクトリ内か検証 |
| SSRF | 外部URL取得先を許可リストで制限。内部IP・メタデータエンドポイントへのアクセスを遮断 |
| XXE | XMLパーサーで外部エンティティを無効化 |
| 安全でないデシリアライズ | 信頼できないデータを pickle / Java シリアライズ等で復元しない |
| CSRF | CSRFトークン、SameSite Cookie、Origin/Referer 検証 |
| ファイルアップロード | 拡張子・MIME・内容を検証、公開ディレクトリ外に保存、ファイル名をランダム化、サイズ上限 |
# ❌ 悪い例
cursor.execute(f"SELECT * FROM users WHERE email = '{email}'")
# ✅ 良い例
cursor.execute("SELECT * FROM users WHERE email = %s", (email,))5. 機密情報・シークレット管理
- APIキー・パスワード・秘密鍵を ソースコードにハードコードしない
-
.envなどは.gitignoreに登録し、リポジトリにコミットしない - シークレットは 専用の管理サービス で保管する
- 例: AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, HashiCorp Vault
- シークレットスキャン をCIとpre-commitに導入する(例: gitleaks, GitHub Secret Scanning)
- 漏洩した場合は「履歴から削除」ではなく 即座に無効化・ローテーション する
- 長期間有効な固定キーより、短寿命トークンやワークロードID(OIDC連携など)を使う
- ログ・エラーメッセージ・URLにシークレットや個人情報を出力しない
6. 暗号化
通信の暗号化
- すべての通信を HTTPS(TLS 1.2以上、推奨 TLS 1.3) にする
- HTTP → HTTPS へリダイレクトし、HSTS を設定
- 内部通信(サービス間・DB接続)も暗号化する
- 証明書の自動更新を設定する(例: Let’s Encrypt + 自動更新)
保存データの暗号化
- DB・ストレージ・バックアップの保存時暗号化を有効にする
- 特に機密性の高い項目(個人情報・決済情報等)はアプリ層での暗号化も検討
アルゴリズム選択
| 用途 | 推奨 | 非推奨 |
|---|---|---|
| 共通鍵暗号 | AES-256-GCM, ChaCha20-Poly1305 | DES, 3DES, RC4, AES-ECB |
| ハッシュ | SHA-256 以上, SHA-3 | MD5, SHA-1 |
| パスワード保存 | Argon2id, scrypt, bcrypt | 単純ハッシュ |
| 乱数 | OS提供のCSPRNG(secrets, crypto.randomUUID 等) | Math.random, random |
7. セッション・Cookie
- セッションIDは十分な長さのランダム値を使う
- ログイン成功時にセッションIDを再生成(セッション固定攻撃対策)
- 適切な有効期限・アイドルタイムアウトを設定し、ログアウト時はサーバー側で無効化
- Cookie属性を設定する
Set-Cookie: session=xxxx; Secure; HttpOnly; SameSite=Lax; Path=/| 属性 | 目的 |
|---|---|
Secure | HTTPS でのみ送信 |
HttpOnly | JavaScript から読み取り不可(XSS時の窃取防止) |
SameSite=Lax/Strict | クロスサイト送信を制限(CSRF対策) |
- JWT を使う場合: 署名アルゴリズムを固定(
alg: noneを拒否)、有効期限を短く、失効手段を用意、機密情報をペイロードに入れない
8. Webセキュリティヘッダー
| ヘッダー | 推奨設定例 | 目的 |
|---|---|---|
Content-Security-Policy | default-src 'self'; object-src 'none'; frame-ancestors 'none' | XSS・不正なリソース読み込みの防止 |
Strict-Transport-Security | max-age=31536000; includeSubDomains | HTTPS 強制 |
X-Content-Type-Options | nosniff | MIMEスニッフィング防止 |
Referrer-Policy | strict-origin-when-cross-origin | リファラ情報の漏洩抑制 |
Permissions-Policy | camera=(), microphone=(), geolocation=() | ブラウザ機能の制限 |
X-Frame-Options | DENY(CSP frame-ancestors と併用) | クリックジャッキング防止 |
-
Server/X-Powered-Byなどバージョン情報を露出するヘッダーを削除 - CORS は
*を避け、許可するオリジンを明示する(認証情報付きの場合は特に)
9. API セキュリティ
- すべてのエンドポイントで 認証・認可 を確認(「隠れたAPI」も含む)
- レート制限・クォータ を設ける(DoS・総当たり・スクレイピング対策)
- レスポンスで返すフィールドを明示的に選ぶ(過剰なデータ露出の防止)
- 一括代入(Mass Assignment)を防ぐため、更新可能なフィールドを許可リストで定義
- リクエストサイズ・ページネーション件数に上限を設ける
- スキーマ(OpenAPI等)でリクエストを検証する
- APIのバージョン・エンドポイント一覧を管理し、古いバージョンは廃止する
- Webhook受信時は署名を検証する
LLM / AI 機能を組み込む場合
- プロンプトインジェクション を前提に設計(外部文書・Web・ユーザー入力に含まれる指示を信頼しない)
- LLMの出力を 信頼できない入力 として扱い、実行・表示前に検証・エスケープ
- LLMに渡すツール・権限は最小限にし、重要操作には人の承認を挟む
- 機密データをプロンプトやログに不用意に含めない
10. 依存関係・サプライチェーン
- ロックファイル(
package-lock.json,poetry.lock等)をコミットし、バージョンを固定 - 脆弱性スキャン を継続的に実施(Dependabot, Renovate,
npm audit,pip-audit, Trivy, Snyk 等) - 使っていない依存関係は削除する
- 新しいパッケージ導入時はメンテナンス状況・ダウンロード数・名前(タイポスクワッティング)を確認
- CI/CD で使う外部アクション・イメージは バージョンではなくハッシュ(SHA)で固定
- コンテナのベースイメージは最小構成(distroless / slim)を使い、定期的に更新
- SBOM(ソフトウェア部品表)を生成・管理する
- 成果物への署名・来歴(provenance)検証を検討(例: Sigstore / SLSA)
11. インフラ・クラウド
アカウント・権限
- ルート / 管理者アカウントは日常利用しない。MFA必須
- IAMは最小権限、ワイルドカード(
*)権限を避ける - 使われていないユーザー・キー・ロールを定期的に棚卸し・削除
ネットワーク
- DB・管理系はプライベートネットワークに配置し、インターネットに直接公開しない
- セキュリティグループ / ファイアウォールは必要なポート・送信元のみ許可
- SSHはパスワード認証を無効化し鍵認証のみ。可能なら踏み台なしのセッション管理サービスを利用
- WAF・DDoS対策を検討
ストレージ・設定
- ストレージバケットの 意図しない公開設定 を防ぐ(パブリックアクセスブロック)
- Infrastructure as Code で構成を管理し、IaCスキャン(Checkov, tfsec 等)を導入
- OS・ミドルウェアのセキュリティパッチを定期適用
- コンテナは root 以外で実行し、読み取り専用ファイルシステムを検討
12. ログ・監視
記録すべきイベント
- ログイン成功・失敗、MFA、パスワード変更・リセット
- 権限変更、管理者操作
- 認可エラー(403)、入力検証エラーの急増
- 重要データへのアクセス・エクスポート
ログの取り扱い
- ログに パスワード・トークン・個人情報・カード番号を記録しない(マスキング)
- ログにユーザー入力を出す際は改行等をエスケープ(ログインジェクション対策)
- ログは改ざんできない場所に集約し、保持期間を定める
- 時刻同期(NTP)を行い、タイムスタンプを統一
- 異常検知のアラートを設定し、誰が対応するか を決めておく
13. 開発プロセス(DevSecOps)
| フェーズ | 取り組み |
|---|---|
| 設計 | 脅威モデリング(STRIDE 等)、セキュリティ要件の定義 |
| 実装 | セキュアコーディング規約、IDE のセキュリティLint |
| レビュー | コードレビューにセキュリティ観点を含める、ブランチ保護 |
| CI | SAST、依存関係スキャン、シークレットスキャン、IaCスキャン、コンテナスキャン |
| テスト | DAST、セキュリティテストケース、必要に応じペネトレーションテスト |
| リリース | 本番と開発環境の分離、デバッグモード無効化、最小権限のデプロイ |
| 運用 | 脆弱性管理、パッチ適用、定期的な権限棚卸し |
- エラー画面でスタックトレースや内部情報を表示しない
- 本番データを開発環境にそのまま持ち込まない(匿名化する)
- 脆弱性報告の窓口(
security.txt等)を用意する
14. インシデント対応・バックアップ
インシデント対応
- インシデント対応手順(検知 → 封じ込め → 根絶 → 復旧 → 振り返り)を文書化
- 連絡体制・エスカレーション先・外部窓口(法務・広報・監督官庁)を明確にする
- 定期的に机上演習を行う
- 事後は非難しない振り返り(ポストモーテム)を行い、再発防止策を実施
バックアップ
- 3-2-1ルール: 3つのコピー、2種類の媒体、1つはオフサイト
- ランサムウェア対策として オフライン / イミュータブル(変更不可)なバックアップ を確保
- バックアップも暗号化し、アクセス権限を制限
- 定期的にリストア訓練 を行い、実際に復旧できることを確認
15. 個人・組織の基本対策
- OS・ブラウザ・アプリを最新に保ち、自動更新を有効にする
- パスワードマネージャー を使い、サービスごとに異なるパスワードを設定
- 重要アカウント(メール・クラウド・金融・SNS)にMFAを設定
- フィッシング対策: 送信元・URLを確認し、メール内のリンクからログインしない
- 端末のディスク暗号化・画面ロックを有効にする
- 公共Wi-Fi利用時は注意し、必要に応じてVPNを使用
- 従業員向けのセキュリティ教育・訓練を定期的に実施
- 退職者・異動者のアカウントと権限を速やかに削除・変更
16. 参考資料
- OWASP Top 10 — Webアプリの主要リスク
- OWASP API Security Top 10
- OWASP Top 10 for LLM Applications
- OWASP Cheat Sheet Series — 個別テーマの具体的な実装ガイド
- OWASP ASVS — 検証基準
- NIST SP 800-63B — 認証・パスワードのガイドライン
- IPA 安全なウェブサイトの作り方
- CIS Benchmarks — OS・クラウドの設定基準