https://codeql.github.com/codeql-standard-libraries/java/semmle/code/java/Maps.qll/module.Maps.html

背景描述

通过编写CodeQL脚本来查询响应包中是否包含了我所关心的敏感数据(例如手机号、身份证号),其中的一种情景是返回值是Map类型的变量,所以分享一下CodeQL对Map类型的一些支持。

CodeQL Maps模块提供的类

FreshMap
用来表示new一个Map类型的表达式
image.png
MapType
用来表示Map类型

用来表示Map对象方法的类

MapMethod
用来表示Map类型的对象所有的方法

MapMutator
用来表示Map类型里面赋值相关的方法
image.png

MapQueryMethod
用来表示Map类型里面查询相关的方法
image.png
MapSizeMethod
用来表示Map类型的Size方法

用来表示调用了Map对象方法的类

MapMutation
查看所有调用了Map对象任意方法的表达式
MapPutCall
查看所有调用了Map对象put方法的表达式

实践

CodeQL提供的Java Map类型的操作类中,在实际使用中用的比较多便是MapPutCall, MapType这两个类,通过下面这两个例子来展示一个Map类型的变量如何关联这两个类。

需求:return语句中调用了Map类型的变量mapVar,获取mapVar的key和value
image.png

  1. import java
  2. import semmle.code.java.Maps
  3. from VarAccess mapPutQualifier,VarAccess returnMapVar, MapPutCall mapPutCall, ReturnStmt returnStmt, Variable mapVar
  4. where
  5. // 声明一个Map类型的变量mapVar,这一句不写也可以,因为在后面的声明中也可以限制类型是Map
  6. mapVar.getType() instanceof MapType and
  7. // 声明mapPutQualifier是变量mapVar的一个引用
  8. mapPutQualifier.getVariable() = mapVar and
  9. // 声明returnMapVar是变量mapVar的一个引用
  10. returnMapVar.getVariable() = mapVar and
  11. // return语句里面调用了mapVar
  12. returnStmt.getResult().getAChildExpr*() = returnMapVar and
  13. // mapVar调用了put方法
  14. mapPutCall.getQualifier() = mapPutQualifier
  15. // 查询mapVar的所有key和value
  16. select mapPutCall.getKey(), mapPutCall.getValue(), mapVar

需求:return语句中调用了Map类型的变量mapVar,获取mapVal所有value的类型
这个需求的话直接用MapType会更加便捷
image.png

  1. import java
  2. import semmle.code.java.Maps
  3. from ReturnStmt returnStmt,MapType mapType
  4. where
  5. returnStmt.getResult().getAChildExpr*().getType() = mapType
  6. select mapType.getValueType()