A04 暗号化の不備

暗号が無い、弱い、使い方が誤っている、の3つ。破られるのは暗号の数学より、鍵、乱数、モード、パラメータ、検証の省略のほうだ。

OWASP Top 10:2025 A04 Cryptographic Failures。2021年版の2位から4位へ下がった。対応するCWEは32で、平均の発生率は3.80%。よく見つかるCWEの多くは、弱い疑似乱数にかかわる[1]。2026年11月時点の記載で書いています。

要点

  • 最初にデータを分類し、要らない機密は持たない。OWASP の言葉では、持っていないデータは盗まれない[1]。
  • 型は4つに分けて見る。平文の通信と格下げ、速いハッシュでのパスワードの保存、暗号用でない乱数、鍵とモードと署名の誤り。
  • 暗号は自作せず、広く信頼された実装を使い、暗号化には必ず認証つき暗号を使う[1]。
  • 2025年版はポスト量子暗号への備えを求め、危険の高い仕組みは遅くとも2030年末までに安全にするよう書く[1]。

成立の条件

機密のデータが通る場所と置かれる場所の、どこか1つで守りが外れれば成り立つ。通信だけ、保存だけを見ていると漏れる。

機密のデータが端末から通信、アプリ、保存、キャッシュとバックアップへと通る各所に、暗号の失敗が起きる点がある 端末 入力 通信 TLS アプリ 乱数、鍵、署名 保存 ハッシュ、暗号化 写し キャッシュ、控え 平文の経路 古い版への格下げ 証明書を見ない 予測できる乱数 埋め込んだ鍵 署名を確かめない 速いハッシュ ECB、同じ IV 認証の無い暗号 平文のまま 中継のキャッシュ 最初にすること データを分類し、機密は持たないか、すぐ捨てるか、トークンにするか、切り詰める
図1 機密のデータの通り道と、暗号の失敗が起きる点
  • 暗号が無い 平文の通信、平文の保存、HTTP を強制しない。FTP や STARTTLS のような暗号化されない手順を OWASP は使わないよう求める[1]。
  • 弱い MD5、SHA-1、CBC、PKCS #1 v1.5 のような避けるべき方式。弱い鍵、期限切れの鍵、格下げできる交渉[1]。
  • 使い方が誤っている パスワードをそのまま鍵にする、暗号用でない乱数、IV の使い回し、ECB、認証の無い暗号化、証明書の連鎖を確かめない、暗号のエラーの差を外へ漏らす[1]。

型1 平文の通信と格下げ

OWASP の例は、全ページで TLS を強制しないサイトの通信を安全でない無線の網で見張り、HTTPS から HTTP に落として、セッションの Cookie を盗むものだ。盗んだ Cookie で本人として振る舞い、送金の宛先のような中身も書き換えられる[1]。

HSTSが無いと最初のHTTPの要求を途中の者が平文のまま保ちCookieを読む。HSTSを受け取った端末は以後HTTPで送らない HSTS が無い 端末 http:// で開く 平文 途中の者 HTTP のまま中継 HTTPS サイト Cookie と入力を読み、書き換える HSTS を受け取った後 端末 http:// と打っても 端末の中で https:// に替えてから送る サイト
図2 HSTS の有無と、格下げの成否

直した例。HTTP は転送だけにし、HTTPS の応答で HSTS を送る

# HTTPS の応答
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Set-Cookie: sid=...; Secure; HttpOnly; SameSite=Lax; Path=/
Cache-Control: no-store    # 機密を返す応答だけ
  • HSTS は、受け取った端末が以後その名前へ HTTP で送らないようにする仕組み[6]。最初の1回は守れないため、preload の一覧への登録で埋める。
  • TLS は 1.3 を既定にし、互換のために 1.2 を残してよい。1.0 と 1.1 は RFC 8996 で廃止された[5][7]。OWASP は前方秘匿性のある暗号の組を求め、CBC の組を外すよう書く[1]。
  • TLS は届いた後のデータを守らない。機密を返す応答は Cache-Control: no-store で端末と中継のキャッシュに残さない[5]。OWASP は CDN、Webサーバー、アプリのキャッシュも対象に挙げる[1]。
  • 内部の通信で証明書の確かめを切る設定は、外からの格下げと同じ穴を内側に作る。CWE-296。

型2 速いハッシュでのパスワードの保存

ハッシュの表が漏れた後の、手元での総当たりの速さで決まる。OWASP は、塩の無いハッシュは事前計算の表で、塩があっても速いハッシュは GPU で破られ得ると書く[1]。

悪い例

const hash = crypto.createHash('sha256').update(password).digest('hex');  // 塩なし、速い

直した例。架空のライブラリの形で、Argon2id の最小の推奨値

const hash = await argon2id.hash(password, {
  memoryKiB: 19456,   // 19 MiB
  iterations: 2,
  parallelism: 1,
});  // 塩は利用者ごとに自動で作られ、結果に含まれる
const ok = await argon2id.verify(hash, input);
方式チートシートの最小の推奨使う場面
Argon2idメモリ 19 MiB、反復 2、並列 1第一の選択
scryptN=2^17、r=8、p=1Argon2id が使えないとき
bcrypt作業係数 10 以上。入力は 72 バイトまで既存の仕組み
PBKDF2HMAC-SHA-256 で 600,000 回以上FIPS-140 への準拠が要るとき
  • 値は 2026年11月時点のパスワード保存のチートシート[3]。Argon2 の引数の定義は RFC 9106[8]。推奨は上がっていくので、ハッシュに方式と引数を含めて保存し、ログインの成功時に新しい引数で作り直せるようにする。
  • bcrypt の 72 バイトの上限を越える入力は切り捨てられる。前処理で速いハッシュを挟む場合の落とし穴もチートシートにある[3]。
  • IPA の「安全なウェブサイトの作り方」も、第2章でウェブサイトにおけるパスワードの取扱いに関する対策を扱っている[12]。

型3 暗号用でない乱数

セッションのID、パスワードの再設定のトークン、招待のURL、APIの鍵を、暗号用でない疑似乱数で作る。出力の一部から内部の状態を推し量り、次の値を当てられる。2025年版の A04 でよく見つかるCWEの多くがここに当たる[1]。

悪い例

const token = Math.random().toString(36).slice(2);  // 暗号用でない。値の空間も狭い
const resetId = Date.now() + userId;               // 予測できる

直した例。OS の暗号用の乱数から 256 ビット

const token = crypto.randomBytes(32).toString('base64url');
  • 暗号用の乱数を使い、自分で種を与えない。OWASP は、近年のAPIは開発者が種を与えなくても安全で、低いエントロピーの種で上書きすると弱くなると書く[1]。
  • トークンはデータベースにハッシュで保存し、期限と使い捨てを付ける。漏れた表から直接使えないようにする。
  • 連番や時刻からIDを作る作りは、乱数でなくても予測できる。CWE-340。

型4 鍵とモードと署名の誤り

正しい方式でも、使い方で守りが消える。ECB は同じ平文のブロックを同じ暗号文にするので、模様が残る。IV を同じ鍵で使い回すと、GCM のような方式では機密性と完全性の両方が崩れる[9]。署名の方式をトークンの側に選ばせると、確かめを素通りされる。

ECBでは同じ平文のブロックが同じ暗号文になり、繰り返しが外から見える。毎回新しいIVを使う認証つき暗号では見分けられない 平文のブロック A B A A ECB の暗号文 7f3a c01e 7f3a 7f3a 同じ平文が同じ暗号文になり、繰り返しが見える 新しい IV の GCM の暗号文 91d4 2be8 e670 4c1b 繰り返しは見えず、改ざんは認証の値で分かる 暗号文の値は説明のための架空のもの
図3 ECB と、毎回新しい IV を使う認証つき暗号の違い

悪い例。埋め込んだ鍵と ECB

const key = Buffer.from('0123456789abcdef');               // ソースに鍵
const c = crypto.createCipheriv('aes-128-ecb', key, null);  // 模様が残り、改ざんも分からない

直した例。鍵は外から渡し、毎回新しい IV で認証つき暗号

const key = await kms.getDataKey('records');    // 架空の鍵の管理の呼び出し。32 バイト
const iv = crypto.randomBytes(12);              // 同じ鍵で二度使わない
const c = crypto.createCipheriv('aes-256-gcm', key, iv);
const body = Buffer.concat([c.update(plain), c.final()]);
const tag = c.getAuthTag();                     // iv と tag を暗号文と一緒に保存し、復号で確かめる

直した例。トークンの署名の方式をサーバーが決める

const claims = jwt.verify(token, publicKey, {
  algorithms: ['ES256'],                       // ヘッダの alg に従わない
  issuer: 'https://id.example.com',
  audience: 'https://api.example.com',
});
  • OWASP は、認証つき暗号を常に使い、IV は同じ鍵で二度使わず、鍵は暗号用の乱数で作り、パスワードを鍵にするなら鍵導出関数を通すよう求める[1]。GCM の仕様は NIST SP 800-38D[9]。
  • 最も機密な鍵はハードウェアかクラウドの HSM に置く[1]。鍵の作成、保管、回転、廃棄は鍵の管理のチートシートにある[10]。
  • JWT の扱いは RFC 8725 が定める。方式の検証、適した方式、発行者と宛先の確かめを求める[11]。役割をトークンから読むなら、ここが A01 の守りの前提になる。
  • 復号の失敗の理由を外へ返し分けると、パディングオラクルの材料になる。OWASP は暗号のエラーと副チャネルの情報の漏れを挙げる[1]。

守り方

根本の直し方
  • データを分類し、法令、規制、業務の要件で機密を決め、分類に応じた守りを掛ける[1]。
  • 要らない機密は持たない。すぐ捨てるか、PCI DSS に沿ったトークン化か切り詰めにする[1]。
  • 機密は保存時に暗号化し、通信は TLS 1.2 以上だけにして HSTS で強制する[1]。
  • パスワードは塩と作業係数のある適応型のハッシュで保存する[1][3]。
  • 暗号の部品は自作せず、信頼された実装の認証つき暗号を使い、乱数は暗号用のものだけを使う[1][4]。
  • 鍵は HSM か鍵の管理の仕組みに置き、ソースと設定に置かない。回転できる作りにする。
緩和の策
  • 設定は専門家か専用の道具で確かめる[1]。TLS の設定は公開の道具で定期に走査する。
  • 機密を返す応答のキャッシュを止める。
  • ポスト量子暗号への移行の計画を持つ。NIST は 2024年8月に最初の3つの標準を確定した[13]。

診断で見る所

許可を得た範囲で行う。範囲の決め方は 診断の許可と範囲 にある。手順は WSTG の弱い暗号の試験が詳しい[2]。

観点見る所当たりの兆候
通信TLS の版と暗号の組、証明書の連鎖、HTTP の受け口、HSTS1.0 か 1.1 が通る。CBC の組。HTTP のまま応答する。HSTS が無い
Cookie と キャッシュSet-Cookie の属性、機密の応答の Cache-ControlSecure が無い。機密がキャッシュされる
パスワード保存されたハッシュの形、ログインの処理のコードMD5、SHA-1、SHA-256 の単発。塩が無いか共通
乱数トークンとIDを作るコードMath.random、時刻、連番。固定の種
暗号化暗号の呼び出しのモード、IV、鍵の出どころECB、固定の IV、ソースや設定の鍵、認証の無い CBC
署名JWT と署名つきデータの検証のコード方式をヘッダに従う。検証の無い読み取り。宛先を見ない
証明書の確かめ外への HTTP の呼び出しの設定確かめを切る指定が残っている

関連するCWE

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

CWE名前この頁の型
CWE-319Cleartext Transmission of Sensitive Information型1
CWE-523Unprotected Transport of Credentials型1
CWE-757Selection of Less-Secure Algorithm During Negotiation型1
CWE-296Improper Following of a Certificate's Chain of Trust型1
CWE-916Use of Password Hash With Insufficient Computational Effort型2
CWE-759Use of a One-Way Hash without a Salt型2
CWE-330Use of Insufficiently Random Values型3
CWE-338Use of Cryptographically Weak Pseudo-Random Number Generator型3
CWE-340Generation of Predictable Numbers or Identifiers型3
CWE-321Use of Hard-coded Cryptographic Key型4
CWE-327Use of a Broken or Risky Cryptographic Algorithm型4
CWE-323Reusing a Nonce, Key Pair in Encryption型4
CWE-347Improper Verification of Cryptographic Signature型4

参照

  1. A04:2025 Cryptographic Failures OWASP Top 10:2025
  2. Testing for Weak Cryptography OWASP Web Security Testing Guide
  3. Password Storage Cheat Sheet OWASP Cheat Sheet Series
  4. Cryptographic Storage Cheat Sheet OWASP Cheat Sheet Series
  5. Transport Layer Security Cheat Sheet OWASP Cheat Sheet Series
  6. RFC 6797 HTTP Strict Transport Security IETF
  7. RFC 8996 Deprecating TLS 1.0 and TLS 1.1 IETF。2021年3月
  8. RFC 9106 Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications IRTF
  9. SP 800-38D Galois/Counter Mode and GMAC NIST
  10. Key Management Cheat Sheet OWASP Cheat Sheet Series
  11. RFC 8725 JSON Web Token Best Current Practices IETF
  12. 安全なウェブサイトの作り方 改訂第7版 IPA 情報処理推進機構
  13. NIST Releases First 3 Finalized Post-Quantum Encryption Standards NIST。2024年8月