CodeQL的自动化代码审计之路(下篇)

news2024/11/26 10:22:37

0x01 前言

CodeQL的自动化代码审计之路(上篇)

CodeQL的自动化代码审计之路(中篇)

在上一篇文章中,我们基于CodeQL官方提供的sdk实现了自动化查询数据库功能,在文章中也提到实现完整的自动化代码审计还缺少“数据库生成”相应的功能,本文主要针对“数据库生成”这一阶段来阐述整个过程实践中的优缺点。

生成数据库是整个CodeQL使用中最重要的一个步骤,对于java语言来说,生成数据库的过程要比其他语言更难。CodeQL的数据库中本质上保存的是与代码相关的AST语法树,通过VSCode提供的AST Viewer功能,可以很清晰地看出来最终生成地AST结果,如图1.1所示。熟悉词法和语法分析的小伙伴相信不会对AST的结构感到陌生。

图1.1 使用CodeQL生成的AST语法树

熟悉JAVA安全的小伙伴可能听过另一种生成AST语法树的方法GadgetInspector。如果单纯只是针对JAVA语言的话,个人觉得GadgetInspector的实现思路和效果是要优于CodeQL的,主要对比如表1.1所示。

表1.1 CodeQL和GadgetInspector对比

个人一直研究基于CodeQL的代码审计工具,主要是想解决多种语言的代码审计问题,虽然目前的严重重点还是在java语言中,但是对其他语言的兼容会是后续的研究重点。

0x02 初探

对于脚本语言(例如python)CodeQL在生成数据库的时候是很简单的,命令如下所以,注意对于脚本语言不应使用--command参数。非ARM系统去除“arch -x86_64”,后续所有命令均按此处理,不再赘述。

arch -x86_64 codeql database create /Users/xxx/CodeQL/databases/giza --language=python --source-root=/Users/xxx/Downloads/giza

在成功生成数据库之后一般会有successfully的提示,如图2.1所示。一般脚本语言创建数据库的过程都很简单,不容易出现问题。

图2.1 使用CodeQL创建python语言对应的数据库

由于java是一种编译型语言,创建的过程中需要指定编译命令。对于源码文件来说,典型的java语言创建数据库的命令如下所示,结果如图2.2所示。

arch -x86_64 codeql database create /Users/test/CodeQL/databases/mvn_test --language=java --command='mvn clean install -DskipTests' --source-root=/Users/pang0lin/java/projects/mvn_test --overwrite

--language: 指定对应源码的语言类型

--command: 执行的编译命令,对于编译型语言,此参数必填

--source-root: 指定源码路径

--overwrite: 覆盖保存生成的数据库,如果当前数据库以存在,则必填

图2.2 使用CodeQL创建java语言对应的数据库

上面的过程中几乎属于是CodeQL官方给出的关于创建数据库的典型案例,但是在现实环境中确不一定能直接拿到目标编译前的源码,一般情况下可以获取到的源码都是编译后的源码,主要表现形式如下。

1) 用于部署SpringBoot项目的jar包或者用于部署tomcat项目的war包。

2) 直接从目标WEB目录拷贝的源码文件,一般包含jsp文件、class文件、配置文件等。

在开始我们的探索之前,首先需要明确一个观点是,使用原生的CodeQL创建数据库的指令不会创建jsp文件对应的AST语法树。为了演示这个现象,我们创建一个SpringMVC的项目,并且在webapp目录中增加一个jsp文件,如图2.3所示。

图2.3 对比SpringMVC生成数据库中的文件和源代码中的区别

从图2.3中可以看出,对于SpringMVC类型的源代码,如果直接采用CodeQL官方demo的方式来生成数据库,并不会创建jsp文件对应的AST语法树。所以在图2.3右边生成的数据库中没有找到shell.jsp和index.jsp对应的文件。

如果需要了解详细的关于CodeQL创建数据库的原理,可以参考大佬的文章https://paper.seebug.org/1921/。

从大佬的文章中可以得出一个结论,如果需要CodeQL创建对应的数据库,则该文件必须要有“编译”过程。所以在实际环境中,不论是jsp文件、class文件,还第三方的jar包,都是不能直接被创建到数据库中的。

如果要用编译后的文件来生成数据库,则必须首先对把对应的文件反编译成java源文件,然后再对java源文件进行“编译”才能成功生成对应文件对应的数据库。

0x03 研究

从上面的分析中,我们首先需要明确的一个事情,就是需要对编译后的源码进行反编译。目前市面上关于java反编译的工具有很多,但是作为idea的忠实粉丝,最初的选择还是直接使用idea自带的反编译工具java-decompiler.jar。

安装了idea之后都存在java-decompiler.jar文件,默认位置是/Applications/IntelliJ IDEA.app/Contents/plugins/java-decompiler/lib/java-decompiler.jar。直接拷贝对应的jar包,源于java-decompiler.jar的用法如下:

java -cp java-decompiler.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dgs=true test/ xxx/

图3.1 使用java-decompiler.jar对目标进行反编译

但是在后面实际的利用过程中发现有大量的文件在反编译之后没法再进行编译,如图3.2所示,这是使用idea进行反编译之后得到的部分代码,在代码中可以很清晰的看到重复定义了变量_hashCode。所以再对这个代码进行编译的时候就会报错。

图3.2 Idea反编译时遇到的重复定义变量的问题

对上面的代码换一个反编译工具,使用jd-gui来对同样的代码进行反编译,得到的代码如图3.3所示。

图3.3 使用jd-gui来反编译代码

从代码中可以明显的看出jd-gui并不会出现重复定义变量的问题,类似的问题还有int i=False;这种,如图3.4所示,在IDEA反编译的代码中会出现类型不匹配的问题,但是jd-gui并不会。所以,经过实践之后,我最终抛弃了idea的java-decompiler.jar,转而开始使用jd-gui。但是jd-gui是属于界面版本工具,我们需要使用其命令行版本jd-cli。

图3.4 由于类型不匹配导致的编译错误

下一个要解决的问题是从jsp文件转java文件,熟悉java的小伙伴应该都很了解tomcat的运行机制,在tomcat解析jsp文件的过程中,会首先通过tomcat-jasper.jar包来把jsp转化为对应的java类文件,如图3.5所示。

图3.5 把shell.jsp文件转化为shell_jsp.java文件

从图3.5可以看出shell.jsp文件已经被jsper转化为shell_jsp.java类文件,此文件是可以被“编译”的。那么我们后续如果要通过CodeQL来生成jsp文件对应的数据库,本质上还是生成的类似于shell_jsp.java文件对应的数据库。

那么,如何利用tomcat-jasper.jar来把jsp转化为java?其实只需要一小段代码,如图3.6所示。

图3.6 通过JspC类把jsp文件转化为java类文件

为了能够直接在python的代码中调用对应的java代码,我把java代码打包成可以直接在命令行中调用的jar包jsp2class.jar(相关文件见源码),使用如图3.7所示。

第一个参数:jsp文件所在网站的跟目录。

第二个参数:jsp文件全路径名,相对于网站跟目录的相对路径。

第三个参数:生成的java文件保存的路径。

图3.7 使用打包好的jsp2class文件来转化jsp文件

目前我们已经解决了反编译需要的问题,剩下就是编译需要的问题。CodeQL给出的官方demo中是通过maven来触发代码的编译过程,但是实际环境中并不是所有的目标环境都是maven,参考大佬https://paper.seebug.org/1921/文章中提到的方式,可以采用ecj.jar来对目标代码进行编译。 

使用ecj.jar与传统使用javac的方式对目标进行编译有容错率更高的优点,javac在编译的过程中遇到错误会报错并退出,但是ecj存在忽略错误并继续编译的选项。通过反编译方式得到的源码在编译过程中遇到错误是很正常的现象,而ecj可忽略错误的特性很好的满足了CodeQL生成数据库的要求,对于CodeQL而言更需要的是编译过程能更全的覆盖源代码文件,而不是编译之后的结果要可运行。

ecj.jar要求jdk1.8的环境运行,完整的ecj支持的参数可以参考官方文档https://www.ibm.com/docs/zh/radfws/9.6?topic=SSRTLW_9.6.0/org.eclipse.jdt.doc.user/tasks/task-using_batch_compiler.html。如图3.8所示。

图3.8 关于ecj.jar支持的参数列表

详细了解ecj.jar支持的参数列表对于我们后期优化ecj编译过程至关重要,因为后面很容易出现的一个情况就是存在的源码在CodeQL数据库中没有生成。典型的运行方式如下所示。

java -jar ecj-4.6.1.jar -extdirs /Users/xxx/lib -encoding UTF-8 -8 -warn:none -proceedOnError -noExit @/Users/xxx/test/CodeQLpy/file.txt

-proceedOnError:指定ecj忽略错误继续运行,这对于CodeQL生成数据库很重要。

-warn:none:忽略所有警告,一般来说警告太多了,没有什么意义。

-extdirs:指定ecj编译过程中依赖的外部jar包目录。

@/Users/xxx/test/CodeQLpy/file.txt::指定要编译的目标java文件列表。

把上面编译的命令保存到sh文件中,然后就可以通过下面的命令来生成数据库,如图3.9所示。

arch -x86_64 codeql database create /Users/xxx/CodeQL/databases/test1 --language=java --command='sh /Users/xxx/Downloads/test/1.sh'

图3.9 通过ecj编译过程生成数据库

0x04 工具

我的初衷是基于CodeQL来达到半自动化代码审计的效果,通过python语言来实现整个工具的流程,虽然目前流程中还有很多已知的不足,但是基本的雏形已经有了,后面就是不断对代码进行优化的过程。

目前已经支持的功能如表4.1所示。

表4.1 项目支持的功能列表

项目运行时截图如图4.1所示。

图4.1 程序支持的参数列表

-d: 指定要进行扫描的数据库,-d和-t参数二选一出现。

-t: 指定目标源码,可以是jar包,war包,文件夹或者maven源代码。-d和-t参数二选一出现。

-c: 指定源码是属于编译前的源码还是编译后的源码,默认是属于编译前源码。

-s: 指定是否跳过环境检查。

注意,如果是-t指定的源码是属于文件夹类型,则要求文件夹必须是网站跟路径。如果不是跟路径会出现相对路径错误导致的异常。

本地运行需要依据实际情况配置config/config.ini文件。

目前的版本更多的考虑是流程功能实现,暂未考虑并发和效率,所以现在跑一个目标花的时间比较久,运行之后会在out/result/目录生成结果,如图4.2,图4.3所示。

图4.2 运行完成的结果

图4.3 运行完成之后结果保存在csv文件

环境搭建过程中注意配置config/config.ini文件。目前已知的问题如下所示。

  • 如果生成数据库的过程中出现很长一段时间无响应,可以使用页面响应的最后一条指令手动生成数据库。

codeql database create out/database/target_db --language=java --command='/bin/bash -c /Users/xxx/test/CodeQLpy/out/decode/run.sh'
  • 由于web.xml配置文件错误导致jsp文件反编译异常的。解决办法是替换web.xml文件,任意找一个可用的web.xml文件替换即可。

图4.4 异常报错情况

原创工具下载地址:

https://github.com/webraybtl/codeQlpy

如有更好建议欢迎留言交流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/115947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ggokabeito | 一般般啵~支持ggplot2和ggraph的配色包!~

1写在前面 天真的好冷啊,不知道各位穿秋裤了没有,有没有感冒。😘 这期就介绍一下ggokabeito包,是一个支持ggplot2和ggraph的即用型配色包,喜欢就去安装吧。🤪 再放一张去年拍的雪人照片,哈哈哈哈…

socket网络编程的5大误区

隐患 1.忽略返回状态 第一个隐患很明显,但它是开发新手最容易犯的一个错误。如果您忽略函数的返回状态,当它们失败或部分成功的时候,您也许会迷失。反过来,这可能传播错误,使定位问题的源头变得困难。 捕…

c++算法基础必刷题目——枚举

文章目录枚举算法1、铺地毯2、回文日期枚举算法 枚举算法是我们在日常中使用到的最多的一个算法,它的核心思想就是:枚举所有的可能。   枚举法的本质就是从所有候选答案中去搜索正确的解,使用该算法需要满足两个条件:   (1)可预先确定候选答案的数量…

[Square 2022] Hard Copy 复现

原来一直没弄过TLS的流,今天看到一个WP,按这个一步步重来一遍。 Square的题目会一直开放下载 原题点这里 下来后的数据包包含一个go的原码程序和一个流量包 流量是经过加密的,所以看不到内容。 第一步就是取得RSA的公钥。先在包里找到 S…

跟海外大牌正面PK,中国品牌如何出圈?

摘要:品牌出海看似风光无限、满是商机,但拆解开来看,无论是打造品牌还是出海,都是很漫长的过程。 导语: 后疫情时代,品牌出海成为大势所趋,从蒙牛、花西子到蜜雪冰城,越来越多的品…

web前端框架Javascript开发基础之JavaScript作用域

在JavaScript中,对象和函数也是变量。在JavaScript中,作用域是你可以访问的变量、对象和函数的集合。JavaScript有函数作用域: 这个作用域在函数内变化。 一、本地JavaScript变量 一个变量声明在JavaScript函数内部,成为函数的局部变量。 …

智慧物联网无线协同代理技术解决方案: 边缘协同感知(EICS)技术解密

无线协同代理技术指基于对目标场景状态变化的协同感知而获得触发响应并进行智能决策,属于蓝奥声核心技术–边缘协同感知(EICS)技术的关键支撑性技术之一。该项技术涉及物联网边缘域的无线通信技术领域,具体主要涉及网络服务节点与目标对象设备…

Hive+Spark离线数仓工业项目--ODS层及DWD层构建(1)

目标:自动化的ODS层与DWD层构建实现 - 掌握Hive以及Spark中建表的语法规则 - 实现项目开发环境的构建 - 自己要实现所有代码注释 - ODS层与DWD层整体运行测试成功 数仓分层回顾 目标:回顾一站制造项目分层设计 实施 ODS层 :原始数…

Vulnhub:Derpnstink靶机渗透

攻击机kali:192.168.56.108 靶机derpnstink:192.168.56.114 扫描同网段下存活主机 扫描服务版本信息 开启了21、22、80端口,分别对应着ftp、ssh、http服务,打开浏览器进行访问 查看源代码发现flag1和info.txt 点开info.txt 这个的…

volantis使用php实现Gitee友链

介绍 本文使用Gitee实现Volantis主题友链功能,其中友链使用的是site标签,因为该标签可以展示图片,如 {% sites repo:example.json api:https://example.dearxuan.com %} 友链api的最终路径为 api “版本” repo,如上面代码的最…

【精准三点定位求解汇总】利用Python或JavaScript高德地图开放平台实现精准三点定位(经纬度坐标与平面坐标转换法求解、几何绘图法求解)

【精准三点定位求解汇总】利用Python或JavaScript高德地图开放平台实现精准三点定位(经纬度坐标与平面坐标转换法求解、几何绘图法求解) 众所周知,如果已知三个点的坐标,到一个未知点的距离,则可以利用以距离为半径画…

初学Nginx

目录 (一)Nginx介绍 (二)Nginx安装和启动 1,Nginx的目录结构 2,查看Nginx版本指令 3,检查配置文件是否正确 4,启动和关闭Nginx服务 (三)Nginx的配置 1&a…

智能工厂数字孪生的运用

信息技术与制造业的融合是当前的发展趋势,数字孪生其中 就包括了“智能工厂”的技术。在过去几年的发展中,我国的工业企业已经初步形成了 5 层的信息化体系结构,而在新一代的智能工厂体系中,借助数字孪生技术让工厂实现智能化生产…

SpringMVC使用Jackson、双向关联的解决策略@JsonIgnore

目录:一、SpringMVC和Jackson的关系:二、Jackson解决双向关联导致的栈溢出问题的解决方法:三、如何使用JsonIgnore:一、SpringMVC和Jackson的关系: SpringMVC返回return Object类型数据给前端时会自动调用jackson将Object类型的数…

pytorch深度学习常用命令

文章目录命令目录.item().items()最大值的索引torch.argmax(input, dimNone, keepdimFalse)_, predicted torch.max(outputs.data, 1).data.detachunsqueeze()squeeze()命令目录 .item() 只是一个值 (浮点型的),适合…

计算机基础知识(基础入门小白专属)三

♥️作者:小刘在这里 ♥️每天分享云计算网络运维课堂笔记,疫情之下,你我素未谋面,但你一定要平平安安,一 起努力,共赴美好人生! ♥️夕阳下,是最美的,绽放,…

精通MyBatis原理,看这两篇就够了!|原创

本文详细介绍了阅读MyBatis源码的学习思路,并且对源码做了详细注释,讲解了整个Mybatis的启动过程。本文篇幅较长,建议收藏阅读,非常适合用于面试前的重点复习。点击上方“后端开发技术”,选择“设为星标” &#xff0c…

BSV 上的零知识隐私机器学习

此前,我们已经演示了在 BSV 上运行一个成熟的深度神经网络,其中机器学习 (ML) 算法的输入和模型都是公开的。在实践中,通常希望将输入或模型保持在链下并因此保持私有,同时仍确保 ML 算法如实运行。我们通过将零知识证明 (ZKP) 应…

你确定没有滥用 goroutine 吗

写在前面 学习 golang ,路还很长呢,犹记得刚开始学习 golang 的时候,写起来确实非常简单,有很多包和工具使用,不需要重复造轮子,但是要真的学好一门语言作为工具,对于其原理是非常有必要学懂的…

极限多标签学习综述(Extreme Multi-label Learning)

A Survey on Extreme Multi-label Learning 先给地址: https://arxiv.org/abs/2210.03968 博主曾整理过Multi-Label Image Classification(多标签图像分类),但这类任务中所用的数据集往往较小,分类数量并不多。但在更…