如何通过CodeQL TaintTracking追踪未知函数的污染变量?
让CodeQL TaintTracking追踪任意函数调用的污点传递
要实现任意函数调用时,将参数的污点传递到返回值,你可以通过重写TaintTracking::Configuration中的isAdditionalTaintStep方法,匹配函数调用实参到返回值的数据流路径。以下是针对Python场景的具体实现:
核心实现代码
import python import semmle.python.TaintTracking class MyTaintConfiguration extends TaintTracking::Configuration { MyTaintConfiguration() { this = "MyTaintConfiguration" } override predicate isSource(DataFlow::Node source) { // 定义你的污点源,示例为字符串字面量,需根据实际场景替换 source.asExpr() instanceof StringLiteral } override predicate isSink(DataFlow::Node sink) { // 定义你的污点 sink,示例为特定危险函数调用,需根据实际场景替换 sink.asExpr() instanceof CallExpr and sink.asExpr().getCalleeName() = "dangerous_function" } override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { // 匹配任意函数调用:将实参的污点传递到函数返回值 exists(CallExpr call, int idx | // node1 是函数调用的第 idx 个实参 node1.asExpr() = call.getArgument(idx) and // node2 是该函数调用的返回值(即调用表达式本身) node2.asExpr() = call and // 确保函数调用结果被赋值给变量,避免无意义的传递 exists(AssignExpr assign | assign.getRhs() = call) ) } }
代码解释
- isAdditionalTaintStep 核心逻辑:
- 匹配所有函数调用表达式
CallExpr,确认node1是该调用的任意一个实参; - 确认
node2是这个函数调用的返回值(即调用表达式本身,对应示例中pd.DataFrame(a)赋值给df的场景); - 通过
exists(AssignExpr...)过滤出被赋值的函数调用,避免追踪无返回值或未被使用的函数调用。
- 匹配所有函数调用表达式
可选优化:减少误报
全局开启所有函数的污点传递可能会引入误报,你可以添加过滤条件排除已知安全的函数:
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { exists(CallExpr call, int idx | node1.asExpr() = call.getArgument(idx) and node2.asExpr() = call and exists(AssignExpr assign | assign.getRhs() = call) and // 排除内置安全转换函数 not call.getCalleeName() in ["int", "str", "bool"] and // 排除特定库的安全函数 not call.getCallee().hasQualifiedName("pd", "Series") ) }
内容的提问来源于stack exchange,提问作者Atlantis
相关产品推荐
相关产品推荐

