オープンソースの脆弱性対策に学ぶ~Apache Struts でリモートから任意のコードが実行可能な脆弱性の対策2(CVE-2017-5638、S2-045)~


ここでは「オープンソースの脆弱性対策に学ぶ」と題して、具体的な事例を紹介しながらセキュアコーディングについて考えてみたいと思います。

引き続き、Apache Struts でリモートから任意のコードが実行可能な脆弱性の対策を紹介していきます。

前回はRESTプラグインにおけるXMLペイロードのデシリアライズの不適切な処理に起因するリモートコード実行(Remote Code Execution)(CVE-2017-9805、S2-052)の脆弱性対策をご紹介しました。

今回はContent-Typeのマルチパートパーサーの処理が引き起こすOGNL(Object Graph Navigation Language)コードの実行(CVE-2017-5638、S2-045)をご紹介したいと思います。

脆弱性の概要は以下のリンクをご確認ください。

脆弱性の情報が公開された3/8から間もなく攻撃が観測され、3/10頃からは被害の報告が相次ぎました。

その多くは、不正なプログラムを仕込まれる、コンテンツを改ざんされる、クレジットカード情報やメールアドレス、氏名住所等の個人情報が盗まれるなど深刻なもので、サイトを停止して対応したケースもあったようです。

脆弱性の原因は、マルチパートコンテンツを処理するパーサー内でContent-Typeヘッダーの解析エラーが発生した際のエラー処理において、ヘッダーの値に注入されたOGNLコードが意図せず実行されてしまう実装の問題になります。


調査

GitHubにてApache Strutsのソースコード修正を追跡しました。

ソースコード修正の核心部分は、FileUploadInterceptorクラスのinterceptメソッドにおいて、マルチパートリクエストにエラーが発生した際のエラー処理です。

修正によって、Content-Typeヘッダーの値を含むエラーメッセージを使わずに、固定のエラーメッセージを使うように変更されています。

外部からOGNLコードを注入される経路を遮断することで、OGNLを解釈実行する機能が悪用されることを回避しています。

以下に修正前のコードの関連図を示します。

FileUploadInterceptorクラスから、com/opensymphony/xwork2パッケージ配下のOGNLを処理する共通機能を呼び出しています。

続いて、修正後のコードの関連図を示します。

com/opensymphony/xwork2パッケージ配下の共通機能にも変更が入っていますが、セキュリティは呼び出し元のFileUploadInterceptorクラスにて実現しています。

なお、以下に2017年9月現在のコードの関連図も示しておきます。

com/opensymphony/xwork2パッケージ配下の共通機能にさらに変更が加えられていました。

今後もしばらくは注意深く追いかけていく必要がありそうです。

 

考察

一般的にエラー処理はプログラム内部の様々な場所で行われるため、汎用性と柔軟性に優れた共通機能を用意して、各場所から共通機能を呼び出すように実装することが多いと思われます。

共通機能が汎用性と柔軟性に優れていることは基本的に好ましいことと思われますが、その度合いが、セキュリティが要求する制限を越える場合には要注意です。

共通機能の汎用性と柔軟性を維持しつつ、セキュリティも確保したい場合、共通機能を呼び出す各場所に応じて「個別に漏れ抜けなく」セキュリティを実装する必要が出てきます。

今回の脆弱性の場合、エラー処理においてOGNLを解釈実行する共通機能が使われていました。

何らかの文法構造にしたがって記述された文字列を解釈実行するような機能は、インジェクションや機能の悪用に対する対策が必要です。

SQLインジェクションやOSコマンドインジェクション、クロスサイトスクリプティング(を引き起こすHTMLインジェクション)はあまりにも有名ですが、OGNLもインジェクションや悪用が想定される機能なのです。

そこで、「個別に漏れ抜けなく」セキュリティを実装することになるのですが、strutsはこれまでにも何度かOGNLコードを実行してしまう脆弱性を指摘され、その都度対策してきた経緯があります。

こうした経緯は、ともすれば「場当たり的」、あるいは「もぐらたたき」などと言われかねないところですが、本質的な問題として「個別に漏れ抜けなく」はセキュアコーディングの中で厄介な課題であると考えられます。

既に対策方法が確立しているはずのSQLインジェクションやOSコマンドインジェクション、クロスサイトスクリプティングでさえ、現在においても根絶することができていない理由として、「個別に漏れ抜けなく」の困難さは大きなウェイトを占めてくるのではないでしょうか。

「個別に漏れ抜けなく」の困難さとその解決策については、別の機会に整理してご紹介できたらと思っています。

 

まとめ

今回はContent-Typeのマルチパートパーサーの処理が引き起こすOGNL(Object Graph Navigation Language)コードの実行(CVE-2017-5638、S2-045)をご紹介しました。

次回は3年ほど遡ってClassLoader が操作可能な脆弱性(CVE-2014-0094、S2-021)をご紹介したいと思います。

 

  • このエントリーをはてなブックマークに追加

PAGE TOP