今天早上在赛博群里看到关于 Grafana 的漏洞通告,但是twitter上没有发出细节,陈师傅和p神等大哥们一挖就挖出来了只能说太强了,由于这玩意儿使用的非常多,之前在实习的时候内网中遇到好多次,所以就来尝试不参考文章自己来挖一波,这篇文章主要是记录一下我挖掘的思路
Grafana 源码:https://github.com/grafana/grafana
之前没怎么看过go框架的代码,由于是任意文件读取所以去搜索了一下 go 中文件读取会用到的一些函数
这里搜到了 os.Open()
我这里直接全局搜索(因为猜测漏洞肯定会用到这个函数
接下来我就尝试一个个进行查看
第一个很显然参数不可控,直接放弃
依次往下粗略的看过去,说来也是运气好第二个其实就是我们的漏洞点,仔细来看一下
首先 pluginFilePath 作为参数传递给了 os.Open ,往上查看参数是否可控
首先会通过 join 来进行一个路径拼接这个不去管他,我们直接从最前面开始看
可以看到这里最上面的注释中 api 的路径为 /public/plugins/{pluginId}/*
首先会获取 pluginId 的参数,然后根据 id 来获取对应的插件,如果不存在的话就会返回 404 Plugin not found
然后 requestedFile 会获取 * 处的内容,并进行路径拼接传递给 os.Open ,那么理论上就可以造成任意文件读取
所以在这里两个点都是可控的
大致思路有了接下来就是搭建环境进行测试了,直接docker开一个环境
先随意测试一下看一下这个接口是否会有权限校验,发现返回的是 Plugin not found 而不是返回到登陆页面,所以首先可以确认这个接口是不需要权限校验的,剩下来一个问题就是如何获取 pluginId
既然不知道 pluginId 那么我们就去找就行了
进入 grafana 页面根据如下进入配置页面可以看到已安装的 plugin(要选择已安装的不然会报 404)
Burp 抓个包看一下,这里已经可以从返回包里看到 id ,但是此时的我还不确定这就是 pluginId
在源码中进行寻找,目的是寻找插件的结构体,我们传入的 pluginId 会传入 GetPlugin,返回的肯定是用插件结构体来接受,所以先去看 PluginManager 的结构体
看到 GetPlugin 返回的是 *plugins.PluginBase 跟进看一下
找到插件的结构体了,和返回包比对了一下对上了
然后就很简单了 构造一个任意文件读取就行了
由于政策原因不能发poc (虽然很多公众号都发了,所以随便找一下就行了
具体后续利用可以看忍者师傅星球和少宇师傅的 Github
文章加密码是什么操作?😂
师傅加我wx