脆弱エンジニアの Advent Calendar 2025 13日目 兼
みすてむずアドカレ1 14日目の記事です。
はじめに
皆さん一度はチェックやレビューを受けて 「これは危ないよ」 と指摘を受けたことがあるのではないでしょうか。
書いたコードのほか、使っているライブラリ、そもそもの設計や仕様の誤り、設定ミスなど、セキュリティの問題というのは様々な要因で起きてしまいます。
一方で要因が様々のため「セキュリティってよくわからん…」という人もよくいるのではないでしょうか。
最近はAIを使ってコードを書くことも増えてきました。
AIモデルの進化によりAI自身が脆弱なコードを書くことが少しずつ減ってきており、 「AIに任せておけば大丈夫だろう…」 と考え、深い理解までは及ばず、レビューで指摘を受けてもとりあえずAIに修正指示を出して終わっていませんか?
今回紹介する OWASP Top 10:20252 は OWASP3 がWebアプリケーションの脆弱性を調査して評価し、上位10カテゴリに整理したものです。
平たく言えば 世の中のWebアプリケーションがやらかしやすい脆弱性ランキング ですね。
このTop 10それぞれのカテゴリでよくありがちなミスをまとめてみました。
これを理解しておけば完璧というものではありませんが、少なくとも今までより視野が広がり、安全な開発や適切なAI指示ができるようになればいいなと思っています!
OWASP Top 10 の変遷
OWASP Top 10 は2003年から始まり、2007年以降は3~4年に1回ずつ発表され 今回8回目 になります。
2017までは具体的な脆弱性の名前でTop 10が構成されていましたが、2021では再編により抽象化され、今回2025では更にカテゴリの統合や拡張がされています。
ソフトウェアが単なるプログラムと実行環境だけで完結せず、様々なリソースを組み合わせて複雑化した結果、脆弱性自体も様々なバリエーションが生じ、カテゴリの抽象化が進んでいるのだと思います。時代を感じます。
Top 10 紹介
紹介にあたり端折って説明している部分があります。
できるだけ原文の表現を採用していますが、普段使わない/意味が通じにくい表現と思われるものは独断で変えています。
A01: Broken Access Control(アクセス制御の不備)
「認可すべきでないユーザーが、本来アクセスできないデータや機能にアクセスできてしまう重大な欠陥」
マンションのオートロック付きの住戸では来訪者は入居者がエントランスを開け、その入居者宅に招くはずです。
この仕組みに不備があると、非常口や階段から侵入したり、他人の部屋をのぞいたり入ったりしてしまう危険な状態になります。
よくあるミス → こんな事故につながる
- URL やパラメータを書き換えて他人のリソースへアクセスできる(IDOR)
→ URL の ID を変えるだけで他人のデータ閲覧や編集ができてしまう - フロントエンド(JavaScript/HTML)だけでアクセス制御をしている
→ UI では非表示でも、API を直接呼び出せば権限外の操作が可能になってしまう - 権限チェックがルールとして統一されていない
→ 一般ユーザーでも管理者機能が実行できてしまい、システム設定やデータが改ざんされる
アプリケーション側の対策
- すべてのアクセス要求でサーバー側の認可チェックを徹底する
→ フロントエンドではなくバックエンドで「許可されているか」を必ず検証する - 最小権限の原則を採用
→ 明示的に許可されている場合のみアクセスを許可し、その他は拒否する設計にする - アクセス制御ロジックを再利用可能な共通ライブラリ/ミドルウェアで集中管理
→ すべての API エンドポイントで一貫した権限判定を行うことでバラつきを防止する
運用側の対策
- WAFやAPI Gatewayで不正アクセスをブロック
→ IDOR・権限外 API 呼び出し・不正トークンなどの異常パターンを遮断 - ASMで意図せず公開されているAPI・管理画面・古いエンドポイントを発見する
→ アクセス制御が欠落している公開領域の早期特定 - CSPMでクラウド権限設定を継続監査
→ 誤った IAM ポリシー、過剰な権限、公開バケットなどを検知して修正を促す
A02: Security Misconfiguration(セキュリティ設定ミス)
「サーバやサービスの初期設定や運用設定が安全に整えられていないことで、攻撃者に入り口を与えてしまうリスク」
家を建てたあとに鍵をつけ忘れたり、勝手口のドアを開けっ放しにするようなものです。
見た目は立派でも、玄関の鍵がかかっていなければ泥棒に簡単に入られてしまいますよね。
よくあるミス → こんな事故につながる
- デフォルトアカウント・パスワードをそのまま使っている
→admin/adminなど誰でも知っている初期の管理者アカウントでログインされ、サーバを乗っ取られる - 不要な機能・サービスを有効にしている
→ サンプルアプリやデバッグ機能、不要なポートが公開されており、既知の脆弱性から侵入される - 詳細なエラー情報やスタックトレースを外部に表示している
→ 内部の仕組みやバージョン情報が漏れて、攻撃者に足がかりを与える(例えばエラーでSQL構造やライブラリ名が丸見えの状態になる場合)
アプリケーション側の対策
- 最低限の機能だけをインストール/有効化し、不要な機能・サンプル・デバッグを排除する
- 各種サーバ・フレームワーク・ミドルウェアで安全な値に設定されたセキュリティヘッダを有効にする(例:Content-Security-Policy, HTTP Strict-Transport-Security(HSTS)など)
- 環境ごと(開発・テスト・本番)の設定を 自動化されたテンプレートで統一管理し、手動ミスを減らす
- 詳細なエラー情報は内部ログのみとし、外部には一般的なエラー表示に抑える(内部情報を出さない)
A03: Software Supply Chain Failures(ソフトウェアサプライチェーンの失敗)
「ソフトウェアの部品・道具・工程全体が壊れたり侵害されたりしてシステム全体に影響が出る問題」
家を建てるときに基礎・材料・工具のどれかに欠陥があると、見た目は立派でも倒壊リスクが高まります。ソフトウェアも同じで、ライブラリやビルド環境、配布プロセスなどのどこかが壊れると、気付かぬうちに悪いものが入り込み、大きな事故につながります。
よくあるミス→こんな事故につながる
- 依存しているコンポーネント(ライブラリ等)のバージョンを追跡していない
→ 古い・脆弱なライブラリをそのまま使い続けて攻撃者に侵害される事故。たとえば既知脆弱性のある部品が入り込む - CI/CD やビルド環境の変更管理やアクセス制御が不十分
→ 攻撃者がビルド工程に介入し、正規の成果物にバックドアを混入させるリスク(代表例として知られるのが SolarWinds 事案です) - サードパーティのコンポーネントを信頼せず適切に検証していない
→ 正規のパッケージが侵害され、開発者の環境や本番環境に悪意あるコードが流入する事故(例:VS Code の拡張機能として配布されたGlassWorm)
アプリケーション側の対策
- SBOMを生成・管理し、全依存関係を可視化する。
→ どの部品が使われているか把握して脆弱性を追跡・管理 - 全ての依存ライブラリとその依存を定期的にスキャン・更新する。
→ 未使用の依存は削除し攻撃対象を減らす - 開発ツール(IDE、CI/CD 等)も含めて最新に保ち、セキュリティチェックを組み込む。
→ ツール自体の欠陥を防ぎ堅牢性を高める
正規の拡張機能に似せた悪意のある拡張機能もありますので、信頼できるものかしっかり確認してください。
運用側の対策
- サプライチェーン全体に対してアクセス制御と最小権限を適用し、変更管理を徹底する。
→ 単一人物がコードから本番反映まで行えないようにする - 依存関係やコンポーネントの脆弱性を自動監視・アラートする仕組み(SCA / SBOM モニタリング)を導入する。
→ 新たな脆弱性や変更の兆候を早期に検知 - コンポーネントや成果物に署名・検証を行い、改ざん検出や安全な配布経路を保証する。
→ 正規以外のソースからの侵入を防ぐ
A04: Cryptographic Failures(暗号の失敗)
「暗号化や鍵管理の失敗によって、保護すべきデータが丸見えになる問題」
暗号化とは家の鍵や金庫のようなものです。
鍵の材質が弱かったり、鍵を玄関に置きっぱなしにすると、泥棒に簡単に入られてしまいます。
よくあるミス→こんな事故につながる
- TLS を必須にしていない/HTTP のままにしている
→ 公衆 Wi-Fi などで通信を盗聴され、セッションやパスワードを盗まれる - 古い暗号(例: MD5 や SHA-1)や弱い乱数生成を使っている
→ パスワードハッシュが破られたり、トークンを攻撃者に推測される - 暗号鍵をコードにベタ書きしてしまう
→ Git リポジトリや共有設定から鍵が漏れて、大量のデータが解読される
アプリケーション側の対策
- 機密データを分類し、必要な箇所で暗号化を強制する
- 信頼できる暗号ライブラリと標準アルゴリズム(AES-256、TLS1.3 等)を使用する
- パスワードは Argon2 / bcrypt / scrypt などでハッシュ化し、必ずソルトを使う
運用側の対策
- 鍵管理の徹底(クラウドKMSなどを利用)
- TLS 証明書・暗号ライブラリを最新バージョンで維持する
- 暗号関連のエラー(証明書チェーン失敗など)を監査ログ・SIEM で検知する
A05: Injection(インジェクション)
「アプリケーションに「悪意あるデータ」をねじ込まれることで、本来の処理が乗っ取られたり、データを盗まれたりする脆弱性」
たとえば玄関の鍵穴に細工をして、正規の鍵以外でもドアを開けられるようにしてしまうようなもの。
よくあるミス→こんな事故につながる
- ユーザー入力を検証・エスケープせずそのまま内部コマンドやクエリに使う
→ 攻撃者が入力欄にSQLを埋め込み、全アカウント情報を抜かれる - 動的に文字列を結合してSQLやコマンド文を生成
→ データベースのデータが勝手に改ざん・削除される - ORMで検証していない検索パラメータを使用
→ 想定外の条件で大量の機密レコードを取得される
アプリケーション側の対策
- パラメータ化クエリ / プレースホルダを使い、データと命令を分離する
- 入力は可能な限り 許可リスト方式で検証する
- SAST / DAST / IAST などセキュリティテストを CI/CD に組み込む
運用側の対策
- 定期的な脆弱性スキャンを実施し、インジェクションの検出を行う
- 本番ログやエラーログで不審な入力やクエリ実行を監視する
- WAFで悪意あるパターンをブロックする
A06: Insecure Design(設計上の不備)
「セキュリティを最初から考慮しない設計ミス」
家を建てるときに「鍵を付ける」「窓ガラスを防弾にする」といったことを最初に決めずに建ててしまうようなものです。どれだけ強いドアやアラームを後から付けても、最初のつくりが危険だと結局安全にはなりません。
ソフトウェアにおいてはコーディングで直せるバグではなく、仕様書や設計図の時点で間違っていることになります。
よくあるミス→こんな事故につながる
- 設計段階で脅威分析やリスク評価をしていない
→重要なビジネスロジックの抜け穴を後で発見し、大量予約や不正利用を許してしまう事故が発生 - セキュリティ要件をユーザーストーリーに統合していない
→「1人当たりの購入上限」など基本設計が無く、転売ボットに大量購入を許してしまい、本来の顧客が購入できないトラブルに発展 - 認証・リカバリフローを安全に設計していない
→NIST非推奨である質問回答式のパスワードリカバリが採用されてしまい、第三者にアカウントを乗っ取られる事故につながる
アプリケーション側の対策
- 早い段階から脅威モデリングを行い、想定される攻撃パターンと防御策を洗い出す
- ユーザーストーリーの段階で悪用されるケースも含めて仕様化する
- 共通のセキュアデザインパターン/コンポーネントライブラリを用意・再利用し、安全な設計を促進する
運用側の対策
- 開発プロジェクトごとにセキュア開発ライフサイクル(SDL)を定着させ、設計レビューやセキュリティ評価を義務付ける
- セキュリティ専門家の早期関与をルール化し、初期要件から設計までレビューを実施する
- 設計段階での決定事項が運用に反映されているか定期的に監査・見直しを行う
A07: Authentication Failures(認証の失敗)
「ユーザーが本当の利用者かどうかをしっかり確認できないと、不正アクセスにつながる認証の弱さ」
マンションのオートロック付きでは本来なら住民だけがエントランスを開けられるはずですが、認証に不備があると「実質オートロックが壊れている」状態になります。
玄関で誰でも「入居者です!」と言えば開く、暗証番号が推測し放題、ドアを開けた後に自動で閉まらない…そんな危険な状態です。
よくあるミス→こんな事故につながる
- 既知の認証情報(漏洩パスワード・総当たり攻撃)を防げない弱い認証
→ 攻撃者がパスワードリストや総当たりを使って不正ログインし、アカウントを乗っ取る - パスワード単体に依存し、多要素認証(MFA)が導入されていない、または任意設定になっている
→ パスワードが漏洩・推測された瞬間にアカウントを即座に奪われる - セッション管理の不備(無効化されないセッション、固定化されたセッションID、URLに露出するセッションIDなど)
→ 攻撃者が有効なセッションを盗み取り、そのまま正規ユーザーとして操作できてしまう
アプリケーション側の対策
- パスワードの強度チェック、使い回し・漏洩済みパスワードの拒否を行う
- 多要素認証(MFA)を必須化し、パスワードだけに依存しない
- セッション管理を厳格化(ログアウトや一定時間で確実に無効化、セッションIDをURLに入れない)
運用側の対策
- 異常なログイン試行(総当たり・リスト攻撃)を監視し、遮断・警告する
- 情報漏洩した認証情報のチェック(例:漏洩一覧との照合)を定期的に行う
- 認証周りの設定・ログ・挙動を定期レビューし、ペンテストで弱点を早期発見
A08: Software or Data Integrity Failures(ソフトウェア/データ整合性の不具合)
「信頼できるソフトウェアやデータであることを検証せずに使ってしまい、改ざんや不正コードを実行されてしまう問題」
建物に例えると、施錠も鍵の確認もしないまま「鍵付きのドア」だと思って勝手に開けてしまうようなものです。本来なら鍵が正規のものかどうか確かめるべきなのに、誰でも入れるドアだと思い込んでしまう状態です。すると泥棒に簡単に入られてしまう可能性があります。
よくあるミス→こんな事故につながる
- 更新プログラムやライブラリを「署名や検証なし」でそのままダウンロードして使う
→ 攻撃者が改ざんしたマルウェア入り更新が配布され、全ユーザのシステムが侵害される - CI/CDパイプラインでコードの出所や検証をせずにビルドやデプロイを進める
→ 悪意ある変更が混入し、意図しない脆弱性やバックドアが本番に乗る - シリアライズ(データを送受信形式にする処理)したデータを検証せずにそのまま実行
→ 攻撃者に細工されたシリアライズデータでリモートコード実行されることがある(特に外部から受け取ったデータを無検証でデシリアライズすると致命的)
アプリケーション側の対策
- ソフトウェアや重要データにデジタル署名・ハッシュ検証を必ず行い、期待するソースからのものか確認する
- 依存関係(npm / Maven など)は信頼されたリポジトリのみを利用する
- CI/CD パイプラインでコード/設定の変更レビュープロセスとアクセス制御を設け、悪意ある改変混入リスクを下げる
- シリアライズ/デシリアライズ処理がある場合、未署名・暗号化されていないデータを検証なしに処理しない
運用側の対策
- ソフトウェアサプライチェーン全体の監視とログを整備し、不審なパッケージ取得や更新挙動を検知する
- CI/CD、パッケージ管理サーバー、リポジトリへのアクセス制御と監査ログを厳格化する
- 定期的にSBOMや依存関係スキャンを行い、未知/不正改変されたコンポーネントを早期に発見・対応する(運用プロセスに組込)
A09: Logging & Alerting Failures(ログ&アラート不備)
「ログ記録や警告・通知が正しく実装されておらず「侵害されても気づけない」致命的なセキュリティ欠陥」
防犯カメラがあっても録画されず、異常が起きてもブザーが鳴らないようなものです。泥棒が入っても誰も気づかず、被害が拡大してしまいます。
よくあるミス→こんな事故につながる
- 重要なイベント(失敗ログインや高額取引)が記録されない
→ 不正アクセスや不正操作が起きても検知できない - エラーや警告に不十分・曖昧なメッセージしか出ない
→ 問題の原因特定・対応が遅れる - アラートの閾値・通知プロセスがなく、見逃しが多い
→ 実際の侵害に対して対応が遅れ、大きな被害に発展
アプリケーション側の対策
- ログイン成功・失敗やアクセス制御の失敗などすべての重要イベントを一貫してログに出力する
- ログ形式はログ集約/管理ツールが扱いやすい標準フォーマットにする
- ログデータに対して改ざん防止(例: 追記のみ、堅牢な格納)を実装する
運用側の対策
- リアルタイムの監視・アラート仕組みを整備する
- 過剰な誤警報を抑える閾値設定・アラートチューニングを行う
- SOC(セキュリティ運用チーム)向けの対応手順やエスカレーションルールを整備し、定期的に見直す
A10: Mishandling of Exceptional Conditions(例外状態の不適切な取り扱い)
「アプリケーションが想定外の状態(エラー・異常系)に遭遇したとき、その扱いが不適切で、情報漏洩・アクセス制御の破綻・クラッシュなどにつながる問題」
オートロック付きマンションが故障したときに「異常だから閉じる(fail-closed)」のではなく、「壊れちゃったので全開放(fail-open)」と勝手にドアを開けてしまうようなものです。これが攻撃者に招かれざる入場を許す原因になります。
よくあるミス→こんな事故につながる
- エラー詳細(スタックトレース・DB名・内部構造)を画面にそのまま表示
→ 攻撃者が手がかりを得て攻撃経路を推測し、脆弱性悪用につながる - パラメータエラーやNULLをチェックせずに処理続行
→ 例外発生 → サービス停止や予期せぬ挙動を誘発し、DoSや権限回避のチャンスを与える - 認可エラー時に「失敗したら許可(fail-open)」の実装
→ 本来アクセスできないユーザーが機密機能にアクセスできる
アプリケーション側の対策
- 例外は必ず捕捉し、内部情報を含まないユーザー向けメッセージを返す(詳細は安全なログへ記録)
- 「失敗したら拒否(fail-closed)」を原則とし、認可・入力チェック・バックエンド障害時の挙動を明示的に定義する
- 全体を統括するグローバル例外ハンドラを導入し、例外漏れを防ぐ
運用側の対策
- 例外ログを中央集約し、異常値・大量例外の発生をアラートとして即時検知する
- 例外系の挙動を含むセキュリティテスト(負荷テスト、ペネトレーションテスト)を定期的に実施
- 障害発生・異常応答パターンの監視メトリクス(高エラーレート、認可失敗の急増など)を設定し攻撃兆候を早期把握する
補足:混同しやすいカテゴリの違いについて
OWASP Top 10 を読んでいると、「あれ、これとこれって何が違うの?」と迷う項目が出てくるかもしれません。迷いやすそうな以下の2組について整理します。
A03(サプライチェーン)と A08(整合性)の違い
どちらも「外部のライブラリやツールに原因がある」点では似ていますが、着眼点が異なります。
- A03: Software Supply Chain Failures(調達・工程の問題)
- 「どこから来たか? その入手ルートや作成プロセスは安全か?」 に注目します
- 例:ライブラリの作者が攻撃された、ビルドサーバーが乗っ取られた、そもそも偽物のライブラリをインストールしてしまった
- A08: Software or Data Integrity Failures(検証・確認の問題)
- 「使う前にそれが本物か確かめたか? データを安全に戻したか?」 に注目します
- 例:ダウンロードしたファイルのハッシュ値を確認しなかった、信頼できないデータを検証せずにデシリアライズ(復元)してしまった
A07(認証)と A01(アクセス制御)の違い
どちらも「ログインとか権限の話」に見えますが、セキュリティ用語では AuthN (Authentication) と AuthZ (Authorization) として明確に区別されます。
- A07: Authentication Failures(認証=あなたは誰?)
- 「本人確認」 の失敗です
- システムに入り口(玄関)で、その人が登録されたユーザーかどうかを確認するフェーズ
- 例:パスワードが弱くて破られる、多要素認証がない、ログイン画面が突破される
- A01: Broken Access Control(アクセス制御=何をしていい?)
- 「権限確認」 の失敗です
- ログインした後に、その人がどこまで操作していいかを制御するフェーズ
- 例:一般社員なのに社長の給与明細が見えてしまう、他人の注文履歴URLを叩いたら見えてしまう
覚え方: 「パスワードがバレて不正ログインされた」 なら A07(認証)。 「ログインは正規だけど、見ちゃいけない他人のデータが見えた」 なら A01(アクセス制御)
おまけ:Top 10に入りきらなかったもの
Top 10に入りきらなかったけれども「危機的状況」にあるリスクが「Next Steps」のページにまとめられていました。
今回詳しくは紹介しませんがぜひ原文をご覧ください。
-
X01: Lack of Application Resilience(アプリケーションの回復力不足)
- 異常な負荷や予期しない状態に耐えられず、サービス停止・データ破損などにつながる弱さ
- OWASP Top 10 2021のサービス拒否攻撃から名称変更
-
X02: Memory Management Failures(メモリ管理の失敗)
- メモリ割当・解放エラーなどによる破壊的な欠陥
宣伝:Webの脆弱性をもっと詳しく勉強したい
PortSwigger Web Security Academyで実際に手を動かして学ぶことをおすすめします!
手前味噌で恐縮ですがやりかたを解説した記事を以前作ったことがありますのでぜひご覧ください。
-
みすてむず いず みすきーしすてむずというMisskeyサーバーのアドベントカレンダーみすてむず いず みすきーしすてむず(2) Advent Calendar 2025です。 ↩
-
2025年12月現在、OWASP Top 10:2025は RC(リリース候補) となっています。今後発表される正式版では内容が変わる可能性があります。 ↩
-
オワスプと読みます。Open Web Application Security Project(国際ウェブセキュリティ標準機構)という組織です。日本にもOWASP Japanがあります。 ↩
