Moodle 5.2.3 - Alto - Remoto - SQLi - enrol_database concatena course idnumber in SQL
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · moodle-enrol-database-sqli
Moodle LMS 5.2.3 - Moodle
Classe: SQLi Raggiungibilità: Remota
enrol_database::db_get_sql continua a fare slash e concatenazione. MSA-26-0005 / MDL-88138 ha parametrizzato auth_db come Execute($sql, [$value]). Questo plugin non ha copiato quella forma. Valori predefiniti nelle impostazioni: dbsybasequoting=0, localcoursefield=idnumber. Il sink è il database di iscrizione esterno. Il $DB del core di Moodle non è su questo percorso.
Un docente con permessi di modifica su un sito con enrol_database abilitato imposta l'idnumber del corso. Cron lo interpola. Righe extra tornano dal DB di iscrizione.
| ID | nessuna CVE al momento |
| CWE | CWE-89 |
| CVSS | Alto: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| Prodotto | Moodle |
| Affetto | tag 5.2.3 v5.2.3 (344232c15336c71b80f9aca8359ce0e0a9f3d116). Il plugin enrol_database deve essere attivo. |
| Auth | docente con permessi di modifica (idnumber del corso, mappa locale predefinita) |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1 |
Un docente con permessi di modifica su un sito con enrol_database abilitato inietta SQL sul database di iscrizione esterno impostando l'idnumber del corso. Il cron sync_enrolments esegue poi quell'SQL.
| Privilegio | Metodo / sink | Ricognizione / integrità / disponibilità | Provato in lab o dedotto |
|---|---|---|---|
| Inserire un frammento SQL nella SELECT di iscrizione esterna | Cron sync_enrolments -> db_get_sql($table, array($coursefield=>$course->mapping), ...) -> $extdb->Execute($sql) | Integrità della stringa di query | Provato in lab. L'SQL concatenato è WHERE courseid = 'LABCOURSE\'' OR 1=1 -- ' |
| Leggere le righe di iscrizione di altri corsi su quel DB esterno | Stessa SELECT dopo la chiusura della stringa | Ricognizione | Provato in lab. Pulito: 1 riga teacher-local. Iniezione: 2 righe inclusa MOODLE-ENROL-DATABASE-SQLI-WITNESS |
| Saltare la query quando il plugin è disattivato | Stesso gadget, plugin=off | n/a | Provato in lab chiuso. executed=false, SQL vuoto, 0 righe |
| Mantenere lo stesso payload come parametro associato | residuo di auth_db di MSA-26-0005: Execute($sql, [$value]) | n/a | Provato in lab chiuso. style=param ha restituito 0 righe, l'SQL contiene ? |
| Iscrivere / disiscrivere / assegnare ruoli a utenti Moodle nominati nelle righe extra | Dopo che il cron applica requestedenrols | Integrità delle iscrizioni | Dedotto. Il lab si ferma alle righe extra sul DB di iscrizione |
| FILE / INTO OUTFILE come utente del DB di iscrizione | Stesso sink se quell'account ha FILE | Integrità / disponibilità di quell'host DB | Dedotto. Non dimostrato. Non è OS LPE |
| Percorso controllato dallo studente | Solo se l'admin mappa localuserfield=email (o simile) | n/a | Dedotto. Il percorso predefinito è l'idnumber del docente |
Chiuso su questo residuo: $DB del core di Moodle; plugin disabilitato (nessuna query); accesso non autenticato; shell del sistema operativo; query impilate (questo gadget mysqli è a singola istruzione). Il Moodle predefinito senza enrol_database non è questo bug.
Altri residui dello stesso pin: Blackboard img file read, grades feedback IDOR, hidden grade items.
Ho fissato moodle/moodle v5.2.3 dopo MSA-26-0042/0043. MSA-26-0005 ha chiuso auth_db con un placeholder. Ho aperto enrol_database perché parla con lo stesso tipo di DB esterno e ha ancora db_addslashes.
dbsybasequoting è impostato a 0 per default, quindi solo ' viene raddoppiato. Un backslash-quote nell'idnumber chiude la stringa MySQL.
Vicoli ciechi già registrati: trattare il $DB del core di Moodle come sink (non lo è); chiamare questo OS LPE perché FILE esiste come privilegio MySQL (non dimostrato, non questo residuo); email dello studente come mappa predefinita (l'admin deve cambiare localuserfield). Una reverse shell. Teatro.
Gadget fedele ai costruttori del pin, non una full Moodle PHP app. php:8.3-cli serve i copiati db_get_sql / db_addslashes / db_encode. mysql:8.0 contiene due righe di iscrizione.
python3 moodle-enrol-database-sqli-Abraxas-Labs.py
oppure
cd lab
./run.sh
Target solo http://127.0.0.1:19570. Progetto Compose moodle-enrol-database-sqli. Lo stack viene smontato dopo l'esecuzione.
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
Copiare le query parametrizzate di auth_db (MDL-88138). Passare il valore mappato di corso / utente come Execute($sql, [$value]). Non concatenare db_addslashes in '$value'. Aggiungere un test che verifichi che un apice nell'idnumber del corso non restituisca righe da altri corsi.
lib.php (db_get_sql, db_addslashes, sync_enrolments)auth_dbGNU Affero GPL v3.0. Vedi LICENSE. Solo lab su loopback. Nessuna garanzia.