java自动化审计
codeql
CodeQL是一个免费开源的代码语义分析引擎(GitHub购买之后的开源项目),其利用QL语言对代码、执行流程等进行“查询”,以此实现对代码的安全性白盒审计,进行漏洞挖掘。
靶场
在网上找到的一个简单的靶场,spring的项目,使用的jdk1.8。
codeql安装
到目前为止,codeql已经更新到v2.7.3版本,
-
下载codeql:下载地址:https://github.com/github/codeql-cli-binaries/releases
-
放入环境变量:
export PATH=/Home/CodeQL/codeql:$PATH
、source /etc/profile
,方便我们后期使用vscode插件。 -
下载codeql sdk:
git clone https://github.com/Semmle/ql
-
下载codeql vsc插件:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qFSwtYgf-1691635253819)(https://image.3001.net/images/20211221/1640052799_61c1383f458046e86b2eb.png!small)]
只需要几步下载就可以完成codeql环境的部署
生成codeql数据库
codeql并不提供语法树解析,只是提供对外查询的接口,所以我们需要给他生成database帮助其进行查询(这里检测的是我在网上clone下的靶场)。
codeql database create databasePath --language="java" --command="mvn clean install --file pom.xml" --source-root=sourcePath
databasePath:数据库路径(要保存到哪)
sourcePath:源文件代码存放路径
执行完之后就会生成对应的数据库,这里需要注意,mvn的路径问题。
测试语句
-
首先用vscode打开codeql sdk,在
ql/java/ql/src
下创建一个test.ql来编写测试脚本。 -
在codeql选项卡中打开之前创建的数据库
-
在test.ql中编写 select “hello word”,右击选择执行ql,选择测试的数据库
如果执行完毕之后出现如下洁面,则说明环境搭建完毕
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vKYxwE4Z-1691635253822)(https://image.3001.net/images/20211221/1640052807_61c138476f6423d286b50.png!small)]
到此为止就可以在test.ql下编写检测脚本了。
codeql语法
和sql语句很类似,可以通过AST视图查看到当前数据库中的内容:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l3JTCEjx-1691635253824)(https://image.3001.net/images/20211221/1640052851_61c1387330cc931c9cf7c.png!small)]
这里简单介绍基本的使用方法
from [datatype] var
where condition(var = something)
select var
对应下面的
from int i
where i = 1
select i
第一行指定的变量,第二行条件判断,第三行输出内容。
类库可以通过查看AST中的内容进行确定
名称 | 解释 |
---|---|
Method | 方法类,Method method表示获取当前项目中所有的方法 |
MethodAccess | 方法调用类,MethodAccess call表示获取当前项目当中的所有方法调用 |
Parameter | 参数类,Parameter表示获取当前项目当中所有的参数 |
这只是举例说明,例如下面这段代码:
import java
from Method method
select method
可以查询出当前项目的所有方法。
下面这段是存在过滤的代码:
import java
from Method method
where method.hasName("getStudent")
select method.getName(), method.getDeclaringType()
查找名称为getStudent的方法和对应的类
并且codeql提供了一种谓词的方法帮助来分割复杂的逻辑代码:
import java
predicate isStudent(Method method) {exists(|method.hasName("getStudent"))}
from Method method
where isStudent(method)
select method.getName(), method.getDeclaringType()
详细的语法内容可以参考:https://codeql.github.com/docs/codeql-language-guides/basic-query-
for-java-code/
污点分析
污点分析可以抽象成一个三元组〈sources, sinks, sanitizers〉的形式, 其中, source即污点源,
代表直接引入不受信任的数据或者机密数据到系统中; sink即污点汇聚点, 代表直接产生安全敏感操作 (违反数据完整性) 或者泄露隐私数据到外界
(违反数据保密性); sanitizer即无害处理,
代表通过数据加密或者移除危害操作等手段使数据传播不再对软件系统的信息安全产生危害.污点分析就是分析程序中由污点源引入的数据是否能够不经无害处理,
而直接传播到污点汇聚点.如果不能, 说明系统是信息流安全的; 否则, 说明系统产生了隐私数据泄露或危险数据操作等安全问题.
简单的理解是,source参数输入的位置,sink危险函数执行的位置,sanitizers过滤函数
通过定义上述三点内容可以定位出一条参数传递链,当然sanitizers可以不存在。
设置source
通过override predicate isSource(DataFlow::Node src) {}
设置source,这是大多常用的source入口,包括spring的也在其中。
设置sink
override predicate isSink(DataFlow::Node sink) {
exists(Method method, MethodAccess call |
method.hasName("query")
and
call.getMethod() = method and
sink.asExpr() = call.getArgument(0)
)
}
上述代码是一个谓语,查询方法名为query的方法。
当然,目前检测的是SQL注入,所以当jdbc执行query方法,则为进入了sink。
Flow数据流
from VulConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select source.getNode(), source, sink, "source"
通过config.hasFlowPath(source, sink)
设置source和sink,这样codeql就可以帮助自动检测漏洞,检索调用链。
测试
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.QueryInjection
import DataFlow::PathGraph
class VulConfig extends TaintTracking::Configuration {
VulConfig() { this = "SqlInjectionConfig" }
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
exists(Method method, MethodAccess call |
method.hasName("query")
and
call.getMethod() = method and
sink.asExpr() = call.getArgument(0)
)
}
}
from VulConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select source.getNode(), source, sink, "source"
上述是拷贝的他人写好的,代码也是上面所讲,运行之后就可以看到所有进入query方法的链路了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rhqxg32u-1691635253828)(https://image.3001.net/images/20211221/1640052860_61c1387c118af7ef50e37.png!small)]
可以点击对应的source和sink查看位置,可以看到,codeql已经帮我们整理出了5条调用链
一步步跟踪第一条调用链,可以得出完整的调用链路:
indexLogic.getStudent(username);
indexDb.getStudent(username);
String sql = "select * from students where username like '%" + username + "%'";
jdbcTemplate.query(sql, ROW_MAPPER);
至此,简单的SQL注入就能查询得到。
codeql缺点
虽然codeql的优点非常的多,但是也是存在一个比较明显的缺点:不能直接通过打包好的程序进行代码审计,当你得到的只是一个jar包,那么将会比较棘手,因为现在市面上的反编译程序反编译的结构都是不太满意,在我的使用体验中其实个人感觉idea是算是最完美的了,但是还是可能存在一些反编译出现问题一点语法错误的地方,最终可能导致编译过程中codeql解析的不准确。
Wker_java_audit
从公司回学校又接近三个周的时间了,虽然白天是在上班,但是晚上的时间相对比较宽裕一些,包括现在已经是凌晨了,我还可以在这里敲键盘,主要是工作是在学校进行,我在外面租了一个出租屋,保证自己的工作不会被舍友打扰和打扰到舍友。
在前几天log4j这个洞爆出之前(听说log4j这个在2020年就有人用codeql扫到了),有看到过一篇通过ASM追踪堆栈查看反序列化漏洞的文章,虽然没有完全看完,但是感觉这种自动化代码审计应该是可行的。
所以在回到学校这接近三个周,晚上我都会抽出一点时间实现一下这个自动化代码审计的工具,目前已经简单实现出了一个初代版本,如果反响比较好的话呢我会继续更新。
为了弥补codeql不能够直接检索打包好的程序,所以我在开发了Wker_java_audit
,当然名字其实没有想好,暂时先这样子叫吧。
思路
我的思路是这样子的:
-
解析jar包,因为打包好的要不是war要不是jar
-
解析class文件结构
-
反编译class文件,得到方法的语法树,当然其他类似注解,属性之类的都是需要获取的
-
优化语法树执行流,其实就是将一些比较笨重的操作进行优化,类似于编译器做的一些优化
-
生成java代码,方便进行审计
-
编写相应脚本,根据语法树查询危险的数据流向
-
脚本中增加过滤,根据过滤函数进行剪枝
大体可以分为上述的7步,也就是将反编译工具和codeql结合起来做到可以实现自动化审计闭源代码的效果。
在这里我还是拿上面的的靶场进行演示。
首先需要准备:
-
靶场
-
Wker_java_audit
使用方法
java -jar DecompileDialog.jar
运行起来,运行起来之后将会让你选择项目jar包,我们选择靶场的jar包,程序就会打开。
spring的项目在BOOT-INF\classes
中能找到对应的class文件。
首先我们可以先对比一下反编译的效果。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3pgqgMVB-1691635253830)(https://image.3001.net/images/20211221/1640052869_61c13885981fd244c3bc7.png!small)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BeSbTIix-1691635253833)(https://image.3001.net/images/20211221/1640052883_61c13893633e2c00f6162.png!small)]
其实效果上的话呢还是比较相似的。
当然反编译这一块的内容我还是做的比较仔细的,就不给大家完全展开看了,最重要的还是要分享对于分析的思路。
codeql是通过类似于sql语句的方式进行检索的,而我还是沿用之前的cheetah,进行更有逻辑的结构分析。
我给大家带了一个例子,是针对于sql注入的,这里详细给大家介绍一些具体是怎样,这里先给大家看一下执行的结果,选择cheetahLangue标签,挑选script下的sqlI.cheetah
然后执行。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AdcF9dye-1691635253835)(https://image.3001.net/images/20211221/1640052897_61c138a1599733f97fffb.png!small)]
可以看到,最终也打印出了所有的流程,并且也进行了颜色区分和信息处理。
sqlI.cheetah:
#define filter1=String.valueOf(.*?)
#define filter2=Integer.valueOf(.*?)
function filter(sentence){
a = StrRe(sentence,filter1);
if(GetArrayNum(a) != 0){return 0;}
a = StrRe(sentence,filter2);
if(GetArrayNum(a) != 0){return 0;}
return 1;
}
function track(className,methodName){
array allNode;
allNode = TrackVarIntoFun(className,methodName,0,"org/springframework/jdbc/core/JdbcTemplate","query",0);
size = GetArrayNum(allNode);
if(StrFindStr(GetJavaSentence(allNode[ToInt(size-1)]),".query(",0) != "-1"){
i = 0;
print(methodName."参数流动:");
cc = 7;
cs = 1;
while(i < size){
sentence = GetJavaSentence(allNode[i]);
if(filter(sentence) == 0){cc = 5;cs = 5;printcolor("想办法绕过此类:",4);}
if(i == ToInt((size-1))){
if(cc != 5){cs = 2;cc = 3;}
}else{}
if(cc == 5){printcolor("[-]",6);}else{printcolor("[+]",1);}
printcolor(GetClassName(GetNodeClassName(allNode[i]))." ",cc);
printcolor(sentence.StrRN(),cs);
i = ToInt(i+1);
}
}
return 0;
}
function main(args){
className = "com/l4yn3/microserviceseclab/controller/IndexController";
methods = GetAllMethodName(className);
size = GetArrayNum(methods);
i = 0;
while(i < size){
if(methods[i] != "<init>"){track(className,methods[i]);
}
i = ToInt(i+1);
}
}
脚本编写
我来解释一下具体是做了一些什么事情,对于语法不懂的可以看我之前的cheetah渗透测试脚本语言的内容。
首先在main函数中指定我们要检索的class名称,通过支持库中的GetAllMethodName
得到所有的方法名称,当然<init>
和<cinit>
这两个是构造方法和静态代码块的内容,我们就不看了,如果不是这两个函数,就调用track
函数进行分析,track中调用支持库提供的TrackVarIntoFun
。
TrackVarIntoFun:
参数1:起始类
参数2:起始方法
参数3:起始方法参数下标
参数4:目标方法的类
参数5:目标方法:参数6:目标方法的参数下标
返回值:执行流node数组
通过调用这个函数得到执行流,返回的执行流中包含着class名称和对应的Node,这个Node并不是一个字符串而是一个AST,这个AST通过GetJavaSentence
方法可以得到对应的java语句,通过GetNodeClassName
可以得到类名称。
下面就是挨个输出,只是输出的时候进行了剪枝,当然这种剪枝并不是完全正确的,但是我咋是没有提供更好的剪枝函数。
这里的剪枝是通过正则匹配Integer.value进行剪枝,当然后期可以自行添加。
如果在路径中存在一处sanitizers
,则被阻断,这样就用红色的进行输出。
如果整个路径都没有过滤函数,那最后的sink就用绿色打印出来,这样子会比较直观。
整个脚本没有什么难点,底层的复杂逻辑我已经实现了,但是肯定还是有一些不足的。
我们还可以测试一下里面的XXE漏洞。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bfYrvreo-1691635253837)(https://image.3001.net/images/20211221/1640052907_61c138abe20f821253622.png!small)]
当然,脚本内容大相径庭,无非就是起始类和目标类有所更改。
TrackVarIntoFun(className,methodName,0,"javax/xml/parsers/DocumentBuilder","parse",0);
当然,如果有兴趣,你也可以看spring的代码:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PEc7OhMj-1691635253839)(https://image.3001.net/images/20211221/1640052917_61c138b5f2e8ee187cbdc.png!small)]
目前存在的一些缺陷,如果有反响的话呢之后会修复的。
-
or 拼接问题,目前看起来很丑
-
new int[]{1,2,3} 类似语句解析成分块的问题
-
目前只支持追踪参数流向,无法满足很多情况
工作顺利~
我们还可以测试一下里面的XXE漏洞。
[外链图片转存中…(img-bfYrvreo-1691635253837)]
当然,脚本内容大相径庭,无非就是起始类和目标类有所更改。
TrackVarIntoFun(className,methodName,0,"javax/xml/parsers/DocumentBuilder","parse",0);
当然,如果有兴趣,你也可以看spring的代码:
[外链图片转存中…(img-PEc7OhMj-1691635253839)]
目前存在的一些缺陷,如果有反响的话呢之后会修复的。
-
or 拼接问题,目前看起来很丑
-
new int[]{1,2,3} 类似语句解析成分块的问题
-
目前只支持追踪参数流向,无法满足很多情况
工作顺利~
学习网络安全技术的方法无非三种:
第一种是报网络安全专业,现在叫网络空间安全专业,主要专业课程:程序设计、计算机组成原理原理、数据结构、操作系统原理、数据库系统、 计算机网络、人工智能、自然语言处理、社会计算、网络安全法律法规、网络安全、内容安全、数字取证、机器学习,多媒体技术,信息检索、舆情分析等。
第二种是自学,就是在网上找资源、找教程,或者是想办法认识一-些大佬,抱紧大腿,不过这种方法很耗时间,而且学习没有规划,可能很长一段时间感觉自己没有进步,容易劝退。
如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!
第三种就是去找培训。
接下来,我会教你零基础入门快速入门上手网络安全。
网络安全入门到底是先学编程还是先学计算机基础?这是一个争议比较大的问题,有的人会建议先学编程,而有的人会建议先学计算机基础,其实这都是要学的。而且这些对学习网络安全来说非常重要。但是对于完全零基础的人来说又或者急于转行的人来说,学习编程或者计算机基础对他们来说都有一定的难度,并且花费时间太长。
第一阶段:基础准备 4周~6周
这个阶段是所有准备进入安全行业必学的部分,俗话说:基础不劳,地动山摇
第二阶段:web渗透
学习基础 时间:1周 ~ 2周:
① 了解基本概念:(SQL注入、XSS、上传、CSRF、一句话木马、等)为之后的WEB渗透测试打下基础。
② 查看一些论坛的一些Web渗透,学一学案例的思路,每一个站点都不一样,所以思路是主要的。
③ 学会提问的艺术,如果遇到不懂得要善于提问。
配置渗透环境 时间:3周 ~ 4周:
① 了解渗透测试常用的工具,例如(AWVS、SQLMAP、NMAP、BURP、中国菜刀等)。
② 下载这些工具无后门版本并且安装到计算机上。
③ 了解这些工具的使用场景,懂得基本的使用,推荐在Google上查找。
渗透实战操作 时间:约6周:
① 在网上搜索渗透实战案例,深入了解SQL注入、文件上传、解析漏洞等在实战中的使用。
② 自己搭建漏洞环境测试,推荐DWVA,SQLi-labs,Upload-labs,bWAPP。
③ 懂得渗透测试的阶段,每一个阶段需要做那些动作:例如PTES渗透测试执行标准。
④ 深入研究手工SQL注入,寻找绕过waf的方法,制作自己的脚本。
⑤ 研究文件上传的原理,如何进行截断、双重后缀欺骗(IIS、PHP)、解析漏洞利用(IIS、Nignix、Apache)等,参照:上传攻击框架。
⑥ 了解XSS形成原理和种类,在DWVA中进行实践,使用一个含有XSS漏洞的cms,安装安全狗等进行测试。
⑦ 了解一句话木马,并尝试编写过狗一句话。
⑧ 研究在Windows和Linux下的提升权限,Google关键词:提权
以上就是入门阶段
第三阶段:进阶
已经入门并且找到工作之后又该怎么进阶?详情看下图
给新手小白的入门建议:
新手入门学习最好还是从视频入手进行学习,视频的浅显易懂相比起晦涩的文字而言更容易吸收,这里我给大家准备了一套网络安全从入门到精通的视频学习资料包免费领取哦!
如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!
![](https://img-blog.csdnimg.cn/img_convert/5038c791428a513aca3d99aac6d0bed5.jpeg)