Equifax 2017年 適用されなかった Apache Struts の修正
修正は公表の当日に出ていた。社内の通知は当てる人に届かず、走査は古い Struts を見つけず、通信の検査装置は証明書が切れたまま素通しだった。1つの穴から、平文の資格情報と分けていないDBを伝って48のDBへ届き、76日のあいだ誰も気付かなかった。
要点
- 弱点の公表と修正は2017年3月7日。翌日に US-CERT から通知が届き、社内では約430人に48時間以内に当てるよう回した。ACIS の Struts は7月末まで古いままだった[2]。
- 通知の宛先は古く、当てる役の人は決まっていなかった。走査は2つの道具とも古い Struts を見つけなかった。修正を当てたかを確かめる仕組みは自己申告だった[1][2]。
- 入った後は、共有のファイルにあった平文の資格情報で、ACIS が使う3つのDBの外の48のDBへ広がり、約9,000回の問い合わせを流した[1][2]。
- 暗号化した通信を検査する装置の証明書が切れていて、検査せずに通していた。証明書を替えた7月29日に、すぐ怪しい通信が見えた[1][2]。
- 根本の守りは、部品の台帳を持ち、当てる責任を名指しで決め、当てた後に実物で確かめること。証明書の期限の管理、資格情報の置き場所、DBの分離、問い合わせの上限を重ねる。
何が起きたか
| 日付 | 出来事 |
|---|---|
| 2017年2月14日 | Apache Software Foundation が、研究者から Struts の弱点の最初の届け出を受ける[2] |
| 2017年3月7日 | Struts の開発元が S2-045 として公表し、同じ日に修正を出す。直した版は 2.3.32 と 2.5.10.1[2][3] |
| 2017年3月8日 | US-CERT が Equifax に、この弱点に修正を当てるよう通知する[2] |
| 2017年3月9日 | Equifax の脆弱性管理の担当が、約430人と複数の配信の宛先へ、48時間以内に当てるよう回す[2] |
| 2017年3月10日 | Equifax の網につながるサーバーで、この弱点を突いた最初の跡。調査会社は、5月13日からの活動と結ぶ直接の証拠は無いとした[2] |
| 2017年3月14日から15日 | 侵入検知の規則を入れる。外向けの958のIPを走査の道具で2回調べたが、古い Struts は見つからなかった[2] |
| 2017年5月13日 | ACIS の Struts の弱点から入り、Webシェルを置く。ここから7月30日まで続く[2][6] |
| 2017年7月29日 | ACIS の通信を検査する装置の切れた証明書を替え、怪しい通信を見つけて遮る[1][2][6] |
| 2017年7月30日 | さらに怪しい動きを見て、ACIS を止める[1][6] |
| 2017年8月2日 | 外部の調査会社 Mandiant に調査を頼み、FBI に知らせる[1][6] |
| 2017年9月7日 | 公表。米国の約1億4,300万人。氏名、社会保障番号、生年月日、住所、一部の運転免許証の番号。ほかにカードの番号約20万9,000人分と、異議申立ての書類約18万2,000人分[5] |
| 2017年9月15日 | 入口が CVE-2017-5638 だったこと、5月13日から7月30日の期間、修正を当ててから戻したことを公表する[6] |
| 2017年10月2日 | 取り違えた問い合わせが見つかり、約250万人を足して1億4,550万人に改める[1] |
| 2018年3月1日 | 氏名と運転免許証の一部の情報を取られた約240万人を新たに公表する。前の数との重なりは、2018年8月時点で確定していない[1] |
| 2019年7月22日 | FTC、CFPB、48州とコロンビア特別区とプエルトリコと和解。少なくとも5億7,500万ドル、最大7億ドル[7] |
| 資料 | 影響を受けた人の数 |
|---|---|
| GAO | 米国で少なくとも1億4,550万人、米国の外で約100万人。ほかに2018年3月の約240万人で、重なりは未確定[1] |
| 下院の委員会 | 1億4,800万人[2] |
| FTC | 約1億4,700万人[7] |
通った道筋
| 段 | 何があったか |
|---|---|
| 入口 | ACIS は、消費者が信用情報の誤りに異議を申し立て、書類を上げるためのWebの仕組みで、1970年代に作られた[1][2]。Webサーバー2台とアプリのサーバー2台からなり、防火壁はWebサーバーの前にあった。弱点はアプリのサーバーの Struts にあり、防火壁を越えて命令が通った[2]。 |
| 足場 | アプリのサーバーにWebシェルを置き、約30の異なるWebシェルを使った。ACIS にはファイルの改ざんを検知する仕組みが入っていなかった[2]。 |
| 権限を広げる | マウントされた共有のファイルに、アプリの資格情報が平文で置かれていた。この置き方は社内の方針に反していた[2]。GAO は、他のDBに入れる利用者名とパスワードが暗号化されずに置かれていたと書く[1]。 |
| 横へ広がる | ACIS の仕事に要るDBは3つだったが、他のDBから分けていなかった。資格情報で48の関係の無いDBへ入った[1][2]。 |
| 探して取る | 表の定義を問い合わせて中身の種類を調べ、個人情報のある表を見つけると中身を取った。約9,000回のうち265回が個人情報を返し、保管時の暗号化は無かった[2]。問い合わせの回数に上限が無く、ふだんの業務よりずっと多い回数を流せた[1]。 |
| 持ち出す | 結果をファイルにして圧縮し、Webから取れる場所に置いて外から取った。一部はWebシェルで出した[2]。少しずつ、ふだんの暗号化したWebの通信に紛れて出した[1]。 |
入口の弱点の型
S2-045 は、Jakarta の Multipart の解析器でファイルを上げる処理の弱点で、影響は 2.3.5 から 2.3.31 と、2.5 から 2.5.10[3]。開発元の説明では、Content-Type の値が正しくないと例外が出て、それが利用者へのエラーの文言の表示に使われ、その経路でコードを実行できる[3]。NVD は、例外の処理とエラーの文言の作り方の誤りとし、ヘッダの細工で任意の命令を実行できると書く[4]。ログインは要らず、ネットワークから届く[4]。
下は、同じ型を示す架空の最小の例で、Struts のコードではない。外から来た値が、例外の文言を通って、式を評価する部品に届く。
架空の文書受付API 例外の文言に外の値を混ぜて評価する
// 悪い例 文言の部品は ${...} を式として評価する
try {
parser.parse(request);
} catch (InvalidHeaderException e) {
// e.getMessage には、受け取った Content-Type の値がそのまま入る
String msg = messages.render("upload.error", e.getMessage());
return error(400, msg);
}
// 直した例 外の値は文言の材料にせず、決まった文言を返す
} catch (InvalidHeaderException e) {
log.warn("invalid_content_type", Map.of("path", request.path()));
return error(400, messages.fixed("upload.error"));
}
- 外から来た値を、評価や解釈をする部品へ渡さない。例外の文言も外から来た値を含みうる、と読む。
- エラーの時に詳しい文言を組み立てる処理は、ふだんの道より試されていない。A10 例外的な状況への不適切な対応 の詳しすぎるエラーと同じく、決まった文言を返し、細部はログへ回す。
なぜ修正が当たらなかったか
| 段 | この件で |
|---|---|
| 通知 | US-CERT の通知は回したが、宛先の一覧が古く、当てる責任の人に届かなかった[1]。回す手段はこのメールと3月16日の月例の会議だけで、届いたかを確かめる二重の仕組みは無かった[2]。 |
| 当てる人 | 2016年版の修正の管理の方針は、業務の持ち主、システムの持ち主、アプリの持ち主の役を定めていたが、誰がその役かは決めていなかった。持ち主には部品と版の台帳を持つ義務があった[2]。2017年7月時点で、IT資産と動いているソフトの網羅した台帳は無かった。2017年1月に別の Struts の弱点に対応した時、ACIS に Struts があると分かっていたが、記録されていなかった[2]。 |
| 走査 | 部品の走査は、Struts の置かれた下の階層でなく、上の階層に向けて流したため外れた[2]。外向けの958のIPを走査の道具で調べたが見つからなかった。下院の委員会は、古い環境の中が見えていなかったためかもしれないと書く[2]。 |
| 確かめ | 方針は、重大な修正を当てた後48時間以内に内と外を走査し直すことを求めていた[2]。2015年の社内の監査は、修正が自己申告で確かめられ、遅れた修正を上げる仕組みが無いことを指摘していたが、直っていなかった[2]。 |
当時の CEO は、議会で人の誤りと、修正の必要が伝わらなかったことを理由に挙げ、Equifax は通知を転送しなかったとして幹部の1人を解雇した[2]。下院の委員会の報告は、役に人が決まっていない、台帳が無い、確かめが自己申告、という仕組みの欠けを主な原因とした[2]。1通のメールに頼る作りなら、誰が漏らしても同じことが起きる。
なぜ76日気付かなかったか
- ACIS への暗号化した通信は、検査装置で復号してから侵入検知と侵入防止の仕組みへ渡していた。証明書が切れても、装置の既定の設定は通信をそのまま ACIS へ通した。侵入検知と侵入防止は暗号化した通信を読めないので、何も見ていなかった[2]。
- 7月29日の夜に67の証明書を替えると、ほぼすぐ怪しい要求が見え、応答の多くが10MBを超えていた[2]。検知の仕組みそのものは働く状態にあり、止まっていたのは証明書1枚だった。
- 侵入の時点で少なくとも324の証明書が切れ、うち79は事業に重要なドメインを見る装置のものだった。2017年1月20日の社内の記録に、検査装置の証明書が無く、Webの攻撃が見えにくいとあった[2]。誰が証明書を替えるかが決まっていなかった[2]。
GAO は、侵入の約10か月前に切れていたと書く[1]。下院の委員会は、委員会に出された証明書の一覧で切れた日を2016年1月31日とし、発見まで19か月と書いて、GAO の数と食い違うことを注に記した[2]。図は、日付の示された下院の委員会の資料による。2016年1月31日から2017年7月29日は暦の上で約18か月になる。
下院の委員会の報告は、当時の NVD の CVSS 3 の基本値10.0を載せている[2]。2026年11月時点の NVD の CVSS 3.1 の値は9.8、CVSS 2 の値は10.0[4]。
どこで止められたか
| 止める所 | この件で | 限り |
|---|---|---|
| 台帳と名指しの持ち主 | 台帳が無く、ACIS に Struts があることが記録されていなかった。役の人が決まっていなかった[2] | 台帳は作った時点から古くなる。手で書く台帳でなく、動いている物から集める |
| 当てて、実物で確かめる | 方針の再走査は働かず、走査も外れた[2] | 走査の道具は、見に行った所しか見ない。届かない階層と古い環境を別に数える |
| 証明書の期限を見張る | 切れた証明書で検査が止まり、装置は既定で通信を通した[2] | 通さない設定にすると、証明書切れで業務が止まる。期限の前に替える仕組みと対で置く |
| ファイルの改ざんを検知する | 調査会社は、改ざんの検知があればWebシェルの作成で気付けたとした。ACIS には入っていなかった[2] | メモリの中だけで動く手口は拾えない |
| 平文で置かない | 共有のファイルの平文の資格情報で、48のDBに入った[1][2] | アプリのサーバーを取られれば、アプリが使える資格情報は使われる。権限を絞ることと対にする |
| 要るDBにだけ届く | 要るDBは3つだが、分けていなかった[1][2] | ACIS が使う3つのDBの中身は守れない |
| 回数と量の上限と警告 | 上限が無く、約9,000回を流せた[1]。応答の多くが10MBを超えていた[2] | 少しずつ取られると閾値に掛からない。ふだんの量を知っていて初めて決められる |
Equifax が後に挙げた原因も、見つける、検知する、分ける、データの統制の4つと、問い合わせの回数の制限の欠けだった[1]。調査会社の11の勧告には、脆弱性の走査と修正の管理の強化、持つ機微なデータを減らすこと、分離、Webアプリの防火壁、改ざんの検知、ログの強化、特権アカウントの管理、暗号化した通信の検査の強化などが並ぶ[2]。
守り方
- 動いている物から部品の台帳を作る。どのサーバーのどの階層に何の部品の何の版があるかを、ビルドの成果物と実際のサーバーの両方から集める。考え方は A03 ソフトウェアサプライチェーンの不備 の型1と、守り方の SBOM にある。
- 部品ごとに、当てる人を名指しで決める。通知はその人と、その人の上の両方に、台帳から自動で届ける。メールの配信の宛先の一覧に頼らない。
- 当てた後に、動いている物の版を確かめる。当たっていない物は期限で自動に上へ上げる。Equifax の2015年の監査が指摘した自己申告をやめる[2]。
- 直せない古い環境は、直せる環境へ移す計画を持ち、移すまでは外から届く口を絞る。2018年の州との同意の命令は、台帳、修正の特定の手順、古い仕組みを止める計画を求めた[2]。
動いている物の版を数える 架空の受付の仕組み portal.example.com
# 悪い例 上の階層の宣言だけを見る
grep -r "framework" /srv/portal/pom.xml
# 直した例 展開された物の全部の階層から、実際の jar を探す
find /srv/portal -type f -name '*.jar' -path '*framework-core*'
# 出力
/srv/portal/webapps/intake/WEB-INF/lib/framework-core-2.3.20.jar
/srv/portal/legacy/upload/WEB-INF/lib/framework-core-2.3.20.jar # 宣言に無い2つ目
- 宣言と動いている物はずれる。古い環境では、宣言のファイルそのものが無いこともある。台帳は、サーバーに入って見た結果で作る。
- 見つけた版は、その部品の公表の文書の影響の範囲と比べる。S2-045 なら 2.3.5 から 2.3.31 と、2.5 から 2.5.10[3]。
- 検査の装置と、TLS を終える所の証明書を一覧にし、期限の30日前に警告を上げる。誰が替えるかを決める。検査できない時に通すか止めるかは、設定で意図して選ぶ。考え方は A10 の失敗した時に開くと同じ。
- Webの置き場とアプリの置き場で、ファイルの改ざんの検知を動かす。Webシェルは、新しいファイルとして現れる。
- 資格情報は秘密の管理の仕組みに置き、共有のファイルに平文で置かない。アプリの資格情報には、そのアプリが使う表だけの権限を付ける。置き場所と権限の絞り方は 秘密の鍵の扱い にある。
- 入口のアプリから届くDBを、網と権限の両方で、業務に要るものだけにする。
- DBへの問い合わせの回数、返した行の数、外への応答の大きさに、ふだんの量から決めた閾値を置いて警告を上げる。記録と警告と保全の作りは A09 セキュリティログとアラートの不備 にある。
- 持たなくてよい機微なデータは持たない。保管時に暗号化し、鍵はDBと別の権限で守る。
AIに修正を頼むとき
- AIは、依存の宣言の版を上げる差分をすぐ作る。宣言の版が上がっても、動いている物の版が上がったとは限らない。この件の走査も、見に行った所だけを見て、無いと報告した[2]。AIの「直しました」は、動いている物の版を見てから受け取る。確かめ方の3段は AIの出力を確かめる にある。
- AIに台帳を作らせるなら、宣言のファイルを読ませるだけでなく、展開した物の全部の階層を数えさせ、宣言とのずれを出させる。
参照
- GAO-18-559 Data Protection: Actions Taken by Equifax and Federal Agencies in Response to the 2017 Breach U.S. Government Accountability Office、2018年8月
- The Equifax Data Breach U.S. House Committee on Oversight and Government Reform、多数派の職員の報告、2018年12月
- S2-045 Apache Struts 2 Security Bulletin
- CVE-2017-5638 NIST NVD
- Equifax Announces Cybersecurity Incident Involving Consumer Information Equifax、2017年9月7日
- Equifax Releases Details on Cybersecurity Incident, Announces Personnel Changes Equifax、2017年9月15日
- Equifax to Pay $575 Million as Part of Settlement with FTC, CFPB, and States Related to 2017 Data Breach Federal Trade Commission、2019年7月22日