
https://hackerone.com/reports/863553
La logica di validazione degli URL applicata quando si gestisce /appsuite/api/oxodocumentfilter&action=addfile presenta tre difetti che possono essere utilizzati per eseguire un attacco SSRF di tipo Time of Check Time of Use (ToCToU). Questo problema consente ad attori malintenzionati di eseguire richieste HTTP GET su servizi di rete interni e può portare alla divulgazione di informazioni protette.
La logica di validazione degli URL nel metodo URITools.getFinalURL implementato qui presenta una vulnerabilità ToCToU
URL u = new URL(url);
if (validator.isPresent()) {
Optional<OXException> exception = validator.get().apply(u);
if (exception.isPresent()) {
throw exception.get();
}
}
URLConnection urlConnnection = u.openConnection();
Nel codice sopra riportato, la risoluzione DNS del nome host dell'URL di input viene eseguita sia al momento del controllo (validator.get().apply(u)) sia al momento dell'uso (u.openConnection()) chiamando il metodo InetAddress.getByName. Quindi, se un attaccante può modificare il risultato della risoluzione DNS dopo il momento del controllo e prima del momento dell'uso, può bypassare il validatore. Questo singolo difetto è estremamente difficile da sfruttare a causa delle seguenti limitazioni:
InetAddress.getByName memorizza nella cache i risultati della risoluzione DNS per 30 secondi se la risoluzione DNS ha successo e per 10 secondi se la risoluzione DNS fallisce.validator.get().apply(u) e u.openConnection() è estremamente ridotto (meno di un millisecondo per gli URL normali). Il Difetto #2 viene utilizzato per bypassare questa limitazione.Il validatore URL AddFileAction.validator implementato qui non valida la lunghezza dell'URL di input. Fornendo un URL di grandi dimensioni, l'attaccante può aumentare l'intervallo di tempo tra le chiamate al metodo InetAddress.getByName al momento del controllo e al momento dell'uso. Un intervallo di tempo maggiore consente all'attaccante di sfruttare facilmente il Difetto #1.
Il metodo HostList.contains implementato qui restituisce false se la risoluzione DNS del nome host dell'URL di input fallisce.
// Need to resolve as last resort
try {
return contains(InetAddress.getByName(toCheck), false);
} catch (UnknownHostException e) {
// Cannot be resolved
return false;
}
Il AddFileAction.validator chiama il metodo blackImageUrlHostlist.contains per verificare se il nome host dell'URL di input o l'indirizzo IP a cui risolve è nella blacklist. Se un attaccante fa fallire la risoluzione DNS del nome host, i controlli sull'indirizzo IP vengono saltati e l'URL viene accettato.
Si consideri un nome host randomid.dns.pointer.pw con nameserver autoritativo controllato dall'attaccante. La strategia d'attacco consiste nel far fallire la risoluzione DNS di randomid.dns.pointer.pw al momento del controllo (validator.get().apply(u);) e farla riuscire al momento dell'uso (u.openConnection()). Ciò consente all'attaccante di bypassare i filtri della blacklist degli indirizzi IP ed eseguire una richiesta HTTP GET su qualsiasi indirizzo IP in blacklist. L'attaccante può seguire i seguenti passaggi per eseguire questo attacco:
InetAddress.getByName sul server eseguendo l'azione addfile con i dati della richiesta {"add_imageurl": "http://randomid.dns.pointer.pw"}. In questo momento, il server DNS autoritativo sarà configurato per far fallire la risoluzione DNS di randomid.dns.pointer.pw restituendo lo stato SERVFAIL. InetAddress.getByName memorizzerà nella cache questo risultato di fallimento per 10 secondi.pointer.pw di restituire 127.0.0.1 per le richieste DNS di tipo A del nome host randomid.dns.pointer.pw.InetAddress.getByName restituisca la risposta memorizzata in cache (SERVFAIL) al momento del controllo e restituisca 127.0.0.1 al momento dell'uso (url.openConnection()).add_imageurl impostato al formato . Qui u{25MB} significa che la parte relativa al nome utente è una stringa di lunghezza 25 x 1024 x 1024 caratteri. go run . -serverRoot="http://172.16.66.130" -username="testuser" -password="secret" -targetPath="appsuite/v=7.10.3-9.20200409.083030/apps/themes/logo.png" -targetPort="80" -payloadSize=25 -startSleepDuration=6600
dove 172.16.66.130 è l'indirizzo IP della VM
http://u{25MB}:[email protected]/path/to/internal/resource.png