CVE-2014-0094 test program for struts1# CVE-2014-0094 のstruts1 対応について
## はじめに
CVE-2014-0094 のstruts1の影響についてまとめる。
特に断りがない限り、各バージョンは、java 1.7.0_02,struts 1.3.10,
apache-tomcat-6.0.39、FreeBSD 8.2 で確認を行った。
なお、いかなる場合も、ソース、文章等の内容については保証しない。
また、いかなる事象が生じても私は関与しない。特にこの内容を悪用した場合も
私は一切関与しない。(と行っても何も目新しいことはないのですが)
今回、各種webを参考にして解決策の具体例を提示した。
既知の事実を除き、参考にしたURLをソース等に記載した。
情報を公開してくださったことに感謝している。
なるべく専門用語を使わず、語弊があるかもしれないが、わかりやすい言葉で
記載した。
struts1 における、今回の脆弱性は、
CVE-2014-0094,S2-020等呼び名があるようでないようなよくわかりませんが、
とりあえず、 CVE-2014-0094 と呼ぶことにします。
## 背景
改めて説明するまでもなく、CVE-2014-0094は、とても大きな問題を抱えている。
http://www.nta.go.jp/sonota/sonota/osirase/service.htm
「e-Taxソフト(WEB版)」、「確定申告書等作成コーナー」、「NISA(日本版ISA)コー\ナー」 サービス停止のお知らせ(重要)平成26年4月25日
によると、国税庁のweb service がstruts1を使用しており、
発見されたその日のうちにサービスを停止している。
被害を最小限に食いとどめるため、早急な停止をおこなったと思われる。
こちらで実証実験を行ったところ、
URLにアクセスするだけで、
サービスの停止、任意のファイルの漏洩を確認した。
URLにアクセスするだけでということで、匿名のメールアドレスで、
URLの書かれたメールをMLに出すだけで、犯人の特定が難しく、
簡単にサービス停止を行うことができる。
これほど簡単に攻撃できる問題かと。
## まず行うことシステムを停止させること
これが一番大事かと。少なくとも影響があるだろうと第三者機関より
発表があったらならば、まず停止させ被害拡大を防ぐのが本来のやり方。
仮に、後の調査で影響がないとわかっても、漏洩した情報はもとに戻らない。
無論政治的判断が必要なことである。企業の場合、倫理観、日ごろの問題意識、
リスク対応など、問われる。
## どのような攻撃か可能か調査する
この問題は、システムが保持している設定値を一部書換え可能であることに起因する。
何の設定値が書換え可能か調査する必要がある。
その値によって、どのような攻撃が可能か判断する。
この設定値は、Servletコンテナによって異っている。
tomcat6では任意のコードの実行はおそらく不可能と思われるが、
tomcat8では任意の実行が可能である。
他、jetty,WebSphere Application Serverなど、使用する環境によって、
どのような設定値が確認する必要がある。
tomcat6の場合、23個この設定変更が可能とされており、
class.classLoader.resources.dirContext.docBase
を変更した場合、通常のシステム可動が不可能になり、
また、JSPを表示する代わりに、サーバ上のファイルを指定することで、
任意のファイルが取得可能(漏洩)となる。
tomcat8の場合、任意のコードが実行可能だが、
これはtomcat6に比べ設定できる値が増えているからである。
その設定値が使用しているServertコンテナに存在しなければ今のところ
問題は少ないと考えられる。
## 攻撃有無を確認する
今回の設定値変更は、URLとして、その文字列を含ませる他に、
通常のリクエストの隠し項目としても可能であり、
また、cookieにその値を含ませても可能とされている。
アクセスログからでは、隠し項目に設定した場合のわからない。
よく日曜日深夜に再起動を行うケースがあるが、
それより少し前に、docBaseの書換え、および、ファイル取得を行い、
その後、再起動がシステムにかかるため、
システム管理者的には、異常に気が付きにくい。
その時間帯を狙って、ステータス404,500など多発していたら、
おそらく何らかのファイルが漏洩した可能性が高いかもしれない。
## 対応を行う
sturs1ではサポートが終了しており
(オープンソースのサポートって何?という話はおいておいて)、
セキュリティパッチがでません。
自力で解決する必要があります。
ことの発端は、BeanUtilの問題であり、これに不適切な文字列が来た場合無視する
実装をする必要があります。
BeanUtilとは、オブジェクトの設定値を変更するツールです
(かなり語弊がある言い方です。)
実装例は
com.haselab.struts.filter
web.xml
です。
簡単に説明すると、
web.xmlにシステム起動時にBeanUtilの振る舞いを変更するプログラムを呼び出します。
SafeResolverListener.java が呼び出され、
SafeResolver.javaを今後、BeanUtilが使ううようになります。
SafeResolver.javaでは、解析する文字列が、
(大文字小文字を無視して)'classLoader'ならば、""を返します。
つまり、classLoaderに対し、任意の値を設定できなくさせます。
このあたりの振る舞いについては
https://gist.github.com/nakamura-to/11347570
を参考にしました。(短いプログラムなのでそのままです)
アプリケーション側で、classLoaderという設定を変更する必要がある場合、
この方法では、この設定をできなくしてしまうため、
対応ではできません。
ですが、一般的に、まずclassLoaderという名前をつける事は
ないはずですので、まずは問題ありません。
不安でしたらアプリケーション側全ソースに対し、
grep -r -i classLoader *
などとして、存在しないことを書くにすれば良いかと。
## 検証内容
docBaseの書換えについて検証してみました。mvnでのdeploy後、struts配下を
ブラウザーで見てください。
ボタン押下ごとに、docBaseの書換えと、/etc/passwdファイルの表示を行っています。
[4.0K] /data/pocs/da57a8c32437ce645ab87018c8b25db81ffa7f8b
├── [ 265] env.set
├── [1.9K] memo.txt
├── [2.0K] pom.xml
├── [6.7K] README.md
└── [4.0K] src
└── [4.0K] main
├── [4.0K] java
│ └── [4.0K] com
│ └── [4.0K] haselab
│ └── [4.0K] struts
│ ├── [4.0K] action
│ │ └── [ 770] HelloWorldAction.java
│ ├── [4.0K] filter
│ │ ├── [ 457] SafeResolver.java
│ │ └── [ 629] SafeResolverListener.java
│ └── [4.0K] form
│ └── [ 304] HelloWorldForm.java
└── [4.0K] webapp
├── [ 177] HelloWorld.jsp
├── [1.4K] index.html
├── [4.0K] META-INF
│ └── [ 129] context.xml
├── [1.8K] target.jsp
└── [4.0K] WEB-INF
├── [ 177] HelloWorld.jsp
├── [ 642] struts-config.xml
└── [ 916] web.xml
12 directories, 15 files