当前位置: 首页 > news >正文

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漏洞版本源码&#xff1a; https://codeload.github.com/apache/struts/zip/refs/tags/STRUTS_2_3_20 2、构建codeql数据库&#xff08;构建失败文末有解决办法&#xff09;&#xff1a; codeql database create ~/CodeQL/databases/struts2-2.3.…...

CVE-2024-27199 JetBrains TeamCity 身份验证绕过漏洞2

漏洞简介 TeamCity Web 服务器中发现了第二个身份验证绕过漏洞。这种身份验证旁路允许在没有身份验证的情况下访问有限数量的经过身份验证的端点。未经身份验证的攻击者可以利用此漏洞修改服务器上有限数量的系统设置&#xff0c;并泄露服务器上有限数量的敏感信息。 项目官网…...

ms office学习记录12:Excel学习记录㈥

数据工具 分列的其他运用&#xff1a;身份证号中“出生日期”切片&#xff1a;分列→固定宽度→下一步→切割出三列→下一步→不导入第一列→导入第二列且转换成日期→不导入第三列→完成 删除重复值&#xff1a;定位到要“数据”选项卡→删除重复项→取消全选再勾选要删除的…...

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的条形码二维码检测系统(深度学习+UI界面+训练数据集+Python代码)

摘要&#xff1a;在物流和制造业中&#xff0c;开发一套高效的条形码与二维码识别系统显得尤为关键。本博文深入探讨了如何利用深度学习技术打造出一套先进的条形码及二维码检测系统&#xff0c;并且提供了一套完整的实施方案。该系统搭载了性能卓越的YOLOv8算法&#xff0c;并…...

npm yarn 一起使用报错

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

基于springboot实现驾校信息管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现驾校信息管理系统演示 摘要 随着人们生活水平的不断提高&#xff0c;出行方式多样化&#xff0c;也以私家车为主&#xff0c;那么既然私家车的需求不断增长&#xff0c;那么基于驾校的考核管理也就不断增强&#xff0c;那么业务系统也就慢慢的随之加大。信息…...

DXP软件界面显示“No Hard Devices”【简单的操作问题】加【软件下载】

目录 一&#xff0c;DXP软件界面显示“No Hard Devices” 二&#xff0c;软件下载的百度网盘资源 一&#xff0c;DXP软件界面显示“No Hard Devices” Protel DXP是2004是澳大利亚Altium公司于2002年推出的一款电子设计自动化软件。它的主要功能包括&#xff1a;原理图编辑、印…...

通过Spring Boot 实现页面配置生成动态接口?

流程介绍 在Spring Boot中实现页面配置生成动态接口通常涉及几个关键步骤: 设计页面配置:首先,你需要设计一个用户界面(UI),允许用户通过此界面来配置接口的各种参数,例如HTTP方法(GET、POST等)、URL路径、请求参数、响应数据格式等。保存配置信息:当用户通过页面配置…...

【数据结构与算法】:插入排序与希尔排序

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

前端性能优化——javascript

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

Docker容器化技术(使用Docker搭建论坛)

第一步&#xff1a;删除容器镜像文件 [rootlocalhost ~]# docker rm -f docker ps -aq b09ee6438986 e0fe8ebf3ba1第二步&#xff1a;使用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一些函数用法的补充】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 string类对象的修改操作 我们来看 c_str 返回c格式的字符串的操作&#xff1a; 我们来看 rfind 和 substr 的操作&#xff1a; string类非成员函数 我们来看 r…...

【Go】令牌桶限流算法

1. 限流 限流&#xff0c;顾名思义&#xff0c;限制用户请求流量&#xff0c;避免大规模并发导致系统宕机。 2. 令牌桶算法 令牌管理员以恒定的速率向令牌桶里放置一个令牌。如果桶满&#xff0c;就丢弃令牌。 请求到达时&#xff0c;都要先去令牌桶里取一个令牌&#xff0c…...

go的slice学习

并发访问slice 线上出现一粒多协程并发append全局slice的情况&#xff0c;导致内存不断翻倍&#xff0c;因此对slice的使用需要重新考虑。 并发读写的情况下&#xff0c; 可以利用锁、channel等避免竞态 问题 func TestDemo32(t *testing.T) {var wg sync.WaitGroupvar n 1…...

软件设计师17--磁盘管理

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

学点Java打小工——Day2Day3一点作业

1 猜数字&#xff08;10次机会&#xff09; 随机生成[1,1000]的一个数&#xff0c;输入你猜的数程序会给出反馈&#xff0c;直到猜对或次数用尽(10次)。 //猜数字 10次机会Testpublic void guessNumber() {Random random new Random();// [0, 1000) 1// [1, 1000]int num ra…...

【话题】2024年AI辅助研发趋势,有那些应用领域

大家好&#xff0c;我是全栈小5&#xff0c;欢迎阅读文章&#xff01; 此篇是【话题达人】系列文章&#xff0c;这一次的话题是《2024年AI辅助研发趋势》 目录 背景概念实践医药领域汽车设计领域展望未来文章推荐 背景 随着人工智能技术的持续发展与突破&#xff0c;2024年AI辅…...

蓝桥杯——数组切分

数组切分 题目分析 这里要搞清楚一个点就是满足区间内数字是连续数字的区间有什么样的特点&#xff0c;既然数字连续重新排列后的数字为n,n1,n2,n3,n4,…nlen&#xff0c;则最大数字和最小数字之差恰好是区间长度减1&#xff0c;即nlen-nlen&#xff0c;同样因为下标也是连续…...

【机器学习】进阶学习:详细解析Sklearn中的MinMaxScaler---原理、应用、源码与注意事项

【机器学习】进阶学习&#xff1a;详细解析Sklearn中的MinMaxScaler—原理、应用、源码与注意事项 这篇文章的质量分达到了97分&#xff0c;虽然满分是100分&#xff0c;但已经相当接近完美了。请您耐心阅读&#xff0c;我相信您一定能从中获得不少宝贵的收获和启发~ &#x1f…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

力扣-35.搜索插入位置

题目描述 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...