Как стать автором
Обновить
258.94
Бастион
Проводим пентесты, проектируем защищенные системы

Сливаем отчетность американской Cyber League с помощью базовых утилит Linux

Время на прочтение11 мин
Количество просмотров1.3K

В этой статье я расскажу, как создать хакерское приложение, используя встроенный язык программирования Linux, и собрать базу данных участников западной "Национальной Киберлиги". Можно сказать, хакнем хакеров! ;)

Начнем со ссылки на отчет о соревнованиях Western National Cyber League, а закончим полноценным инструментом автоматизации. По пути рассмотрим основы работы с сURL, научимся обходить базовые ограничения веб-приложений и поработаем с PDF-документами из командной строки. 

Статья будет полезна специалистам по информационной безопасности и всем, кто интересуется автоматизацией процессов в Linux.


Недавно мне написала американская коллега из города Эдмонд, штат Оклахома.

После стандартного обмена любезностями типа "Как дела?", "Как погода в Москве?" она поделилась отчетом о своем участии в осенних хакерских соревнованиях за 2023 год. Это была ссылка на портал cyberskyline.com:

https://cyberskyline.com/report/9LT51V9K786C

При переходе по ссылке вместо того, чтобы показать отчет, сайт запросил адрес моей электронной почты. Конечно, только… создам ее)

Идем на мой любимый ресурс генерации одноразовой почты и получаем свеженький почтовый ящик. После ввода электронной почты сразу открывается отчет о результатах индивидуальных соревнований "Национальной Киберлиги" за осень 2023 года:

Интересно, что система не просила меня перейти по ссылке и подтвердить валидность адреса. Кроме того, сайт Киберлиги не проверил, что почта относится к существующему домену. Не были проведены даже минимальные проверки почты. 

Из этого следует два вывода: можно вводить абракадабру для доступа к отчетам; сайт Киберлиги просто собирает адреса, чтобы потом проводить рекламные рассылки.

Окей, временный ящик защитит нас от спама. Давайте теперь изучим отчет. Помимо результатов тестирования и текста о том, какая Киберлига крутая, мы видим важную для любого хакера информацию — полное имя и фамилию, а также адрес электронной почты.

Хм, очень интересно, а сколько всего таких отчетов существует? В тексте указано число соревнующихся — 7879. Это почти 8 тысяч документов с полным именем и адресом электронной почты участников международных хакерских турниров. Попробуем получить к ним доступ.

Проанализируем адрес документа:

https://cyberskyline.com/report/9LT51V9K786C

В нем есть слово "report" (отчет), а затем идет буквенно-цифровой идентификатор 9LT51V9K786C. Скорее всего (на самом деле так и есть), для доступа к другим отчетам потребуется подобрать аналогичную комбинацию цифр и букв. Это классический IDOR — уязвимость, о которой коллеги уже рассказывали на Хабре.

Рассмотрим возможное количество комбинаций в идентификаторе. В английском алфавите 26 букв, но в системах на базе Linux строчные и прописные буквы считаются разными символами. Это дает нам 52 возможных буквенных символа. 

Но нам повезло: в ссылке на наш отчет только прописные буквы. Будем надеяться, что так оно и останется. По-хорошему, чтобы убедиться, нужны дополнительный анализ и энумерация. С цифрами все проще — их всего 10.

Итого мы получаем 26 прописных букв и 10 цифр, что дает нам 36 вариантов для каждой позиции. В идентификаторе 12 символов, поэтому общее количество возможных комбинаций составляет 36^12, или 4 738 381 338 321 616 896. Как бы… немало. А у нас всего около 8 тысяч записей, что составляет примерно 0,00000000000001% от всех возможных комбинаций. Такое число мы в жизни не забрутфорсим.

Мы пойдем другим путем.

Существует более простой способ получения номеров отчетов — через поисковую индексацию Google. Что, если поисковик уже проиндексировал эти отчеты?

Давайте поищем. Используем специальный оператор поиска "site:", который ограничивает результаты конкретным доменом. В поисковую строку вводим запрос "site:cyberskyline.com/report", чтобы Google показывал только страницы, расположенные по этому адресу.

В результатах поиска сразу обнаруживаются номера отчетов — они появляются уже во второй и третьей строке выдачи, если не считать рекламный блок. Теперь проверим общее количество проиндексированных отчетов в поисковой системе.

На каждой странице отображается по 10 ссылок, что дает нам возможность получить данные 270 пользователей. Ручной сбор этой информации неэффективен и займет много времени.

Главная сила командной строки Linux, которой раньше не хватало Windows CMD, заключается в возможности объединять небольшие приложения в единую цепочку команд — конвейеры. Более того, конвейеры можно объединять между собой, создавая полноценные приложения, такие как LinEnum и AutoSUID. Так что напишем приложение, которое соберет данные за нас.

Шаг 1. Алгоритм и анализ

Даже для небольшого скрипта важно четко представлять последовательность действий. 

На первом этапе необходимо реализовать парсинг Google: программа должна открыть поисковую страницу, выполнить запрос, получить результаты, скачать найденные Гуглом файлы и автоматически перейти к следующей странице выдачи для повторения процесса.

После загрузки PDF-файлов программа должна извлечь из каждого документа персональные данные пользователей. В рамках этого примера будем собирать имена и адреса электронной почты. Затем сохраним полученную информацию в отдельный файл. 

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

Ну что, поехали пункт за пунктом. Для анализа механизма взаимодействия с поисковиком используем BurpSuite — перехватим и изучим трафик поисковых запросов.

Отлично, мы нашли верный запрос, но в нем слишком много шума. Почистим его и "причешем". Для этого направим запрос в Repeater и последовательно удалим лишние параметры. Проверим корректность его работы с помощью поискового выражения "url=https://cyberskyline.com/report/", в котором содержится номер отчета.

Упростили запрос до минимума, оставив только необходимые параметры: GET-запрос, Host и User-Agent. Теперь нужно разобраться с переходом на следующие страницы поисковой выдачи. Для этого откроем вторую страницу поисковика через браузер и проанализируем изменения в перехваченном трафике через BurpSuite.

В перехваченном запросе появился дополнительный параметр — start=10. Он определяет начальную позицию вывода результатов: значения 0–9 соответствуют первой странице, 10–19 — второй странице и так далее.

Проверим это предположение, отправив запрос с новым параметром через Repeater: выводные значения меняются, значит, мы все делаем правильно. Теперь сделаем все то же самое, только через командную строку.

Шаг 2. Парсим Google

curl -s -A "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:128.0)
Gecko/20100101 Firefox/128.0"
"https://www.google.com/search?q=site:cyberskyline.com/report/&start=20"

Запрос работает корректно. Теперь перейдем к следующему этапу: отфильтруем ответ сервера, чтобы получить только строки с адресами отчетов. Для этого воспользуемся утилитой grep.

curl -s -A "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:128.0)
Gecko/20100101 Firefox/128.0"
"https://www.google.com/search?q=site:cyberskyline.com/report/&start=20"
| grep -i "url=https://cyberskyline.com/report/" -o

Почти сработало, но мы так и не получили последние 12 символов после "report". Здесь не обойтись без регулярного выражения. Давай напишем наш grep следующим образом:

grep -i "https://cyberskyline\.com/report/[A-Z0-9]\{12\}"

Как можно понять из "регулярки", мы выбираем символы от A до Z в количестве 12 штук. Также уберем "url=" чтобы получить более верный вывод.

curl -s -A "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:128.0)
Gecko/20100101 Firefox/128.0"
"https://www.google.com/search?q=site:cyberskyline.com/report/&start=20"
| grep -i "https://cyberskyline\.com/report/[A-Z0-9]\{12\}" -o

Теперь возникает дублирование результатов в выводе, но эту проблему легко решить добавлением команды uniq в конец нашего конвейера.

curl -s -A "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:128.0)
Gecko/20100101 Firefox/128.0"
"https://www.google.com/search?q=site:cyberskyline.com/report/&start=20"
| grep -i "https://cyberskyline\.com/report/[A-Z0-9]\{12\}" -o | uniq

В результате мы получили список уникальных ссылок на отчеты. В выводе видим 18 ссылок с учетом дубликатов, но их можно убрать с помощью сортировки и удаления повторов командами sort -u и uniq. А пока проверим работоспособность последней ссылки.

И все прекрасно работает. В финальной версии приложения будем последовательно изменять значение параметра start (0, 10, 20, 30 и так далее) для перебора всех доступных страниц поисковой выдачи Google.

Этап 3. Качаем отчеты

Переходим к этапу загрузки отчетов. После реализации парсинга эта задача не должна вызвать затруднений. Для скачивания файлов у нас есть два варианта: curl или wget. Для разнообразия будем использовать wget.

wget https://cyberskyline.com/report/B2L7UK1KQJ2B

Отлично, наш отчет успешно скачан, и мы можем его посмотреть... или нет?

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

Помните, что при первом обращении к отчету сайт запрашивал электронную почту? Еще раз проанализируем запрос на получение отчета через BurpSuite.

Вот и почта, которую мы вводили в самом начале статьи. В cookies она представлена как параметр sky.verifyEmail со значением "loxomeb677@rogtat.com". Добавим этот параметр в wget-запрос. Иногда здесь нужно указывать User-Agent. Так многие приложения защищаются от автоматизированных запросов, но в данном случае можно обойтись без него.

wget --header "Cookie: sky.verifyEmail=loxomeb677@rogtat.com"
https://cyberskyline.com/report/B2L7UK1KQJ2B

Отлично, теперь в ответе мы можем видеть, что был скачан именно PDF-документ. Переходим на рабочий стол, где видим файл B2L7UK1KQJ2B.1. Файл корректно открывается и содержит нужную информацию.

Шаг 4. Парсим PDF

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

Поиск электронной почты в исходном коде PDF не дал результатов. Поищем альтернативное решение: обратимся к Google. Среди первых результатов находим релевантный ответ на SuperUser.com.

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

Указанное приложение у меня не установлено. Но умный Линукс подсказывает, как его скачать:

sudo apt install poppler-utils

Почитав мануал к приложению, определяем правильный синтаксис команды для извлечения текста:

pdftotext [options] <PDF-file> [<text-file>]

Попробуем сконвертировать PDF в текст и потом прочитать первые 10 строчек файла: 

pdftotext B2L7UK1KQJ2B.1 pdfintotext.txt; head pdfintotext.txt

Работает! Имя киберспортсмена находится на третьей строке в выводе, а его электронная почта — на седьмой. 

Для извлечения этих данных используем утилиту awk с командой 'NR==3 || NR==7', которая выведет только содержимое третьей и седьмой строк. Команда 'NR==3 {printf "%s | ", $0} NR==7 {print $0}' выведет 3 и 7 строку в одну строку, разделенную вертикальной чертой (|). Ну и наконец, добавление двойных правых скобок перенаправит вывод в текстовый файл, который мы потом прочитаем.

Осталась самая малость — объединить все наши отдельные скрипты в один большой файл.

Шаг 5. Объединяем части в одно приложение

Подходим к завершающему этапу — объединению всех компонентов в рабочее решение. Согласно разработанному алгоритму, сначала загружаем PDF-файлы, затем обрабатываем их. Для демонстрации концепции ограничимся анализом первых трех страниц поисковой выдачи. Создаем на рабочем столе папку PDFParser для хранения файлов и запускаем mousepad для написания скрипта.

Создадим цикл от 0 до 20 с шагом в 10. Таким образом получим три значения: 0, 10 и 20, которые подставим в парсер поисковика. Цикл будет выглядеть следующим образом:

for start in `seq 0 10 20`; do ...; done

Где 0 — начало отсчета включительно; 10 — шаг каждого цикла; 20 — конец отсчета включительно. 

Подставим формулу парсинга в цикл и запустим код. Не забудьте заменить цифру в адресной строке на переменную $start. Код будет выглядеть таким образом:

#!/bin/bash

for start in `seq 0 10 20`;

do curl -s -A "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:128.0)
Gecko/20100101 Firefox/128.0"
"https://www.google.com/search?q=site:cyberskyline.com/report/&start=$start" | grep -i "https://cyberskyline\.com/report/[A-Z0-9]\{12\}" -o |
sort -u | uniq

done

Запускаем файл стандартной командой bash pdfparser.sh

Отлично, все работает как задумано. Теперь нужно сохранить полученные ссылки для дальнейшей работы. Есть два варианта: временно хранить их в переменной (в оперативной памяти) или сохранить в файл на диск. Для учебных целей выберем второй вариант. Добавим в конце команды >> links.txt, чтобы перенаправить вывод в файл.

Мы записали ссылки в файл, убедились в его создании командой ls и проверили содержимое через cat links.txt. Теперь можем работать с полученными ссылками. Чтобы избежать блокировки со стороны Google (компания зарабатывает на API и ограничивает бесплатный парсинг), закомментируем строку с парсингом и продолжим работу с уже имеющимся файлом ссылок.

Теперь создадим цикл для чтения файла, где каждая строка станет переменной для скачивания файла.

for link in $(cat links.txt)

do
wget --header "Cookie: sky.verifyEmail=loxomeb677@rogtat.com" $link

done

Вставляем, запускаем, проверяем.

Хорошая новость — мы скачали часть файлов. Плохая — только 12 из 27. Почему так произошло? В ответе сервера видим: HTTP request sent, awaiting response... 429 Too Many Requests.

На сайте работает защитный механизм — Web application firewall, который блокирует множественные и частые соединения. Вероятно, система отслеживает подключения по IP-адресу или email из cookies.

Попробуем изменить email — это самый быстрый способ обойти блокировку. Если не поможет, придется добавлять временную задержку между запросами, но это существенно замедлит выполнение скрипта. Для начала добавим в конец адреса случайно сгенерированное число.

for link in $(cat links.txt)

do
wget --header "Cookie: sky.verifyEmail=loxomeb677$(rand)@rogtat.com" 
$link

done

Изменение email не помогло — удалось скачать только 5 файлов из 27, так что добавим задержку между запросами в 3 секунды с помощью команды sleep.

Также используем параметр wget -t (--tries), чтобы ограничить количество попыток скачивания до трех. Если установить его на 0, wget будет пытаться скачивать файл бесконечно. В нашем случае это избыточно.

Обновим код, добавив эти параметры. Для лучшего результата рекомендуется включить VPN или прокси — это позволит сменить IP-адрес и обойти ограничения со стороны сервера.

for link in $(cat links.txt)

do
wget --header "Cookie: sky.verifyEmail=loxomeb677$(rand)@rogtat.com" 
$link
sleep 3

done

Отлично, мы скачали большую часть файлов — 22 из 27. Этого достаточно для текущих целей. Чтобы добиться большего, нужно увеличить интервал между запросами и количество попыток скачивания.

Теперь осталось извлечь информацию из скачанных PDF-файлов. Для этого используем цикл с командой ls — встроенным средством Linux для листинга файлов. Внутрь цикла поместим ранее подготовленный скрипт извлечения текста из PDF:

for pdffile in $(ls -1);
do 
pdftotext $pdffile pdfintotext.txt && awk 'NR==3 {printf "%s | ", $0} NR==7 {print $0}' 
pdfintotext.txt >> database.txt
done

Запустим получившийся скрипт.

Скрипт показал синтаксическую ошибку: May not be a PDF file (continuing anyway) — возможно, файл не является PDF-форматом (обработка продолжается). Действительно, помимо PDF-файлов в папке находятся файл links.txt со ссылками и сам скрипт pdfparser.sh.

Проверим, был ли создан файл database.txt и если да, прочитаем его содержимое.

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

Верно, этот файл оказался отчетом о киберсоревнованиях 2019 года, а не целевым документом 2023 года, и имеет другой формат. Скрипт отработал корректно. Осталось добавить комментарии для пояснений и отформатировать код для удобства чтения, после чего можно запускать готовую программу.

Сам скрипт в текстовом виде:

#!/bin/bash

echo "::::    :::  ::::::::  :::             :::        ::::::::::     :::     :::    :::     :::      ::::::::  :::::::::: 
:+:+:   :+: :+:    :+: :+:             :+:        :+:          :+: :+:   :+:   :+:    :+: :+:   :+:    :+: :+:        
:+:+:+  +:+ +:+        +:+             +:+        +:+         +:+   +:+  +:+  +:+    +:+   +:+  +:+        +:+        
+#+ +:+ +#+ +#+        +#+             +#+        +#++:++#   +#++:++#++: +#++:++    +#++:++#++: :#:        +#++:++#   
+#+  +#+#+# +#+        +#+             +#+        +#+        +#+     +#+ +#+  +#+   +#+     +#+ +#+   +#+# +#+        
#+#   #+#+# #+#    #+# #+#             #+#        #+#        #+#     #+# #+#   #+#  #+#     #+# #+#    #+# #+#        
###    ####  ########  ##########      ########## ########## ###     ### ###    ### ###     ###  ########  ########## "

echo -e "\nStart Google parsing..."
for start in `seq 0 10 20`;
do 
curl -s -A "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0" 
"https://www.google.com/search?q=site:cyberskyline.com/report/&start=$start" | 
grep -i "https://cyberskyline\.com/report/[A-Z0-9]\{12\}" -o | 
sort -u | uniq >> links.txt
done
numberoflines=`wc -l links.txt | cut -d " " -f 1`
echo "Google parsing is done! We got $numberoflines links"

echo -e "\nStart downloading reports..."
for link in $(cat links.txt)
do
wget --header "Cookie: sky.verifyEmail=loxomeb677$(rand)@rogtat.com" -t 3 $link
sleep 3
done
echo "Downloading is done!"

echo -e "\nStart extracting personal data from PDFs..."
for pdffile in $(ls -1);
do 
pdftotext $pdffile pdfintotext.txt && awk 'NR==3 {printf "%s | ", $0} NR==7 {print $0}' pdfintotext.txt >> database.txt
done
echo "Extracting is done! Enjoy"

Скрипт успешно извлек данные участников Киберлиги. Можно ли считать это утечкой? Безусловно — такая информация открывает широкие возможности для целевого фишинга. Злоумышленники могут создавать убедительные письма, используя полные имена пользователей, их рейтинг на платформе, достижения и другие детали из отчета. Отсутствие валидации email-адресов, недостаточная защита от автоматизированного сбора данных создали серьезные риски для пользователей платформы.

Что ж, коллегу я удивил, а вот организаторы Киберлиги, кажется, не впечатлились. Я связался с администрацией платформы. Они подтвердили получение информации и обещали провести проверку, но даже спустя месяц проблема остается нерешенной.

Однако я надеюсь, что этот небольшой эксперимент помог вам глубже понять принципы работы с командной строкой Linux и продемонстрировал, как можно находить неочевидные возможности в исследованиях информационной безопасности.

Хотите узнавать о свежих уязвимостях раньше, чем о них напишут в новостях? Подписывайтесь на Telegram-канал HydrAttack, чтобы первыми получать актуальную ИБ-статистику и инсайды из мира кибербеза!

Теги:
Хабы:
+21
Комментарии0

Публикации

Информация

Сайт
bastion-tech.ru
Дата регистрации
Дата основания
2014
Численность
101–200 человек
Местоположение
Россия
Представитель
Игорь Santry