Moodle 5.2.3 - Hoch - Remote - SQLi - enrol_database fügt course idnumber in SQL ein
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · moodle-enrol-database-sqli
Moodle LMS 5.2.3 - Moodle
Klasse: SQLi Reichweite: Remote
enrol_database::db_get_sql escaped weiterhin und konkateniert. MSA-26-0005 / MDL-88138 hat auth_db als Execute($sql, [$value]) parametrisiert. Dieses Plugin hat diese Form nicht übernommen. Standardwerte in den Einstellungen: dbsybasequoting=0, localcoursefield=idnumber. Die Senke ist die externe Einschreibungsdatenbank. Der Moodle-Core $DB liegt nicht auf diesem Pfad.
Ein bearbeitender Lehrer auf einer Seite mit aktiviertem enrol_database setzt die Kurs-idnumber. Cron interpoliert sie. Zusätzliche Zeilen kommen aus der Einschreibungs-DB zurück.
| ID | noch keine CVE |
| CWE | CWE-89 |
| CVSS | Hoch: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Produkt | Moodle |
| Betroffen | 5.2.3 Tag v5.2.3 (344232c15336c71b80f9aca8359ce0e0a9f3d116). Plugin enrol_database muss aktiv sein. |
| Auth | bearbeitender Lehrer (Kurs-idnumber, Standard-Local-Map) |
| Lizenz | GNU Affero GPL v3.0 |
| Lab | nur 127.0.0.1 |
Ein bearbeitender Lehrer auf einer Seite mit aktiviertem enrol_database injiziert SQL in die externe Einschreibungsdatenbank, indem er die Kurs-idnumber setzt. Cron sync_enrolments führt dann dieses SQL aus.
| Berechtigung | Methode / Senke | Recon / Integrität / Verfügbarkeit | Lab-belegt oder abgeleitet |
|---|---|---|---|
| Ein SQL-Fragment in das externe Einschreibungs-SELECT einschleusen | Cron sync_enrolments -> db_get_sql($table, array($coursefield=>$course->mapping), ...) -> $extdb->Execute($sql) | Integrität des Query-Strings | Lab-belegt. Konkateniertes SQL ist WHERE courseid = 'LABCOURSE\'' OR 1=1 -- ' |
| Einschreibungszeilen anderer Kurse auf dieser externen DB lesen | Dasselbe SELECT, nachdem der String geschlossen wurde | Recon | Lab-belegt. Sauber: 1 Zeile teacher-local. Injektion: 2 Zeilen inklusive MOODLE-ENROL-DATABASE-SQLI-WITNESS |
| Die Abfrage überspringen, wenn das Plugin aus ist | Dasselbe Gadget, plugin=off | n/a | Lab-belegt geschlossen. executed=false, leeres SQL, 0 Zeilen |
| Dieselbe Payload als gebundenen Parameter halten | auth_db-Überbleibsel von MSA-26-0005: Execute($sql, [$value]) | n/a | Lab-belegt geschlossen. style=param lieferte 0 Zeilen, SQL enthält ? |
| Moodle-Benutzer, die in zusätzlichen Zeilen genannt werden, einschreiben / ausschreiben / Rollen zuweisen | Nachdem Cron requestedenrols anwendet | Integrität der Einschreibungen | Abgeleitet. Lab stoppt bei zusätzlichen Zeilen auf der Einschreibungs-DB |
| FILE / INTO OUTFILE als der Einschreibungs-DB-Benutzer | Dieselbe Senke, falls dieses Konto FILE hat | Integrität / Verfügbarkeit dieses DB-Hosts | Abgeleitet. Nicht demonstriert. Kein OS-LPE |
| Studentengesteuerter Pfad | Nur wenn Admin localuserfield=email (oder ähnlich) mappt | n/a | Abgeleitet. Standardpfad ist Lehrer-idnumber |
Geschlossen bei diesem Überbleibsel: Moodle-Core $DB; Plugin deaktiviert (keine Abfrage); unauthentifizierter Zugriff; OS-Shell; gestapelte Abfragen (dieses mysqli-Gadget ist Single-Statement). Standard-Moodle ohne enrol_database ist nicht dieser Bug.
Gleiche Pin-Überbleibsel: Blackboard img file read, grades feedback IDOR, hidden grade items.
Ich habe moodle/moodle v5.2.3 nach MSA-26-0042/0043 gepinnt. MSA-26-0005 hat auth_db mit einem Platzhalter geschlossen. Ich habe enrol_database geöffnet, weil es mit derselben Art externer DB spricht und weiterhin db_addslashes hat.
dbsybasequoting ist standardmäßig 0, also wird nur ' verdoppelt. Ein Backslash-Quote in der idnumber schließt den MySQL-String.
Bereits festgehaltene Irrwege: Moodle-Core $DB als Senke zu behandeln (ist es nicht); dies als OS-LPE zu bezeichnen, weil FILE als MySQL-Privileg existiert (nicht demonstriert, nicht dieses Überbleibsel); Studenten-E-Mail als Standard-Map (Admin muss localuserfield ändern). Eine Reverse Shell. Theater.
Getreues Gadget der Pin-Builder, keine vollständige Moodle-PHP-App. php:8.3-cli bedient die kopierten db_get_sql / db_addslashes / db_encode. mysql:8.0 hält zwei Einschreibungszeilen.
python3 moodle-enrol-database-sqli-Abraxas-Labs.py
oder
cd lab
./run.sh
Ziel nur http://127.0.0.1:19570. Compose-Projekt moodle-enrol-database-sqli. Der Stack wird nach dem Lauf abgebaut.
SUCCESS moodle-enrol-database-sqli how=gadget plugin-off=no-query clean-rows=1 inject-rows=2 sql-concat=yes param-rows=0 extra=yes sink=enrol-db MOODLE-ENROL-DATABASE-SQLI-WITNESS
Kopiere die parametrisierten Abfragen von auth_db (MDL-88138). Übergib den gemappten Kurs-/Benutzerwert als Execute($sql, [$value]). Konkateniere db_addslashes nicht in '$value'. Füge einen Test hinzu, dass ein Quote in der Kurs-idnumber keine Zeilen aus anderen Kursen zurückliefert.
lib.php (db_get_sql, db_addslashes, sync_enrolments)auth_dbGNU Affero GPL v3.0. Siehe LICENSE. Nur Loopback-Lab. Keine Gewährleistung.