CodeQL入门规则编写篇-SQL注入
2024-4-23 21:40:57 Author: mp.weixin.qq.com(查看原文) 阅读量:5 收藏

△△△点击上方“蓝字”关注我们了解更多精彩

0x01 概述

以java-sec-code为例子,对CodeQL提供的官方规则进行修改优化,更契合项目本身的规则。

0x02 规则优化

在官方的规则下
\ql\src\experimental\Security\CWE\CWE-089\MyBatisMapperXmlSqlInjection.ql

有个是关于MyBatisMapper注入规则,现在我们看下效果如何

可以看到,一共找到了9个注入点,那我们去看看这9个是不是都是注入点,人工验证一下。

1、查看Controller的AST

在CodeQL的插件这里,右键点击我们导入的数据库,将源码添加到我们的工作区

接下来就会在工作区发现我们的java项目



点进Controller目录,找到对应的类右键View AST,通过语法树有助于我们学习CodeQL语法,更好理解规则编写,不然老感觉很空,没具体效果。

2、分析AST

原本是在左下角,有点小,看得很麻烦,可以直接拖到控制台,放大看我们可以看到,刚刚好有9个,那就是CodeQL官方规则扫描发现这9个都存在注入,实际上并不是全部存在注入,明显存在误报,所以接下来我们要对官方的规则进行优化。

3、去除误报

分析一下MyBatisMapperXmlSqlInjectionLib,在

\ql\java\ql\src\experimental\Security\CWE\CWE-089\MyBatisMapperXmlSqlInjectionLib.qll 

这里,点击Quick Evaluation进行查询

这段查询语句,在 MyBatisMapperMethodCallAnArgument 构造函数使用了exists关键字,其作用是在CodeQL查询中定义存在某种关联关系或满足某种条件的情况,从而影响查询结果。
exists中,定义了两个变量 MyBatisMapperSqlOperation mbmxe MethodCall ma,它们分别表示 MyBatis 映射器的 SQL 操作和方法调用。
mbmxe.getMapperMethod() = ma.getMethod()指定了 mbmxe 的映射方法与 ma 的调用方法相匹配。
ma.getAnArgument() = this.asExpr()指定了方法调用m*的一个参数与当前实例相匹配。
最终结果如下:找到了调用MyBatis Mapper的sink
但是从这个结果看来存在着对应的问题,就是可以看到,这个传参的类型的Integer类型,这种是不可能存在注入的
还有就是使用了filter进行过滤,此时我们也需要对其进行排除在外
这时候就需要用到我们的isSanitizer方法,isSanitizer是CodeQL的类TaintTracking::Configuration提供的净化方法。
它的函数原型是:override predicate isSanitizer(DataFlow::Node node) {},
其实在函数原型中已经对基础类型进行了判断(忘记在哪个qll下面了,有空找找),
这里直接使用了freebuf师傅上写的规则(妙啊,前人栽树后人乘凉,怪偷)。
CodeQL从入门到放弃 - FreeBuf网络安全行业门户https://www.freebuf.com/articles/web/283795.html
override predicate isSanitizer(DataFlow::Node sink){        exists(Call call |              sink.asExpr() = call.getArgument(0) and            //这里是检查方法调用的调用者是否是名为sqlFilter的            call.getCallee().toString() = "sqlFilterd"            ) or        sink.getType() instanceof PrimitiveType or        sink.getType() instanceof BoxedType or        sink.getType() instanceof NumberType or        exists(ParameterizedType pt| sink.getType() = pt and pt.getTypeArgument(0) instanceof NumberType )    }
查找一个executeQuery()方法的调用点,并把它的第一个参数设置为sink
predicate querySink(DataFlow::Node sink) {      exists(Method method, MethodAccess call |          method.hasName("executeQuery")           and call.getMethod() = method           and sink.asExpr() = call.getArgument(0)      )  }
最终结合语句如下:找到了三处存在注入的点,
注意:
    由于我们引用了import MyBatisMapperXmlSqlInjectionLib
    所以必须要与MyBatisMapperXmlSqlInjectionLib.qll同级目录
import javaimport semmle.code.java.dataflow.DataFlowimport semmle.code.java.dataflow.FlowSourcesimport MyBatisMapperXmlSqlInjectionLib

class SqlinjectConfiguration extends TaintTracking::Configuration{ SqlinjectConfiguration() { this = "java-sec-code SqlinjectConfiguration" }
override predicate isSource(DataFlow::Node source){ source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof MyBatisMapperMethodCallAnArgument or querySink(sink)}
override predicate isSanitizer(DataFlow::Node sink){ exists(Call call | sink.asExpr() = call.getArgument(0) and call.getCallee().toString() = "sqlFilter" ) or sink.getType() instanceof PrimitiveType or sink.getType() instanceof BoxedType or sink.getType() instanceof NumberType or exists(ParameterizedType pt| sink.getType() = pt and pt.getTypeArgument(0) instanceof NumberType ) }
predicate querySink(DataFlow::Node sink) { exists(Method method, MethodAccess call | method.hasName("executeQuery") and call.getMethod() = method and sink.asExpr() = call.getArgument(0) ) }}
from SqlinjectConfiguration dataflow, DataFlow::Node source, DataFlow::Node sinkwhere dataflow.hasFlow(source, sink)select "source", source, "sink", sink, , source.getLocation()

0x03 参考学习

https://www.freebuf.com/articles/web/283795.htmlhttps://www.ctfiot.com/65681.htmlhttps://github.com/SummerSec/learning-codeqlhttps://codeql.github.com/docshttps://www.yuque.com/loulan-b47wt/rc30f7/pchp0a

END

如您有任何投稿、问题、需求、建议

NOVASEC公众号后台留言

或添加 NOVASEC 联系人

感谢您对我们的支持、点赞和关注

加入我们与萌新一起成长吧!

本团队任何技术及文件仅用于学习分享,请勿用于任何违法活动,感谢大家的支持!


文章来源: https://mp.weixin.qq.com/s?__biz=MzUzODU3ODA0MA==&mid=2247489500&idx=1&sn=36ffb89e557ecb8af780f81a49b0ed4a&chksm=fad4cacbcda343dd395136eccaceee66fb050436cf62ba6b4530fe9e3e3ba53b4a7ef6d78812&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh