Discussione Come ho capitalizzato il mio fallimento al bug bounty di Instagram

Stato
Discussione chiusa ad ulteriori risposte.

Netcat

Helper
17 Gennaio 2022
523
145
380
716
Ultima modifica:
Ieri, dopo una notte che mi ha provocato la perdita del sonno, ho fallito (accettando la sconfitta) il bug bounty di Instagram. Il fallimento è stato causato dall'obbligazione di testare l'app manualmente, e neppure un crawler passivo è consentito, concludendosi con il ban della cavia.

Come si può rimediare ad una sconfitta così miserevole?

In seguito alla mia fatidica esperienza, ho sviluppato un umile progetto in Python che permette di testare la sicurezza delle webapp dal "botting". Questo fenomeno, che conosciamo tutti, consiste nell'inviare richieste automatizzate ad un sito web attraverso uno script o un software.

Stanco dei falsi positivi forniti da ZAP, dei suoi falsi PII (Private Information Disclosure), dei suoi falsi injection point per OS command injection immaginari, della sua presunzione e della sua arroganza, delle 500,000 webrequest che risultano in un DDOS alla meglio, il mio progetto "ad albero" si propone un semplice scopo: studiare il comportamento di un sito web, facendo scraping+rendering dei contenuti HTML, CSS e JS. Il tutto con un approccio "full userless", no chromedriver, no geckodriver (viene invocato pyppeteer, un modulo python che sfrutta una tecnica simile). Questi programmi infatti, permettono di facilitarci troppo il lavoro, impedendoci di capire cosa fa effettivamente un server quando invia codice HTML, CSS e Javascript a noi (che siamo il client), comprendere le richieste client/risposte server e il funzionamento della programmazione asincrona, che ci permette di gestire il flusso dei dati senza la generazione di errori.

In questo tipo di approccio, il mio bot riceve in input il link di un sito arbitrario, che dev'essere specificato nel formato "https://www.example.com", poi crea una cartella chiamata "downloaded_content" dove va a scaricare i seguenti contenuti:
  • il codice HTML della pagine ospitate dal link, aspetto su cui mi sono focalizzato senza trascurare il rendering Javascript e CSS attraverso i moduli requests-html e BeautifulSoup. In questo modo, le pagine HTML vengono parsate correttamente, e scaricate senza trascurare le modifiche dinamiche apportate da CSS e Javascript, e DOM;

  • I link delle sotto-directory appartenenti al link originale vengono salvati in un file chiamato "link.txt";

  • Crawling del sito a caccia di indirizzi e-mail pubblicamente accessibili nel codice HTML;

  • Viene chiamato uno script esterno che crea una sottocartella in "downloaded_content" e ci salva dentro il codice Javascript della pagina, permettendone la futura ispezione. Può essere usato sia per comprendere come funziona Javascript nei siti web, che per rilevare vulnerabilità vere e proprie nel modo in cui la webapp testata processa Javascript. Nello script è possibile aggiustare il delay per assicurarsi che l'esecuzione di JS sia completata in situazioni dove c'è più codice da processare;

  • Un secondo script esterno viene chiamato per effettuare il crawling delle immagini, che vengono rilevate attraverso il tag "img" piuttosto che specificare le singole estensioni, e salvate in una seconda cartella, di nome "downloaded_images"
Il main file è "parser.py". Durante la sua esecuzione, parser.py chiamerà automaticamente "parse_javascript.py" per il JS parsing, mentre la chiamata a "image_downloader.py" sarà opzionale, per garantirci più controllo sul tipo di contenuti che vogliamo scaricare. In caso si vogliano anche scaricare le immagini, basterà inserire nuovamente il link "cavia" quando verrà richiesto da "image_downloader.py". Per l'esecuzione servirà Python 3.7 (minimo), ma io ho lavorato con Python 3.12

Adesso voi vi chiederete, *azzo c'entra questo con il fatto che hai fallito il bug bounty di Instagram?
Da come si è comportato IG nei confronti di ZAP, ho intuito che se una webapp permette l'uso sconsiderato del botting, questo può costituire un rischio di DOS, anche quando le azioni del bot sono apparentemente innoque, come in questo caso. Il mio bot infatti, non svolge attività "ignoranti" come testare a caso SQL injection, OS command injection, XSS e robe varie, tuttavia usa una pratica di scraping insicura, dal momento che neppure un browser "headless" come chromedriver è chiamato nel simulare fedelmente il comportamento di un browser. Viene usata una variante meno popolare invece, che può risultare quindi insicura.

Di seguito, elenco una lista dei siti web che si sono lasciati fare scraping da questo bot:
Siti vulnerabili:
https://www.google.it (ha scaricato tutto, e ha pure fatto un buon rendering)
https://www.w3.org/contact/ (ha estratto correttamente tutti gli indirizzi e-mail + altri contenuti)
https://www.qgis.org/en/site/ (nonostante ho stabilito più regole possibili per impedire al bot di incepparsi, qua sopra succede qualcosa e ad un certo punto si blocca, ma non importa. Perché si blocca quando ormai ha scaricato tutto)

Siti non vulnerabili:
https://www.inforge.net/forum/forums/sicurezza-informatica.434/ (Cloudflare gli ha cacciato letteralmente gli occhi, intoccabile)

Siti quasi vulnerabili:
https://www.instagram.com/Questo_Profilo_è_una_Cavia (la pagina del login era vulnerabile, tuttavia il bot non supporta un metodo d'autenticazione, causando errori di rendering e di downloading ad autenticazione compiuta, ma secondo me aggiungendo supporto all'auth il problema si risolve)

Lo script è stato testato con successo su Windows, per girare su Unix può richiedere una riadattazione. Per ragioni di sicurezza, ho deciso di non compilarlo con Pyinstaller o Py2exe, fornendo il codice in plain text e commentato al 100%.
 

Allegati

  • scraper.zip
    4.6 KB · Visualizzazioni: 2
  • Mi piace
Reazioni: JunkCoder
Stato
Discussione chiusa ad ulteriori risposte.