#!/usr/bin/env python3 """ MongoDB honeypot. Implements the MongoDB wire protocol OP_MSG/OP_QUERY handshake. Responds to isMaster/hello, listDatabases, and authenticate commands. Logs all received messages as JSON. """ import asyncio import json import os import socket import struct from datetime import datetime, timezone HONEYPOT_NAME = os.environ.get("HONEYPOT_NAME", "mongodb") LOG_TARGET = os.environ.get("LOG_TARGET", "") # Minimal BSON helpers def _bson_str(key: str, val: str) -> bytes: k = key.encode() + b"\x00" v = val.encode() + b"\x00" return b"\x02" + k + struct.pack(" bytes: return b"\x10" + key.encode() + b"\x00" + struct.pack(" bytes: return b"\x08" + key.encode() + b"\x00" + (b"\x01" if val else b"\x00") def _bson_doc(*fields: bytes) -> bytes: body = b"".join(fields) + b"\x00" return struct.pack(" bytes: # OP_REPLY header: total_len(4), req_id(4), response_to(4), opcode(4)=1, # flags(4), cursor_id(8), starting_from(4), number_returned(4), docs header = struct.pack( " None: if not LOG_TARGET: return try: host, port = LOG_TARGET.rsplit(":", 1) with socket.create_connection((host, int(port)), timeout=3) as s: s.sendall((json.dumps(event) + "\n").encode()) except Exception: pass def _log(event_type: str, **kwargs) -> None: event = { "ts": datetime.now(timezone.utc).isoformat(), "service": "mongodb", "host": HONEYPOT_NAME, "event": event_type, **kwargs, } print(json.dumps(event), flush=True) _forward(event) class MongoDBProtocol(asyncio.Protocol): def __init__(self): self._transport = None self._peer = None self._buf = b"" def connection_made(self, transport): self._transport = transport self._peer = transport.get_extra_info("peername", ("?", 0)) _log("connect", src=self._peer[0], src_port=self._peer[1]) def data_received(self, data): self._buf += data while len(self._buf) >= 16: msg_len = struct.unpack("