Codeql复现CVE-2018-11776学习笔记
基本使用
1、首先下载struts2漏洞版本源码:
https://codeload.github.com/apache/struts/zip/refs/tags/STRUTS_2_3_20
2、构建codeql数据库(构建失败文末有解决办法):
codeql database create ~/CodeQL/databases/struts2-2.3.20-database --language="java" --command="mvn clean install --file pom.xml" --source-root=~/CodeQL/struts-STRUTS_2_3_20/xwork-core
QL代码编写
source的建模
以S2-032 ( CVE-2016-3081 )、S2-033 ( CVE-2016-3687 ) 和S2-037 ( CVE-2016-4438 )为例,这三个漏洞都是与调用ognlUtil.getValue有关,比如下列代码:
String methodName = proxy.getMethod(); //<--- untrusted source, but where from?
LOG.debug("Executing action method = {}", methodName);
String timerKey = "invokeAction: " + proxy.getActionName();
try {UtilTimerStack.push(timerKey);Object methodResult;try {methodResult = ognlUtil.getValue(methodName + "()", getStack().getContext(), action); //<--- RCE
上面的代码中使用了proxy.getMethod()方法来获取不受信任的数据源,最终导致了调用ognlUtil.getValue造成了RCE,但除此之外还有各种方法,例如getActionName()和getNamespace(),所以可以编写如下QL代码,对这些不受信任的源进行建模:
class ActionProxyGetMethod extends Method {ActionProxyGetMethod() {getDeclaringType().getASupertype*().hasQualifiedName("com.opensymphony.xwork2", "ActionProxy") and(hasName("getMethod") orhasName("getNamespace") orhasName("getActionName"))}
}predicate isActionProxySource(DataFlow::Node source) {source.asExpr().(MethodAccess).getMethod() instanceof ActionProxyGetMethod
}
因为proxy是com.opensymphony.xwork2.ActionProxy类型,所以getDeclaringType().getASupertype*().hasQualifiedName(“com.opensymphony.xwork2”, “ActionProxy”),其中*号代表递归
sink的建模
S2-032、S2-033和S2-037使用了 OgnlUtil::getValue(),然而在漏洞 S2-045(CVE-2017-5638)中,使用了 TextParseUtil::translateVariables(),所以推测一下OgnlUtil::compileAndExecute() 和 OgnlUtil::compileAndExecuteMethod() 也可能存在漏洞,所以对传入compileAndExecute、和compileAndExecute的sink进行建模:
predicate isOgnlSink(DataFlow::Node sink) {exists(MethodAccess ma | ma.getMethod().hasName("compileAndExecute") or ma.getMethod().hasName("compileAndExecuteMethod") | ma.getMethod().getDeclaringType().getName().matches("OgnlUtil") and sink.asExpr() = ma.getArgument(0))
}
MethodAccess表示方法访问,即当调用xxx.compileAndExecute或者xxx.compileAndExecuteMethod
ma.getMethod().getDeclaringType().getName().matches(“OgnlUtil”)表示该方法所在的类为OgnlUtil。
进行污点追踪
之前已经定义好了sink和source,所以直接将这两个套进去,这里重写了一个isAdditionalFlowStep,用来衔接一些没匹配到的参数。
class OgnlTaintTrackingCfg extends DataFlow::Configuration {OgnlTaintTrackingCfg() {this = "mapping"}override predicate isSource(DataFlow::Node source) {isActionProxySource(source)}override predicate isSink(DataFlow::Node sink) {isOgnlSink(sink)}override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {TaintTracking::localTaintStep(node1, node2) orexists(Field f, RefType t | node1.asExpr() = f.getAnAssignedValue() and node2.asExpr() = f.getAnAccess() andnode1.asExpr().getEnclosingCallable().getDeclaringType() = t andnode2.asExpr().getEnclosingCallable().getDeclaringType() = t)}
}from OgnlTaintTrackingCfg cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select source, sink
isAdditionalFlowStep用于衔接一些没匹配上的数据流,简单来说可能有如下情况,在调用bar()时没有提前调用foo(),导致数据流并不认为foo到bar是连通的所以默认DataFlow::Configuration是不包括这个流步骤的,因为也不能确定bar()中对this.field的访问总是被污染的,但是在漏洞挖掘中,包含这种形式的调用是非常有意义的。
public void foo(String taint) {this.field = taint;
}public void bar() {String x = this.field; //x is tainted because field is assigned to tainted value in `foo`
}
对isAdditionalFlowStep进行逐步分析:
TaintTracking::localTaintStep(node1, node2) 测试node1到node2的连通性。
Field 表示字段,RefType表示除了原始类型(int、float等)、null、数组的任何类型
f.getAnAssignedValue()表示获取被赋值给该字段的表达式。例如有一个字段int a,其中a = 10+20,那么表达式为10+20
f.getAnAccess()表示该字段的访问。例如int y = x;//访问字段x
node1.asExpr() = f.getAnAssignedValue() and node2.asExpr() = f.getAnAccess()这段连起来:表示有一个获取被赋值给字段的表达式node1,node2表达式对该字段进行了访问。
node1.asExpr().getEnclosingCallable().getDeclaringType() = t and node2.asExpr().getEnclosingCallable().getDeclaringType() = t表示node1和node2都是同一个类
初版代码
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTrackingclass ActionProxyGetMethod extends Method{ActionProxyGetMethod(){getDeclaringType().getASupertype*().hasQualifiedName("com.opensymphony.xwork2", "ActionProxy") and(hasName("getMethod") orhasName("getActionName") orhasName("getNamespace"))}
}predicate isActionProxySource(DataFlow::Node source) {source.asExpr().(MethodAccess).getMethod() instanceof ActionProxyGetMethod}predicate isOgnlSink(DataFlow::Node sink) {exists(MethodAccess ma | ma.getMethod().hasName("compileAndExecute") or ma.getMethod().hasName("compileAndExecuteMethod") | ma.getMethod().getDeclaringType().getName().matches("OgnlUtil") and sink.asExpr() = ma.getArgument(0))
}class OgnlTaintTrackingCfg extends DataFlow::Configuration {OgnlTaintTrackingCfg() {this = "mapping"}override predicate isSource(DataFlow::Node source) {isActionProxySource(source)}override predicate isSink(DataFlow::Node sink) {isOgnlSink(sink)}override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {TaintTracking::localTaintStep(node1, node2) orexists(Field f, RefType t | node1.asExpr() = f.getAnAssignedValue() and node2.asExpr() = f.getAnAccess() andnode1.asExpr().getEnclosingCallable().getDeclaringType() = t andnode2.asExpr().getEnclosingCallable().getDeclaringType() = t)}}from OgnlTaintTrackingCfg cfg, DataFlow::Node source, DataFlow::Node sinkwhere cfg.hasFlow(source, sink)select source, sink
改进isBarrier
查看数据流步骤:
在数据流经过几步之后,调用getActionName()返回的值流入到了对pkg.getActionConfigs()返回的对象上调用get()的一个参数中:
String chainedTo = actionName + nameSeparator + resultCode; //actionName comes from `getActionName` somewhere
ActionConfig chainedToConfig = pkg.getActionConfigs().get(chainedTo); //chainedTo contains `actionName` and ended up in the `get` method.
点进入ValueStackShadowMap::get()函数内部,代码类似如下:
public Object get(Object key) {Object value = super.get(key); //<--- key gets tainted?if ((value == null) && key instanceof String) {value = valueStack.findValue((String) key); //<--- findValue ended up evaluating `key`}return value;
}
通过查看数据流步骤发现,因为pkg.getActionConfigs()返回一个Map,而ValueStackShadowMap实现了Map接口,理论上,pkg.getActionConfigs()返回的值可能是ValueStackShadowMap的一个实例。因此,CodeQL DataFlow库显示了从变量chainedTo到ValueStackShadowMap类中get()实现的这一潜在流动。
但实际上,ValueStackShadowMap类属于jasperreports插件,且该类的实例只在几个地方创建,其中没有任何一个是通过pkg.getActionConfigs()返回的。所以ValueStackShadowMap::get()可能是个误报,不太可能被触发。
定义一个isBarrier,如果污点数据流入ValueStackShadowMap的get()或containsKey()方法,则不继续跟踪它。
override predicate isBarrier(DataFlow::Node node) {exists(Method m | (m.hasName("get") or m.hasName("containsKey")) andm.getDeclaringType().hasName("ValueStackShadowMap") andnode.getEnclosingCallable() = m)
}
最终代码:
https://github.com/Semmle/SecurityQueries/blob/master/semmle-security-java/queries/struts/cve_2018_11776/initial.ql
坑点
1、构建数据库失败
~/CodeQL/struts-STRUTS_2_3_20/xwork-core/target/surefire-reports
-------------------------------------------------------------------------------
Test set: TestSuite
-------------------------------------------------------------------------------
Tests run: 741, Failures: 5, Errors: 0, Skipped: 0, Time elapsed: 13.404 sec <<< FAILURE!
testSetPropertiesDate(com.opensymphony.xwork2.ognl.OgnlUtilTest) Time elapsed: 0.011 sec <<< FAILURE!
junit.framework.AssertionFailedError: expected:<Fri Feb 12 00:00:00 CST 1982> but was:<null>at junit.framework.Assert.fail(Assert.java:47)at junit.framework.Assert.failNotEquals(Assert.java:283)at junit.framework.Assert.assertEquals(Assert.java:64)at junit.framework.Assert.assertEquals(Assert.java:71)at com.opensymphony.xwork2.ognl.OgnlUtilTest.testSetPropertiesDate(OgnlUtilTest.java:351)testRangeValidation(com.opensymphony.xwork2.validator.DateRangeValidatorTest) Time elapsed: 0.028 sec <<< FAILURE!
junit.framework.AssertionFailedError: Expected date range validation error message.at junit.framework.Assert.fail(Assert.java:47)at junit.framework.Assert.assertTrue(Assert.java:20)at junit.framework.Assert.assertNotNull(Assert.java:214)at com.opensymphony.xwork2.validator.DateRangeValidatorTest.testRangeValidation(DateRangeValidatorTest.java:60)testVisitorChildConversionValidation(com.opensymphony.xwork2.validator.VisitorFieldValidatorTest) Time elapsed: 0.015 sec <<< FAILURE!
junit.framework.AssertionFailedError: expected:<6> but was:<4>at junit.framework.Assert.fail(Assert.java:47)at junit.framework.Assert.failNotEquals(Assert.java:283)at junit.framework.Assert.assertEquals(Assert.java:64)at junit.framework.Assert.assertEquals(Assert.java:195)at junit.framework.Assert.assertEquals(Assert.java:201)at com.opensymphony.xwork2.validator.VisitorFieldValidatorTest.testVisitorChildConversionValidation(VisitorFieldValidatorTest.java:189)testVisitorChildValidation(com.opensymphony.xwork2.validator.VisitorFieldValidatorTest) Time elapsed: 0.015 sec <<< FAILURE!
junit.framework.AssertionFailedError: expected:<5> but was:<3>at junit.framework.Assert.fail(Assert.java:47)at junit.framework.Assert.failNotEquals(Assert.java:283)at junit.framework.Assert.assertEquals(Assert.java:64)at junit.framework.Assert.assertEquals(Assert.java:195)at junit.framework.Assert.assertEquals(Assert.java:201)at com.opensymphony.xwork2.validator.VisitorFieldValidatorTest.testVisitorChildValidation(VisitorFieldValidatorTest.java:167)testContextIsPropagated(com.opensymphony.xwork2.validator.VisitorFieldValidatorTest) Time elapsed: 0.008 sec <<< FAILURE!
junit.framework.AssertionFailedError: expected:<3> but was:<2>at junit.framework.Assert.fail(Assert.java:47)at junit.framework.Assert.failNotEquals(Assert.java:283)at junit.framework.Assert.assertEquals(Assert.java:64)at junit.framework.Assert.assertEquals(Assert.java:195)at junit.framework.Assert.assertEquals(Assert.java:201)at com.opensymphony.xwork2.validator.VisitorFieldValidatorTest.testContextIsPropagated(VisitorFieldValidatorTest.java:153)
报错的都是一些测试方法,解决方法:删除测试目录,即:
~/CodeQL/struts-STRUTS_2_3_20/xwork-core/src/test
参考链接
https://www.freebuf.com/articles/web/283795.html (入门推荐)
https://securitylab.github.com/research/apache-struts-CVE-2018-11776/
相关文章:

Codeql复现CVE-2018-11776学习笔记
基本使用 1、首先下载struts2漏洞版本源码: https://codeload.github.com/apache/struts/zip/refs/tags/STRUTS_2_3_20 2、构建codeql数据库(构建失败文末有解决办法): codeql database create ~/CodeQL/databases/struts2-2.3.…...

CVE-2024-27199 JetBrains TeamCity 身份验证绕过漏洞2
漏洞简介 TeamCity Web 服务器中发现了第二个身份验证绕过漏洞。这种身份验证旁路允许在没有身份验证的情况下访问有限数量的经过身份验证的端点。未经身份验证的攻击者可以利用此漏洞修改服务器上有限数量的系统设置,并泄露服务器上有限数量的敏感信息。 项目官网…...
ms office学习记录12:Excel学习记录㈥
数据工具 分列的其他运用:身份证号中“出生日期”切片:分列→固定宽度→下一步→切割出三列→下一步→不导入第一列→导入第二列且转换成日期→不导入第三列→完成 删除重复值:定位到要“数据”选项卡→删除重复项→取消全选再勾选要删除的…...

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的条形码二维码检测系统(深度学习+UI界面+训练数据集+Python代码)
摘要:在物流和制造业中,开发一套高效的条形码与二维码识别系统显得尤为关键。本博文深入探讨了如何利用深度学习技术打造出一套先进的条形码及二维码检测系统,并且提供了一套完整的实施方案。该系统搭载了性能卓越的YOLOv8算法,并…...

npm yarn 一起使用报错
项目记录,具有独特性,仅供参考 项目好好的运行,前一天装个测试工具包, 突然就不行了,卸载重装也不行,所有的项目都安装失败,新起一个项目也不行,有时候某个单独安装一个包可以&…...

基于springboot实现驾校信息管理系统项目【项目源码+论文说明】计算机毕业设计
基于springboot实现驾校信息管理系统演示 摘要 随着人们生活水平的不断提高,出行方式多样化,也以私家车为主,那么既然私家车的需求不断增长,那么基于驾校的考核管理也就不断增强,那么业务系统也就慢慢的随之加大。信息…...

DXP软件界面显示“No Hard Devices”【简单的操作问题】加【软件下载】
目录 一,DXP软件界面显示“No Hard Devices” 二,软件下载的百度网盘资源 一,DXP软件界面显示“No Hard Devices” Protel DXP是2004是澳大利亚Altium公司于2002年推出的一款电子设计自动化软件。它的主要功能包括:原理图编辑、印…...
通过Spring Boot 实现页面配置生成动态接口?
流程介绍 在Spring Boot中实现页面配置生成动态接口通常涉及几个关键步骤: 设计页面配置:首先,你需要设计一个用户界面(UI),允许用户通过此界面来配置接口的各种参数,例如HTTP方法(GET、POST等)、URL路径、请求参数、响应数据格式等。保存配置信息:当用户通过页面配置…...

【数据结构与算法】:插入排序与希尔排序
🔥个人主页: Quitecoder 🔥专栏: 数据结构与算法 欢迎大家来到初阶数据结构的最后一小节:排序 目录 1.排序的基本概念与分类1.1什么是排序的稳定性?1.2内排序与外排序内排序外排序 2.插入排序2.1实现插入排序2.3稳定性…...

前端性能优化——javascript
优化处理: 讲javascript脚本文件放到body标记的后面 减少页面当中所包含的script标记的数量 课堂练习: 脚本优化处理 使用原生JavaScript完成操作过程。 document.querySelector document.querySelectorAll classList以及类的操作API Element.class…...

Docker容器化技术(使用Docker搭建论坛)
第一步:删除容器镜像文件 [rootlocalhost ~]# docker rm -f docker ps -aq b09ee6438986 e0fe8ebf3ba1第二步:使用docker拉取数据库 [rootlocalhost ~]# docker run -d --name db mysql:5.7 02a4e5bfffdc81cb6403985fe4cd6acb0c5fab0b19edf9f5b8274783…...

C# ListView 控件使用
1.基本设置 listView1.Columns.Add("序号", 60); //向 listView1控件中添加1列 同时设置列名称和宽度listView1.Columns.Add("温度", 100); //下同listView1.Columns.Add("偏移", 100);listView1.Columns.Add("分割", 50);listView1…...

【string一些函数用法的补充】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 string类对象的修改操作 我们来看 c_str 返回c格式的字符串的操作: 我们来看 rfind 和 substr 的操作: string类非成员函数 我们来看 r…...
【Go】令牌桶限流算法
1. 限流 限流,顾名思义,限制用户请求流量,避免大规模并发导致系统宕机。 2. 令牌桶算法 令牌管理员以恒定的速率向令牌桶里放置一个令牌。如果桶满,就丢弃令牌。 请求到达时,都要先去令牌桶里取一个令牌,…...
go的slice学习
并发访问slice 线上出现一粒多协程并发append全局slice的情况,导致内存不断翻倍,因此对slice的使用需要重新考虑。 并发读写的情况下, 可以利用锁、channel等避免竞态 问题 func TestDemo32(t *testing.T) {var wg sync.WaitGroupvar n 1…...

软件设计师17--磁盘管理
软件设计师17--磁盘管理 考点1:存储管理 - 磁盘管理调度算法磁盘调度 - FCFS磁盘调度 - SSTF例题: 考点1:存储管理 - 磁盘管理 存取时间寻道时间等待时间,训导时间是指磁头移动到磁道所需的时间;等待时间为等待读写的扇…...

学点Java打小工——Day2Day3一点作业
1 猜数字(10次机会) 随机生成[1,1000]的一个数,输入你猜的数程序会给出反馈,直到猜对或次数用尽(10次)。 //猜数字 10次机会Testpublic void guessNumber() {Random random new Random();// [0, 1000) 1// [1, 1000]int num ra…...

【话题】2024年AI辅助研发趋势,有那些应用领域
大家好,我是全栈小5,欢迎阅读文章! 此篇是【话题达人】系列文章,这一次的话题是《2024年AI辅助研发趋势》 目录 背景概念实践医药领域汽车设计领域展望未来文章推荐 背景 随着人工智能技术的持续发展与突破,2024年AI辅…...
蓝桥杯——数组切分
数组切分 题目分析 这里要搞清楚一个点就是满足区间内数字是连续数字的区间有什么样的特点,既然数字连续重新排列后的数字为n,n1,n2,n3,n4,…nlen,则最大数字和最小数字之差恰好是区间长度减1,即nlen-nlen,同样因为下标也是连续…...

【机器学习】进阶学习:详细解析Sklearn中的MinMaxScaler---原理、应用、源码与注意事项
【机器学习】进阶学习:详细解析Sklearn中的MinMaxScaler—原理、应用、源码与注意事项 这篇文章的质量分达到了97分,虽然满分是100分,但已经相当接近完美了。请您耐心阅读,我相信您一定能从中获得不少宝贵的收获和启发~ …...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...