CVE-2021-43798
这里以 Graana 的任意文件读取漏洞举例说明使用方法(初学 Codeql,如有错误之处,轻点喷)
该漏洞版本为 8.0.0 - 8.3.0 , 修复版本为 8.3.1, 8.2.7, 8.1.8, 8.0.7
这个漏洞发生在
/public/plugins/:pluginId/* api 中,当输入的 pluginId存在时,会匹配*内容,使用filepath.Clean清理路径中的多余字符后,直接拼接到pluginFilePath,然后使用os.open(pluginFilePath)打开该文件,最终回显到页面。而且plugins api权限为public,是未授权的,任何人都可以查看。
fmt.Println(filepath.Clean("./.../../../../../../../etc/passwd"))输出:../../../../../etc/passwd 只清除了前面的./.../../
Codeql分析
生成 codeql 数据库
sink
os.open(),这个显而易见
source
我将
Source 点定在了macaron.Params()函数网上的文章都是以
github.com/grafana/grafana/pkg/api/routing.RouteRegister作为起始点,这就导致一个问题,写完的规则只对grafana项目起作用,不通用。仔细研究会发现,
RouteRegister的实现是以gopkg.in/macaron.v1框架为基础的,但是官方的go/ql/lib/semmle/go/frameworks/Macaron.qll,只是实现了一个重定向相关的检测规则,emmm,只能自己动手写了。
其实就是获取
net/http中Request.Context的值,而参数r,又是通过pkg/macaron/context.go
修改
go/ql/lib/semmle/go/frameworks/Macaron.qll文件,加入如下代码单独执行,可以找到污染点

直接将 sink、source 拼接跑,并没有出结果,因此需要一些处理来连接数据流
isAdditionalTaintStep
这里 tyskill 师傅说的很详细,引用一下
- 限制函数为Params
- 函数可被污染就说明参数可控,那么就让pred节点作为参数
- SimpleAssignStmt结构表示一个赋值表达式,如
a+=b,Rhs表示等号右边,通过查看源码可知Params函数调用几乎都是在等号右边,因此可以通过该结构减少误报
- 最后将输出节点连接到赋值表达式
运行,成功发现该漏洞

加入工具监控、扫描
因为项目中调用 Codeql 将扫描结果保存为文件,这里需在文件头添加一些描述,完整代码如下
将此 ql 文件路径加入配置文件
config.yaml中, - go/ql/src/myRules/ReadFile.ql ,之后程序会自动对监控的项目运行此条规则,等待捡洞即可(笔者已经捡到了^_^)效果图


项目的具体介绍请看 https://github.com/ZhuriLab/Yi
参考
- 作者:yhy
- 链接:https://fireline.fun/article/page-24
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。


.png?table=block&id=2ed97da5-45e9-8064-bc5e-ea3540aaeb5c&t=2ed97da5-45e9-8064-bc5e-ea3540aaeb5c)





.png?table=block&id=2f897da5-45e9-80f3-be17-c682d5baa107&t=2f897da5-45e9-80f3-be17-c682d5baa107)

