
https://hackerone.com/reports/863553
Логика проверки URL, применяемая при обработке /appsuite/api/oxodocumentfilter&action=addfile, имеет три дефекта, которые могут быть использованы для выполнения атаки SSRF типа «время проверки — время использования» (ToCToU). Эта проблема позволяет злоумышленникам выполнять HTTP GET-запросы к внутренним сетевым службам и может привести к утечке защищённой информации.
Логика проверки URL в методе URITools.getFinalURL, реализованном здесь, страдает от уязвимости 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();
В приведённом выше коде разрешение DNS для имени хоста входного URL выполняется как во время проверки (validator.get().apply(u)), так и во время использования (u.openConnection()) путём вызова метода InetAddress.getByName. Таким образом, если злоумышленник может изменить результат разрешения DNS после момента проверки и до момента использования, он может обойти валидатор. Сам по себе этот дефект чрезвычайно сложно эксплуатировать из-за следующих ограничений:
InetAddress.getByName кэширует результаты разрешения DNS на 30 секунд, если разрешение успешно, и на 10 секунд, если разрешение не удалось.validator.get().apply(u) и u.openConnection() чрезвычайно мал (менее одной миллисекунды для обычных URL). Для обхода этого ограничения используется Дефект №2.Валидатор URL AddFileAction.validator, реализованный здесь, не проверяет длину входного URL. Предоставляя URL большого размера, злоумышленник может увеличить временной интервал между вызовами метода InetAddress.getByName во время проверки и во время использования. Больший временной интервал позволяет злоумышленнику легко эксплуатировать Дефект №1.
Метод HostList.contains, реализованный здесь, возвращает false, если разрешение DNS имени хоста входного URL не удалось.
// Need to resolve as last resort
try {
return contains(InetAddress.getByName(toCheck), false);
} catch (UnknownHostException e) {
// Cannot be resolved
return false;
}
Валидатор AddFileAction.validator вызывает метод blackImageUrlHostlist.contains для проверки, находится ли имя хоста входного URL или IP-адрес, на который оно разрешается, в чёрном списке. Если злоумышленник делает так, что разрешение DNS имени хоста не удаётся, проверки IP-адреса пропускаются, и URL принимается.
Рассмотрим имя хоста randomid.dns.pointer.pw с авторитетным сервером имён, контролируемым злоумышленником. Стратегия атаки заключается в том, чтобы разрешение DNS для randomid.dns.pointer.pw не удалось во время проверки (validator.get().apply(u);), но удалось во время использования (u.openConnection()). Это позволяет злоумышленнику обойти фильтры чёрного списка IP-адресов и выполнить HTTP GET-запрос на любой занесённый в чёрный список IP-адрес. Злоумышленник может выполнить следующие шаги для проведения этой атаки:
InetAddress.getByName на сервере, выполнив действие addfile с данными запроса {"add_imageurl": "http://randomid.dns.pointer.pw"}. В этот момент авторитетный DNS-сервер должен быть настроен на возврат статуса SERVFAIL при разрешении DNS для randomid.dns.pointer.pw, чтобы разрешение не удалось. InetAddress.getByName закэширует этот результат неудачи на 10 секунд.pointer.pw возвращать 127.0.0.1 для DNS-запросов типа A имени хоста randomid.dns.pointer.pw.InetAddress.getByName вернул кэшированный ответ (SERVFAIL) во время проверки и вернул 127.0.0.1 во время использования (url.openConnection()).add_imageurl в формате . Здесь u{25MB} означает, что часть имени пользователя представляет собой строку длиной 25 × 1024 × 1024 символов.Установите golang с сайта https://golang.org/dl/
Установите Open-Xchange и Documents на виртуальной машине с не менее чем 4 ГБ ОЗУ, следуя руководствам https://oxpedia.org/wiki/index.php?title=AppSuite:Open-Xchange_Installation_Guide_for_Debian_9.0 и https://oxpedia.org/wiki/index.php?title=AppSuite:Documents_Installation_Guide#Debian_GNU.2FLinux_9.0_.28valid_from_v7.10.29
Загрузите и распакуйте файл poc.zip
Откройте терминал / командную строку и установите текущий каталог на распакованную папку poc.zip
Выполните команду
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
где 172.16.66.130 — IP-адрес виртуальной машины.
http://u{25MB}:[email protected]/path/to/internal/resource.png