ESET Eesti Blogi

Взломано! Главное из KringleCon 5: Золотые Кольца

ОБНОВЛЕНИЕ: На закрытии, состоявшемся 25 января 2023 года, команда организаторов SANS Holiday Hack Challenge объявила победителей, а этот отчет был внесен в список Почетных упоминаний. Слава всем победителям, и надеюсь увидеть некоторых из вас на KringleCon 6, где будут шесть гусей, несущих яйца!

Это мой первый год участия в SANS Holiday Hack Challenge, и это было потрясающе. В серии из 16 испытаний, от легких до сложных, я практиковал анализ подозрительного сетевого трафика и логов PowerShell, написание правил Suricata, выход из Docker-контейнера, поиск утечек ключей для эксплуатации GitLab CI/CD пайплайна и AWS-пользователя, проведение XML External Entity атак и взлом смарт-контракта для покупки невзаимозаменяемого токена (NFT).

Самое лучшее в этом опыте — то, что он познакомил меня с новыми инструментами и технологиями, тем самым расширив мои знания в области кибербезопасности. Здесь я делюсь несколькими яркими моментами решения задач.

Ориентация

Каждый участник получает аватар для навигации в игровом окружении в браузере, расположенном на Северном полюсе:

Во время ориентации вы получаете криптовалютный кошелек, который игра использует для награждения KringleCoins за выполнение заданий, и который вы используете в последнем задании для взлома смарт-контракта. Интересно, что игра отслеживает все транзакции KringleCoin в блокчейне Ethereum, а это значит, что полный отчет о вашем прогрессе хранится и в этом блокчейне.

Переходим к первому кольцу игры.

1. Кольцо Толкина

Поиск Кольца Толкина потребовал от меня напрячь свои навыки анализа логов.

Фишинг через Wireshark

Сначала я использовал Wireshark для анализа предоставленного файла .pcap, который показал, что сервер по адресу adv.epostoday[.]uk скачивает файл Ref_Sept24-2020.zip на компьютер:

Заглянув внутрь ZIP-архива, я обнаружил исполняемый файл Ref_Sept24-2020.scr, который вызвал два срабатывания в ESET Endpoint Security: BAT/Runner.ES и Generik.TAGTBG. Этот malware в конечном итоге привел к запуску вредоносного исполняемого файла в памяти под названием config.dll, который был обнаружен Advanced Memory Scanner от ESET как Win32/Dridex.DD.

Журналы событий Windows

Далее я проанализировал предоставленный файл .evtx, содержащий логи PowerShell, с помощью Event Viewer. Хотя существуют и другие инструменты для анализа логов PowerShell, если злоумышленники знают, как использовать встроенные средства операционной системы (living-off-the-land binaries), чтобы оставаться незамеченными, то и защитники должны хорошо разбираться в нативных инструментах, предоставляемых ОС.

Поскольку логи содержали 10 434 события, я сгруппировал события по дате, а затем использовал функцию поиска, чтобы найти любые события, содержащие символ $. В PowerShell $ используется для создания и обращения к переменным. Я обнаружил атаку, произошедшую 24 декабря 2022 года, когда злоумышленник запустил следующий скрипт:

Похоже, злоумышленник нашел секретный рецепт, заменил секретный ингредиент honey на fish oil, а затем создал новый файл рецепта. Это вызвало событие с ID 4104, которое означает выполнение удаленных команд PowerShell. Поэтому я отфильтровал события по этому ID, что помогло мне быстрее находить дополнительные вредоносные события.

Suricata Regatta

Последнее упражнение для Кольца Толкина заключалось в написании четырех правил Suricata для мониторинга сетевого трафика на предмет заражения Dridex:

alert dns $HOME_NET any -> any any (msg:»Known bad DNS lookup, possible Dridex infection»; dns.query; content:»adv.epostoday.uk»; nocase; sid:1; rev:1;)

alert http 192.185.57.242 any <> any any (msg:»Investigate suspicious connections, possible Dridex infection»; sid:2; rev:1;)

alert tls any any -> any any (msg:»Investigate bad certificates, possible Dridex infection»; tls.cert_subject; content:»CN=heardbellith.Icanwepeh.nagoya»; sid:3; rev:1;)

alert http any any -> any any (msg:»Suspicious JavaScript function, possible Dridex infection»; file_data; content:»let byteCharacters = atob»; sid:4; rev:1;)

По порядку, эти правила отлавливают DNS-запросы к adv.epostoday[.]uk, соединения с IP-адресом 192.185.57[.]242, использование вредоносного сервера heardbellith.Icanwepeh[.]nagoya, идентифицированного по общему имени (CN) в TLS-сертификате, и использование JavaScript atob() функции для декодирования бинарной строки, содержащей base64-закодированные данные на клиенте.

Завершение этих трех испытаний принесло мне Кольцо Толкина:

Переходим ко второму кольцу.

2. Кольцо Эльфов

Наиболее заметными испытаниями для Кольца Эльфов были «Побег из тюрьмы» и «Веселый CI/CD».

Побег из тюрьмы

«Побег из тюрьмы» стал суровым напоминанием о том, что предоставление root-привилегий пользователю в Docker-контейнере — это то же самое, что и предоставление root-привилегий хост-системе. Задача заключалась в том, чтобы выбраться из контейнера. Ну, это легко сделать, когда ты root:

Будучи root-пользователем, я перечислил таблицы разделов устройства, а затем смонтировал файловую систему хоста, получив полный доступ к хосту. Теперь я мог искать ключ, который, как подсказывали внутриигровые подсказки, должен был находиться в домашнем каталоге:

Веселый CI/CD

Хотя это было быстро, «Веселый CI/CD» занял у меня больше всего времени. Сначала нам дали Git-репозиторий для клонирования по HTTP:

Из URL я увидел, что название репозитория было wordpress.flag.net.internal, поэтому я перешел в репозиторий и обнаружил сайт WordPress. Я проверил, работает ли сайт:

Да, сайт работал. Мне было интересно, были ли какие-либо утечки ключей в истории исходного кода. Если да, то я должен был бы иметь возможность отправлять изменения в исходный код. Поэтому я запустил git log:

Из сообщений коммитов видно, что коммит был сделан после добавления ресурсов для исправления «ой». Пора проверить коммит до «ой»:

Отлично, я нашел директорию .ssh с ключами. Давайте скопируем эти ключи и настроим SSH-агент и Git-пользователя, чтобы проверить, смогу ли я выдать себя за владельца этих ключей:

Теперь вернемся в основную ветку и проверим, можем ли мы отправить тривиальное изменение в исходный код (используя nano, я просто добавил пробел в один из файлов):

Таким образом, я выполнил первую часть задания, выдав себя за одного из разработчиков WordPress, но работал ли сайт после моего пуша?

Мой пуш что-то изменил, потому что теперь сайт перенаправлял на порт 8080.

До сих пор я игнорировал часть задания, связанную с CI/CD, которая должна была стать ключом к его завершению. Репозиторий содержит файл .gitlab-ci.yml, который предоставляет конфигурацию для пайплайна GitLab CI/CD. Каждый раз, когда вы отправляете изменения в репозиторий, запускается система CI/CD, и GitLab Runner выполняет скрипты из этого YML-файла. Я подумал, что это почти эквивалентно удаленному выполнению кода на сервере, где установлен GitLab Runner.

Присмотревшись, я увидел rsync скрипт, копирующий все файлы из Git-репозитория в директорию на веб-сервере, где размещался сайт. Сначала я попытался использовать rsync для обращения потока данных, копируя все файлы с веб-сервера в Git-репозиторий, но безуспешно.

После множества проверок гипотез я наконец-то пришел к прорыву: вместо того, чтобы пытаться «исправить» сайт WordPress или запускать вредоносные скрипты через систему сборки, я решил выдать сайт, который утекает информацию с веб-сервера. Внутри index.php (расположенного в корне репозитория) я могу закомментировать код, который загружает сайт WordPress, и запустить PHP-команды, которые сканируют веб-сервер.

Действительно, я могу даже запускать команды оболочки с помощью PHP. Я обнаружил, что passthru() работает легко.

В index.php я использовал // для комментирования двух строк и добавил passthru(‘ls -la /’); в последней строке. Это создает веб-сайт, который выводит список всех файлов в корневой директории веб-сервера:

Затем я отправил это изменение в Git-репозиторий, и система GitLab CI/CD позаботилась об обновлении сайта для меня:

Ага, Кольцо Эльфов должно быть в flag.txt! Я повторил предыдущие шаги, но на этот раз использовал passthru(‘cat /flag.txt’); раскрывая Кольцо Эльфов при следующем запросе к сайту:

Переходим к третьему кольцу.

3. Веб-кольцо

Самым интересным испытанием для меня было «Открыть дверь шахты Бории», хотя «Фонтан Галадриэль» тоже был интересным и содержал загадки.

Открыть дверь шахты Бории

В «Открыть дверь шахты Бории» нам было представлено шесть штырьков или мини-испытаний для обхода валидации ввода или Content Security Policy для соединения входных и выходных труб между штырьками, включая подбор цветов труб. Для большинства штырьков я использовал HTML для написания списка соединяющих букв ‘o’. Вот мое окончательное решение:

Штырек 1

Для Штырька 1 не было никакой валидации, поэтому это было простое дело HTML и встроенного CSS:

<p style="letter-spacing: -4px; margin: 0; padding: 0;">oooooooooooooo</p>

Штырек 2

Штырек 2 имел Content Security Policy, которая запрещала JavaScript, но разрешала встроенный CSS, так что это не было проблемой для моего метода:

<ul style="list-style: none; line-height:0.5; letter-spacing: -4px; margin: 0; padding: 0;"> <li>o</li> <li>o</li> <li>o</li> <li>o</li> <li>o</li> <li>o</li> <li>o</li> <li>o</li> <li>o</li> <li>oooooooooooooo</li> </ul>

Штырек 3

Штырек 3 имел Content Security Policy, которая запрещала CSS, но разрешала встроенный JavaScript, поэтому я использовал JavaScript для изменения стилей:

<script> document.write("" + "<ul id='o'>" + "<li>o</li>" + "<li>oooooooooooooooooooooo</li>" + "<li>o</li><li>o</li><li>o</li><li>o</li>" + "</ul>"); const o = document.getElementById('o'); o.style.color = "blue"; o.style.listStyle = "none"; o.style.lineHeight = "0.5"; o.style.letterSpacing = "-4px"; o.style.margin = "0"; o.style.padding = "0"; </script>

Штырек 4

У Штырька 4 не было Content Security Policy, но у него была функция sanitizeInput на стороне клиента, которая удаляла двойные кавычки, одинарные кавычки, левые угловые скобки и правые угловые скобки. Хитрость здесь заключалась в том, чтобы понять, что эта функция не срабатывала при отправке формы, а при событии onblur. Другими словами, перемещение мыши за пределы поля ввода вызывало событие onblur, очищая любой ввод. Решением было отправить форму, нажав клавишу Enter, при этом позаботившись о том, чтобы не выводить курсор мыши за пределы поля ввода:

<ul style="list-style: none; line-height:0.5; letter-spacing: -4px; margin: 0; padding: 0;"> <li>o</li> <li>o</li> <li>oooooooooooooo</li> <li>o</li> <li>o</li> <li>o</li> <li>o</li> <li>o</li> <li style="color: blue;">oooooooooooooo</li> </ul>

Штырек 5

Штырек 5 имел ту же функцию sanitizeInput и обход, а также Content Security Policy, запрещающую встроенный CSS, но разрешающую встроенный JavaScript:

<script> document.write("" + "<ul id='o'>" + "<li>o</li>" + "<li>o</li>" + "<li class='red'>oooooooooooooo</li>" + "<li><span class='red'>o</span></li>" + "<li><span class='red'>o</span></li>" + "<li><span class='red'>o</span>" + "<span class='blue'> ooooooooooo</span></li>" + "<li><span class='red'>o</span>" + "<span class='blue'> oo</span></li>" + "<li><span class='red'>o</span>" + "<span class='blue'> oo</span></li>" + "<li><span class='red'>o</span>" + "<span class='blue'> oo</span></li>" + "<li>o<span class='blue'> oo</span></li>" + "<li>o<span class='blue'> B</span></li>" + "</ul>"); const o = document.getElementById('o'); o.style.listStyle = "none"; o.style.lineHeight = "0.5"; o.style.letterSpacing = "-4px"; o.style.margin = "0"; o.style.padding = "0"; o.style.fontSize = "xx-large"; const reds = document.getElementsByClassName("red"); for (let red of reds) { red.style.color = "red"; } const blues = document.getElementsByClassName("blue"); for (let blue of blues) { blue.style.color = "blue"; } </script>

Штырек 6

Наконец, Штырек 6 не очищал ввод, но использовал более строгий Content Security Policy, запрещающий как встроенный CSS, так и JavaScript. Моим решением было использовать устаревший HTML для получения необходимых стилей и использовать таблицу вместо списка:

<table border="0" frame="void" rules="none" cellpadding="0" cellspacing="0" width="100%"> <tr bgcolor="#00FF00"> <td><font color="#00FF00" size="7">o</font></td> <td><font color="#00FF00" size="7">o</font></td> <td><font color="#00FF00" size="7">o</font></td> <td><font color="#00FF00" size="7">o</font></td> </tr> <tr bgcolor="red"> <td><font color="red" size="5">o</font></td> <td><font color="red" size="5">o</font></td> <td><font color="red" size="5">o</font></td> <td><font color="red" size="5">o</font></td> </tr> <tr bgcolor="blue"> <td><font color="blue" size="9">o</font></td> <td><font color="blue" size="9">o</font></td> <td><font color="blue" size="9">o</font></td> <td bgcolor="red"><font color="red" size="9">o</font></td> </tr> <tr bgcolor="blue"> <td><font color="blue" size="9">o</font></td> <td><font color="blue" size="9">o</font></td> <td><font color="blue" size="9">o</font></td> <td><font color="blue" size="9">o</font></td> </tr> </table>

Фонтан Галадриэль

Фонтан Галадриэль был возможностью попрактиковаться в XML External Entity (XXE) атаках. Понять, как определить пользовательскую XML-сущность, определить сущность, которая запрашивает файл с сервера, и добавить эту сущность в качестве полезной нагрузки в HTTP-запрос, было несложно. Самым трудным было разгадать внутриигровые загадки, чтобы определить путь к файлам, которые сервер будет утекать. Вот прорывной запрос, раскрывающий местоположение золотого кольца:

Я бы дал два урока, извлеченных из этого испытания. Во-первых, используйте расширение Content Type Converter в Burp для преобразования JSON-полезных нагрузок в XML. Во-вторых, попробуйте поместить XXE-полезную нагрузку в разные теги — мне потребовалось много времени, чтобы понять, что все, что мне нужно было сделать, это поместить &xxe; полезную нагрузку в тег reqType вместо тега imgDrop.

Переходим к четвертому кольцу.

4. Облачное кольцо

Игра за Облачное кольцо была начальным погружением в интерфейс командной строки Amazon Web Services (AWS).

Главным событием этого набора испытаний стало использование trufflehog для поиска учетных данных AWS в Git-репозитории, а затем их эксплуатации для аутентификации в качестве пользователя AWS. Злоумышленник, оказавшийся в такой ситуации, может использовать команды aws iam для запроса политик, применяемых к пользователю, и, следовательно, для определения того, какие облачные ресурсы могут быть доступны и использованы злонамеренно.

Переходим к пятому кольцу.

5. Горящее кольцо огня

Наиболее поучительной частью этого набора испытаний было изучение деревьев Меркла для эксплуатации смарт-контракта и попадания в список предварительной продажи для покупки невзаимозаменяемого токена (NFT). Здесь задача заключалась в том, чтобы обнаружить доказательственные значения, которые вместе с моим адресом кошелька и корневым значением дерева Меркла подтверждали бы мое включение в список предварительной продажи.

После нескольких безуспешных попыток предоставить доказательственные значения я понял, что никогда не смогу найти доказательственные значения для предоставленного корневого значения, поскольку не было способа узнать все листовые значения, использованные для его вычисления. Мне нужно было изменить корневое значение, чтобы я мог предоставить действительное дерево Меркла.

Используя инструмент профессора QPetabyte, я создал дерево Меркла из двух листьев, состоящих из моего адреса кошелька и адреса смарт-контракта BSRS_nft, который я нашел с помощью внутриигрового обозревателя блокчейна во втором блоке блокчейна Ethereum игры. Инструмент сгенерировал корневое значение этого дерева и доказательственное значение для моего адреса кошелька. Затем я использовал Burp, чтобы перехватить запрос к серверу и изменил значение корневого узла по умолчанию, чтобы я мог отправить действительное дерево Меркла. Вот мой NFT sporc, купленный по фиксированной цене 100 KringleCoins:

Действительно уродливый экземпляр.

Финал

Большое спасибо организаторам SANS Holiday Hack Challenge за то, что они заставили мой мозг работать по-новому и помогли углубить мои знания в области кибербезопасности. Я не только с нетерпением жду вызова в следующем году, но и собираюсь попробовать издания этого вызова 2020 и 2021 годов. И если вы раньше не участвовали в этом испытании, я надеюсь, что эти основные моменты вызвали у вас интерес.

Читать полный анализ на WeLiveSecurity →

Exit mobile version