Skip to content

[critical] fix: [wiki] escape SPARQL literal built from user text - #869

Open
elhoim wants to merge 1 commit into
MISP:mainfrom
elhoim:fix/060-wiki-sparql-injection
Open

[critical] fix: [wiki] escape SPARQL literal built from user text#869
elhoim wants to merge 1 commit into
MISP:mainfrom
elhoim:fix/060-wiki-sparql-injection

Conversation

@elhoim

@elhoim elhoim commented Aug 31, 2026

Copy link
Copy Markdown
Member

BLUF — wiki.py interpolates untrusted text into a SPARQL literal unescaped, allowing query injection.

  • Problemmisp_modules/modules/expansion/wiki.py builds its SPARQL query by concatenating the untrusted text attribute into a quoted literal, and SPARQLWrapper does not escape it, so a value containing a double quote or backslash injects arbitrary SPARQL into the query sent to Wikidata.
  • Fix — Escapes backslashes and double quotes before interpolation.
  • Effect — Analysts enriching attributes from shared events or feeds can no longer have the query manipulated into falsified enrichment results.

The defect

misp_modules/modules/expansion/wiki.py built its SPARQL query by string-concatenating the untrusted text attribute directly into a quoted literal:

query_string = 'SELECT ?item \nWHERE { \n?item rdfs:label"' + request.get("text") + '" @en \n}\n'

SPARQLWrapper does not escape values interpolated into a manually built query string. Any text value containing a double quote (or backslash) breaks out of the string literal, letting an attacker-controlled attribute inject arbitrary SPARQL into the query sent to Wikidata's public endpoint.

Impact

The wiki expansion module is typically run against attribute values pulled from event data, which may originate from external/untrusted sources (e.g. shared events, automated feeds). A crafted text value can manipulate the SPARQL query executed on behalf of the analyst, altering or corrupting the enrichment results returned into the MISP event. The endpoint is read-only and public, so this is query manipulation / false enrichment output, not data exfiltration or compromise of the endpoint itself.

The fix

Escape backslashes and double quotes in text before interpolating it into the query string literal, following standard SPARQL literal escaping rules. Text with no special characters produces an identical query to before, so there is no behaviour change for the common case.

Verification

  • .venv/bin/python -m py_compile misp_modules/modules/expansion/wiki.py — compiles cleanly.
  • Fixer's full run: flake8 clean (rc=0); test suite 161 passed, 4 skipped, 5 subtests passed in 37.61s.

Found during a review of the repository; other findings are being submitted as separate PRs.

🤖 Generated with Claude Code

The Wikidata Lookup module builds a SPARQL query by concatenating the
attacker-controlled `text` attribute directly into a quoted RDF literal.
A value containing a double quote breaks out of the literal and lets an
analyst-supplied attribute value inject arbitrary SPARQL into the query
sent to Wikidata's public endpoint, changing what is matched or causing
a malformed query the module reports as an opaque "wikidata API not
accessible" error instead of the real cause.

Escape backslashes and double quotes in the text before interpolating
it into the literal, matching the escaping SPARQL string literals
require.

Verified with flake8 (clean) and the full pytest suite against a local
modules server on port 6760: 161 passed, 4 skipped, 5 subtests passed,
matching the documented baseline.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018dfYpyaSZd1nxSRLr8suj8
@elhoim elhoim closed this Sep 3, 2026
@elhoim elhoim reopened this Sep 3, 2026
@elhoim elhoim changed the title fix: [wiki] escape SPARQL literal built from user text [critical] fix: [wiki] escape SPARQL literal built from user text Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant