GitLabのパスワード再設定バグで5,300台超のサーバーが危険に
(scmagazine.com)- GitLabのCVE-2023-7028脆弱性が、パッチ公開から約2週間後も世界中の5,379台のサーバーに残っており、リモートで開発者アカウントの乗っ取りにつながる可能性がある
- 問題はログインシステムのパスワード再設定フローにあり、攻撃者は被害者の操作なしに、自分の未検証メールアドレスで再設定リンクを受け取れるようにできる
- GitLabは2024年1月11日にCVSS 10の脆弱性を公開し、16.5.6、16.6.4、16.7.2および16.1.6〜16.4.5のバックポート版にセキュリティアップデートを提供した
- Shadowserver Foundationは1月23日に脆弱なインスタンス5,379件を検出し、米国964件、ドイツ730件が最多で、1月24日には4,652件に減少した
- Self-managed GitLab Community EditionおよびEnterprise Editionの運用者は、ログで複数メール配列形式の再設定リクエストを確認し、2FAを有効化してアカウント乗っ取りリスクを下げる必要がある
CVE-2023-7028の危険性
- CVE-2023-7028はGitLabのログインシステムの脆弱性で、未パッチのGitLabサーバーではリモートでのアカウント乗っ取りにつながる可能性がある
- GitLabは2024年1月11日にこの脆弱性を初めて公開し、パッチを提供した
- 脆弱性のCVSSスコアは10で、最も深刻なレベルに当たる
- 攻撃者は細工したHTTPリクエストにより、被害者の操作なしでパスワード再設定メールを自分の未検証メールアドレスに送らせることができる
- GitLab Community Edition 16.6.1でテストしたある研究者は、AttackerKBでCVE-2023-7028を「非常に効果的で悪用しやすい」と評価した
影響を受けるバージョンとパッチ
- GitLabは次のバージョンにセキュリティアップデートを提供した
- 16.5.6
- 16.6.4
- 16.7.2
- パッチは次のバージョンにもバックポートされた
- 16.1.6
- 16.2.9
- 16.3.7
- 16.4.5
Shadowserverの検出結果
- Shadowserver Foundationは、パッチ公開から約2週間後の1月23日に、世界中で脆弱なGitLabインスタンス5,379件を検出した
- 国別では、米国とドイツに脆弱なインスタンスが最も多かった
- 米国: 964件
- ドイツ: 730件
- 1月24日のShadowserverダッシュボードでは、脆弱なインスタンス数は4,652件に減少した
- Shadowserverは、この減少自体は前向きだが、実際の傾向なのかスキャン上の一時的な変動なのかを判断するには、さらに時間が必要だと述べた
侵害指標の確認方法
- Self-managed GitLab Community EditionおよびGitLab Enterprise Editionの顧客は、ログでCVE-2023-7028の悪用痕跡を確認する必要がある
- 確認すべきログと条件は次のとおり
gitlab-rails/production_json.log:/users/passwordパスへのHTTPリクエストのうち、params.value.emailが複数のメールアドレスを含むJSON配列である場合gitlabs-rails/audit_json.log:meta.caller.idがPasswordsController#createで、target_Detailsが複数のメールアドレスを含むJSON配列である場合
GitLab.com、GitLab Dedicated、2FAへの影響
- GitLabは、GitLab.comまたはGitLab Dedicatedインスタンスでこのバグが悪用された事例は検出していないと明らかにした
- 顧客には2FAの有効化が推奨されている
- 2FAはCVE-2023-7028によるアカウント乗っ取りを防ぐが、未パッチのインスタンスでは攻撃者がパスワードを再設定し、ユーザーをアカウントから締め出す可能性がある
1件のコメント
Hacker Newsの意見
アカウントベースのWebアプリでメールアドレスをアカウントに関連付ける機能は本当に恐ろしいと思う。
このバグの経緯は知らないが、侵入テスターが真っ先に触る領域であり、2000年代初頭の標準的な Unix MTA 実装でパスワード再設定メールを複数アドレスに送らせる脆弱性にまでさかのぼる古いタイプの問題だ。
GitLabでは多機能なWebフレームワークがこの攻撃面を復活させたように見えるし、関心を持った一般のHN読者ならパスワード再設定機能、特にメールアドレス関連付けロジックをぜひ確認した方がいい。
GitLabのセキュリティチームはかなり優秀だと認識しているのにこういうバグが出たという点からも、この系統のバグを避けるのがどれほど難しいかが分かる。
静的型付け言語を使っていれば、わざとこう作らない限り起きにくいし、コードレビューでもあまりに目立つので、同僚がバックドアを仕込もうとしているのではと疑うレベルだったと思う。
補助メールアドレスの関連付け機能は最近追加されたもので、元からあった機能でもないのだから、アカウントセキュリティに関わる新機能を十分に悪用テストせず近道を選んだように見える。
しかも、統合機能が別ユーザー権限でコマンドを実行できてしまうCVSS 9.6のCVEもあったはずだ。
外から見ると、機能リリースの速度が安全にテストできる速度を上回っているように見えるし、収益化が難しいからかもしれない。
ビジネスの観点では理解できる面もあるが、セルフホスト型Gitソリューションの中核が実質的にアカウント管理なのだとすれば、こうしたセキュリティ問題は事業そのものを崩壊させかねない。
メールでなければ何に関連付けるべきだというのか。20年以上、大規模なユーザーベースのサイトを運営してきたが、最初はユーザー名を使っていて、それは惨事だった。
みんなが互いのユーザー名を知っているので、パスワード総当たりや再設定の試行が容易だった。
問題はメールを使うこと自体ではなく、ログインとパスワード復旧のロジックを過度に複雑化し、抽象化を乱用し、過剰設計し、セキュリティ上センシティブな領域で十分な確認もせずコードを押し込むことにある。
GitLabのセキュリティ履歴も見ておくべきだ。年に何度も致命的なエクスプロイトが出てGitLabディストリビューションを緊急アップグレードしなければならず、セキュリティ面では私が使った製品の中でGitLabが最悪だった。
まだ自分に起きたことはないが、今回の事例のように残念ながら十分あり得る話だ。
Railsコードベースでこのエクスプロイトにつながった箇所を見たいなら、修正コミットはこれ。
https://gitlab.com/gitlab-org/gitlab/-/commit/c571840ba2f0e9...
修正はこっちのようだ: https://gitlab.com/gitlab-org/gitlab/-/commit/abe79e4ec43798...
recoverable.send_reset_password_instructions(to: email) if recoverable&.persisted?からrecoverable.send_reset_password_instructions if recoverable&.persisted?に変わっている。# Concern that overrides the Devise methods/# to send reset password instructions to any verified user email/module RecoverableByAnyEmailって、これが機能だったのか?しかも修正版でもなお
RecoverableByAnyEmailという名前を使っている。人は自分が変更するコードの周辺を読まないのか?うちもこの攻撃を受けたし、露出をさらに広げる2つ目の「機能」と組み合わせて使われるのも見た。
基本的にこの攻撃では再設定対象ユーザーのメールを知っている必要があるが、GitLabにはユーザーIDにひも付いた隠しメールアドレスがある。このIDは1から増えていく数字だ。
ID 1や2は管理者である可能性が高いので格好の標的になり、メールは
1-user@mail.noreply..のような形式になる。本当にひどく、しかも自動化されているように見えた。ここでは2FAが救いになった。
メールによるパスワード再設定は、正しく実装してもセキュリティ上の悪夢だ。
さらに悪いことに、ほとんどのサービスでは無効化もできず、回避するにはたいていEnterprise SSOしかない。
一部のサービスではSMSトークン用の電話番号を設定できるが、メールとSMSトークンの両方を要求する方式は見たことがない。
ログインフォームにパスワードの配列を入れるとアカウントを総当たりできたバグを思い出す。
よりによってスパム機器の粗末なWebインターフェースで、意図されたものだったのか、PHP初心者が書いたコードだったのかは分からない。
当時としては珍しかった特殊文字をパスワードに含むユーザーがそれを見つけた。
.where(...)パラメータに配列を渡すと、配列の値同士をOR条件として扱う。だからコードが
User.where(name: name, password: password)のような形だったなら、こういうことが起きても十分あり得る。GitLabのような内部サービスは、信頼されたユーザーだけがアクセスできるVPNの背後に置くべきだという良いリマインダーだ
まさにそのためにVPNがある
私は大手国営通信会社で働いていて、ネットワーク担当者は本当に優秀だ。サーバー担当者が一線を越えないように抑えてくれる
特定の外部プロジェクトやコンサルタント向けにGitLabをある程度公開してはいたが、それでもインターネットから自由にアクセスできるわけではない
ユーザーもADで管理しているので、パスワード再設定のためのSMTP接続自体がない
ただし2FAの強制はもっと強化すべきだ。今は各プロジェクトが独自に2FAルールを決められる状態になっている
正直、どんな内部サーバーも公開インターネットには置かないだろう
VPN経由でのみアクセスさせて、第2の防衛線を設けるほうがよい
そのリクエストだけを正確に許可リストに入れることもできるが、かなり面倒になりうる
高セキュリティ環境ではより防御的な戦術を取ることに同意するが、ソフトウェアは公開ウェブ上でも耐えられるように設計されるべきだと思う
GitLabのアップデート自動化は本当に簡単だ
一つの方法として、Docker+ComposeでGitLabを使えば非常に安定していて、Watchtowerのようなツールで毎日更新させることもできる
私は7年以上このやり方で運用しているGitLabサーバーを2台持っているが、何の問題もなかった
周りを見ると古いGitLabが多すぎて、管理者はいったい何をしているのか分からない
Ruby/Railsが、安全でなければならないソフトウェアに適した選択肢であるかのように装うのは、もうやめてほしい
GitLabがすでにそうなってしまった以上、それを受け入れなければならないのは理解するが、今後は賢さや隠れた制御フローを優先する言語やフレームワークが、もっと退屈な代替案より優れているかのように振る舞うのはやめるべきだ
私が過剰にいら立っているように聞こえるなら、それは実運用中のRubyコードベースを扱わなければならないからだ
誰かが17層の抽象化でコードがものすごく拡張可能になると思い込んだせいで、似たような問題が悪用されるのを待っているシナリオが十分に見えてしまう
この一度のミスのコストは、その機能の利用で得られた価値全体を上回る可能性が高い
SSOと2FAを常に使えという、もう一つのリマインダーだ