0x00 前言
早上看到chybeta发群里这漏洞的推特截图,隐隐约约记得我们也在用,不过我也没咋在意,直到chybeta和p?秒秒钟复现压力来到了我这边。我十分无助的硬着头皮打开github看grafana的最新版本代码,结果花了一中午,终于在吃了个猪肘饭后分析好了。(唉想上吊了)
下面就大概讲讲我是如何以一个不懂GO基础语法的角度来复现该漏洞的。另外后面会解释一下一些其他实际中遇到的情况。
0x01 分析与复现
我们可以借助历史漏洞的思路来简单分析一下
看到这个经典漏洞是先从api.go文件入手,那么我们也从这个入手 这边可以通过github的在线vscode直接审计,比如
我们打开api.go
看到很多路由,第二个参数看起来是需不需要验证。当然我们也能看到一些只有两个参数的,猜测两个参数的是默认不需要验证。那么既然是未授权读取文件,首先先找未授权接口:
通过名字就能判断功能,看两个参数还是三个参数就能知道授权不授权,粗略的看一下找一找未授权可能需要读取文件的功能接口。看看哪个函数里看着像读取文件的,比如有什么filepath什么的参数,通过这种方式快速过一下,大概就能找到了。比如这个plugins
进入getpluginassets里看看,
具体过程看上图即可,你看这个plugins就挺像的( 那么payload就很显然了,我们找到一个默认存在或者大概率存在的plugin比如grafana-clock-panel、prometheus等,我在复现的时候用的welcome
GET /public/plugins/welcome/../../../../../../../../etc/passwd HTTP/1.1
Host: localhost:3000
Connection: close
0x02 探测插件
因为插件本身可能会因为环境不同而不同,那么有几种思路
字典爆破
收集全部插件列表直接进行爆破请求确保百分百命中,可以直接去官方进行抓取字典(https://grafana.com/grafana/plugins/) 当然群友也收集了一些热门的作为字典
alertmanager
grafana
loki
postgres
grafana-azure-monitor-datasource
mixed
prometheus
cloudwatch
graphite
mssql
tempo
dashboard
influxdb
mysql
testdata
elasticsearch
jaeger
opentsdb
zipkin
alertGroups
bargauge
debug
graph
live
piechart
status-history
timeseries
alertlist
candlestick
gauge
heatmap
logs
pluginlist
table
welcome
annolist
canvas
geomap
histogram
news
stat
table-old
xychart
barchart
dashlist
gettingstarted
icon
nodeGraph
state-timeline
text
页面抓取
这个思路也是群友提供的,在登录页面上的js里可以探测到一些插件信息,只要用其中的一个插件名称来做字典就行了。也就是说可以按如下步骤进行:
-
请求登录页面 -
抓取登录页面的js里的插件名称 -
组合成url进行请求
比如上图的welcome插件和timeseries插件名称都有了,这些在登录页面就能获取到
0x03 400错误
关于400错误是很多人都遇见到的。这个错误主要出现在存在中间件反向代理的场景下,很多人不理解为什么自己复现不了,其实根本原因在于nginx或者apache这些常见反向代理中间件会对url进行normalize的操作,简单来说就是会在转发前将’../’这些去掉,而当去掉后的路径超出web根目录的限制就会直接返回400错误而不会把请求转发到grafana,因此就会导致复现失败。下面给出normalize的大致逻辑: nginx 主要参考文章(https://www.codenong.com/cs110392483/)
-
替换”为’/’,并且判断如果存在空字符,则直接返回false ,也就是之后的400 -
替换’//’ 为 ‘/’ -
对结尾的’/.’ 和’/…’ 加上’/’ -
去除’./’ -
然后处理’…/’, 并且检查如果处理完后开头是’…/’的话就返回false,这也防止了路径穿越
apache 这个我之前分析过就直接抄自己的了
-
判断url第一个字符是不是’/’,只有option * http/1.1这种的可以接受,其他返回400错误 -
判断url编码是否符合规范,不规范的返回400错误 -
将所有的’//////’变成’/’ -
去除’/./’,如果存在’/../’或者’/.%2e/’则进行跳跃目录但是不能跨越web根目录,如果跨越返回400 另外补上url解码的一些特点 -
判断是否存在’%2f’即解码后是不是’/’,如果是就返回404 -
判断是否存在’%00’即解码后是不是’