API Rate Limit: Brute-force логина без ограничений
Отсутствие rate limiting на эндпоинте логина позволяет brute-force пароля администратора.
Карта уязвимостей и их исправлений. Каждая лаба — это рабочее приложение, в которое внедрена ошибка, типичная для production-кода. Сломай — почини — пойми.
Отсутствие rate limiting на эндпоинте логина позволяет brute-force пароля администратора.
Уязвимость Mass Assignment возникает, когда приложение слепо доверяет входному JSON и биндит его напрямую в модель базы данных.
Broken Object Level Authorization (BOLA): API возвращает заказы любого пользователя по ID без проверки владельца.
Приложение подписывает JWT токеном HMAC-SHA256 со слабым ключом. Подбери секрет и подделай токен администратора.
JWT RS256/HS256 key confusion: the server exposes the public key and doesn't enforce the signing algorithm, allowing token forgery via algorithm switch.
В этой лаборатории сервер использует JWT для авторизации, но совершает сразу две критические ошибки: использует слабый секретный ключ и доверяет заголовку alg.
Форма регистрации принимает любые пароли, включая однозначные. Аккаунт admin защищён паролем 'admin'.
Обработчик логина имеет разное время ответа для существующих и несуществующих пользователей, что позволяет перечислять аккаунты.
Форма входа не ограничивает количество попыток, позволяя подобрать пароль администратора перебором по словарю.
Форма сброса пароля принимает user_id из клиента, позволяя атакующему сбросить пароль любого пользователя через IDOR.
Сессионные токены генерируются через MD5(username), что позволяет предсказать токен администратора и захватить его сессию.
Регистрация принимает любой пароль без проверки сложности. Пароль администратора — 'admin'.
Обработчик входа раскрывает существование пользователей через разницу во времени ответа — bcrypt вызывается только для существующих аккаунтов.
Форма входа Express-приложения не ограничивает количество попыток, позволяя подобрать пароль администратора перебором по словарю.
JWT подписан слабым секретом — подберите его через brute-force и подделайте токен администратора.
Сервер подписывает JWT через RS256, но при валидации читает алгоритм из заголовка токена. Атакующий меняет alg на HS256, подписывает токен публичным RSA-ключом как HMAC-секретом и получает admin.
Сервер принимает JWT с алгоритмом none — подделайте токен без подписи и получите права администратора.
Регистрация принимает любой пароль без проверки сложности, что позволяет dictionary attack на аккаунты.
Обработчик входа раскрывает существование пользователей через разницу во времени ответа — bcrypt вызывается только для существующих аккаунтов.
Эндпоинт логина не ограничивает количество попыток аутентификации, позволяя атакующему перебирать пароли.
JWT подписан слабым секретом — подберите его через brute-force и подделайте токен администратора.
Сервер принимает JWT с alg:none и доверяет роли из claims — подделайте токен для получения прав администратора.
Сервер подписывает JWT через RS256, но не проверяет алгоритм при валидации. Атакующий скачивает публичный ключ и подписывает HS256-токен этим ключом как HMAC-секретом.
Регистрация принимает любой пароль без проверки сложности. Пароль администратора — 'admin'.
Обработчик входа раскрывает существование пользователей через разницу во времени ответа — bcrypt вызывается только для существующих аккаунтов.
Форма входа не ограничивает количество попыток, позволяя подобрать пароль администратора перебором по словарю.
API-эндпоинт /api/admin/users проверяет заголовок Referer вместо роли пользователя. Атакующий может подделать заголовок и получить доступ к данным администратора.
Middleware проверяет путь с учётом регистра (strings.HasPrefix). Замена /admin на /Admin позволяет обойти проверку роли администратора.
Административный эндпоинт /admin/export зарегистрирован без проверки роли — любой авторизованный пользователь может получить CSV-экспорт с конфиденциальными данными.
Обработчик обновления аватара принимает user_id из формы вместо сессии -- атакующий может изменить профиль любого пользователя, включая администратора.
Админ-эндпоинты Express проверяют наличие сессии, но не роль пользователя. Любой залогиненный demo-пользователь может открыть /admin/stats и забрать флаг.
Заказы интернет-магазина идентифицируются UUID v1 (timestamp + MAC + clock_seq). Все заказы созданы внутри одного процесса, поэтому делят те же node/clock_seq биты — отличаются только по timestamp. Эндпоинт /order/:uuid не проверяет владельца, и атакующий, имея один свой UUID, угадывает UUID соседних заказов и получает чужие данные, включая CTF-флаг.
Эндпоинт просмотра счёта в Express + better-sqlite3 не проверяет владельца ресурса. Получи доступ к счёту администратора и извлеки флаг.
Middleware проверяет доступ к /admin по точному совпадению префикса. Обойдите проверку, изменив регистр символов.
API-эндпоинт /api/users/:user_id/notes не проверяет владельца. Получите заметки администратора.
Административные страницы доступны без аутентификации. Перейдите напрямую и получите конфиденциальные данные.
Middleware проверяет доступ к /admin по точному совпадению. Обойдите проверку, изменив регистр символов.
API-эндпоинт /api/users/<id>/notes не проверяет владельца. Получите заметки администратора.
Административные страницы доступны без аутентификации. Перейдите напрямую и получите конфиденциальные данные.
Checkout читает цену товара из скрытого поля формы вместо базы данных, позволяя подменить стоимость заказа
Корзина магазина принимает отрицательное количество товаров, позволяя получить отрицательную сумму заказа и увеличить баланс
Система купонов позволяет применять несколько купонов одновременно, суммируя скидки сверх допустимого
Мутирующий эндпоинт смены email реализован через GET. SameSite=Lax не защищает от top-level навигации. Измени email администратора через CSRF.
Приложение использует проверку заголовка Referer вместо CSRF-токена. Обойди проверку и смени email администратора.
JSON API эндпоинт не требует кастомных заголовков. Используй CSRF для смены пароля admin через API.
Форма администратора не защищена CSRF-токеном. Заставь бота выполнить действие от имени admin.
Сервер подписывает JWT слабым секретом из словаря. Получив один валидный токен, атакующий за секунды подбирает секрет по словарю офлайн, подписывает новый токен с role=admin и забирает флаг.
Express-приложение подписывает JWT через RS256 и публикует RSA публичный ключ через JWKS-эндпоинт. Функция верификации вызывает jwt.verify без явного whitelist алгоритмов — это позволяет атакующему подписать HS256-токен публичным ключом и получить admin-доступ.
Сервер принимает JWT с alg:none и доверяет роли из claims — подделайте токен для получения прав администратора в SecureShop.
Критичное действие смены пароля выполняется через GET-запрос. SameSite=Lax не защищает от top-level навигации. Сменив пароль администратора через CSRF, залогинься под admin и забери флаг.
JSON-endpoint /api/profile принимает state-changing запрос без проверки CSRF-токена и кастомного заголовка X-Requested-With. Простой fetch с Content-Type:text/plain даёт CSRF.
Админ-эндпоинт активации распродажи не проверяет CSRF-токен. Заставь бота выполнить действие от имени admin.
Endpoint смены email доступен через GET. SameSite=Lax не защищает от top-level GET navigation — измени email admin одной ссылкой.
Приложение проверяет Referer как защиту от CSRF, но проверка некорректна — атакующий может обойти её, указав домен жертвы как часть пути.
JSON API endpoint /api/profile не требует кастомного заголовка X-Requested-With. Смени пароль admin через CSRF-атаку на API.
Форма администратора не защищена CSRF-токеном. Заставь бота выполнить действие от имени admin.
Комментарии к товарам хранятся без санитаризации и отображаются как HTML. Укради сессию администратора.
Поисковый запрос отражается в HTML без экранирования. Выполни произвольный JS в контексте магазина.
JavaScript на странице каталога читает location.hash и вставляет его в DOM через innerHTML. Укради сессию администратора.
Reflected XSS эксплуатируется благодаря CSP с 'unsafe-inline'. Исправление требует nonce-based CSP.
XSS через javascript: URL-схему в атрибуте href. Go html/template экранирует HTML, но пропускает опасные URL-схемы.
Комментарии к товарам рендерятся через nunjucks-фильтр |safe без санитайзинга. Укради сессию администратора через Stored XSS, чтобы получить доступ к флагу.
Поисковый запрос выводится через |safe фильтр Nunjucks без экранирования. Выполни произвольный JS и укради cookie администратора.
Клиентский JavaScript на странице каталога читает фрагмент URL (location.hash) и вставляет его через innerHTML без санитизации. Серверный код чист, защита и уязвимость живут полностью в браузерном JS.
Поисковый запрос выводится через |safe без экранирования, а CSP содержит unsafe-inline — inline-скрипты не блокируются. Исправь экранирование и убери unsafe-inline из script-src.
XSS через javascript: URL-схему в атрибуте href. Nunjucks экранирует HTML-сущности, но не блокирует опасные URL-схемы.
Комментарии к товарам выводятся без экранирования — Stored XSS позволяет украсть cookie администратора.
Поисковый запрос отображается на странице без экранирования, позволяя выполнить произвольный JavaScript в браузере жертвы.
JavaScript читает location.hash и вставляет значение через innerHTML — DOM XSS без участия сервера.
Пользовательский URL выводится в атрибуте href без валидации схемы — javascript: выполняется при клике.
Комментарии к товарам выводятся через |safe без санитизации. Укради сессию администратора через Stored XSS.
Поисковый запрос выводится через |safe фильтр Jinja2 без экранирования. Выполни произвольный JS и укради cookie администратора.
Клиентский JavaScript читает location.hash и вставляет через innerHTML без санитизации. Выполни произвольный JS и укради cookie администратора.
Поисковый запрос выводится через |safe без экранирования, а CSP содержит unsafe-inline — inline-скрипты не блокируются. Исправь оба файла: убери |safe и настрой nonce-based CSP.
XSS через javascript: URL-схему в атрибуте href. Jinja2 экранирует HTML-сущности, но не блокирует опасные URL-схемы.
Подробные сообщения об ошибках раскрывают структуру БД
Debug-эндпоинт раскрывает переменные окружения и список пользователей без аутентификации
FileServer раздаёт .env и .bak файлы из корня проекта
Ошибки сервера возвращают полные stack traces с путями файлов, SQL-схемой и переменными.
Flask запущен с debug=True. Через Werkzeug debugger можно получить переменные окружения.
Статическая директория содержит backup-файлы с конфиденциальными данными. Найдите SQL-дамп и извлеките флаг.
unserialize() без allowed_classes + классы с magic-методами (__destruct, __toString) позволяют собрать POP-цепочку, которая пишет PHP webshell в /static и даёт RCE.
Эндпоинт просмотра инвойсов пытается «прочитать структурированные метаданные» и вызывает Phar::loadPhar() + getMetadata() на пути из параметра без проверки расширения. Атакующий загружает PHAR-архив под видом .jpg с объектом InvoiceCache в metadata — getMetadata() делает unserialize(), триггерит __destruct() → system() → RCE.
Cookie user_prefs десериализуется через unserialize() — подделайте объект с магическим __wakeup() и получите админские права.
Админ-эндпоинты /admin/stats и /admin/users/delete проверяют аутентификацию, но не авторизацию. Любой залогиненный пользователь может получить флаг.
Эндпоинт просмотра счета не проверяет владельца. Получи флаг из счета другого пользователя.
Админ-форма импорта продуктового фида проверяет hostname URL и отвергает loopback и приватные сети, но fetch() автоматически следует HTTP-редиректам — внешний сервер атакующего перенаправляет на внутренний /admin/stats и утечка флага.
SSRF в /fetch-url без блокировки link-local адресов — IMDS отдаёт IAM credentials.
Обработчик загрузки аватара в Express делает fetch по пользовательскому URL без валидации — доступ к внутреннему /admin/stats и утечка флага.
Admin-эндпоинты /admin/stats и /admin/users/delete защищены только аутентификацией, но не авторизацией. Обычный пользователь может выполнять действия администратора.
Заказы используют последовательные integer ID. Атакующий перебирает ID и просматривает чужие заказы.
Эндпоинт /invoice?id=N возвращает инвойс без проверки владельца. Атакующий перебирает ID и читает чужие данные.
Админ-эндпоинты проверяют аутентификацию, но не роль пользователя.
Заказы используют последовательные целочисленные ID без проверки владельца.
API-эндпоинт обновления профиля принимает все JSON-поля, включая role.
Эндпоинт просмотра счёта не проверяет владельца. Получи данные чужого счёта.
Параметр page передаётся в include() при включённом allow_url_include — атакующий загружает и выполняет произвольный PHP-код с удалённого сервера.
Наивная фильтрация ../ не блокирует php://filter — атакующий читает исходники PHP-файлов в base64.
Параметр file передаётся напрямую в include() без валидации — атакующий читает произвольные файлы сервера.
Обработчик сетевой диагностики передаёт пользовательский ввод в sh -c без фильтрации. Результат команды не отображается — используйте time-based технику для подтверждения инъекции.
Простая OS Command Injection через инструмент сетевой диагностики в админ-панели.
Обработчик архивации файлов использует exec.Command без shell, но не фильтрует аргументы, начинающиеся с '-'. Атакующий может внедрить произвольные флаги команды tar.
Эндпоинт смены email реализован через GET. SameSite=Lax не защищает top-level navigation — измени email админа через CSRF и забери флаг из /api/admin/email.
JSON API /api/profile на Express принимает запросы без CSRF-токена и без проверки кастомного заголовка X-Requested-With. Смени пароль admin через cross-origin CSRF — затем войди и забери флаг.
Форма администратора не защищена CSRF-токеном. Заставь бота выполнить действие от имени admin.
Пользовательский ввод передаётся в eval(), позволяя выполнить произвольный PHP-код.
Админ-панель содержит функцию ping с blacklist-фильтром (пробел, ;, cat, flag). Фильтр обходится через ${IFS}, $(), backticks и регистр имени переменной окружения.
Панель администратора содержит функцию ping, передающую ввод напрямую в shell без фильтрации.
Калькулятор на e-commerce сайте вычисляет выражения через eval(), позволяя любому авторизованному пользователю выполнить произвольный Python-код.
API сетевой диагностики выполняет команду shell, но не возвращает вывод. Уязвимость обнаруживается через задержку ответа (timing-based).
Панель администратора содержит функцию ping, передающую ввод напрямую в os.popen() без фильтрации.
Атака на инфраструктуру через /proc/self/environ.
Обработчик скачивания файлов применяет filepath.Clean ДО URL-декодирования. Двойное кодирование (%252e%252e%252f) обходит проверку и позволяет читать произвольные файлы.
Обход неумелого использования функции filepath.Clean.
Классическая уязвимость Path Traversal через os.Open.
Обработчик скачивания файлов проверяет только '..' в пути, но не блокирует абсолютные пути (/etc/passwd, /.env). Атакующий может читать любой файл на сервере.
Эндпоинт скачивания файлов фильтрует путь через replace('../', '') без флага /g — фильтр срабатывает только один раз, и любая цепочка ../../../ обходит его.
Классическая Path Traversal в Express через fs.readFileSync(path.join(base, userInput)) без проверки выхода за пределы базовой директории.
Эндпоинт скачивания изображений склеивает имя файла с базовой директорией через path.resolve. Из-за поведения path.resolve абсолютный аргумент отбрасывает базовый путь — атакующий читает любой файл сервера.
Нормализация пути применяется ДО конкатенации с базовым каталогом — traversal-последовательности сохраняются после Clean, позволяя читать произвольные файлы.
Обход пути через параметр file в эндпоинте загрузки файлов (PHP).
Сервер фильтрует '..' в запросах на скачивание, но не проверяет абсолютные пути — можно читать любой файл системы.
Обработчик скачивания файлов не блокирует /proc/self/environ — утечка секретов через переменные окружения.
Обработчик использует os.path.normpath() до конкатенации, что не предотвращает выход за пределы директории.
Классическая уязвимость Path Traversal через os.path.join() без проверки выхода за пределы базовой директории.
Обработчик скачивания файлов проверяет только '..' в пути, но не блокирует абсолютные пути. В Python os.path.join('/base', '/etc/passwd') возвращает '/etc/passwd' — второй аргумент абсолютный, base игнорируется.
Состояние гонки при активации промокодов.
Race condition: чтение и списание баланса без транзакции позволяет двойную трату при параллельных запросах.
Заказы используют последовательные целочисленные ID. Эндпоинт /order/{id} не проверяет владельца — можно перебрать чужие заказы и найти флаг.
Эндпоинт обновления профиля принимает JSON и записывает все поля, включая role. Отправь {"role":"admin"} и получи доступ к админ-панели с флагом.
Эндпоинт активации промокода в Express + better-sqlite3 содержит TOCTOU между проверкой счётчика и обновлением баланса. Получи бонус несколько раз параллельными запросами, накопи баланс и открой VIP-функцию с флагом.
Состояние гонки при активации промокодов (PHP).
Состояние гонки при активации промокодов (Python).
Обход фильтрации пробелов и черного списка команд для RCE.
Веб-калькулятор вычисляет пользовательские выражения через eval(). Это даёт атакующему полный RCE: доступ к process.env, child_process и любым модулям Node.js.
Функция ping в админ-панели защищена blacklist-фильтром, блокирующим пробелы и ключевые слова cat/flag/tail/less/more. Фильтр обходится через ;id, ;env и другие конструкции без пробелов.
API сетевой диагностики Express выполняет ping через child_process.exec, но вывод не возвращается клиенту. Уязвимость подтверждается через задержку ответа (timing-based blind injection).
Панель администратора содержит инструмент диагностики сети, передающий ввод напрямую в child_process.exec() без фильтрации.
Функция ping защищена blacklist-фильтром, блокирующим пробелы и ключевые слова. Фильтр обходится через ${IFS}, brace expansion и другие техники.
Case-sensitive blacklist SQL keywords обходится через смешанный регистр (uNiOn, sElEcT)
Payload сохраняется в БД через безопасный INSERT, но выполняется в другом запросе через конкатенацию строк
Получение пароля администратора с использованием UNION SELECT
Эксплуатация слепой SQL-инъекции, основанной на задержках времени ответа (Time-Based) в SQLite.
Слепая Boolean-based SQL-инъекция через Cookie купона
Обход авторизации с использованием SQL Injection
Обход WAF с чёрным списком SQL-ключевых слов для эксплуатации SQL-инъекции в форме логина Express + better-sqlite3.
Извлечение данных из таблицы users через UNION-based SQL injection в поиске каталога Express-приложения.
Second-order SQL injection: вредоносный username безопасно сохраняется при регистрации, но выполняется как часть SQL позже, когда обработчик профиля собирает запрос истории заказов конкатенацией.
Обход аутентификации через классическую SQL-инъекцию в форме логина Express + better-sqlite3.
WAF с blacklist-фильтром блокирует SQL-ключевые слова, но обходится через mixed case.
UNION-based SQL-инъекция через поиск товаров позволяет извлечь данные из таблицы пользователей.
Имя из БД подставляется в SQL через конкатенацию — Second-Order SQLi.
Значение купона из cookie подставляется в SQL-запрос без параметризации, позволяя извлечь данные через boolean-based blind инъекцию.
Обход аутентификации через SQL-инъекцию в форме логина.
Обход WAF с чёрным списком SQL-ключевых слов для эксплуатации SQL-инъекции в форме логина.
Извлечение данных из БД через UNION SELECT в поиске каталога Flask-приложения.
SQL-инъекция второго порядка: payload сохраняется при регистрации и срабатывает при просмотре профиля.
Извлечение данных через Time-based Blind SQLi в форме восстановления пароля Flask-приложения.
Извлечение данных через Boolean-based Blind SQLi в эндпоинте проверки купонов.
Обход авторизации через SQL-инъекцию в форме логина Flask-приложения.
Эксплуатация SSTI через вызов методов объектов в контексте шаблона.
SSRF-уязвимость: валидация URL обходится через HTTP-редирект на внутренний адрес.
SSRF-уязвимость: неполная фильтрация IP позволяет обратиться к link-local адресу облачных метаданных (169.254.169.254).
SSRF с обходом слабого фильтра хоста в URL и эксплуатация через альтернативные IP-адреса.
Простая SSRF-уязвимость, позволяющая получить доступ к внутренним ресурсам сервера.
Профиль SecureShop рендерит пользовательское приветствие через pug.render() — SSTI в JavaScript-окружении с чтением секретов и RCE.
Server-Side Template Injection в Express + EJS: пользовательский ввод используется как сам EJS-шаблон, что позволяет выполнить произвольный JavaScript на сервере и прочитать переменные окружения.
Пользовательское приветствие в SecureShop рендерится через nunjucks.renderString() — SSTI позволяет выполнять JS и читать переменные окружения.
Приложение проверяет IP адрес при первом запросе, но cURL автоматически следует редиректам на внутренние адреса — атакующий обходит проверку через промежуточный сервер.
Приложение блокирует только loopback-адреса, но не link-local 169.254.169.254 — атакующий читает облачные метаданные AWS.
Приложение загружает аватар по URL без проверки — атакующий может обратиться к внутренним сервисам.
Обработчик загрузки аватара проверяет IP начального URL, но requests.get() автоматически следует редиректам — внешний сервер перенаправляет на внутренний адрес.
SSRF-защита проверяет is_loopback но не is_link_local — доступ к cloud metadata 169.254.169.254.
Обработчик загрузки аватара делает HTTP-запрос по пользовательскому URL без валидации — доступ к внутренним сервисам.
SSTI-уязвимость: пользовательский ввод передаётся в template.Parse(), позволяя читать серверные данные.
Утечка конфиденциальных данных из контекста страницы через небезопасную обработку шаблонов.
Express SecureShop валидирует адрес персонального сайта пользователя через регулярное выражение с вложенными квантификаторами в последней метке хоста. Тщательно подобранная строка вызывает catastrophic backtracking движка V8: event loop блокируется на секунды, инцидент фиксируется в журнале и admin-эндпоинт выдаёт флаг.
Сервис ProfileGuard валидирует email пользователя на стороне сервера через регулярное выражение с вложенными квантификаторами. Тщательно подобранная входная строка вызывает экспоненциальный backtracking движка V8, поток событий блокируется на десятки секунд, инцидент фиксируется в логе администратора — и вместе с ним выдаётся флаг.
Админ-панель SecureShop рекурсивно сливает JSON-патч предпочтений с in-memory объектом, что позволяет загрязнить Object.prototype. Превью дашборда через EJS читает опции компиляции через цепочку прототипов — это превращает prototype pollution в RCE-гаджет и даёт чтение LAB_FLAG.
Express-эндпоинт POST /profile/settings делает рекурсивный merge JSON-объекта в per-user настройки без фильтрации __proto__. Атакующий загрязняет Object.prototype, после чего hot-path обработчик /catalog падает с 500 на каждом запросе — Denial of Service. Endpoint /api/incident-response регистрирует инцидент и выдаёт флаг.
Эндпоинт обновления пользовательских настроек в Express делает recursive merge тела запроса без фильтрации ключа __proto__. Загрязни Object.prototype.isAdmin и получи доступ к /admin/flag.
Пользовательский ввод передаётся в Twig createTemplate(), что позволяет выполнить произвольный код на сервере.
Greeting template executed via eval() allows arbitrary PHP code injection.
Пользовательский шаблон отчёта рендерится через render_template_string() — SSTI позволяет выполнить произвольный код через цепочку __subclasses__.
Форма восстановления пароля использует str.format() с пользовательским шаблоном — атакующий может читать атрибуты объектов через {username.__class__.__init__.__globals__}.
Админ-шаблон email-уведомлений рендерится через render_template_string() — слепая SSTI через time-based payload.
Пользовательское приветствие рендерится через render_template_string() — SSTI позволяет читать секреты и выполнять код.
Эндпоинт /promo сравнивает секретный токен через strcmp() с `== 0`. Отправка promo_token[]=x превращает strcmp() в NULL, а NULL == 0 — true: проверка обходится.
JSON-API логина сравнивает пароль с хешем через loose == . В БД хранится хеш-строка вида 0e830... (magic hash), которая коэрсится в число 0.0. Отправив {"password": 0}, атакующий заходит как admin.
API-логин через токен использует loose comparison (==) между md5-хэшами. Magic hash вида 0e[0-9]+ интерпретируется как научная нотация (0.0), что приводит к коллизии хэшей и обходу аутентификации.
Обработчик загрузки использует filepath.Ext() для проверки расширения, но эта функция возвращает только последнее расширение. Файл test.html.jpg проходит проверку, а Go http.FileServer может определить Content-Type по первому расширению.
Обработчик загрузки файлов проверяет только расширение (.jpg, .png, .gif), но не реальное содержимое файла. HTML-файл с расширением .jpg будет принят и отдан браузеру.
Сервер принимает файлы с расширением .jpg, но слепо доверяет имени файла из Content-Disposition. Используйте Path Traversal, чтобы подбросить свой токен конфигурации и получить флаг.
Загрузчик изображений товара доверяет MIME-типу, который пришёл в заголовке Content-Type части multipart-формы. Атакующий подделывает заголовок и загружает HTML с активным контентом, выдавая его за PNG.
Загрузка аватара без санитизации имени файла позволяет перезаписать серверные шаблоны через path traversal в filename.
Загрузка .htaccess позволяет выполнять PHP-код внутри файлов с произвольным расширением.
Загрузка файлов проверяет только расширение, но не содержимое. Атакующий может загрузить HTML/JS в файле с расширением .jpg.
Загрузка аватара использует оригинальное имя файла без санитизации. Подмени filename в multipart-запросе для перезаписи шаблона и получения RCE.
Загрузка документов сохраняет файлы в директорию templates/ без проверки содержимого. Просмотр файлов через render_template() позволяет выполнить Jinja2 SSTI.
Загрузчик изображений проверяет расширение файла, но не его содержимое. HTML-файл, переименованный в .jpg, загружается и исполняется в браузере.
Загрузка аватара без санитизации имени файла позволяет перезаписать серверные шаблоны через path traversal в filename.
WebSocket chat broadcasts unsanitized messages. Client renders via innerHTML, enabling XSS.
Сервер открывает WebSocket-соединение для отправки приватных уведомлений, но забывает проверять Origin. Воспользуйтесь ботом администратора, чтобы заставить его открыть вашу вредоносную страницу и угнать флаг через сокет.