|
| 1 | ++++ |
| 2 | +title = "13 Dicembre 2024" |
| 3 | +description = "SQLi" |
| 4 | +author= "Renny" |
| 5 | +date = "2024-12-11" |
| 6 | +tags = ["web", "sql"] |
| 7 | ++++ |
| 8 | + |
| 9 | +[Slide PDF](./web-sqli.pdf) |
| 10 | + |
| 11 | +## Preambolo |
| 12 | + |
| 13 | +cosa ci serve: |
| 14 | + |
| 15 | +- basi di web security (`requests`) |
| 16 | +- conoscenza di base di **SQL** (ma anche no) |
| 17 | +- creatività |
| 18 | + |
| 19 | +Questa lezione si può seguire da Windows o Linux (ma sempre meglio installare Linux 🙏). |
| 20 | + |
| 21 | +## a cosa mi serve SQL? |
| 22 | + |
| 23 | +Alcuni di voi avranno visto **SQL** in sè per sè, ma come lo integro in un applicazione e per cosa lo uso? |
| 24 | + |
| 25 | +Use cases ovvi: |
| 26 | + |
| 27 | +- conservare dati strutturati -> |
| 28 | + - credenziali applicazioni web 🔥? |
| 29 | + - dati personali di utenti? |
| 30 | + |
| 31 | +Chiaramente per un attaccante un database è sempre una superficie d'attacco notevole. |
| 32 | + |
| 33 | +## come interagisce un applicazione con il DB? |
| 34 | + |
| 35 | +In qualche modo la mia applicazione farà **query** al database sottostante. |
| 36 | + |
| 37 | +Possiamo immaginarci qualcosa del genere: |
| 38 | + |
| 39 | +```python |
| 40 | +user_input = ... #prendiamo input dall'utente |
| 41 | +query = "SELECT * FROM users WHERE id = " + user_input |
| 42 | +cursor.execute(query) |
| 43 | +``` |
| 44 | + |
| 45 | +Come al solito, il primo approccio che prendiamo è spesso sbagliato. Come posso rompere un codice del genere? |
| 46 | + |
| 47 | +Se avete voglia di testare un po' (e dovreste) provate questo [sito](https://sqlfiddle.com/mysql/online-compiler?id=5bd5008e-3f1d-4386-9c52-6fb4c9363925). |
| 48 | + |
| 49 | +## cosa non va? |
| 50 | + |
| 51 | +Guardando qualsiasi applicativo conviene sempre ragionare partendo da dove abbiamo **controllo**, ovvero il nostro input. Dove andrà a finire ciò che mandiamo? Che tipo di restrizioni sono imposte su ciò che mandiamo? |
| 52 | + |
| 53 | +Ragionando su questi binari, ci rendiamo presto conto che |
| 54 | + |
| 55 | +- Possiamo mandare quello che ci pare |
| 56 | +- andrà a finire direttamente nella query |
| 57 | + |
| 58 | +Nulla a questo punto ci vieta di mandare **comandi**, ovvero parole che SQL interpreta come codice : possiamo iniettare (injection) **SQL** a nostro piacimento! |
| 59 | + |
| 60 | +Abbiamo una SQL injection, e questo vuol dire che siamo liberi di leggere e scrivere nel DB, in modo (spesso) arbitrario. |
| 61 | + |
| 62 | +## un esempio più complesso (e utile) |
| 63 | + |
| 64 | +Spesso abbiamo meno **controllo** sul nostro input : o è filtrato o è piazzato in modo sconveniente se vogliamo rompere l'applicazione. |
| 65 | + |
| 66 | +Provate a risolvere questa [challenge](http://web-17.challs.olicyber.it/logic) di OliCyber (hint hint : **control characters**). |
| 67 | + |
| 68 | +### definizione: injection |
| 69 | + |
| 70 | +Quando un programma interpreta il nostro input, che dovrebbe essere letterale ed inerte, come codice. Spesso richiede un qualche **escape character** o **sequence**. |
| 71 | + |
| 72 | +## tangente : come si fa un app sicura? |
| 73 | + |
| 74 | +Ci sono modi e modi di fare query: |
| 75 | + |
| 76 | +- I modi giusti e sicuri 🥱 : |
| 77 | + - query parametrizzate : uso dei placeholder per rappresentari i miei valori nella query : |
| 78 | + ``` |
| 79 | + cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,)) |
| 80 | + ``` |
| 81 | +- ORM (Object Relational Mapping) : Uso librerie per astrarre le query (SQLAlchemy) |
| 82 | + |
| 83 | +Ricordatevi che in questo modo vi state semplicemente affidando al codice di altre persone, che spesso è ugualmente [rotto](https://nvd.nist.gov/vuln/detail/cve-2024-1597), però meglio di niente |
| 84 | + |
| 85 | +## e se non vedo tutto l'output? |
| 86 | + |
| 87 | +é molto raro che i server connettano direttamente gli utenti al DB senza fare qualche altro calcolo in mezzo. |
| 88 | + |
| 89 | +Forse l'**injection** è in un endpoint che restituisce solo un valore numerico, oppure booleano per la logica dell'applicazione. |
| 90 | + |
| 91 | +O ancora, immaginiamoci di avere un **injection** che ci permette di sovvertire un endpoint per vedere i dettagli di un utente, in modo da poter vedere anche la sua password : magari la query che viene eseguita è giusta, ma il server prova a interpretarla secondo il formato che si aspetta (senza la password) e crasha, senza darci altre informazioni. |
| 92 | + |
| 93 | +Ci troviamo davanti a un esempio di **oracolo** |
| 94 | + |
| 95 | +### definizione : oracolo |
| 96 | + |
| 97 | +~L'oracolo (dal latino oraculum) è un essere o un ente considerato fonte di saggi consigli o di profezie, un'autorità infallibile, solitamente di natura spirituale.~ |
| 98 | + |
| 99 | +In cybersecurity, una funzione che ci permette di interrogare un programma ricevendo una risposta booleana (si o no). |
| 100 | + |
| 101 | +Spesso nel mondo reale la risposta non è diretta, ma deriva dalla presenza o meno di un errore : **error-based oracle** |
| 102 | + |
| 103 | +## come si chiede un nome ad un oracolo? |
| 104 | + |
| 105 | +Noi vogliamo una stringa, ma l'oracolo ci dà solo si e no! -> `divide et impera` |
| 106 | + |
| 107 | +Chiediamo un carattere alla volta, testando con tutto l'alfabeto -> `la prima lettera è [A-Z]?` |
| 108 | + |
| 109 | +Dopo qualche richiesta avremo il primo carattere, e procediamo così fino alla fine. |
| 110 | + |
| 111 | +### si può fare di meglio (meno richeste)? |
| 112 | + |
| 113 | +Lasciato come esercizio al lettore |
| 114 | + |
| 115 | +### una challenge ad oracolo |
| 116 | + |
| 117 | +Familiarizzate con le challenge ad oracolo risolvendo [questa](http://web-17.challs.olicyber.it/blind)! |
| 118 | + |
| 119 | +## E se l'output non c'è? |
| 120 | + |
| 121 | +A volte il server non ha bisogno di mandarci nulla indietro nel suo uso inteso (ex. aggiornare il proprio username). Come facciamo? |
| 122 | + |
| 123 | +Forti del fatto che la giusta combinazione di 0 ed 1 possono rappresentare tutto il rappresentabile, non ci rimane che trovare un modo nuovo di ricavarli. |
| 124 | + |
| 125 | +In diversi dialetti di **SQL** abbiamo delle simpatiche funzioni, che possiamo usare in congiunzione ad `IF` per ottenere oracoli : |
| 126 | + |
| 127 | +- `SLEEP` : blocca il DB per x secondi -> se la risposta del server è lenta, abbiamo un 1 altrimenti 0 |
| 128 | +- Funzioni di read di risorse : alcuni server **SQL** permettono la lettura di risorse, sia locali che remote (protocolli HTTP o FTP) -> secondo voi come derivo un oracolo? |
| 129 | + |
| 130 | +Queste sono alcuni casi comuni, ma la parte divertente è adattarsi alle circostanze in modi nuovi. |
| 131 | + |
| 132 | +Non usate tool già fatti come `sqlmap`, non impararete molto e di sicuro non furbi quanto voi (**aka** non funzionano) |
0 commit comments