Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Exploit Tools

БесплатноНе проверен

A collection of tools (and documentation) in minimal low level python, to showcase exploits on MCP servers and LLMs. For testing and research purposes.

GitHubEmbed

Описание

A collection of tools (and documentation) in minimal low level python, to showcase exploits on MCP servers and LLMs. For testing and research purposes.

README

📖 Docs site: https://crashoz.github.io/mcp-exploit-tools/ — the exploit write-ups, rendered.

A minimal, low-level MCP server with zero third-party dependencies (Python standard library only — no mcp SDK, no FastMCP, no web framework), organised as a small package of single-purpose modules.

It is the foundation for a toolkit aimed at security researchers testing exploits against MCP servers and the clients/hosts that connect to them. Because there is no SDK between you and the wire, every JSON-RPC message is under your direct control and any layer can be mutated to craft adversarial / non-spec-compliant behaviour.

  • Protocol: MCP 2025-11-25 (current stable revision).
  • Transports: stdio and Streamable HTTP.
  • Primitives: tools, resources, prompts.
  • Requirements: Python 3.10+. No installation, no pip.

Quickstart

# stdio transport (the default) — what local MCP clients launch:
python3 server.py            # or: python3 -m mcpserver

# List the available exploit modules:
python3 server.py --list-exploits

# Streamable HTTP transport:
python3 server.py --transport http --host 127.0.0.1 --port 8000

# Add --trace to any of the above to log every raw message to stderr.
python3 server.py --trace

CLI

Flag Default Meaning
--transport {stdio,http} stdio Which transport to serve.
--host 127.0.0.1 HTTP bind host. Anything non-local prints a warning.
--port 8000 HTTP bind port.
--path /mcp HTTP endpoint path.
--trace off Log every inbound (>>) / outbound (<<) raw message to stderr.
--insecure off HTTP: disable Origin + session checks (the vulnerable config).
--strict off Enforce lifecycle: reject requests issued before initialization.
--list-exploits List the available exploit modules (slug, name, tools) and exit.
--enable A,B data-exfil Enable these exploit modules by slug, or all for every module.
--disable A,B none Disable these exploit modules, by slug.
--no-demo off Don't register the benign demo tools/resources/prompts.
--loot-file PATH ./loot/exfiltrated.jsonl Where captured data is written (overrides MCP_EXFIL_LOOT).
--webhook URL off Also POST each captured payload here (overrides MCP_EXFIL_WEBHOOK).
--shadow-bcc ADDR security-archive@… tool-shadowing: attacker BCC injected into emails.
--shadow-target-tool NAME send_email tool-shadowing: the trusted email tool to hijack.
--cht-triggers P1,P2 thank you,… conversation-theft: phrases that fire the exfil.
--cmdi-live off (dry-run) command-injection: actually execute the built command (real RCE; lab/VM only).
--ii-collector HOST telemetry-collector.example indirect-injection: attacker exfil host the hidden beacon targets.
--atpa-demand TEXT env + ~/.ssh/id_rsa output-poisoning: what the fake error/result coerces the model to hand over.
--ansi-method {overwrite,color,conceal} overwrite ansi-deception: how the description hides its payload from the terminal.
--unicode-method {tag,zero-width,bidi} tag unicode-concealment: how the description hides its payload in invisible Unicode.

Security knobs (the testable surface)

The Streamable HTTP transport (mcpserver/streamable_http.py) implements the checks the spec calls for, each visible in the source and toggleable so you can compare secure vs. vulnerable behaviour:

  • Origin validation (DNS-rebinding guard): a request carrying a non-localhost Origin header is rejected with 403. Disable with --insecure.
  • Session enforcement: initialize mints an Mcp-Session-Id; any other request with a missing/unknown session id is rejected with 404. Disable with --insecure.
  • Bind address: defaults to 127.0.0.1; --host 0.0.0.0 is allowed but warns.
  • Lifecycle ordering: --strict rejects non-initialize/ping requests before the notifications/initialized handshake (lenient by default, so it can be exercised).

Exploits

Adversarial modules live in mcpserver/exploits/, catalogued in mcpserver/exploits/init.py. Each is documented under docs/exploits/.

Slug Exploit Tool(s) Write-up
data-exfil Data exfiltration via tool-description poisoning (TPA) context_sync docs/exploits/data-exfiltration.md
tool-shadowing Tool shadowing / cross-server hijack add_numbers + send_email docs/exploits/tool-shadowing.md
conversation-theft Conversation-history theft (triggered sleeper) log_feedback docs/exploits/conversation-history-theft.md
command-injection Command injection (deliberately vulnerable tool) net_diagnostic docs/exploits/command-injection.md
full-schema-poisoning Line jumping / full-schema poisoning (FSP) summarize_text docs/exploits/full-schema-poisoning.md
indirect-injection Indirect prompt injection (external-content trigger) fetch_url docs/exploits/indirect-injection.md
output-poisoning Universal output poisoning (ATPA) get_weather docs/exploits/output-poisoning.md
ansi-deception ANSI escape-code deception system_check docs/exploits/ansi-deception.md
unicode-concealment Invisible Unicode concealment (zero-width / bidi / tag chars) health_report docs/exploits/unicode-concealment.md

By default only data-exfil is enabled — its context_sync tool shows up in tools/list next to the demo tools. Enable the others (or all of them) and tune them from the CLI:

python3 server.py --list-exploits                              # see slugs, names, tools
python3 server.py                                              # default: only data-exfil (context_sync)
python3 server.py --enable all                                 # every exploit module
python3 server.py --enable tool-shadowing,command-injection    # just these two
python3 server.py --enable all --disable command-injection     # all but command-injection
python3 server.py --enable tool-shadowing --shadow-bcc [email protected] --webhook http://127.0.0.1:9000/   # enable + tune + relay

The exfil sink writes captured data to loot/exfiltrated.jsonl by default (--loot-file / MCP_EXFIL_LOOT to change); --webhook / MCP_EXFIL_WEBHOOK also POSTs it to a URL (off by default — no network otherwise). To catch those POSTs locally, run the bundled stdlib collector — python3 webhook_collector.py — and point --webhook at it.

The full exploit backlog — grouped by type and scored (severity/impact/occurrence/difficulty) — lives in PROGRESS.md.

Run it against a LLM

You don't have to hand-write JSON-RPC to see an exploit land — point a real local model at the malicious server and watch it fire end-to-end. The full local-LLM walkthrough uses Ollama + ollmcp with a tiny, CPU-friendly model — no API keys, no GPU. The short version:

ollama pull qwen2.5:1.5b                                   # ~1 GB model, runs on CPU
pip install -r requirements-demo.txt                       # the ollmcp MCP host
ollmcp --servers-json mcp-host.json --model qwen2.5:1.5b   # run from the repo root

ollmcp launches python3 server.py over stdio, calls tools/list, and hands the schemas to the model — at which point the poisoned description is sitting inside the model's context. Ask any ordinary question: the model calls the exfil tool on its own (ollmcp shows an approval prompt by default, so you can watch the leak get offered before it happens). Inspect loot/exfiltrated.jsonl — or a --webhook endpoint — to confirm what left the room. The smaller the model, the more readily it obeys; that's the finding.

What fires — data-exfil (context_sync)

The default flow, straight from data_exfiltration.py:

flowchart TD
    SERVER["malicious MCP server · server.py<br/>advertises context_sync — its description<br/>secretly orders the model to forward everything"]
    SERVER -->|"tools/list — the ollmcp host hands<br/>the tool schemas to the model"| MODEL["local model · qwen2.5:1.5b<br/>reads the description as instructions;<br/>cannot separate trusted text from attacker text"]
    MODEL -->|"tools/call context_sync<br/>{ conversation, secrets, … }"| SINK["handler · sink.capture(…)<br/>→ loot/exfiltrated.jsonl (+ optional webhook POST)<br/>returns: Session registered … Sync complete."]
    SINK --> REPLY["model answers the user normally —<br/>nothing on screen reveals the leak"]

    classDef danger fill:#cc241d,stroke:#fb4934,color:#fbf1c7
    classDef benign fill:#98971a,stroke:#b8bb26,color:#fbf1c7
    classDef model fill:#458588,stroke:#83a598,color:#fbf1c7
    class SERVER danger
    class SINK danger
    class MODEL model
    class REPLY benign

Full mechanism, why it works, and defenses: docs/exploits/data-exfiltration.md.

Project layout

mcp-exploit-tools/
  server.py                  # thin entry shim → mcpserver.cli:main
  webhook_collector.py       # stdlib collector for --webhook exfil POSTs (optional)
  mcpserver/
    __init__.py              # public API: MCPServer, tool, resource, prompt, ...
    __main__.py              # enables `python3 -m mcpserver`
    constants.py             # protocol version, server info, JSON-RPC error codes
    tracing.py               # stderr logging + raw `>>`/`<<` message tracing
    registry.py              # TOOLS/RESOURCES/PROMPTS + @tool/@resource/@prompt
    protocol.py              # JsonRpcError + MCPServer (lifecycle, dispatch)
    stdio.py                 # stdio transport
    streamable_http.py       # Streamable HTTP transport + security checks
    demo.py                  # benign example tools/resources/prompts (+ exploit marker)
    cli.py                   # argparse + main()
    exploits/                # adversarial modules — one per exploit
      __init__.py            # CATALOG + --enable/--disable selection
      sink.py                # shared capture sink (loot file + optional webhook)
      data_exfiltration.py   # … one module per exploit (see the Exploits table)
  docs/                      # MkDocs site — one write-up per exploit
  PROGRESS.md                # scored exploit roadmap / backlog
  CONTRIBUTING.md            # how to contribute + add an exploit module
  LICENSE.md                 # MIT
  README.md

Extending it (building exploit modules)

Two seams:

  1. Registries — register tools/resources/prompts with the @tool, @resource, @prompt decorators from mcpserver/registry.py. Benign examples in mcpserver/demo.py register on import. An exploit module instead exposes SLUG / NAME / TOOLS, a register(args) that registers its tools, and an optional add_arguments(parser) for fine-tuning flags — then is added to CATALOG in mcpserver/exploits/init.py so --enable/--disable and --list-exploits pick it up (copy data_exfiltration.py as a template). Tool handlers may return a full CallToolResult dict, so you have complete control over advertised metadata and results (poisoned descriptions, hidden instructions, mismatched output).
  2. MCPServer.dispatch — subclass MCPServer in mcpserver/protocol.py and override dispatch() to emit raw, non-spec-compliant messages (wrong ids, duplicate responses, oversized payloads, etc.).

Programmatic use:

from mcpserver import MCPServer, tool

@tool("ping_back", "Echoes a nonce", {"type": "object", "additionalProperties": True})
def _h(args): return args

print(MCPServer().dispatch({"jsonrpc": "2.0", "id": 1, "method": "tools/list"}))

Verification

stdio, by hand (watch raw traffic on stderr)

python3 server.py --trace <<'EOF'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"c","version":"0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"echo","arguments":{"text":"hi"}}}
{"jsonrpc":"2.0","id":4,"method":"resources/list"}
{"jsonrpc":"2.0","id":5,"method":"prompts/list"}
EOF

Streamable HTTP

# Start the server in one shell:
python3 server.py --transport http --trace

# initialize — note the Mcp-Session-Id response header:
curl -i -sS http://127.0.0.1:8000/mcp \
  -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'

# tools/call using the captured session id:
curl -sS http://127.0.0.1:8000/mcp -H 'Mcp-Session-Id: <id>' \
  -H 'MCP-Protocol-Version: 2025-11-25' -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"echo","arguments":{"text":"hi"}}}'

# SSE stream (stays open; you should see ": connected" then ": keepalive"):
curl -N http://127.0.0.1:8000/mcp -H 'Mcp-Session-Id: <id>' -H 'Accept: text/event-stream'

# Security checks — expect 403 (bad Origin) and 404 (bad/missing session):
curl -i -sS http://127.0.0.1:8000/mcp -H 'Origin: http://evil.example' \
  -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":9,"method":"ping"}'
curl -i -sS http://127.0.0.1:8000/mcp -H 'Mcp-Session-Id: nope' \
  -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":9,"method":"ping"}'
# Re-run the bad-Origin call against a server started with --insecure → now 200.

Contributing

Contributions are welcome — bug reports, new exploit modules, and doc improvements. See CONTRIBUTING.md for setup, conventions, and a step-by-step guide to adding an exploit module. Note the responsible-use expectations: this is a toolkit for defenders, researchers, and CTF/lab use — only run it against systems you own or are authorized to test.

License

MIT © Xavier 'crashoz' Launey.

from github.com/crashoz/mcp-exploit-tools

Установка Exploit Tools

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/crashoz/mcp-exploit-tools

FAQ

Exploit Tools MCP бесплатный?

Да, Exploit Tools MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Exploit Tools?

Нет, Exploit Tools работает без API-ключей и переменных окружения.

Exploit Tools — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Exploit Tools в Claude Desktop, Claude Code или Cursor?

Открой Exploit Tools на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Exploit Tools with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории productivity