1-4. OWASP Top 10 - Webアプリ脆弱性の地図
所要時間: 35-50分 ゴール: OWASP Top 10(2021年版)の10項目それぞれの本質、典型的な攻撃、最低限の対策を概観できる。自分のサービスがどこに弱いか感覚を持つ コミット内容: 自サービス(架空でOK)の Top 10 自己点検チェックリストを
~/learn/security/day04_owasp/checklist.mdに残す
前章とのつながり
このレッスンの位置づけ
1-1〜1-3 で 「認証 / 認可 / 通信路」 という基礎の3本柱を立てた。本章は 業界全体が共有する『脆弱性地図』 を概観する回。
- 1-1 で学んだ AuthN/AuthZ は A01 (Broken Access Control) と A07 (Auth Failures) に直結
- 1-2 のパスワード保存は A02 (Cryptographic Failures) と A07
- 1-3 の HTTPS/TLS は A02
- 次章 1-5 SQLi / 1-6 XSS は A03 (Injection) の深掘り
本章は「目次」、次章以降が「各章本文」。ここで全体地図を頭に入れておくと、後続の個別深掘りが「全体のどこの話か」分かって理解が速くなる(スキャフォールディング)。
実害シーン: Top 10 の実被害
- A01 Broken Access Control: First American Financial の 8.85億件流出 (2019)
- A02 Cryptographic Failures: Equifax の 1.4億件流出 (2017、暗号通信の不適切実装)
- A03 Injection: TalkTalk の 400万件流出 (2015、SQLi)
- A06 Vulnerable Components: Equifax (Struts2 の既知脆弱性放置、上記と同事件)
- A07 Auth Failures: Disney+ ローンチ時のクレデンシャル・スタッフィング攻撃
「Top 10 を語れる」は、防御側として最低限のリテラシー。攻撃手法を知らないと防御もできない。
大前提: OWASP Top 10 は「最低限知ってないと恥」のリスト
OWASP(Open Web Application Security Project) は、Web アプリのセキュリティを推進する非営利団体。彼らが数年に一度発表する Top 10 は、世界中の脆弱性データを集計した「現代Webアプリで最も多い・致命的な脆弱性 トップ10」。
採用面接、コードレビュー、社内研修、すべてで前提知識として扱われる。バックエンドエンジニアで「OWASP Top 10 を聞いたことがない」は転職市場で不利になるレベル。
このレッスンでは2021年版(次回更新は2024-2025年予定)の10項目を概観する。深掘りは別レッスン(SQL Injection、XSS など)で個別に行う。
各項目について 「これは何か」「実例」「最低限の対策」 をセットで覚える。完璧主義より「全項目を1分で説明できる」を目指す。
セッション①: A01〜A05(25-30分)
0. 録画&メモ準備
mkdir -p ~/log ~/learn/security/day04_owasp
cd ~/learn/security/day04_owasp
script ~/log/security_day04.logA01: Broken Access Control(アクセス制御の不備)
2021年版で1位に躍進。前回4位から急上昇した、現代Webで最大の脆弱性カテゴリ。
A01 の本質
認可(AuthZ)が壊れている / 欠けている問題。
「ログインしたユーザーが、本来見られないはずのリソースを見られる」が典型。
代表的なパターン:
- IDOR(Insecure Direct Object Reference): URLに
/users/1234/profileのようにIDを直書きしていて、他人のID5678に書き換えれば他人のデータが見える- 権限昇格: 一般ユーザーが
/admin/...を叩いたら通ってしまう- 強制ブラウジング: ログイン前提のURLにログインせず直接アクセスできる
- CORS設定ミス:
Access-Control-Allow-Origin: *で全ドメインに API を開放してしまう
実例: First American Financial Corp (2019)
9億件の不動産取引文書がURL改変で見えてしまった。
document/1をdocument/2document/3… と辿るだけで、認証なしで他社の契約書がダウンロードできた。典型的な IDOR で、保険会社の評価額1.4億ドル相当の事故になった。
A01 の最低限対策
- すべてのエンドポイントで「リソース所有者か」をチェック
- ID は連番ではなく UUID やランダム文字列に(推測不能化)
- 管理画面のURLにアクセスした時点でロール検証
- 「default deny」: 明示的に許可した操作以外は全部拒否
A02: Cryptographic Failures(暗号化の不備)
旧称「Sensitive Data Exposure」(機密データの露出)。
A02 の本質
実例: Adobe (2013)
1.5億件流出。パスワードを 可逆暗号化(共通鍵 + 弱いモード)で保存していたため、漏洩時に大半が解読された。「パスワードヒント」も同時漏洩していたので解読が促進された。
「ハッシュ化」と「暗号化」を混同した典型例として今も語り継がれる。
A02 の最低限対策
- HTTPS 必須(HSTS で強制)
- パスワードは bcrypt / argon2id
- 機密データ(クレカ番号、マイナンバー)はDB保存時にも暗号化
- 秘密鍵・APIキーは環境変数 or KMS、ソースコードに書かない
- 古いアルゴリズム(MD5、SHA-1、DES)を排除
A03: Injection(インジェクション)
ずっと長年首位だった代表選手。2021年版で3位に下がったが依然重大。
A03 の本質
ユーザー入力を コードや構文の一部として解釈させる 攻撃の総称。
種類:
- SQL Injection (SQLi): SQL文に悪意ある文字列が混入し、想定外のクエリが実行される
- コマンドインジェクション: シェルコマンドに混入(
os.system("ping " + user_input)のような実装)- LDAP インジェクション: LDAP クエリへの混入
- NoSQL インジェクション: MongoDB などへの混入(クエリ言語がJSONでも発生する)
- テンプレートインジェクション: テンプレートエンジンに評価される構文を流し込む(SSTI)
実例: Sony Pictures (2011) / TalkTalk (2015)
どちらも SQL Injection が侵入の起点。Sonyは7700万件、TalkTalkは15.7万件流出。
数十年前から知られている古典的攻撃なのに、未だに大企業で起きるレベル。ORMがあっても生SQLを書く場面で油断すると死ぬ。
A03 の最低限対策
- prepared statement / placeholder(
?$1)を絶対に使う- 文字列連結でSQLを組み立てない
- 入力検証(許可リスト / allowlist)も併用
- ORM の生SQL機能を使う場合は特に注意
- 詳細は次レッスン 1-5 SQL Injection で
A04: Insecure Design(安全でない設計)
A04 の本質
コード単体ではなく、設計レベルで セキュリティ要件が抜けている問題。Top 10 に2021年から新登場。
パターン:
- 「パスワードリセット」のフローが甘い(ヒント質問が「母の旧姓」など特定容易)
- 「電話番号でアカウント復旧」させる仕様(SIMスワップで乗っ取られる)
- レート制限の欠如(ログイン試行・SMS送信が無制限)
- 削除機能の認可が「IDが一致するだけ」(CSRFと組み合わせて他人に削除される)
コードがきれいでも、仕様が壊れていれば脆弱。
実例: Twitterの「SMS復旧」乗っ取り
2019年頃から多発した、SIMスワップ攻撃による著名人アカウントの乗っ取り。CEOのジャック・ドーシー本人も被害に。
「電話番号で復旧できる」という仕様自体が脆弱だった。SMS自体は技術的に攻撃されていない、設計が悪い。
A04 の最低限対策
- 設計段階で脅威モデリング(STRIDE)(1-1で扱った)
- デフォルト安全な仕様(オプトインではなくオプトアウト)
- 多層防御(defense in depth): 1つの仕組みが破られても他で守れる
- レート制限・MFA・監査ログを設計時から組み込む
A05: Security Misconfiguration(設定の不備)
A05 の本質
ソフトウェアの 設定 が安全でない状態。コードに穴がなくても設定で穴を開けてしまうパターン。
パターン:
- デフォルトパスワード で運用(admin/admin)
- デバッグモード本番有効化: スタックトレースが攻撃者に丸見え
- 不要な機能が有効: 管理コンソール、サンプルアプリ、デフォルトアカウント
- HTTPヘッダー欠如: CSP、X-Frame-Options、X-Content-Type-Options
- クラウドストレージ公開: S3バケットを誤って public にしてデータ全公開
- Docker イメージに認証情報埋め込み
実例: Capital One (2019)
1億件流出。AWS の WAF 設定ミスで、攻撃者が EC2 のメタデータエンドポイントから一時認証情報を取得し、S3 にアクセスできた。コードのバグというより設定ミス。
元AWS従業員が攻撃者で、社内事情を知っていたため発見できた。
A05 の最低限対策
- Infrastructure as Code(Terraform 等)で設定を明示
- 本番でデバッグモード絶対オフ
- 使わない機能・ポートはすべて閉じる(最小権限の原則)
- クラウドのデフォルト公開設定に注意(S3、GCSは作成時に明示的にprivate)
- セキュリティヘッダーをチェック(securityheaders.com で診断可能)
セッション②: A06〜A10(25-30分)
A06: Vulnerable and Outdated Components(脆弱・古いコンポーネント)
A06 の本質
自分のコードではなく、使っているライブラリ/フレームワーク に脆弱性があるパターン。
現代のWebアプリはコード行数の 9割が依存ライブラリ。これらに既知のCVE(脆弱性)があれば、自分のコードがどんなに完璧でもアウト。
パターン:
- npm / pip / Go modules で古いバージョンを使い続けている
- 「動いてるから触らない」運用
- Docker のベースイメージが古い
- OS パッケージのアップデートをサボっている
実例: Equifax (2017)
1.5億件の信用情報流出。Apache Struts 2 の脆弱性(CVE-2017-5638)が原因。パッチは攻撃の2ヶ月以上前に公開されていた が、適用されなかった。
「セキュリティパッチを当てるだけで防げた」事件。アメリカの個人情報漏洩史上トップクラスの事故。
A06 の最低限対策
npm audit/pip-audit/govulncheckを定期実行- Dependabot / Renovate で自動PRを受け取る
- 依存をできるだけ少なく(左寄せの原則)
- CVE情報をウォッチ(重要ライブラリは公式アカウントフォロー)
- 古いランタイム(EOL過ぎたNode、Python)を本番で動かさない
A07: Identification and Authentication Failures(認証の不備)
A07 の本質
認証(AuthN)の仕組み自体に問題があるケース。
パターン:
- クレデンシャル・スタッフィング許可: 他社流出パスワードのリストでログイン試行し放題
- 弱いパスワードポリシー: 「abc123」が通る
- セッションIDの推測可能: 連番、タイムスタンプベース
- セッション固定攻撃: ログイン後にセッションIDを更新していない
- MFAが任意: 攻撃対象になりやすい管理者アカウントも素のパスワードのみ
- パスワードリセットフローの脆弱性(トークン長すぎ短すぎ、期限なし、ワンタイムでない)
実例: Dropbox (2012) からの連鎖被害
Dropbox から漏洩したパスワードハッシュリストが、その後 LinkedIn・GitHub などへの クレデンシャル・スタッフィング攻撃 に使われた。ユーザーがパスワード使い回しているため、1社の漏洩が他社の侵害につながる。
同様の事件は毎月どこかで起きている。
A07 の最低限対策
- bcrypt / argon2id でハッシュ化(既出)
- 流出パスワードDB(Have I Been Pwned API)と照合して登録時に弾く
- レート制限: 5回失敗で15分ロック
- MFA を提供、管理者には強制
- セッションID は暗号学的乱数、ログイン成功時に再生成
A08: Software and Data Integrity Failures(整合性の不備)
A08 の本質
コード/データの「正しさ」が検証されていない 問題。サプライチェーン攻撃が主軸。
パターン:
- 信頼できないソースからプラグイン/ライブラリを取得
- CI/CD パイプラインに署名検証がない
- 自動アップデートに署名検証がない
- JWT の署名検証をスキップ(
alg: noneを許容)- シリアライズデータ(pickle、Java Serialization)の改ざんを検知しない
実例: SolarWinds (2020)
SolarWinds社のITソフトウェア「Orion」のアップデートにマルウェアが混入。正規の署名付きでアップデートが配布されたため、米連邦政府含む18000組織が侵害された。
ビルドパイプラインそのものが攻撃された、史上最悪級のサプライチェーン攻撃。
実例: event-stream (2018)
npm パッケージ
event-streamのメンテナが別人に引き継いだ後、悪意あるコードが混入。ビットコインウォレットを盗む処理が仕込まれた。人気パッケージのメンテナ権限を譲るリスクを示した。
A08 の最低限対策
- 依存ライブラリのバージョンを lock ファイルで固定(package-lock.json、go.sum)
- subresource integrity (SRI): CDN から JS を読み込むとき
integrity属性でハッシュ検証- コンテナイメージに署名(Sigstore、cosign)
- JWT のアルゴリズムを明示(
alg: none拒否)
A09: Security Logging and Monitoring Failures(ログと監視の不備)
A09 の本質
攻撃を 検知できない 問題。
一般的な侵入から発見までの中央値は 200日以上(業界調査)。これは「ログを取っていない」「取っているが見ていない」「アラートが鳴らない」のいずれかが原因。
パターン:
- 認証失敗・成功のログがない
- 重要な操作(削除、権限変更、設定変更)のログがない
- ログがアクセス可能な場所に保存(攻撃者が消せる)
- アラート設定がない(あっても誤検知だらけで無視されている)
- ログの長期保管(最低1年)がされていない
A09 の最低限対策
- 認証イベント・認可失敗・重要操作を必ずログ化
- ログは別ストレージに(攻撃者から守る)
- 異常検知アラート(同一IPから連続失敗、深夜の管理者ログインなど)
- SIEM(Splunk、Datadog Security、CloudWatch Logs Insights)への集約
- インシデント対応プレイブック(事故発生時の手順書)を事前作成
A10: Server-Side Request Forgery (SSRF)
A10 の本質
アプリに 「指定されたURLを取りに行く」 機能があり、そのURLを攻撃者が 内部リソースに向けさせる 攻撃。
シナリオ:
- アプリに「画像URLを指定すればプロキシしてくれる」機能がある
- 攻撃者が
http://169.254.169.254/latest/meta-data/(AWS EC2 のメタデータエンドポイント)を指定- アプリが内部から取得して結果を返す
- 攻撃者がEC2の一時認証情報を取得
実例: Capital One (2019、再登場)
上の A05 で書いたのと同じ事件。SSRF も同時に絡んでいた。WAF サーバーから内部メタデータエンドポイントへのリクエストを許してしまったのが原因。
A10 の最低限対策
- ユーザー入力URLは必ず allowlist で検証
- 内部IPアドレス(10.0.0.0/8、169.254.169.254 など)への接続をブロック
- DNS解決結果も検証(外部ドメインのフリして内部IPを返すDNSリベインディング攻撃)
- クラウドのメタデータエンドポイントは IMDSv2 を使う(AWSの場合、トークン必須)
まとめ表
| 略号 | 名前 | 一言で |
|---|---|---|
| A01 | Broken Access Control | 認可漏れ・IDOR |
| A02 | Cryptographic Failures | 暗号化サボり・平文 |
| A03 | Injection | SQLi、コマンドi、XSSなど |
| A04 | Insecure Design | 設計レベルの欠陥 |
| A05 | Security Misconfiguration | デフォ設定・S3公開・デバッグON |
| A06 | Vulnerable Components | ライブラリの脆弱性 |
| A07 | Authentication Failures | クレデンシャルスタッフィング・MFAなし |
| A08 | Integrity Failures | サプライチェーン・JWT署名スキップ |
| A09 | Logging and Monitoring Failures | 攻撃に気づけない |
| A10 | SSRF | サーバー経由で内部に侵入 |
覚え方
「1認可、2暗号、3注入、4設計、5設定、6依存、7認証、8整合、9監視、10SSRF」と数字とセットで唱える。面接でも頻出。
練習課題
# 自サービス(架空でOK、TaskNote と仮定)の Top 10 自己点検
touch ~/learn/security/day04_owasp/checklist.mdチェックリストのテンプレ
# TaskNote セキュリティ自己点検(OWASP Top 10 / 2021) ## A01 Broken Access Control - [ ] 各APIで「リソース所有者かチェック」を実装している - [ ] ユーザーIDはUUID - [ ] 管理画面エンドポイントでロール検証 ## A02 Cryptographic Failures - [ ] HTTPS 必須化 - [ ] パスワード bcrypt - [ ] 秘密鍵は環境変数、コミットしていない ## A03 Injection - [ ] prepared statement のみ使用 - [ ] 入力検証(allowlist) ## A04 Insecure Design - [ ] パスワードリセットがワンタイム・期限付き - [ ] レート制限実装 ## A05 Security Misconfiguration - [ ] 本番でデバッグモードオフ - [ ] セキュリティヘッダー設定 - [ ] S3バケットは private 確認 ## A06 Vulnerable Components - [ ] Dependabot 有効 - [ ] `npm audit` / `govulncheck` を CI で実行 ## A07 Authentication Failures - [ ] 流出パスワードチェック(HIBP API) - [ ] 5回失敗で15分ロック - [ ] MFA 提供 ## A08 Integrity Failures - [ ] package-lock.json / go.sum コミット - [ ] CDN リソースに SRI ## A09 Logging and Monitoring - [ ] ログイン成功/失敗をログ化 - [ ] 認可失敗アラート - [ ] ログ集約先(CloudWatch等)あり ## A10 SSRF - [ ] 外部URL指定機能がある場合、allowlist で制限 - [ ] 内部IP(169.254.169.254 等)アクセス禁止
締め: 振り返り(10分)
1. セッション録画を終了
exit2. 今日の発見
- 自分が一番ピンと来た項目(一番怖い):
- 自分が一番盲点だった項目:
- 自社サービス(or 過去のプロジェクト)で当てはまっていた弱点:
- 次に深掘りしたい項目:
チェックリスト
- A01〜A10 を見ずに3つ以上挙げられる
- それぞれ「実例事件」を1つ挙げられる
- 自サービスの自己点検チェックリストを書いた
- 一番自分のチームに不足している項目を特定した
詰まった時のチートシート
| 略号 | 一言メモ |
|---|---|
| A01 | 「他人のIDで叩いたら見える」を絶対防ぐ |
| A02 | HTTPS + bcrypt + 秘密はリポ外 |
| A03 | prepared statement、文字列連結禁止 |
| A04 | 設計の段階でSTRIDE、MFA、レート制限 |
| A05 | 設定が公開・デフォになっていないか |
| A06 | ライブラリの更新・脆弱性スキャン |
| A07 | パスワードハッシュ、MFA、レート制限 |
| A08 | 署名検証、lock ファイル、SRI |
| A09 | ログ取って監視して通知 |
| A10 | 外部URL取得は内部IPブロック |
「実務OK」基準
- OWASP Top 10 という言葉に動じない: 面接でも会議でも普通に出る
- コードレビューで該当項目を指摘できる
- 自分のプロジェクトの弱点を Top 10 にマッピングして説明できる
- 「これは A01 だね」と項目番号で会話できる(業界共通言語)
メタ認知: 自分の理解度を診断する
30秒セルフテスト
- A01〜A10 のうち、ここ数年で 「常に1位」 は何で、その理由は?
- A03 (Injection) の代表3つを挙げよ
- A05 (Security Misconfiguration) の「最も典型的なやらかし」を1つ
- A06 (Vulnerable Components) で具体的に何をする習慣が必要?
- A10 (SSRF) はクラウド時代に重要性が増したのはなぜ?
5問中3問以上スラスラ言えるか がライン。詰まったらその項目を再読。
次のレッスン
1-5 SQL Injection でA03の代表選手SQLiに深掘り。次の 1-6 XSS で同じくA03のXSSを扱う。Top 10 の中でも開発者が日常的に遭遇する2大脆弱性を、コード例とともに体得する。
間隔反復ポイント
Top 10 の 項目名と番号 は業界共通言語。1ヶ月後にこの章の表だけ眺める を習慣化すれば、ミーティングで「これ A01 だね」と即座に出るようになる。