A02 セキュリティ設定の不備

コードが正しくても、動かす環境の既定値と手で足した設定で穴が開く。直し方は1つずつの修正でなく、固めた設定を毎回同じに作り直せる仕組みにすることだ。

OWASP Top 10:2025 A02 Security Misconfiguration。2021年版の5位から2位へ上がった。対応するCWEは16。検査したアプリの100%に何らかの設定の不備があり、平均の発生率は3.00%[1]。2026年11月時点の記載で書いています。

要点

  • OS、Webサーバー、枠組み、データベース、クラウドの各層に既定値がある。1層でも開いていれば、その上のコードの守りを迂回される。
  • 型は4つに分けて見る。既定とデバッグの残り、XML の外部実体参照、クラウドの保管庫の公開と静的な鍵、応答のヘッダと Cookie と CORS。
  • 根本の直し方は、最小の構成を自動で組み、開発、検証、本番を同じ定義から作り、資格情報だけを環境ごとに替えること[1]。
  • 設定の有効性を自動で確かめる。自動でなければ、OWASP は最低でも年1回の手での確認を求める[1]。

成立の条件

設定の不備は、本番が定義から外れたときに生まれる。手で直した本番、検証にしか無い修正、更新で増えた新しい既定値。

同じ定義から組んだ開発と検証と本番は揃うが、本番を手で変えると定義から外れ、確かめの対象からも漏れる 固めた定義 コードとして版を管理 最小の構成 開発 資格情報だけ別 検証 資格情報だけ別 本番 手で変えた差分 定義に無いもの 障害対応で開けたポート 戻し忘れたデバッグ 更新で増えた既定値 定義から作り直せば 差分は消え、確かめは 定義を見れば足りる
図1 定義から外れた本番に設定の不備がたまる
  • 既定値が開いている 既定のアカウント、サンプルのアプリ、ディレクトリの一覧、詳しいエラー、共有が公開になった保管庫。
  • 要らない機能が入っている 使わないポート、サービス、ページ、アカウント、試験の枠組み、権限[1]。
  • 守りの設定が付いていない 応答のヘッダ、Cookie の属性、CORS の許可、更新で入った新しい守りの機能を有効にしていない。後方互換を優先して安全でない設定を残すことも OWASP は挙げる[1]。

型1 既定とデバッグの残り

OWASP の例は、本番に残したサンプルのアプリの管理画面に、変えていない既定のパスワードで入られるもの、ディレクトリの一覧からコンパイル済みのクラスを取られて解析されるもの、スタックトレースが部品の版を漏らすものだ[1]。

外からの要求が、残ったサンプル、ディレクトリの一覧、詳しいエラーのそれぞれから、入口や内部の情報を得る 外からの要求 認証なし 残ったサンプルの管理画面 既定のパスワードのまま ディレクトリの一覧 ビルド物、バックアップ 詳しいエラー スタックトレース、部品の版 管理の権限を得る コードを解析して 別の穴を探す 既知の脆弱性を持つ 版を特定する
図2 既定とデバッグの残りから得られるもの

悪い例。架空のアプリのエラー処理

app.use((err, req, res, next) => {
  res.status(500).json({ message: err.message, stack: err.stack });
});

直した例。中身は記録にだけ残し、利用者には照合の番号を返す

app.use((err, req, res, next) => {
  const ref = crypto.randomUUID();
  logger.error({ ref, err });
  res.status(500).json({ message: 'internal error', ref });
});
  • OWASP は、詳しすぎるエラーを止める中央の設定を、予備として置くよう求める[1]。エラー処理のチートシートも、技術の構成と版が偵察の材料になると書く[4]。
  • 例外の扱いそのものの誤りは A10 が扱う。A02 で見るのは、本番の設定で詳しい出力が有効になっていないか。
  • デバッグの有効化は、コードでなく環境変数か設定の定義で切り替え、本番の定義で固定する。CWE-489 Active Debug Code。

型2 XML の外部実体参照 XXE

XML のパーサーが文書型宣言の外部実体を解決すると、文書の中から手元のファイルや内側のURLを読ませられる。2017年版では独立したカテゴリで、2021年版から設定の不備に入った[9]。パーサーの既定値の問題なので、ここに入る。

外部実体の宣言を含むXMLを受け取ったパーサーが、宣言に従って手元のファイルや内側のURLを読み、その中身を応答に混ぜる 送られた XML 文書型宣言の中に 外部実体の宣言 XML のパーサー 宣言を解決する 既定値のまま 手元のファイル 設定、鍵 内側のURL A01 の SSRF と同じ先
図3 XXE が通る道筋

悪い例。Java の DOM パーサーを既定のまま使う

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
Document doc = dbf.newDocumentBuilder().parse(input);

直した例。文書型宣言そのものを拒む

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setXIncludeAware(false);
Document doc = dbf.newDocumentBuilder().parse(input);
  • 最も確実なのは文書型宣言を拒むこと。内部の DTD が要るときは、外部の参照で例外を投げる解決器を置き、外部の一般実体と引数実体の機能を切る[5]。
  • 既定値は言語とライブラリと版で違う。libxml2 は 2.9 から外部実体の置き換えを既定で切ったが、PHP の LIBXML_NOENT などの指定で戻る[5]。使っているパーサーごとに確かめる。
  • 入れ子の実体で膨らませる攻撃は CWE-776。文書型宣言を拒めば、こちらも止まる。
  • XML は API の本文だけでなく、SVG、Office の文書、SAML、設定ファイルの取り込みにも来る。

型3 クラウドの保管庫の公開と静的な鍵

OWASP の例には、クラウドの事業者の共有の権限が既定でインターネットに開いていて、保管したデータに誰でも届くものがある[1]。2025年版は、コードや設定やパイプラインに静的な鍵を埋めず、基盤のID連携と短命の資格情報を使うよう求める項目を新しく足した[1]。

静的な鍵は漏れると誰の手からでも使え、期限も無い。ID連携の短命の資格情報は、決まった実行環境でだけ得られ、すぐ切れる 静的な鍵 置き場所設定ファイル、環境変数、CI の変数 使える人鍵の文字列を持つ全員 期限人が止めるまで無期限 漏れ方リポジトリ、ログ、イメージ、 エラーの出力 ID連携と短命の資格情報 置き場所置かない。実行時に基盤から得る 使える人決まった実行環境と役割だけ 期限分から時間の単位で切れる 漏れ方漏れても使える時間が短い
図4 静的な鍵と、短命の資格情報の違い

悪い例。架空の保管庫を誰にでも読ませる方針

{
  "Effect": "Allow",
  "Principal": "*",
  "Action": "s3:GetObject",
  "Resource": "arn:aws:s3:::example-reports/*"
}
  • 保管庫は、アカウントの単位で公開を止める設定を入れ、読ませる相手は役割で指定する。AWS は S3 のパブリックアクセスのブロックを、アカウントと保管庫の単位で用意している[7]。
  • 公開して配るものは、保管庫を直接開けず、配信の仕組みの後ろに置く。公開する保管庫と非公開の保管庫を分ける。
  • 秘密の管理は、置き場所を1つにし、使う側には実行時に渡し、回転できる形にする[6]。

型4 応答のヘッダと Cookie と CORS

守りの指示を端末へ送らないか、送っても弱い値で送る。CORS では、要求の Origin をそのまま返し、資格情報付きで許すと、どのサイトの JavaScript からも利用者の権限でAPIを読める。

罠のサイトのスクリプトが資格情報付きでAPIを呼び、APIが要求のOriginをそのまま許可として返すので、端末が応答を罠のサイトに渡す 利用者の端末 罠のスクリプト trap.example.net api.example.com の Cookie を持っている Origin: https://trap.example.net ACAO: https://trap.example.net ACAC: true api.example.com Origin をそのまま返す 利用者の記録を返す 許可のヘッダを付ける ACAO は Access-Control-Allow-Origin、ACAC は Access-Control-Allow-Credentials
図5 Origin をそのまま許す CORS の設定が通す読み取り

悪い例

res.set('Access-Control-Allow-Origin', req.get('Origin'));
res.set('Access-Control-Allow-Credentials', 'true');

直した例。許すオリジンを一覧で決める

const ALLOWED_ORIGINS = new Set(['https://app.example.com']);
const origin = req.get('Origin');
if (ALLOWED_ORIGINS.has(origin)) {
  res.set('Access-Control-Allow-Origin', origin);
  res.set('Access-Control-Allow-Credentials', 'true');
  res.set('Vary', 'Origin');  // 中継のキャッシュで他のオリジンへの応答と混ざらないように
}
  • 資格情報付きの要求に * は使えない決まりがあるため、Origin を写して返す実装が生まれる[10]。写す前に一覧と完全一致で比べる。前方一致や後方一致の比較は別のドメインに抜けられる。
  • OWASP は CORS の利用そのものを最小にするよう求める[1]。同じオリジンに置ければ要らない。
設定推奨の値欠けたとき
Strict-Transport-Securitymax-age=63072000; includeSubDomains; preload初回や手入力で HTTP に落とされる。A04
Content-Security-Policy少なくとも frame-ancestors で枠に入れてよい先を絞る他サイトの枠に入れられ、クリックを盗まれる
X-Content-Type-Optionsnosniff端末が中身から型を推測し、スクリプトとして扱う
Referrer-Policystrict-origin-when-cross-originURLの中の値が他サイトへ渡る
Cookie の Secure付けるHTTP の通信で Cookie が流れる。CWE-614
Cookie の HttpOnlyセッションの Cookie に付けるスクリプトから読まれる。CWE-1004
X-Powered-By などの版の表示出さない既知の脆弱性を持つ版を特定される

値は HTTP ヘッダのチートシートの推奨[3]。Cookie の属性は RFC 6265 が定める[11]。

守り方

根本の直し方
  • 固める手順を自動化し、開発、検証、本番を同じ定義から組む。違うのは資格情報だけにする[1]。
  • 要らない機能、部品、文書、サンプルを入れない最小の構成にする[1]。
  • 本番を手で変えない。変えたら定義へ戻し、定義から作り直す。
  • XML のパーサーは文書型宣言を拒む設定を共通の生成関数に入れ、直接 newInstance を呼ばせない。
  • 静的な鍵を埋めず、基盤のID連携、短命の資格情報、役割による権限を使う[1]。
  • 部品と層の間、テナントの間を、コンテナやセキュリティグループで分ける[1]。
緩和の策
  • 全部の環境で、設定の有効性を自動で確かめる。OWASP が参照に挙げる CIS Benchmarks や NIST SP 800-123 を基準にできる[1][8]。
  • 詳しいエラーを止める中央の設定を、予備として置く。
  • 修正や更新の告知ごとに、設定を見直す工程をパッチの管理に入れる[1]。A03 とつなぐ。

IPA の「安全なウェブサイトの作り方」は、第2章でウェブサーバの運用に関する対策を、アプリの実装と分けて扱っている[12]。

診断で見る所

許可を得た範囲で行う。範囲の決め方は 診断の許可と範囲 にある。手順は WSTG の構成と配備の管理の試験と、エラー処理の試験が詳しい[2]。要件は ASVS 5.0 の V13 Configuration にある[13]。

観点見る所当たりの兆候
残り物サンプル、管理画面、試験用の経路、ディレクトリの一覧、.git、バックアップ認証なしで開く。既定のパスワードで入れる
エラー型の違う値、欠けた引数、長すぎる値を送るスタックトレース、SQL の文、部品の名前と版が返る
XMLXML、SVG、Office の文書、SAML を受け取る所。コードではパーサーの生成の箇所文書型宣言が拒まれない。パーサーの機能の設定が無い
ヘッダと Cookie応答のヘッダと Set-Cookie の属性上の表の値が無いか弱い
CORSOrigin を替えて送り、許可のヘッダを見る任意の Origin が資格情報付きで許される。null が許される
クラウド保管庫の方針、公開の設定、役割の権限、コードと CI の変数の中の鍵誰でも読める。静的な鍵が残っている
環境の差本番と定義を突き合わせる定義に無い設定が本番にある

関連するCWE

A02 に対応する16のうち、Webアプリでよく当たるもの[1]。

CWE名前この頁の型
CWE-16Configuration全体
CWE-489Active Debug Code型1
CWE-611Improper Restriction of XML External Entity Reference型2
CWE-776Improper Restriction of Recursive Entity References in DTDs型2
CWE-260Password in Configuration File型3
CWE-526Exposure of Sensitive Information Through Environmental Variables型3
CWE-547Use of Hard-coded, Security-relevant Constants型3
CWE-942Permissive Cross-domain Policy with Untrusted Domains型4
CWE-614Sensitive Cookie in HTTPS Session Without Secure Attribute型4
CWE-1004Sensitive Cookie Without HttpOnly Flag型4
CWE-315Cleartext Storage of Sensitive Information in a Cookie型4

参照

  1. A02:2025 Security Misconfiguration OWASP Top 10:2025
  2. Configuration and Deployment Management Testing OWASP Web Security Testing Guide
  3. HTTP Security Response Headers Cheat Sheet OWASP Cheat Sheet Series
  4. Error Handling Cheat Sheet OWASP Cheat Sheet Series
  5. XML External Entity Prevention Cheat Sheet OWASP Cheat Sheet Series
  6. Secrets Management Cheat Sheet OWASP Cheat Sheet Series
  7. Blocking public access to your Amazon S3 storage Amazon Web Services
  8. SP 800-123 Guide to General Server Security NIST
  9. OWASP Top 10:2021 日本語版 OWASP Foundation
  10. Fetch Standard, CORS protocol and credentials WHATWG
  11. RFC 6265 HTTP State Management Mechanism IETF
  12. 安全なウェブサイトの作り方 改訂第7版 IPA 情報処理推進機構
  13. V13 Configuration OWASP Application Security Verification Standard 5.0