Equifax 2017年 適用されなかった Apache Struts の修正

修正は公表の当日に出ていた。社内の通知は当てる人に届かず、走査は古い Struts を見つけず、通信の検査装置は証明書が切れたまま素通しだった。1つの穴から、平文の資格情報と分けていないDBを伝って48のDBへ届き、76日のあいだ誰も気付かなかった。

入口は消費者の異議申立てのポータル ACIS で動く Apache Struts 2 の CVE-2017-5638。NVD の CVSS 3.1 の基本値は9.8、CWE-755 例外の状態の不適切な処理[4]。侵入は2017年5月13日から7月30日[6]。公表は2017年9月7日[5]。Equifax は修正を当ててからポータルを戻した[6]。調査会社の11の改善の勧告は、2018年8月に全て実施済みと Equifax と調査会社が下院の委員会に説明した[2]。2019年7月に FTC、CFPB、州と和解し、情報セキュリティの計画と2年ごとの外部の評価を課された[7]。2026年11月時点の公開資料で書いています。

要点

  • 弱点の公表と修正は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の分離、問い合わせの上限を重ねる。

何が起きたか

3月7日の公表から、3月15日の走査の見落とし、5月13日からの侵入、7月29日の発見、9月7日の公表までの4つの段 1 公表と通知 3月7日 修正が出る 3月8日 US-CERT 3月9日 社内へ回す 2 確かめ漏れ 3月15日 外向けを走査 958のIPに出ない ACIS は古いまま 3 侵入と持ち出し 5月13日から76日 51のDBに届く 約9,000回の問い合わせ 4 気付く 7月29日 証明書を更新 怪しい通信が見える 7月30日 止める 1から3まで約2か月。修正が当たらないまま開いていたのは3月8日から7月30日 公表は9月7日。止めてから39日後
図1 修正の公表から、侵入、発見、公表まで
日付出来事
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 の Struts の弱点からWebシェルを置き、共有のファイルの平文の資格情報で48の別のDBへ広がり、問い合わせの結果をWebから外へ出した 攻撃する側 約35のIPから 暗号化の検査装置 証明書切れで素通し 後ろの侵入検知に届かない Webサーバー 2台 前に防火壁 ACIS の入口 ACIS の環境。1970年代に作った仕組みの上で動く アプリのサーバー 2台 古い Struts から実行 Webシェル 約30 共有のファイル 平文の資格情報 資格情報で入る ACIS が使うDB 3つ ACIS と関係の無いDB 48 分けていないので届く。保管時に暗号化していない 約9,000回の問い合わせ。265回が個人情報を返す 結果を圧縮し、Webから取れる場所に置いて外へ
図2 入口から持ち出しまでの道筋
段何があったか
入口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 例外的な状況への不適切な対応 の詳しすぎるエラーと同じく、決まった文言を返し、細部はログへ回す。

なぜ修正が当たらなかったか

通知、当てる人、走査、当てた後の確かめの4つの段が、それぞれ別の理由で途切れた 1 通知を回す 約430人へのメール 2 当てる人が受ける 台帳を見て自分のことと知る 3 走査で拾う 人が漏らしても機械で 4 当てた後に確かめる 48時間以内に再走査 宛先の一覧が古い 当てる責任の人に届かなかった 役は方針にあるが、人が決まっていない 部品の台帳も無く、ACIS に Struts があると知られていない 2つの道具とも見つけない 部品の走査は上の階層だけを見た 自己申告で済ませる 当たっていない物を上げる仕組みが無い
図3 修正を当てる段ごとの途切れ
段この件で
通知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]。
1人がメールを転送しなかったせい、ではない

当時の CEO は、議会で人の誤りと、修正の必要が伝わらなかったことを理由に挙げ、Equifax は通知を転送しなかったとして幹部の1人を解雇した[2]。下院の委員会の報告は、役に人が決まっていない、台帳が無い、確かめが自己申告、という仕組みの欠けを主な原因とした[2]。1通のメールに頼る作りなら、誰が漏らしても同じことが起きる。

なぜ76日気付かなかったか

検査装置の証明書は2016年1月31日に切れ、2017年7月29日まで替えられず、侵入の76日はすべてその中に入る ACIS の通信の検査 検査せずに通す 約18か月 2016-01-31 証明書が切れる 2017-07-29 替えて検査が戻る 侵入 5月13日から7月30日の76日 期間の長さは下院の委員会の資料による。GAO は約10か月とする 横の長さは月の数に合わせた
図4 検査が止まっていた期間と、侵入の期間
  • 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か月になる。

CVSS の値

下院の委員会の報告は、当時の NVD の CVSS 3 の基本値10.0を載せている[2]。2026年11月時点の NVD の CVSS 3.1 の値は9.8、CVSS 2 の値は10.0[4]。

どこで止められたか

部品と持ち主、修正、入口の検査、サーバーの中、資格情報、DBの分離、データの取り出しの7つの段に止める所を置く 部品と持ち主 修正を当てる 入口の検査 サーバーの中 資格情報 DBの分離 データの取り出し 1 台帳と名指しの持ち主 どのサーバーに何の版があり、誰が当てるか 2 当てて、実物で確かめる 動いている物の版を見る。遅れは上へ上げる 3 証明書の期限を見張る 検査できない時は通さないか、警告を上げる 4 ファイルの改ざんを検知する Webの置き場に増えたファイルで気付く 5 平文で置かない 秘密の管理の仕組みに置き、権限を絞る 6 要るDBにだけ届く 3つのDBのためのアプリが51に届かない 7 回数と量の上限と警告 9,000回はふだんの業務の量を大きく超える
図5 段ごとの止める所
止める所この件で限り
台帳と名指しの持ち主台帳が無く、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に台帳を作らせるなら、宣言のファイルを読ませるだけでなく、展開した物の全部の階層を数えさせ、宣言とのずれを出させる。

参照

  1. 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月
  2. The Equifax Data Breach U.S. House Committee on Oversight and Government Reform、多数派の職員の報告、2018年12月
  3. S2-045 Apache Struts 2 Security Bulletin
  4. CVE-2017-5638 NIST NVD
  5. Equifax Announces Cybersecurity Incident Involving Consumer Information Equifax、2017年9月7日
  6. Equifax Releases Details on Cybersecurity Incident, Announces Personnel Changes Equifax、2017年9月15日
  7. 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日