Struts2漏洞浅析之Ongl代码执行分析

2012-12-09 13:38:46 8 2619 1
0x01 简述
      2010年7月exploitdb爆出的《Struts2/XWork < 2.2.0 Remote Command Execution Vulnerability》,可以称之为神一样的漏洞,攻击者只要构造出合适的语句,就有很大的几率获得系统权限(System或者root,因为tomcat默认都会以这样的权限运行),而且时至今日存在这个漏洞的网站仍然大有存在。本文将从源码层面简单的分析这个漏洞形成的根本原因。
0x02 Ognl表达式实现代码执行
      Ognl表达式是一种基于Java的功能强大的表达式。通过使用它,我们能够通过表达式存取Java对象树中的任意属性和调用Java对象树的方法,可以轻松解决在数据流转的过程中所碰到的各种问题。但是在实际使用中,编程人员更多使用的是Ognl的数据流转传输的功能,却忘记了Ognl表达式可以执行Java代码的功能。下面我们来通过一个常用的方法来看下它的实现过程。
public class Login extends ActionSupport{
        public String execute() {
                ActionContext AC = ActionContext.getContext();
                Map Parameters = (Map)AC.getParameters();
                String[] username = (String[])Parameters.get("username");                System.out.println(AC.getValueStack().findValue(username[0]));
                return SUCCESS;
        }
}
上面这段代码是我自己搭建的一个Struts2实现的简单java web功能的action部分的代码,具体功能就是,获得用户提交的username参数,然后从值栈(Value Stack)中找到符合参数值的内容,并打印。红色字体部分的findValue方法是关键点,下面我将在这句代码中加上断点,来跟踪分析它的行为。
      跟踪进入OgnlValueStack文件中的findValue(String expr)方法,关键代码如下:
Object value = ognlUtil.getValue(expr, context, root);
继续深入追踪进入OgnlUtil文件,看到如下代码:
public Object getValue(String name, Map context, Object root) throws OgnlException {
        return Ognl.getValue(compile(name), context, root);
    }
红色部分为Ognl类自带的方法,其作用是根据表达式(参数1),在上下文(参数2)和指定类中(参数3)查找响应的内容,并返回,若没有则返回空。在查询的过程中,表达式会被执行,这使得攻击者有可乘之机,可以利用这个方法来执行一些恶意的行为。
0x03利用实现
      还是使用之前部分构造的代码,搭建一个可以用于web交互的测试平台。通过传递名为username的参数来看下这个函数的威力。提交如下url:
http://target:8080/Login.action?username='#_memberAccess["allowStaticMethodAccess"]=true,@java.lang.Runtime@getRuntime().exec('calc'))'
在目标服务器中,弹出了计算器

      我们所传递的内容被作为参数传递给了AC.getValueStack().findValue,之后它的内容便被执行了。解释下传入的语句作用,首先是给#_memberAccess["allowStaticMethodAccess"]变量赋予true值,这个变量是Xwork用于管理Ognl权限类中的成员,它控制Ognl是否可以执行Java的静态方法。第二句调用Java方法执行系统调用,“@”是Ognl调用Java静态方法的标识。
0x04总结
      Ognl被用户Xwork和Struts框架的核心代码中,在这些框架中很多地方都存在findValue的调用,例如:Struts的校验框架,如果类型不匹配则默认也会调用findValue函数来检索用户输入的内容。2010年爆出的Struts2远程代码执行和其之后出现的代码执行问题,都和这个函数有关系。
      findValue函数很像是PHP中的eval、assert函数,可以造成代码执行,但又是必须存在的函数。看Struts和Xwork修补它们漏洞的补丁也是,去对用户输入的内容进行过滤或检验。这方面的漏洞没有被大范围的发现和发掘,个人认为主要原因是因为,使用这些框架进行开发的源码大多是闭源的,外界很难获得,所以少有人去审计。但是,它的威胁性极其强大,本篇文章所涉及的不过是九牛一毛,相对于已经有完善审计方法的PHP,Java Web还算得上是尚未开发的处女地。

关于作者

唐门三少17篇文章105篇回复

评论8次

要评论?请先  登录  或  注册
  • 8楼
    2012-12-10 13:41

    有段时间没见到楼主的帖子了。

  • 7楼
    2012-12-10 08:52

    我也是刚开始学,慢慢来,有心就没有什么学不会的

  • 6楼
    2012-12-10 00:42

    正在学 Struts2 额。。。

  • 5楼
    2012-12-10 00:21

    哥们牛b java 也懂 佩服 小菜就看的懂php

  • 4楼
    2012-12-9 22:17

    前一段时间看了一点struts2中ognl资料的介绍。ognl一般有一个称为root的根,从根上查找值,如果查找不到依次向下查,这个向下查怎么个具体查法忘记了,2年前看过一点忘记了 #user.id 是不从root查找user.id的值

  • 3楼
    2012-12-9 21:09

    原来如此,用了好久还没有去搞明白原理,感谢楼主

  • 2楼
    2012-12-9 20:06

    他的那个树状存储结构,我还没搞明白,exploitdb上给的利用方法好像就是要用到这个树状结构的机理,能不能给科普下

  • 1楼
    2012-12-9 17:33

    在Struts2中,只用到了ognl表达式强大功能的一部分,ognl有一个树形存储结构,全部是Map<K,V>形式存进去的。struts2中ActionContext即是ognl的上下文 对象,貌似可以直接通过String username=ActionContext.getContext().get("username"); ActionContext.getContext() request ActionContext.getContext().getSession() session ActionContext.getContext().getApplication() application 全部是Map<String,Object>的 重在讨论 互相交流