
在Ognl表达式中,括号“()”中包含的变量内容将作为Ognl表达式执行. Ognl表达式的这一功能导致了一个新的想法. 通过将恶意代码存储在一个变量中,然后在调用Ognl表达式的函数中使用该变量来执行恶意代码,即可实现***.
本文将使用CVE-2011-3923漏洞作为示例来描述此利用想法的特定过程. 但是,本文的内容绝不限于此漏洞. 在实际的审计过程中,这种想法可以用来发现许多类似的漏洞.
第二,背景介绍和原理分析
此漏洞与CVE-2010-1870非常相似,后者通过Ognl表达式执行Java以实现远程代码执行的效果. 让我们首先回顾CVE-2010-1870漏洞. ***是通过get方法提交Ognl表达式并直接调用java的静态方法来实现代码执行的. 问题爆发后,struts正式加强了对用户提交内容的审查,禁止使用“#”,“ \”和其他特殊字符作为提交参数.
那么我们就没有办法远程执行Ognl表达式?当然不是,Ognl为我们提供了另一种执行它的方法. 让我们看一些官方文件:
例如,此表达式
#fact(30H)
looksupthefactvariable,andinterpretsthevalueofthatvariableasanOGNLexpressionusingtheBigIntegerrepresentationof30astherootobject.Seebelowforanexampleofsettingthefactvariablewithanexpressionthatreturnsthefactorialofitsargument.NotethatthereisanambiguityinOGNL'ssyntaxbetweenthisdoubleevaluationoperatorandamethodcall.OGNLresolvesthisambiguitybycallinganythingthatlookslikeamethodcall,amethodcall.Forexample,ifthecurrentobjecthadafactpropertythatheldanOGNLfactorialexpression,youcouldnotusethisapproachtocallit
事实(30H)
因为OGNL会解释这种对事实方法的呼吁. 您可能希望通过用括号括起来的属性引用来强制执行这种解释:
(事实)(30小时)

Ognl表达式为我们提供了调用“ #fack()”之类的上下文对象方法的功能,我们需要注意红色文本,大致含义如下: 使用格式“(fact)()” “来写.
在测试过程中,发现形式(一个)(两个)的Ognl表达式将首先作为另一个Ognl表达式执行一个,然后继续他的工作. 在这种情况下,如果程序调用了可以执行Ognl表达式的函数,并且我们通过变量传递了恶意表达式,则struts执行的过滤将变成“透明门”.
在常规调用中,我们找到了函数setValue,该函数用于根据Ognl表达式为目标分配一个值. 在此过程中,将执行Ognl表达式. 在struts2中,通过在继承ActionSupport的类中设置setter和getter方法,用户可以通过get和post方法直接将值分配给私有成员变量. 此方法将使用setValue函数. 让我们构建一个像这样的类:
packageaction;
importognl.Ognl;
importcom.opensymphony.xwork2.ActionSupport;
publicclassHelloWorldextendsActionSupport {
privateStringtang3;
publicvoidsettang3(Stringtang3){
this.tang3 = tang3;

}
publicStringgettang3(){
returntang3;
}
publicStringexecute()throwsException {
System.out.println(tang3);
returnSUCCESS;
}
}
上面的代码仅实现了接受参数“ tang3”并将其内容打印到控制台的功能. 在跟踪过程中,发现当用户提交参数时,将通过调用com.opensymphony.xwork2.interceptor.ParametersInterceptor类中的setParameters方法来获取参数,并且此方法将调用setValue函数,代码如下:
if(acceptableName){

Objectvalue = entry.getValue();
尝试{
stack.setValue(名称struts2ognl表达式和运算符,值); //红色字体
}捕获(RuntimeExceptione){
请注意红色字体部分,名称参数是Ognl表达式部分,值是要分配的对象,并且以前的CVE-2010-1870漏洞也是此函数执行的Ognl表达式. 让我们看一下如何使此函数与前面提到的内容结合起来执行我们需要的Java代码.
根据我们前面提到的Ognl表达式功能,我们应该构建这样的网址:
/helloword.acton?tang3=
提交此类网址后,网络服务器将执行两件事. 首先,将Ognl表达式的内容存储到tang3变量中;第二,名为(tang3)('meh')的http参数将作为另一个Ognl表达式执行,并且动作属性tang3将恢复动作的内容,该内容变为(
由于将http参数传递到变量中后会自动对其进行解码,因此我们可以使用特定字符(例如url编码“#”)绕过正则表达式过滤.
构造语句时要注意的另一件事是,我们要确保tang3属性的内容首先执行. 所以这是一个小技巧. 提交参数时,以这种形式使用z [(tang3)('meh')] = 1以确保首先执行tang3变量. 在这里,我们构造了一个可以弹出计算器的网址:
/helloworld.action?tang3 =(#context [“ xwork.MethodAccessor.denyMethodExecution”] = newjava.lang.Boolean(false),#_ memberAccess [“ allowStaticMethodAccess”] = true,@ java.lang.Runtime @ getRuntime().exec('calc'))(meh)&z [(tang3)('meh')] = 1

URL编码后:
/helloworld.action?tang3=%28%23context [“ xwork.MethodAccessor.denyMethodExecution”]%3D +新建+ java.lang.Boolean%28false%29,%20%23_memberAccess [“ allowStaticMethodAccess”]%3dtrue, %[电子邮件] 20@java.lang.Runtime [/电子邮件] @ getRuntime%28%29.exec%28%27calc%27%29%29%28meh%29&z [%28tang3%29%28%27meh%27 %29] = 1
效果如下:

从底部的红色框中,我们可以看到控制台打印的tang3变量的内容就是我们刚刚输入的代码.
四个摘要
1. 利用此漏洞的方法有局限性. 目标代码需要有一个私有成员变量,可以通过http参数直接分配该成员变量. 同时,***需要知道此私人成员的名称. 但是,从代码审核的角度来看,此问题很容易识别. 但是,由于大多数使用struts框架构建的网站都是封闭源代码,因此很难进行白盒测试.
2. 在struts2.3.1.2版本之后,此问题已得到修复,官方补丁的原始文本如下:
更改了参数内部的规则表达式,以提供可接受的参数名称的狭窄空间.
此外,值堆栈提供的新参数方法将不会再在参数名中出现遗漏.
修复方法是进一步减少ParameterInterceptor的白名单中包含的内容,并禁止执行参数名称的正则表达式
3. 从这些由支杆爆炸的漏洞中可以清楚地看到Ognl表达式的功能. 只要有调用Ognl表达式的函数,就可能发生代码执行问题. 在之前的“ Ongl代码执行分析的Struts2漏洞分析”中,我将findValue称为struts中的eval函数,这显然有点狭窄. Ognl表达式可以称为eval函数,我们在编写代码的过程中必须谨慎处理它们的表达式.
4. 为了重申本文开头所强调的内容,本文不仅限于CVE-2011-3923的漏洞,并且已对其进行了修补. 本文的目的是希望读者能够理解通过括号将变量包装在括号中并通过该漏洞执行Ognl表达式的功能,从而为我们将来的审核添加思路.
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-225060-1.html
#吴亦凡#生日会必须约期待新歌
放家里跟放银行里都贬吧
美国佬喜欢欺负小字辈