
Разбор комнаты Source на TryHackMe и Python-скрипт для эксплуатации уязвимости
Разбор комнаты Source на TryHackMe и Python-скрипт для эксплуатации уязвимости
Я не претендую на авторство в обнаружении этой уязвимости. Спасибо следующим людям за предоставление ресурсов, благодаря которым такие люди, как я, могут учиться!
Обнаружение уязвимости:
Özkan Mustafa Akkuş
Модуль MSF:
https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/http/webmin_backdoor.rb
https://www.rapid7.com/db/modules/exploit/linux/http/webmin_backdoor/
Автор модуля MSF:
wvu
Комната TryHackMe:
https://tryhackme.com/room/source
Автор THM:
https://tryhackme.com/p/DarkStar7471
Ресурсы:
https://www.webmin.com/exploit.html
https://github.com/webmin/webmin/issues/947
https://www.perlmonks.org/?node_id=301355
Я ни в коем случае не опытный специалист по безопасности. Это значит, что я могу предоставить неверную информацию. Если вы опытный профессионал/исследователь и видите что-то неправильное, пожалуйста, сообщите мне, чтобы я мог вернуться, изучить свою ошибку и предоставить правильную информацию. Это полезно и мне, и другим начинающим исследователям, которые могут наткнуться на этот разбор. Если вы найдёте неверную информацию, которую я написал, свяжитесь со мной по адресу , чтобы я мог это исправить. Спасибо!
1. История
Webmin — это веб-инструмент для администрирования UNIX-подобных систем. В первом квартале 2018 года Webmin подвергся атаке на цепочку поставок: неизвестный злоумышленник смог внедрить вредоносный код в файл password_change.cgi, создав уязвимость, которая позволяла открыть бэкдор на любой системе с этой версией Webmin (1.890) и стандартной конфигурацией. Я называю это атакой на цепочку поставок, потому что исходный код продукта разработчиков/распространителей программного обеспечения был скомпрометирован. Когда поставщик выпустил скомпрометированный продукт, все, кто обновил своё ПО, начинали работать с уязвимым кодом, давая атакующему возможность скомпрометировать любую систему, работающую на этом теперь уже уязвимом коде. В том же году разработчики Webmin заметили произошедшее и вернули файл в исходное состояние, однако атакующему снова удалось внедрить код. На этот раз код становился уязвимым только в том случае, если была включена опция смены истёкших паролей. Эта уязвимость не была обнаружена до августа 2019 года. Уязвимость была исправлена в версии Webmin 1.930.
2. Код
Итак, немного поискав, я нашёл строку кода, которая делала Webmin версии 1.890 уязвимым для внедрения команд. Мне было трудно найти правильную информацию, потому что с этой проблемой связаны два разных CVE (CVE-2019-15231/CVE-2019-15107). CVE-2019-15231 относится к уязвимости стандартной конфигурации в версии 1.890, а CVE-2019-15107 — к уязвимости, требующей включения опции смены истёкших паролей в версиях до 1.920. Давайте посмотрим на код версии 1.890. В строке 12 файла password_change.cgi находится следующая строка кода:
$in{'expired'} eq '' || die $text{'password_expired'},qx/$in{'expired'}/;
На момент написания этого текста я никогда не писал на Perl. Мы разберём эту строку кода с помощью поисковых систем, чтобы лучше понять, что она делает и почему она уязвима для эксплуатации. Первая часть кода слева от оператора ||, похоже, представляет собой переменную ($in), которая принимает параметр (expired) и проверяет, равна ли она (eq) пустой строке ''. В середине у нас оператор ||. || — это ещё один способ использования логического оператора or в Perl. При использовании || в Perl, если левая часть оператора истинна, правая часть не вычисляется. Если левая половина ложна, то вычисляется правая половина. В первой половине кода справа от оператора || мы видим die $text{'password_expired'}. В Perl die — это функция, которая завершает процесс скрипта и выводит сообщение об ошибке. Предположительно, это сообщение из переменной $text, сообщающее об истечении срока действия пароля. Последняя часть кода — самое интересное. Мы видим запятую ,, за которой следует qx/$in{'expired'}/ и точка с запятой ;, завершающая строку кода. Запятая действует как разделитель кода: сначала вычисляется левая половина, а затем вторая половина. В Perl qx — это функция, которая позволяет выполнять системные команды на хосте. Символы // — это разделители, используемые для идентификации параметра. В данном случае у нас есть qx/$in{'expired'}/, который выполняет параметр $in{'expired'} как системную команду. Я полагаю, что переменная $in может быть чем-то похожим на $_GET в PHP, по следующей причине. В написанном мной эксплойте есть параметр expired, который хранит полезную нагрузку перед отправкой на сервер через POST-запрос. Вот как выглядит этот код: data = {'expired':payload,}. Переменная $in, должно быть, каким-то образом извлекает значение, которое мы задали в expired, чтобы полезная нагрузка могла быть выполнена функцией qx. Подводя итог: уязвимая строка кода обнаруживает, что наш параметр expired в POST-запросе не равен пустой строке, поэтому оператор || вычисляет правую половину кода и выполняет нашу полезную нагрузку, хранящуюся в параметре expired. Перейдём к разбору комнаты Source с TryHackMe.com
Начнём со сканирования портов. Используем rustscan для общего обзора, потому что nmap может быть мучительно медленным.

Похоже, у нас открыто 2 порта: 22 и 10000. Теперь используем nmap, чтобы выяснить, какие службы работают на каждом порту.

Итак, у нас есть SSH на стандартном порту и HTTP-сервис на порту 10000. Давайте перейдём на страницу, работающую на порту 10000, и посмотрим, что там.

Вам нужно использовать HTTPS и обойти предупреждение о SSL-сертификате, чтобы получить доступ к этой странице. Похоже, перед нами страница входа в службу Webmin. Когда я впервые проходил эту машину, я перепробовал несколько вариантов перебора каталогов, но ничего интересного не нашлось. Посмотрим, есть ли уязвимость для версии Webmin, которую мы получили из сканирования nmap, через searchsploit.

Похоже, здесь есть несколько вариантов, но ни один из них не соответствует нашей версии. Откроем MSF и посмотрим, что у нас есть.

Здесь есть несколько вариантов на выбор. Поищем версию Webmin, полученную от nmap, и посмотрим, найдутся ли какие-либо CVE, которые помогут нам сузить круг.

В сводке об уязвимости упоминается файл password_change.cgi. Давайте используем номер 5 из нашего поиска в MSF, так как он также упоминает файл password_change.cgi и ту же дату раскрытия.

Лол, на самом деле мы не будем использовать MSF. MSF — это хорошо, но не так весело, как разобраться, как эксплуатировать уязвимость с помощью собственного кода! Я использовал исходный код на Ruby как справочник для этого эксплойта, чтобы написать собственный код эксплойта на Python. Воспользуемся им вместо этого!

Бада-бинг, бада-бум — у нас root shell в этой комнате! Я не буду раскрывать флаги. Уверен, вы сможете найти их сами! Спасибо за чтение и хорошего дня!