
https://hackerone.com/reports/863553
La logique de validation d'URL appliquée lors du traitement de /appsuite/api/oxodocumentfilter&action=addfile présente trois défauts qui peuvent être utilisés pour exécuter une attaque SSRF de type Time of Check Time of Use (ToCToU). Ce problème permet à des acteurs malveillants d'exécuter des requêtes HTTP GET sur des services réseau internes et peut entraîner la fuite d'informations protégées.
La logique de validation d'URL de la méthode URITools.getFinalURL implémentée ici souffre d'une vulnérabilité 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();
Dans le code ci-dessus, la résolution DNS du nom d'hôte de l'URL d'entrée est effectuée à la fois au moment de la vérification (validator.get().apply(u)) et au moment de l'utilisation (u.openConnection()) en appelant la méthode InetAddress.getByName. Ainsi, si un attaquant peut modifier le résultat de la résolution DNS après le moment de la vérification et avant le moment de l'utilisation, il peut contourner le validateur. Ce défaut seul est extrêmement difficile à exploiter en raison des limitations suivantes
InetAddress.getByName met en cache les résultats de résolution DNS pendant 30 secondes si la résolution DNS réussit et pendant 10 secondes si la résolution DNS échoue.validator.get().apply(u) et u.openConnection() est extrêmement faible (moins d'une milliseconde pour des URL normales). Le défaut #2 est utilisé pour contourner cette limitationLe validateur d'URL AddFileAction.validator implémenté ici ne valide pas la longueur de l'URL d'entrée. En fournissant une URL de grande taille, l'attaquant peut augmenter l'intervalle de temps entre les appels à la méthode InetAddress.getByName au moment de la vérification et au moment de l'utilisation. Un intervalle de temps plus grand permet à l'attaquant d'exploiter facilement le défaut #1
La méthode HostList.contains implémentée ici renvoie false si la résolution DNS du nom d'hôte de l'URL d'entrée échoue
// Need to resolve as last resort
try {
return contains(InetAddress.getByName(toCheck), false);
} catch (UnknownHostException e) {
// Cannot be resolved
return false;
}
Le validateur AddFileAction.validator appelle la méthode blackImageUrlHostlist.contains pour vérifier si le nom d'hôte de l'URL d'entrée ou l'adresse IP vers laquelle il résout figure sur la liste noire. Si un attaquant fait échouer la résolution DNS du nom d'hôte, les vérifications d'adresse IP sont ignorées et l'URL est acceptée.
Considérons un nom d'hôte randomid.dns.pointer.pw dont le serveur de noms faisant autorité est contrôlé par l'attaquant. La stratégie d'attaque consiste à faire échouer la résolution DNS de randomid.dns.pointer.pw au moment de la vérification (validator.get().apply(u);) et à la faire réussir au moment de l'utilisation (u.openConnection()). Cela permet à l'attaquant de contourner les filtres de liste noire d'adresses IP et d'exécuter une requête HTTP GET sur n'importe quelle adresse IP figurant sur la liste noire. L'attaquant peut suivre les étapes suivantes pour exécuter cette attaque
InetAddress.getByName sur le serveur en exécutant l'action addfile avec les données de requête {"add_imageurl": "http://randomid.dns.pointer.pw"}. À ce moment, le serveur DNS faisant autorité sera configuré pour faire échouer la résolution DNS de randomid.dns.pointer.pw en renvoyant le statut SERVFAIL. InetAddress.getByName mettra en cache ce résultat d'échec pendant 10 secondespointer.pw de renvoyer 127.0.0.1 pour les requêtes DNS de type A du nom d'hôte randomid.dns.pointer.pwInetAddress.getByName renvoie la réponse mise en cache (SERVFAIL) au moment de la vérification et renvoie 127.0.0.1 au moment de l'utilisation (url.openConnection())add_imageurl définie au format . Ici, u{25MB} signifie que la partie nom d'utilisateur est une chaîne de 25 x 1024 x 1024 caractèresInstaller golang depuis https://golang.org/dl/
Installer Open-Xchange et Documents dans une machine virtuelle avec au moins 4 Go de RAM en suivant les guides https://oxpedia.org/wiki/index.php?title=AppSuite:Open-Xchange_Installation_Guide_for_Debian_9.0 et https://oxpedia.org/wiki/index.php?title=AppSuite:Documents_Installation_Guide#Debian_GNU.2FLinux_9.0_.28valid_from_v7.10.29
Télécharger et extraire le fichier poc.zip
Ouvrir un terminal / une invite de commande et définir le répertoire courant sur le dossier extrait de poc.zip
Exécuter la commande
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
où 172.16.66.130 est l'adresse IP de la machine virtuelle.
http://u{25MB}:[email protected]/path/to/internal/resource.png