长亭百川云 - 文章详情

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

赛博回忆录

87

2024-07-13

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

  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的问题。


相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2