Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rails の CVE-2019-5418 は RCE (Remote code execution) です

Rails の CVE-2019-5418 は RCE (Remote code execution) です

2019-03-23 更新

前置き

  • これは休日に書いた記事で所属している組織とは一切の関係がない。

概要

  • CVE-2019-5418 は実際のところ高確率でRCEなのだが File Content Disclosure という聞き慣れない名前で公表されて、CVE-2019-5419 で DoSが出来るという内容になっている
  • やあ、脆弱性の開示方法というのは実際に難しい問題だ、広範に使われていて影響範囲が甚大になるようなソフトウェアの脆弱性となると、具体的な攻撃コードを載せるなと言う人が多いのはよく分かる。
  • しかしながら、影響範囲についてまでも、不正確な記述がされてしまっている。これは悪い傾向だと自分は思う。これは配慮の結果なのか? それとも無知の結果か?

前提知識

3/13 に Railsのsecurity updateが出ている。

CVE-2019-5418, CVE-2019-5419 の 報告者は github の John Hawthorn となっていて、Railsのアップデートから間を置かずに、github enterpriseの修正版もリリースされている

同じタイミングで CVE-2019-5420 も報告されていて、こちらは日本人のななおく氏が報告者になっている。

この脆弱性は実際のところ何なのか?

  • CVE-2019-5418 Railsアプリケーションサーバー上の任意のファイルを取得できる。
  • CVE-2019-5420 Railsのsecretが漏れると任意コード実行が可能で、開発モードを使っているとsecretを推測することが出来る。だから、開発モード限定での潜在的なRCEというタイトルとなっている

CVE-2019-5418について、一般的には「パストラバーサルでアプリケーション実行権限で読み取り可能な任意のファイルを盗み出すことが出来る」と説明したほうが話が早いだろう。検索して出てくる実証コードでは、もっぱら ../../../../../../../../../../etc/passwd を読み出そうとしている。

/etc/passwd は無害すぎる例で、脅威が正しく伝わっていない。任意のファイルを読み取ることが出来るため、例えば ../../../config/secrets.yml を読み取ることが可能であることを確認した。このファイルには CVE-2019-5420 での攻撃に必要な secret_key_base という変数が書かれている。つまり CVE-2019-5418 が成立する環境においては、CVE-2019-5420の「開発環境限定」という条件が外れて、単に CVE-2019-5420 によるRCEが出来るということになる。

一般にパストラバーサルで意図しないファイルが露出するというのは、そこからもっと悪いことが起きる。Railsのsecurityアナウンスを確認したところ、パストラバーサルでは以下の内容があった。

Carefully crafted requests can cause the above code to render files from
unexpected places like outside the application's view directory, and can
possibly escalate this to a remote code execution attack.

CVE-2019-5418 のアナウンスにおいては、なぜかこのような記載がなく、CVE-2019-5419 で 巨大なファイルを読み出すことによる DoS が出来るなどと書かれている。(githubの人が考えた最大の脅威がそれだったのかもしれない)

2019-03-22: 訂正

  • DoSの要因を勘違いしていた。後述のペパボの記事に影響を受けた https://tech.pepabo.com/2019/03/18/analysis-rails-vulnerabilities/ もので、オリジナルのアナウンスにはこのような記載は無い。
  • これはおそらくヘッダの処理過程で複雑な正規表現を使ったDoSが出来るというもので、任意のファイル出力とは独立してDoSが可能であるため、別のCVEに分けたのだろう。

補足1: ファイル漏洩でsecretが漏洩するかどうか?

Rails5.2 からファイル上のsecretを暗号化して保存するようになった

しかし、これの効果は、もっぱら暗号化につかう key ファイルをgitignoreに入れておくことで間違ってsecretをソースコード上に含めたり公開してしまったりすることを抑止することにあるようだ。ファイルが読み取れるのであれば、暗号化済みの enc ファイルと key ファイルの両方を取得することが出来る。

secretを環境変数に入れるという作法もある。

補足2: secretが漏洩した場合にどこまで悪いことが起きるのか?

信用できないオブジェクトのデシリアライズでコード実行が可能だというのは、よく知られている

Railsでは、encrypted cookie based sessionを使った場合のシリアライズ方法を、MarshalからJSONに変更したようだ。互換性のために Marshalもサポートする hybridが用意されている。

最大の影響範囲は任意コード実行だが、コード実行が出来なくても、暗号化ベースのsession cookieを使っているなら、任意のユーザーのセッションを偽装することは引き続き出来るだろう。また、各種外部サービスのAPI Keyなどを保存しているケースも考えられるので、各アプリケーションの仕様には依存することにはなるが、基本的にはsecretが漏洩すれば最悪レベルの影響が考えられる。

補足3: どういうときに、RCEが出来るのか?

Advisoryを読んで確認しましょう。典型的には、以下のような状況だとRCEが出来る。

  • render file を使っている + Rails 5.2 を使っている (攻撃に利用可能な Active Storage 用の Endpointがデフォルトで有効になっている)
  • render file を使っている + CookieStore の Marshal または Hybridを使っている

確認する際には、依存ライブラリやmiddlewareも含めて、全部見ましょう。また render file で該当した時点で、RCEが出来なくても、secret が漏洩することによる不特定の影響がある(高い確率で任意コード実行相当のことが出来ると考えたほうが良い)

同じ処理が実装されているとしても様々な書き方があるので、危険なケース全てを列挙しているわけではなく、私はあなたのアプリケーションのコードを読んでいないので、条件に該当しないから安全だという保証はしない。

補足4: 結局何をすればいいの?

  • 実証コードは既に広く公開されており、この記事を読んでからRailsのアップデートをしたのであれば、悪用されていないかの確認をしたほうが良い。
  • Accept Headerの中身なんて通常はログに残していないだろうから、レスポンスサイズを見れば、本来と異なる出力が行われたことの確認が出来るだろう。
  • 必要であれば、secretや各種API Keyを変更しましょう。
  • この際に CookieStore と Marshal をやめろ。

トリアージへの影響

これは自分の個人的な話だが、CVEで流れてくる脆弱性情報や、各種著名どころのOSSの脆弱性情報などは基本的に全部少なくともタイトル程度は目を通すようにしている。自分が CVE-2019-5418, CVE-2019-5419, CVE-2019-5420 を見たときに、これはDoSと開発環境限定でのRCEであって「これはあまり自分の仕事とは関係無さそうだな」と考えて、優先度は低く設定された。(deserialize起因でのRCEだろうというのは一瞬で予測がついた)

Railsをメインで使っているような会社だったら、もちろんもう少し真面目に内容を読むだろう。Slack channelの通知では code execution がキーワードハイライトされるので、自分が優先して内容を確認するのは、CVE-2019-5418 ではなくて、 CVE-2019-5420 のほうだ。

もう少し具体的に影響範囲の精査をしたのは以下の記事が公開されてからになる

さらにいうと、この記事を読んだのは、以下のようなコメント付きで言及があったから。

おお、本当なのか? みんな、実はRCEできるというのを分かってたけど黙ってたのか? Railsの公式アナウンスの内容で、十分に伝わる人には伝わるのだから、わざわざ攻撃方法を広める必要は無い?

実際、ふだんからRailsを使っているわけではないわたくしなどはすっかり勘違いをして、

  • 意図しないコンテンツ露出が起きる脆弱性があったけど
  • 影響範囲は 巨大ファイルを出力することによる DoS で
  • 開発モードに限定のRemote code executionがあった

というふうに、全然影響を正しく理解していなかったよ。 なぜ、Remote code execution と書いてくれなかったんだ?

誰が気付いていますか?

読む人がちゃんと読めば、CVE-2019-5418 がRCEにつながるということはわかる。

逆に、気付いてい無さそうな言及やニュース記事は多い。DoSじゃねえよ。

むすび

自分は、これを読むような読者にとっては文章での解説と実証コードの違いはさほど無く、内容が悪用される可能性についても十分に理解して予見している。対応が出来ていない企業もあるだろうし、誰かに恨まれたりするかもしれないし、下手すると訴えられたり馬鹿な警察に逮捕されたりするかもしれない。

自分は、この文章を公開する意味があると思って書いているが、わざわざ書いていなかったり、言及を避けていたり、書いておいて公開していないようなことも多い。

理由を言語化すると以下のようなことが主な理由になるだろう。

  • 自分の関わっている、あるいは間接的に関わっているサービスで、対応が万全ではない状態で公開することが憚られるため
  • 公開することで、自分の関わっている、あるいは間接的に関わっているサービスの対応が万全であると、勘違いされることが困るため
  • みんな当然に気付いてて、意図的に黙っているのだから口に出すなというコミュニティによる圧力

自分は無法者なので法律や警察のことは実際には気にしていないんだ。だから脆弱性情報について語るときには悪用される可能性も予見して書いているとハッキリ書いておく、嘘をつきたくない。

そんなことよりも自分が気にしているのは、コミュニティによる圧力のことだ。黙っているのは本当に配慮の結果なのか、本当にちゃんと影響は理解されているのか、無知の結果ではないのか、どうやればそれを確認できるのか?

今回の Rails の Advisory は実際に書き方が悪い。最大の影響範囲が Remote code execution であるならば、影響は Remote code execution だと書くべきだ。


更新履歴

  • 2019-03-23 Advisoryが更新されたので追記、影響を受けるケースと取るべき対応について追記
  • 2019-03-22 CVE-2019-5419 について誤解があったので訂正
  • 2019-03-21 公開
@guoygang

This comment has been minimized.

Copy link

@guoygang guoygang commented Mar 22, 2019

So cool

@YusukeIwaki

This comment has been minimized.

Copy link

@YusukeIwaki YusukeIwaki commented Mar 22, 2019

👍

@niconegoto

This comment has been minimized.

Copy link

@niconegoto niconegoto commented Mar 22, 2019

👍

@tenderlove

This comment has been minimized.

Copy link

@tenderlove tenderlove commented Mar 22, 2019

Advisory の修正を送りました。悪い書き方は私のせいだった。すみません。今からもっと頑張ります。

@mala

This comment has been minimized.

Copy link
Owner Author

@mala mala commented Mar 23, 2019

@rhutaba

This comment has been minimized.

Copy link

@rhutaba rhutaba commented Mar 23, 2019

👍

@akira345

This comment has been minimized.

Copy link

@akira345 akira345 commented Apr 20, 2019

開発者とインフラはやっぱ噛み合わないものですね…
PoCが出回ってる段階で既知情報なのに躍起になって隠そうとしなくても…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment