
Joomla 6.1.3 - Hoch - Remote - Überschreiben - Media-Manager überschreibt Überbleibsel
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · joomla-media-override
Klasse: Privilegien-Überrest Reichweite: Remote
Joomla CMS 6.1.3 (0f2d4de) - Open Source Matters
CVE-2026-48947 brachte der Webservice-Medien-API bei, core.edit zu verlangen, wenn override gesetzt ist. Die Site-JSON-API tut das noch immer nicht. Der Standard-Author hat core.create auf com_media und kein core.edit. Der Site-Dispatcher hält core.create für ausreichend und lädt den Administrator-ApiController. postFiles() reicht dann override direkt an createFile() weiter.
Ein Standard-Author kann eine Datei ersetzen, die bereits auf der Festplatte liegt. Besucher rufen weiterhin dieselbe öffentliche URL auf und erhalten die neuen Bytes.
| ID | noch keine CVE |
| Klasse | Privilegien-Überrest / Integrität |
| Reichweite | Remote (Standard-Author, kein API-Token) |
| CWE | CWE-863, CWE-639 |
| CVSS | Mittel: 6.5 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N |
| Produkt | Joomla CMS |
| Betroffen | 6.1.3 (0f2d4de4729eb951e0878fec98c7990da07915b2), Site-com_media-JSON-API |
| Auth | Standard-Author (Gruppe 3). Kein API-Token. |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
Als Standard-Author anmelden und eine Datei ersetzen, die bereits auf der Site liegt. Das ist Defacement / Bait-and-Switch von gespeicherten Medien, keine Übernahme der Site. Die Erweiterungs-Denylist ist unverändert, es handelt sich also nicht um einen .php-Upload.
| Privileg | Methode / Pfad | Art | Lab-belegt oder abgeleitet |
|---|---|---|---|
| Eine vorhandene Mediendatei überschreiben (Logo, Artikelbild) | Site POST /index.php?option=com_media&task=api.files&format=json&path=local-images:/ mit JSON override: true | Integrität | Lab-belegt. HTTP 200, Disk-SHA geändert, öffentliches GET /images/joomla_black.png lieferte das neue PNG, das JOOMLA-MEDIA-OVERRIDE-WITNESS trägt |
| Verunstalten, was auch immer noch auf diese URL zeigt | Derselbe öffentliche Pfad, kein Cache-Bust | Integrität | Lab-belegt, dass die öffentlichen Bytes umgeschlagen sind. Abgeleitet für andere Adapter unter images/ |
| Eine neue erlaubte Datei erstellen | Derselbe POST ohne override | beabsichtigt | Author hat core.create auf com_media |
| Bearbeiten via PUT | PUT dieselbe Task, Pfad enthält den Dateinamen | n/a | Lab-belegt geschlossen. HTTP 403. putFiles() verlangt bereits core.edit |
| Erstellen, wenn der Name existiert, kein override | POST override: false (Standard) | n/a | Lab-belegt geschlossen. HTTP 409, ursprünglicher SHA unverändert bis zum override-POST |
.php oder andere verweigerte Typen hochladen | createFile / isMediaFile-Denylist | n/a | Abgeleitet geschlossen. Dieses Lab sendet nur ein PNG |
| Die Webservice-Medien-API mit override aufrufen | /api/index.php/v1/media/files | n/a | Abgeleitet geschlossen. MediaController::allowAdd prüft core.edit, wenn override gesetzt ist (CVE-2026-48947) |
| Super User / RCE | n/a | n/a | Geschlossen. Author bleibt Author |
Ich habe 6.1.3 nach der JSST-Welle 2026-07/08 festgenagelt. Die Groups-API verlangt bereits core.admin. Der Webservice-Medien-API verlangt bereits core.edit bei override. Der interne Controller noch nicht.
Der Standard-Author hat core.create auf com_media und nichts in core.edit:
{"core.admin":{"7":1},"core.manage":{"6":1},"core.create":{"3":1},"core.delete":{"5":1}}
Der Site-Dispatcher lässt core.create durch und lädt den Administrator-ApiController. postFiles() dann:
if (!$this->app->getIdentity()->authorise('core.create', 'com_media')) {
throw new \Exception(Text::_('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED'), 403);
}
$override = $content->get('override', false);
if ($mediaContent) {
$name = $this->getModel()->createFile($adapter, $name, $path, $mediaContent, $override);
Korrigierter Webservice (api/.../MediaController.php):
if ($this->input->json->get('override', false)) {
return $user->authorise('core.edit', 'com_media');
}
Bereits festgehaltene Irrwege: PUT als den Überrest zu behandeln (PUT ist bereits 403); den Webservice-Pfad als noch offen zu behandeln (CVE-2026-48947 hat ihn geschlossen); 409 ohne override als Fehlschlag zu lesen (das ist der beabsichtigte create-if-absent-Pfad). Theater: eine Reverse Shell. Das Orakel ist POST override 200 plus PUT 403 plus öffentliches GET des Witness-PNG.
Überreste desselben Pins: levels API, menu items API, articles catid.
python3 joomla-media-override-Abraxas-Labs.py
oder
cd lab
./run.sh
Ziel nur http://127.0.0.1:19540. Image joomla:6.1.3-php8.3-apache plus mariadb:11.4.
SUCCESS joomla-media-override post-http=200 override=yes bytes-changed=yes put-http=403 no-edit=yes conflict-http=409 JOOMLA-MEDIA-OVERRIDE-WITNESS
Dieselbe override -> core.edit-Prüfung wie MediaController::allowAdd innerhalb von ApiController::postFiles() vor createFile(). PUT auf core.edit belassen.
0f2d4de4729eb951e0878fec98c7990da07915b2)ApiController.php postFilesGNU Affero GPL v3.0. Siehe LICENSE. Nur Loopback-Lab. Keine Gewährleistung.