起因
最近用 influxdb + grafna 整了一个可视化服务器监控平台,同时监控我的电脑和两台的云服务器的运行情况。
整个项目的架构非常简单:
信息采集器----->influxdb------>grafna
- 信息采集器是用go写的,部署到两个服务器上定时采集有关 cpu、磁盘、网络、内存的各项数据。
- influxdb 是一个时序性数据库,它提供了RESTful API,并起了一个web服务监听8086端口,来接收信息采集器采集到的的数据
- grafna是数据可视化平台,默认监听3000端口,提供web服务。
由于以前完全没有使用过的 influxdb,实在不怎么放心,索性研究了一下influxdb相关的漏洞。
经过
我百度了下,发现influxdb 有一个认证绕过漏洞,不少人写了复现文章。但是经过我个人的实践,发现文章中还是有不少谬误:
- influxdb 默认的管理员用户并不是 admin,而是在于部署人员怎么设置。所以在利用时,可能需要枚举管理员用户名,才能成功伪造token。只要开启了身份认证选项,必须至少有一个管理员级别的用户
- 这个认证绕过漏洞实际上是使用者的配置疏忽导致的(或者也可以说因为influxd 1.x 并没有遵循 secure by default原则,导致使用者如果使用默认配置,influxd就是不安全的。)influx 1.x 默认情况下不会开启身份效验, influxd 1.7.6 以下的版本,默认 使用 空字符串来生成jwt的消息认证码。我在shodan上搜索了一下,发现不少influxd ,都没有开启身份效验,任意用户都可以登录,更悲催的是有些使用者开启了身份认证,却忘记了修改jwt 秘钥为其他字符串。
- 有些复现文章只是将怎么利用漏洞操作了一遍,并没有彻底分析清楚漏洞形成的原因,给出合理的修复建议。有些文章非常粗暴简单的说:升级版本为> 1.7.6。 其实完全没有必要升级版本, 只要修改配置文件中的 [http] shared-scret = “你的秘钥” 就可以了。想想看,如果你的influxdb 已经存了很多数据,要升级版本需要花费多大的代价。
下面先来谈谈这个漏洞如何利用吧。
jwt token 秘钥泄漏的利用
这个漏洞涉及到jwt token的消息认证码的伪造。那么jwt token是怎么生成的?如何使用jwt token来实现登录功能呢?
一般情况下,web登录系统会这样设计:前端发送 username +password给后端,后端对username 和password 进行效验,如果数据库中确实有对应的数据,就向前端发送一个携带了消息认证码的 jwt token 令牌,证明用户登录成功。
以后用户请求需要鉴权的api时,只需要携带 该token令牌 给服务端即可。服务端 输入秘钥和消息,再次生成消息认证码进行比对,对token的合法性进行验证,看看是不是自己颁发的令牌。验证通过,则允许用户访问对应资源。
那么攻击者能不能伪造jwt token 呢?要解答这个问题,就得讨论下jwt的原理了:
一个 jwt 的token 由三部分组成:base64编码的头部.base64编码的体部.消息认证码。
头部的alg 定义的是生成消息认证码的算法,即采用 HMAC sha256 来生成消息认证码 。只要输入消息和秘钥给消息认证码算法,该算法就可以生成一个定长的消息认证码。发送时,将消息和消息认证码一起发送给接受者。 由于攻击者并不知道秘钥,所以一旦篡改了消息,一定无法生成一个相同的消息认证码。这这样就确保了token的不可否认性和完整性,同时因为只有服务端知道秘钥,所以token只有可能是服务端生成的。
读到这里,你肯定明白了:只要攻击者知道了秘钥,就可以伪造任意的消息认证码。
那么influxdb 1.x 是如何实现身份效验呢?攻击者能不能知道生成jwt的秘钥呢?
Influxdb 1.x 的版本,身份认证方式有三种:
1.get 或者post 传参 ?u=username&p=password
2.basic auth 身份认证
3.jwt token
influxdb 使用一个 共享秘钥(shared secret)去生成消息认证码,默认情况下,这个 shared secret 是空字符串。所以需要用户在配置文件中配置 自定义的秘钥。这个秘钥字符串越长,则越安全。
[http]
shared-secret = "my super secret pass phrase"
但是往往部署influxd 的人,只知道在配置文件开启身份效验(auth-enabled 设为true),但是忘记了配置shared-secret 的值。甚至于很多主机根本没有开启身份效验(可以去shodan搜搜8086看)
这种配置疏忽,导致:即便开启了身份效验,但是由于攻击者已经知道了生成消息认证码的秘钥(空字符串),所以攻击者自己可以生成的合法的token,来通过身份效验。
由于服务端会读取 token payload 中username字段,在之后的业务逻辑中使用,所以:
- 如果一开始你就知道 influxd 中有那些用户,那么可以利用该漏洞,直接伪造身份访问敏感资源。
- 如果一开始你并不知道有哪些用户,那么可以利用该漏洞,枚举用户名,直到发现存在的用户名为止。(枚举思路:常用管理员用户列表+数据库名列表+其他信息收集得到的可能的用户名,数据库名列表可以通过调用influxd 的debug api 获取)
influxdb > 1.7.6 的版本,为了避免使用者犯这种 配置疏忽。只要配置文件中的shared-secret 的值为 空字符串,就关闭jwt token的认证方式。
讲道理,influxdb 1.x 在secure by default 方面做得确实很糟糕,除了jwt token 的默认秘钥非常简单外。如果你忘记了打开 pprof-auth-enabled 选项。那么攻击者可以调用一些api 来收集很多有用的敏感信息。
influxd 的信息搜集:
我大致总结了一下,有以下可用接口:
-
http://ip:8086/debug/vars
可以收集到数据库信息,influxd 可执行文件的路径,influxd 配置文件的路径,influxd 的启动时间,运行了多长时间等信息 -
http://ip:8086/debug/requests
跟踪其他 http客户端的 write 和query的请求
可以拿到和influxdb 通信的其他主机的ip地址,写入量,读取量的 -
http://ip:8086/ping
可以用来查询对应实例是否在线,以及influxd 的版本号(请求任何一个api 都可以,就在响应头的:x-influxdb-version 字段) -
http://ip:8086/ping/query?q=show users
执行查询语句,这个api不单单可以用来查询数据,还可以执行新建管理员用户或者新建数据库等危险语句。(前提是你通过了身份效验)
自动化利用
工具是开发者渗透思路的体现。有了上面的思路,我们完全可以开发一个自动化的利用工具。
工具运行思路如下:
1.请求敏感api 进行信息收集,判断是否开启了身份认证,是否存在身份认证绕过漏洞。
2.如果没有开启身份认证,直接调用query api,创建一个管理员用户
3.如果开启了身份认证 且 存在token 伪造漏洞,就枚举用户名,尝试伪造token,调用query api,创建一个管理员用户。
工具地址:https://gitee.com/nothing-is-nothing/biu-network-security-toolbox
防御手段:
只要正确配置,基本上就可以防御的差不多了。
- 开启身份认证 auth-enabled = true
- 修改jwt share-screat 为一个很长字符串 (如果你的版本大于>1.7.6 也可以不修改)
- 开启 pprof-auth-enabled =true
开启后,攻击者要通过调用debug 相关的api获取敏感信息都需要身份认证
influx 中两种用户类型:管理员用户和普通用户,开启身份效验必须得有一个管理员用户。因为只有管理员级别的用户才拥有管理用户和管理数据库级别的权限。普通用户只能对某个表具有读写权限。
参考资料:
- influxd1.7 官方文档:https://docs.influxdata.com/influxdb/v1.7/administration/authentication_and_authorization/
其中详细介绍了 influxd 身份认证的机制,以及如何生成 jwt token
influxdb执行命令方式 https://www.cnblogs.com/gongniue/p/12496866.html - influxdb1.7.5认证绕过漏洞复现 https://www.freesion.com/article/5206948842/
- https://www.debian.org/security/2021/dsa-4823
- 在线jwt token生成网站:https://jwt.io/