| Título | emekaokoye mcp-rdf-explorer Latest Server-Side Request Forgery |
|---|
| Descrição | Summary
A Server-Side Request Forgery (SSRF) vulnerability exists in the mcp-rdf-explorer MCP Server implementation (src/mcp-rdf-explorer/server.py). The root cause is that the url parameter in the explore_url tool is passed directly to Python’s requests.get() with no input validation, allowing the server process to send HTTP GET requests to arbitrary destinations — including internal services, cloud metadata endpoints, and attacker-controlled servers.
The url parameter provided by the MCP client is consumed directly in server.py, where requests.get(url) is executed without scheme restrictions, domain allowlisting, IP-range restrictions, port restrictions, request timeouts, or redirect hardening.
Details
This MCP server exposes explore_url, intended to fetch RSS/OPML feeds and extract RDF triples into the feed graph. However, an MCP client can supply any URL value as input. Because no validation is performed on url before the outbound request, the backend performs outbound HTTP GET requests to attacker-controlled or internal targets.
This enables SSRF through direct tool invocation (and potentially via prompt-influenced tool arguments in real agent workflows).
Vulnerable Code
Version: v1.0.0
File: src/mcp-rdf-explorer/server.py
@mcp.tool()
def explore_url(url: str, ctx: Context) -> str:
"""Extract triples from an RSS/OPML feed URL and store them in the feed graph.
...
"""
graph = ctx.request_context.lifespan_context["graph"]
feed_graph = ctx.request_context.lifespan_context["feed_graph"]
try:
response = requests.get(url)
feed = feedparser.parse(response.content)
for entry in feed.entries[:5]:
feed_graph.add((rdflib.URIRef(entry.link), rdflib.URIRef("http://example.org/title"), rdflib.Literal(entry.title)))
if not (HAS_SPARQLSTORE and isinstance(graph, SPARQLStore)):
for triple in feed_graph:
graph.add(triple)
return f"Added {len(feed.entries[:5])} entries from {url} to feed_graph"
except Exception as e:
logger.error(f"Explore URL error: {str(e)}")
raise
There is no validation on url before the HTTP request. There is no restriction on:
URL scheme (e.g., http://, https://, or other schemes supported by requests),
destination hostname/domain,
resolved IP range (e.g., loopback/private/link-local),
destination port,
redirect targets,
request timeout or response size.
As a result, attacker-controlled url input reaches the HTTP request sink directly.
Note: The same SSRF pattern also exists in execute_on_endpoint and connect_external_triplestore, where user-supplied endpoint URLs are passed to rdflib.SPARQLStore(query_endpoint=endpoint) without validation. This report focuses on explore_url as the primary HTTP-based SSRF vector.
Data Flow (source → sink)
MCP client invokes tools/call for explore_url with attacker-controlled url.
MCP server receives url argument in explore_url.
Server executes requests.get(url).
Outbound HTTP GET request is sent from the server’s network context to the attacker-selected destination.
Response body is parsed by feedparser.parse(response.content); parsed feed metadata may be stored in feed_graph and merged into the main graph.
Malicious attackers can inject malicious tool parameters through methods such as indirect prompt/message injection or hijacking MCP client behavior, thereby triggering SSRF.
Using MCP Inspector (Proof of Concept)
Prerequisites
Dependencies installed for mcp-rdf-explorer (pip install -r requirements.txt).
MCP Inspector available (npx @modelcontextprotocol/inspector).
A request-capture endpoint (e.g., webhook.site) or local HTTP listener.
Steps
Start the vulnerable server via Inspector (stdio transport):
npx -y @modelcontextprotocol/[email protected] python src/mcp-rdf-explorer/server.py -- --triple-file test.ttl
The test.ttl file is as follows:
@prefix ex: <http://example.org/> .
ex:person1 ex:name "Alice" .
ex:person2 ex:name "Bob" .
Open the Inspector URL printed in the terminal.
In Inspector:
Transport: stdio (default when launched via npx)
Click Connect
Open Tools
Select explore_url
Start a local server using PowerShell: python -m http.server 8000
Use payload in explore_url: http://127.0.0.1:8000/ssrf-test
Observe the local PowerShell and receive the corresponding information.
Impact
Server-Side Request Forgery (SSRF). |
|---|
| Fonte | ⚠️ https://github.com/emekaokoye/mcp-rdf-explorer/issues/3 |
|---|
| Utilizador | skywings (UID 98274) |
|---|
| Submissão | 25/06/2026 10h23 (há 2 meses) |
|---|
| Moderação | 13/08/2026 17h12 (2 months later) |
|---|
| Estado | Aceite |
|---|
| Entrada VulDB | 389554 [Model Context Protocol mcp-rdf-explorer 1.0.0 MCP Server server.py explore_url Elevação de Privilégios] |
|---|
| Pontos | 20 |
|---|