Getting Root: Railsgoat
Settimana scorsa ho tenuto un talk all’Università di Parma, presso la facoltà di ingegneria, dal titolo “Vulnerability Assessment and safe coding in web applications”. Le slide le potete trovare qui.
L’idea, in tre ore di intervento, era di usare Railsgoat ed il progetto Owasp Broken Web Application per far vedere come l’enumerazione, il saper cogliere dettagli ed indizi ed un pizzico di fortuna, ci possono portare da un’applicazione web ad una shell di root.
Sul più bello, ovvero alla terza ora, quando dovevamo armarci, partire e bucare Railsgoat, il proiettore ha fatto le bizze. Quindi lascio qui un piccolo walkthrough, dei passi fatti per partire dall’indirizzo IP e URL, fino ad una shell di root.
Owasp Broken Web Application Project
Il progetto Owasp Broken Web Application è nato con lo scopo di fornire una macchina virtuale, differente dalla solita metasploitable, per permettere a chiunque di esercitarsi con applicazioni volutamente vulnerabili.
Railsgoat è una di queste. Scritta in Ruby on Rails, vuole simulare un portale aziendale dedicato alla gestione del personale. L’amministratore, avrà a disposizione la form di gestione di alcuni dipendenti e, tra le altre cose, sarà possibile fare l’upload delle polizze sanitarie aziendali, gestire i dati dello stipendio e molto altro.
Durante il talk siamo partiti con solo 2 dati a nostra disposizione:
- l’indirizzo IP del server: 172.16.202.241
- il nome dell’applicazione web: Railsgoat
Setup dell’ambiente
Questa volta avevo entrambe le macchine in esecuzione con VMWare Fusion sotto Mac OS X. Questo semplicemente perché avevo già pronta la macchina Kali Linux usata per l’oscp.
L’importante è che mettiate entrambe le macchine in una rete privata e non siano nattate con il vostro host fisico.
Enumeration
Come prima cosa, andiamo a vedere quali sono i servizi in ascolto sul mio target:
Dalle prime informazioni che ho, potrebbe essere una macchina con una distribuzione Ubuntu di Linux. Apache è in esecuzione con un sacco di moduli per il supporto di vari linguaggi di programmazione. Difficilmente una macchina di produzione ci riserverà così tanta soddisfazione.
Mi dedico al web server sulla porta 80, perché essendoci passenger in esecuzione, sarà lui a servire l’applicazione railsgoat.
Proseguo con dirb, restringendo però il campo alla sola directory /railsgoat. Per esercizio provate ad enumerare tutto il sito; troverete un sacco di indizi per bucare anche le altre applicazioni.
Partendo da un indirizzo IP ed una url, /railsgoat, abbiamo i seguenti indizi:
- si tratta di un server Linux, presumibilmente Ubuntu
- ha in esecuzione un server web (sia in HTTP che HTTPS) e un Tomcat sulla porta 8080
- l’applicazione railsgoat è scritta in Ruby, non sappiamo ancora quale framework è stato utilizzato.
- /railsgoat ha un suo meccanismo di login, di registrazione degli utenti e di download di file. Questo ci può far sperare che esista anche un meccanismo di upload.
Web assault
Navigando l’url ‘/railsgoat’ possiamo ossrevare che ci viene dato un messaggio d’errore differente a seconda che si stia provando uno username non esistente o che si stia sbagliando solamente la password.
Questo ci permette di provare un attacco a forza bruta per enumerare sia gli username esistenti e poi provare ad enumerare le password.
Per prima cosa, mi credo un dizionario custom per questa attività, usando il comando cewl. cewl permette infatti di, partendo dal contenuto di un sito, costruire un file di testo da utilizzare come primo dizionario, magari sperando in qualche password di default contestualizzata alla realtà che stiamo attaccando.
Poi, invece di usare hydra o lo stesso intruder di Burp, per motivi puramente didattici (e perché mi divertiva l’idea) ho buttato giù due linee di python. poster.py è uno script che, letto un dizionario in ingresso, permette, a seconda di come viene invocato, di fare il bruteforce di utenti o di password della url passata come argomento.
cheater note: admin1234 non sarebbe stato incluso nel dizionario e non avevo tempo di implementare nello script, una funzione di permutazione delle parole trovate con l’aggiunta di numeri. Mi serviva per far vedere cewl durante il talk. L’aggiunta della funzionalità in poster.py è abbastanza semplice.
Lancio poster.py per enumerare gli username di /railsgoat:
Ora lancio poster.py per enumerare la password di admin@metacorp.com
Ed ecco qui, admin1234 è la password di admin@metacorp.com
Uploading the bomb
Navigando come utente admin non riusciamo ad arrivare alla url /download. Quello che però possiamo fare, invece di investire tempo in altri bruteforce, è registrare un nuovo utente.
Registrati come utente tre@metacorp.com, possiamo navigare la directory /download che ci redirige su http://172.16.202.241/railsgoat/users/8/benefit_forms. L’8 è l’id del nostro utente e, sì, ci sono tanti problemi di insecure direct object reference.
Per l’oscp, mi sono scritto uno scriptino python che mi genera il codice PHP per fare una reverse shell con la funzione exec().
Eseguendo questo script, mi genero il codice PHP per eseguire bash e creare una reverse shell. Scelgo PHP, perché, tra le mille informazioni, ho visto che Apache ha il modulo per questo linguaggio in esecuzione, quindi, presumibilmente, eseguirà questo script.
Dalla form di upload della polizza sanitaria della Metacorp, scelgo il file PHP che ho appena generato e metto netcat in ascolto sulla porta 31337 con il comando:
Navigando l’url http://172.16.202.241/railsgoat/data/rs.php, invoco lo script e la mia shell non privilegiata viene aperta sulla macchina.
Let’s root
Da dentro la macchina è più facile prendere tutte le informazioni che ci servono per prendere il controllo della macchina. In particolare, la versione del kernel e del sistema operativo, con la quale andremo alla ricerca di exploits.
Questa la lista di exploit dalla quale possiamo partire:
E la scelta cade su Full-Nelson.c privilege escalation.
Questo exploit, sfrutta la bellezza di tre vulnerabilità distinte per darci una shell di root:
La CVE-2010-3850 è relativa alla mancanza di controlli sull’assegnazione di un indirizzo Econet ad interfacce arbitrarie mentre la CVE-2010-3849 è una NULL pointer dereference nel procollo Econet.
Nell’exploit, le due vulnerabilità sono realizzate in questa routine che causa un OOPS e permette al programma chiamante di fruttare la CVE-2010-4258 che mi permette di scrivere NULL in porzioni arbitrari del kernel, quando un OOPS si verifica durante una clone(2).
In particolare attraverso commit_creds e prepare_kernel_cred faremo in modo dai dare EUID 0 al nostro processo in esecuzione.
Tralasciando questa spiegazione superficiale e non accurata, trasferiamo il nostro exploit sulla macchina di railsgoat. Possiamo usare wget, basterà copiare il nostro file in /var/www/html sulla nostra Kali Linux ed avviare il servizio apache.
Una volta trasferito sulla macchina, lo possiamo compilare, grazie alla presenza del gcc a bordo ed, eseguendo l’attacco, siamo root sulla macchina.
Off by one
Ringrazio l’Università di Parma, ma soprattutto Danilo e l’Unione degli Universitari di Parma, per avermi invitato a tenere un talk e aver sopportato le bizze del proiettore nell’ultima ora.
Come promesso, ho ripercorso con questo post, quello che vi avrei mostrato successivamente. Spero vi sia piaciuto e se ci sono domande o dubbi, lasciatele qui nei commenti e vi risponderò.
#tryharder
Vuoi aiutarmi a portare avanti il progetto Codice Insicuro con una donazione? Fantastico, allora non ti basta che premere il pulsante qui sotto.
Supporta il progetto