Dalle 23:59 del 31/03/2017 alle 23:59 del 02/04/2017 è stato possibile partecipare alla CTF di HackInBo, organizzata da Voidsec e dagli amici di Hacktive Security.
I primi 45 in classifica avranno la possibilità di accedere ai LAB di HackInBo il 7/05/2017, infatti per la 3° volta, nella sua edizione primaverile, HackInBo durerà 2 giorni, il primo con diversi talk e una tavola rotonda conclusiva, mentre durante il secondo i vincitori della CTF si potranno cimentare in alcuni laboratori tenuti dai relatori e da altri esperti di vari settori legati al mondo della Sicurezza Informatica.
Il nostro team ha partecipato alla CTF e siamo lieti di condividere con voi passo per passo come abbiamo risolto le varie challenge.
La CTF era studiata per rispecchiare uno scenario realistico, ovvero non con l’approccio jeopardy, di conseguenza non si poteva “scegliere” quale challenge fare, ma esisteva un percorso abbastanza (lo vedremo più avanti) ferreo che passava per passaggi obbligati.
Ai partecipanti veniva fornito unicamente un link a un sito web, che era il punto di partenza della CTF: http://ctf-hib.thesthack.com
Per trovare la prima flag è stato sufficiente visualizzare il sorgente della home page e decodificare il base64 contenuto nel commento HTML.
|
|
La CTF era configurata per bannare chi facesse eccessivo utilizzo di tool automatici di scansione (es. Acunetix) e reindirizzava questa tipologia di tentativi verso la pagina 403.php.
Analizzando il sorgente di questa pagina è stato possibile trovare la seconda flag.
Questa flag ha bloccato la maggior parte dei partecipanti alla CTF, infatti era necessario sfruttare una SQL Injection molto difficile da scovare data la posizione insolita e i filtri applicati.
Dopo aver fuzzato tutti i campi disponibili abbiamo provato a lavorare con il cookie settato dalla pagina (PHPSESSID).
Questo cookie normalmente viene impostato alla creazione di una sessione PHP e viene utilizzato per tenere attiva la sessione degli utenti e riferirsi alla variabile $_SESSION lato server in cui vengono normalmente inseriti i dati di sessione di un utente. Dopo aver provato una serie di Payload abbiamo identificato la presenza di una SQL Injection Blind Time Based, tuttavia la presenza di una serie di filtri non permetteva di sfruttarla ed è stato necessario sostituire gli spazi con i commenti di MySQL /**/
e i caratteri <> con la keyword di MySQL BETWEEN
.
Malgrado queste accortezze, impostando gli accorgimenti in fase di detection, con sqlmap risultavano dei falsi positivi, di conseguenza è stato necessario effettuare la fase di detection senza utilizzare alcun tamper e la fase di exploitation con i tamper space2comment
e between
.
Salvando quindi la richiesta a una delle pagine vulnerabili (es. search.php) in un file req_search.txt
e lanciando il seguente comando è stato possibile far riconoscere la vulnerabilità a sqlmap.
|
|
Lanciando successivamente questo comando è stato possibile ottenere lo user di MySQL in uso.
|
|
Una volta dumpato il database markito_db
è stato possibile trovare nella tabella aact
il PHPSESSID
dello user tgialli, ovvero la flag.
5, 'tgialli', '*70AB5C6D9BA2E215AB6B746C8C459AAF3BDF9DC4', 'tgialli@example.com', '0', 'bkmu18q6edsn2h74kge1sp2eu3'
Ottenuto il cookie di sessione di tgialli è stato sufficiente impostarlo nel nostro browser per poter accedere come tgialli e recarci in user.php, dove analizzando il sorgente è stato possibile trovare una nuova flag.
Nella pagina user.php abbiamo notato la possibilità di inviare una richiesta di supporto all’amministratore del sito.
Abbiamo innanzitutto provato a mandare una Question con il seguente contenuto, per verificare la possibilità di inserire codice HTML e il fatto che qualcuno (o qualcosa) controllasse le richieste.
|
|
Visualizzando gli access.log del nostro server abbiamo visto una richiesta da parte dell’IP del server della CTF con come refferer: http://ctf-hib.thesthack.com/support/support_inquiry_gerijhgrw545427hgt2hjgg8u398.html
Visitando tale pagina abbiamo trovato il nostro payload e questo ci ha dato la possibilità di vedere se e quali caratteri venissero filtrati dall’applicativo. Dopo alcuni tentativi abbiamo scoperto che script
, alert
e altri caratteri venivano rimossi, quindi abbiamo scritto un payload che rispettasse tali regole con lo scopo di identificare il cookie dell’amministratore, non essendo presente nel DB appena dumpato.
|
|
Nei nostri access.log abbiamo ricevuto queste richieste.
Il cookie dell’amministratore era la nostra flag.
PHPSESSID=7fa26c8192a47a49b9530be18e1310e5
Utilizzando il cookie appena ottenuto è stato possibile accedere alla sezione amministrativa del sito administrator.php (questa pagina è stata ottenuta effettuando una scansione con dirsearch: dirsearch --url "http://ctf-hib.thesthack.com/" -e php
).
Navigando le varie sezioni disponibili abbiamo identificato la pagina settings.php come unica con parametri dinamici, nello specifico caso abbiamo notato la presenza di un cookie editor con il seguente contenuto.
TzoxMToiU3R5bGVFZGl0b3IiOjM6e3M6ODoiZmlsZXBhdGgiO3M6MTU6Ii4vY3NzL2Fzc2V0LmNzcyI7czo4OiJmdWxscGF0aCI7czoyNjoiL3Zhci93d3cvQ1RGL2Nzcy9hc3NldC5jc3MiO3M6NzoiYXVkaXRvciI7TzoxMzoiU2VjdXJpdHlDaGVjayI6Mjp7czo3OiJhdHRhY2tzIjthOjI6e2k6MDtzOjk6IihbLl0rXC8pLyI7aToxO3M6ODoiKFx4MDApJC8iO31zOjc6InJlcGxhY2UiO3M6MjoiLi8iO319
Una volta effettuata una base64_decode
abbiamo identificato il seguente oggetto PHP serializzato.
O:11:"StyleEditor":3:{s:8:"filepath";s:15:"./css/asset.css";s:8:"fullpath";s:26:"/var/www/CTF/css/asset.css";s:7:"auditor";O:13:"SecurityCheck":2:{s:7:"attacks";a:2:{i:0;s:9:"([.]+\/)/";i:1;s:8:"(\x00)$/";}s:7:"replace";s:2:"./";}}
Nella pagina in questione era presente una textarea contente il file asset.css, lo stesso a cui si fa riferimento nella variabile filepath dell’oggetto StyleEditor, di conseguenza abbiamo provato a modificare tale path con quella di altri file, ottenendone il sorgente.
Arrivati a questo punto abbiamo scaricato il sorgente dei file collegati a settings.php, così da poter scoprire se fosse possibile ottenere una Remote Command Execution
sul server attraverso la unserialize.
/var/www/CTF/settings.php
|
|
/var/www/CTF/config/editor.php
|
|
Appena ottenuto il codice un sorriso ci ha coperto i volti, essendo lo stesso codice utilizzato durante la nostra CTF Hands Off My Money.
Fondamentalmente settings.php effettuava una unserialize dell’oggetto presente nel cookie, instanziando 2 oggetti PHP (StyleEditor
e SecurityCheck
) di cui potevamo controllare tutte le variabili pubbliche.
Al __wake_up
della classe StyleEditor
veniva effettuata una sostituzione nella variabile fullpath
dei caratteri presenti nell’array attacks
con la stringa presente nella variabile replace
, a patto che questa non contenesse nessuna delle stringhe presenti nell’array badwords
.
Tale sostituzione veniva fatta dalla funzione preg_replace di PHP, la quale, in presenza del modifier /e nel primo parametro, esegue il codice PHP presente nel secondo argomento.
Di conseguenza inserendo nel nostro oggetto serializzato una stringa presente in fullpath all’interno di attacks, seguito da un /e e del codice PHP in replace, a patto che questo non fosse presente in badwords, questo codice veniva eseguito.
Tuttavia per ottenere RCE
sul server era necessario bypassare i controlli presenti nelle badword
s, per farlo abbiamo utilizzato la funzione assert, la quale svolge la medesima azione di eval
; al suo interno abbiamo inserito una str_replace, che sostituiva gli spazi all’interno della parola s y stem
, infine all’interno della system abbiamo inserito $_GET['a']
, ottenedo di fatto che la pagina eseguisse system($_GET['a'])
e che il controllo delle badwords fosse bypassato.
Il payload finale pertanto è il seguente.
O:11:"StyleEditor":3:{s:8:"filepath";s:19:"./config/editor.php";s:8:"fullpath";s:22:"/var/www/CTF/index.php";s:7:"auditor";O:13:"SecurityCheck":2:{s:7:"attacks";a:2:{i:0;s:7:"(php)/e";i:1;s:8:"(\x00)$/";}s:7:"replace";s:58:"assert(str_replace(' ','','s y s tem(').'$_GET["a"]'.')');";}}
Dalla precedente scansione con dirsearch era stato possibile identificare la pagina http://ctf-hib.thesthack.com/invoker/JMXInvokerServlet/ con il seguente contenuto.
Abbiamo quindi provato ad effettuare una cat
del file /var/www/CTF/invoker/JMXInvokerServlet/index.php
e abbiamo trovato la flag al suo interno.
/*Double rainbow flag: 6333d7fdc399af3b94177f037de19c2f*/
Arrivati a questo punto potevamo eseguire comandi arbitrari sulla macchina target, abbiamo quindi provveduto ad effettuare una reverse shell per semplificare l’interazione con il server e, ricordandoci la presenza di un riferimento all’IP 10.0.0.165
nel file settings.php
proprio in merito a una PCI Zone, abbiamo controllato quali interfacce di rete fossero presenti.
Ottimo! Ecco il nostro IP nella medesima /24
del server PCI, non avendo a disposizione nmap sul server target abbiamo provveduto a scriverne un mini sostituto in bash
, sfruttando netcat
per vedere le porte aperte del server PCI.
$ for port in `seq 1 65535`; do nc -z 10.0.0.165 $port && echo "$port Open"; done 22 Open 80 Open 65099 Open
Avendo la porta 80 aperta abbiamo provato con curl
a vedere se fosse presente un webserver e se fosse esposta qualche pagina.
Provando ad effettuare una curl
su /server
siamo entrati in possesso del binario esposto sulla porta 65099
del server 10.0.0.1
65.
Scaricato il binario in locale abbiamo provveduto ad analizzarlo.
Il file in questione era un eseguibile a 32-bin
linkato dinamicamente e utilizzava libc
. Analizzandone il comportamento con strace
abbiamo identificato che all’avvio bindava la porta 65099 e forkava un processo, il quale rimaneva in ascolto di eventuali connessioni.
Aprendo il binario in gdb abbiamo provato ad inviare una stringa composta da 1000 A per vedere come si comportava.
Successivamente abbiamo provato con 2000 A, ottenendo una sovrascrittura di EIP
e un crash del programma.
A questo punto era chiaro che fosse presente un buffer overflow
che ci permetteva di aver controllo di EIP
. Quindi con checksec
abbiamo analizzato le restrizioni presenti per l’exploitation.
Come si può vedere NX
risultava abilitato, di conseguenza non era possibile scrivere uno shellcode
nello stack
ed eseguirlo, proprio perché era NX (Not Executable)
, per l’exploitation era necessario quindi effettuare una ROP chain
. Non essendo però presenti gadget
utili nel binario stesso era necessario utilizzare una ret2libc
e sfruttare le funzioni incluse in libc (es. system
).
Per prima cosa è stato necessario trovare la corretta versione di libc
. Questo era possibile attraverso la versione del kernel e del sistema operativo presenti nel changelog.txt
, tuttavia anche con questi dati non era one-shot la scelta, quindi durante la CTF è stato fornito l’address della system
come hint ( (gdb) p system $1 = {} 0xb7e643e0 <__libc_system>
).
Avendo l’indirizzo della funzione system, sapendo che ASLR era disabilitato e avendo individuato il buffer overflow è stato possibile scrivere un exploit che facesse le seguenti cose:
Il problema di questo exploit è che non potevamo sapere con certezza la posizione del comando nello stack dell’eseguibile sul server target, tuttavia un bruteforce era possibile in quanto l’indirizzo era compreso tra 0xbfffe000 e 0xbfffffff.
Di conseguenza l’exploit finale è il seguente.
sploit.py
|
|
launcher.py
|
|
$ for i in `python launcher.py`; do python sploit.py $i; done
Lanciandolo veniva eseguita una bind shell sul server 10.0.0.165 sulla porta 4647, alla quale era possibile collegarsi ed eseguire comandi arbitrari sul server target.
Effettuando un cat del file flag.txt è stato possibile ottenere la flag.
pci zone flag: 95429c6709bb99d1ed06d2a99bc6ffbc
Avendo ottenuto RCE sul server della PCI è stato possibile recuperare la flag di questa challenge.
Il file php completo è il seguente.
/var/www/PCI/index.php
|
|
Per una descrizione completa di questa challenge ecco 2 writeup molto ben fatti:
Avendo compromesso il primo server è stato possibile dumpare il database e ottenere i dati della carta 6666 ('6666','7cLGMYqWY2bGgYPIDlE+CODHAwwLJiAMIUSghfke+QgCMNrEQyj7TlnqU4nNuZFTLsVvVWQ15jH3JYsgvwq6/CcaQczRD/0csxB7rqiR3DQ=')
, tuttavia era presente un campo token con una stringa cifrata, sapendo però che sul secondo server era presente il decrypter in php è stato sufficiente settare un cookie pci_crypt
contente il token, per ottenere in risposta la versione decifrata.
Effettuando un md5
della stringa decifrata si otteneva la flag.
$ php -r 'echo(md5("5512782764526946|170|10/08/2020"));'
bc13ff4c1b4a7ada0c6dcf2dec4e4404
Questa flag purtroppo non era accessibile in quanto era stata impostata in una costante del codice C
del server, ma non era utilizzata nello stesso, di conseguenza al momento della compilazione è stata rimossa dai processi di ottimizzazione di gcc
.
|
|
Speriamo che il nostro writeup sia di aiuto per chi si fosse bloccato durante la CTF e speriamo di vedervi tutti ad HackInBo il 6 Maggio.
Per chi volesse leggere un altro writeup il team di JBZ, di faccio orgogliosamente parte (smaury) e i cui membri sono stati gli unici a completare tutta la CTF, ne ha pubblicato uno: https://jbzteam.github.io/web/crypto/reversing/HackInBo17-SpringEdition
Su richiesta degli organizzatori sono stati rimossi i sorgenti della CTF. Nel caso non siate riusciti a partecipare e/o vogliate provare con mano ad exploitare le varie vulnerabilità contattate direttamente Hacktive Security.
Previous post