0x01Brief Description

最近面试几家公司,很多都问到了s2漏洞的原理,之前调试分析过java反序列化的漏洞,觉得s2漏洞应该不会太难,今天就分析了一下,然后发现其实漏洞的原理不难,但是搭建j2ee调试的环境花了将近半天的时间QAQ.

Struts 是Apache软件基金会(ASF)赞助的一个开源项目,通过采用JavaServlet/JSP技术,实现基于Java EEWeb应用的MVC设计模式的应用框架,Struts 2是Struts的下一代产品,是在 Struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。
Struts2框架广泛应用于政府、公安、交通、金融行业和运营商的网站建设,作为网站开发的底层模板使用。Struts2漏洞,主要指的是J2EE开源框架struts2出现的命令执行漏洞,危害巨大,可导致远程执行任意系统命令,进而获取系统控制权,数据库控制权,导致信息泄露。所有使用struts2框架开发的系统都会受到影响。(copy from Link),之前大学的时候学习过,工作之后就很少接触过了,基本上就是用用工具测试一下s2的漏洞。

OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。OGNL一般是配合struts框架一起使用的,表达式语言一般是为了方便数据的存取所自定义的语言,然而邪恶攻击者却在Struts2中Ognl执行Java代码,同样的Elasticsearch可以用Groovy可以实现任意Java功能。更多ognl的介绍可参考Link百科。

0x02 s2-032漏洞分析

s2-032漏洞影响的s2版本:Struts 2.3.20 - Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)

官方的公告:https://struts.apache.org/docs/s2-032.html

此次漏洞存在于struts2的动态方法引用功能。只要在struts2配置文件中开启该功能,就可能被利用。

在配置了 Struts2 DMI 为 True 的情况下,可以使用 method:<name> Action 前缀去调用声明为 public 的函数,DMI 的相关使用方法可参考官方介绍(Dynamic Method Invocation),这个 DMI 的调用特性其实一直存在,只不过在低版本中 Strtus2 不会对 name 方法值做 OGNL 计算,而在高版本中会。所以只要找到目标应用中有效的 Action 例如 index.action,那么直接使用 DMI 在 method: 后面带上需要执行 OGNL 表达式即可。
比如这样的ognl  表达式: #_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#f=@java.lang.Runtime@getRuntime().exec(#parameters.cmd[0]),#f.close&cmd=open /Applications/Calculator.app    通过反射调用(关于java的反射调用可以参考之前的一篇文章Link)Runtime类的exec方法进行命令执行,这里是打开计算器的操作。

ognl表达式分析:

@符号的作用:在对静态方法或者变量访问的时候使用@class@member或者@class@method(args),所以这里就是通过反射调用了Runtime class的exec method(后者)。

1、“#”符号有三种用途:

(1)、访问非根对象(struts中值栈为根对象)如OGNL上下文和Action上下文,#相当于ActionContext.getContext();下表有几个ActionContext中有用的属性:

parameters
包含当前HTTP请求参数的Map
#parameters.id[0]作用相当于request.getParameter("id")

request
包含当前HttpServletRequest的属性(attribute)的Map
#request.userName相当于request.getAttribute("userName")

session
包含当前HttpSession的属性(attribute)的Map
#session.userName相当于session.getAttribute("userName")

application
包含当前应用的ServletContext的属性(attribute)的Map
#application.userName相当于application.getAttribute("userName")

注:attr 用于按request > session > application顺序访问其属性(attribute),#attr.userName相当于按顺序在以上三个范围(scope)内读取 userName属性,直到找到为止。用于过滤和投影(projecting)集合,如books.{?#this.price<100};构造 Map,如#{'foo1':'bar1', 'foo2':'bar2'}。

(2)、用于过滤和投影(projecting)集合,如: books.{?#this.price>35}

books.{?#this.price>35}

(3)、构造Map,如: #{'foo1':'bar1', 'foo2':'bar2'}

#{'foo1':'bar1', 'foo2':'bar2'}这种方式常用在给radio或select、checkbox等标签赋值上。如果要在页面中取一个map的值可以这样写:

<s:property value="#myMap['foo1']"/>

<s:property value="#myMap['foo1']"/>

将_memberAccess赋值成DEFAULT_MEMBER_ACCESS是为绕过SecurityMemberAccess为false的限制。

简单的payload分析之后,我们来调试一下代码。

首先添加存在漏洞版本的struts2包(这里使用的是2.3.28)以及对应的source Attachement(为方便调试查看到源代码)。如下图所示。

然后呢,构造一个有效的Action,这里就不实现具体的功能。

struts.xml中配置action对应的处理方法。

下一步就是下断点,断点下在哪里?参考他人的文章,聪明的我们自然就下在了该下的地方,让它在该断下的地方断下(这不废话么。。)

1.在DefaultActionMapper.java中,DefaultActionMapper方法将method的值存入到ActionMapping的method属性中。

2.在DefaultActionProxyFactory.java中,DefaultActionProxy方法将ActionMapping的method值经过escapeEcmaScript,escapeHtml4过滤后传到了ActionProxy的method属性中。

3.最后DefaultActionInvocation.java中的invokeAction将ActionProxy的method值放入到了ognlUtil.getValue()方法中执行表达式。

最终,执行完这一步就执行了我们的命令。

0x03 关于escapeHtml4的疑问

我们注意到在整个参数的传递过程中有这样一个函数escapeHtml4的函数会对传输的参数进行处理,查看文档可以知道这个函数的作用是对特殊的符号进行过滤,那么我们的payload中有那么多的特殊符号,像#@,([])/&._= 按理说应该是会被html encode的啊

关于html4 entities 可参考 https://www.w3schools.com/charsets/ref_html_entities_4.asp

为何还能成功,我们尝试在payload中添加双引号,然后再跟一下执行过程。

http://localhost:8080/Demo/index.action?method:#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS"",#f=@java.lang.Runtime@getRuntime().exec(#parameters.cmd[0]),#f.close&cmd=open /Applications/Calculator.app

跟踪发现,双引号在这里确实是进行了html encode

为何&不会呢?在此猜测应该是#$等符号是ognl里面的一些符号,所以这个函数并不会对这些符号进行htmlencode。

0x03Diff Patch

可见,修复的版本在对method参数进行了cleanActionName的过滤,具体的过滤是

protected Pattern allowedActionNames = Pattern.compile(“[a-zA-Z0-9._!/\\-]*”);,这样我们payload中的]./等就被过滤掉了。

0x04 Reference

1.http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html

2.http://dogewatch.github.io/2016/04/29/struts2/

3.http://blog.topsec.com.cn/ad_lab/apache-structs2-s2-032%E6%8A%80%E6%9C%AF%E5%88%86%E6%9E%90%E5%8F%8A%E6%BC%8F%E6%B4%9E%E6%A3%80%E6%B5%8B%E8%84%9A%E6%9C%AC/

4.http://www.cnblogs.com/LittleHann/p/4606891.html

struts2 s2-032漏洞分析的更多相关文章

  1. Struts2漏洞分析,漏洞波及全系版本

    Struts漏洞分析    Apache Struts团队已经发布了Struts 2.3.15.1安全更新版本.在Struts2.3.15.1版本之前,存在着严重的安全漏洞,如果现在一些比较大的网站是 ...

  2. Struts2开发模式漏洞

    当Struts2中的devMode模式设置为true时,存在严重远程代码执行漏洞.如果WEB服务以最高权限运行时,可远程执行任意命令,包括远程控制服务器. 如果为受影响的版本,建议修改配置文件stru ...

  3. Struts2-057/CVE-2018-11776两个版本RCE漏洞分析(含EXP)

    0x01 前言 2018年8月22日,Apache Strust2发布最新安全公告,Apache Struts2存在远程代码执行的高危漏洞(S2-057/CVE-2018-11776),该漏洞由Sem ...

  4. CVE-2010-3333-office RTF栈溢出漏洞分析

    0x00 前言 此漏洞是根据泉哥的<漏洞战争>来学习分析的,网上已有大量分析文章在此只是做一个独立的分析记录. 0x01 复现环境 操作系统-->windows7 x64 软件版本- ...

  5. S2-002漏洞分析

    漏洞概述 Struts2-002是一个 XSS 漏洞,该漏洞发生在 <s:url> 和 <s:a>标签中,未对标签内字符进行转义,当标签的属性 includeParams=al ...

  6. S2-001漏洞分析

    前言 开始好好学Java,跟着师傅们的文章走一遍 Strust简介 Struts2是流行和成熟的基于MVC设计模式的Web应用程序框架. Struts2不只是Struts1下一个版本,它是一个完全重写 ...

  7. 漏洞分析:CVE-2017-17215

    漏洞分析:CVE-2017-17215 华为HG532路由器的命令注入漏洞,存在于UPnP模块中. 漏洞分析 什么是UPnP? 搭建好环境(使用IoT-vulhub的docker环境),启动环境,查看 ...

  8. [javaweb]strut2-001漏洞分析

    Strut2-001 漏洞描述 框架解析JSP页面标签时会对用户输入的Value值获取,在获取对应的Value值中递归解析%{.}造成了二次解析,最终触发表达式注入漏洞,执行任意代码 影响版本 2.0 ...

  9. DLink 815路由器栈溢出漏洞分析与复现

    DLink 815路由器栈溢出漏洞分析与复现 qemu模拟环境搭建 固件下载地址 File DIR-815_FIRMWARE_1.01.ZIP - Firmware for D-link DIR-81 ...

随机推荐

  1. ckeditor django admin 中使用

    ckeditor settings配置 ############ # CKEDITOR # ############ MEDIA_ROOT = os.path.join(BASE_DIR, 'medi ...

  2. MySQL存储引擎简单介绍

    MySQL使用的是插件式存储引擎. 主要包含存储引擎有:MyISAM,Innodb,NDB Cluster,Maria.Falcon,Memory,Archive.Merge.Federated. 当 ...

  3. javascript错误信息

    ECMA-262 定义了下列 7 种错误类型: TypeError 类型错误 ReferenceError 引用错误 SyntaxError 语法错误 Error 错误 EvalError 全局错误 ...

  4. day08(字符编码,字符与字节,文件操作)

    一,复习 ''' 类型转换 1.数字类型:int() | bool() | float() 2.str与int: int('10') | int('-10') | int('0') | float(' ...

  5. vue路由传对象刷新会报错,数据丢失,用json字符串解决

    变成json字符串,且加密 this.$router.push({name: response.body.PowerList[0].opPowerurl ,query :{ all: encodeUR ...

  6. Excel阅读模式/聚光灯开发技术序列作品之三 高级自定义任务窗格开发原理简述—— 隐鹤

    Excel阅读模式/聚光灯开发技术序列作品之三 高级自定义任务窗格开发原理简述——    隐鹤 1. 引言 Excel任务窗格是一个可以用来存放各种常用命令的侧边窗口(准确的说是一个可以停靠在类名为x ...

  7. C# NetStream

    标题:NetStream 关注点:Read.Write 正文: int size = Read(buf, 0, buf.length); 这里一次会读入length个字节,如果小于这个数量,后面的就是 ...

  8. mysql中explain的type的解释

    type -- 连接类型 type意味着类型,这里的type官方全称是“join type”,意思是“连接类型”,这样很容易给人一种错觉觉得必须需要俩个表以上才有连接类型.事实上这里的连接类型并非字面 ...

  9. jquery ajax几种书写方式的总结

    Ajax在前端的应用极其广泛,因此,我们有必要对其进行总结,以方便后期的使用. AJAX优点: 可以异步请求服务器的数据,实现页面数据的实时动态加载, 在不重新加载整个页面的情况下,可以与服务器交换数 ...

  10. 南邮 base64全家桶

    这几天不想学逆向 做做crypto(菜还瞎j2做)..... 题目: 全家桶全家桶全家桶!我怎么饿了......密文(解密前删除回车):R1pDVE1NWlhHUTNETU4yQ0dZWkRNTUpY ...