DOM XSS через location.hash и innerHTML (Express)
Клиентский JavaScript на странице каталога читает фрагмент URL (location.hash) и вставляет его через innerHTML без санитизации. Серверный код чист, защита и уязвимость живут полностью в браузерном JS.
mediumnodejsPro
Задача
# DOM-based XSS через URL-фрагмент
## Сценарий
Перед вами Express-приложение интернет-магазина SecureShop (Node.js + Nunjucks). На странице каталога подключён небольшой клиентский JavaScript-скрипт, который читает «фрагмент» URL-адреса (часть после `#`), декодирует его и отображает наверху списка товаров как метку «Filtering by:..» — типичная UX-фича для запоминаемых ссылок-фильтров.
В отличие от server-side XSS (Reflected/Stored), у этого варианта своя специфика: **фрагмент URL не отправляется на сервер вообще** — браузер хранит его локально и обрабатывает только клиентский код. То есть никакая серверная санитизация, никакая autoescape-логика Nunjucks, никакой WAF не имеют отношения к проблеме. Уязвимость и её фикс полностью живут в JavaScript-коде в браузере.
В реализации этого скрипта декодированный фрагмент склеивается со статической HTML-обёрткой и присваивается элементу через свойство, которое **парсит строку как HTML** и вставляет результат в DOM. Любые HTML-теги в фрагменте URL — включая теги-векторы исполнения JavaScript — оказываются настоящими тегами в дереве страницы и срабатывают с правами скрипта на этой странице, в том числе видят сессионные cookies пользователя.
В сочетании с формой «Report to Admin» (бот открывает присланный URL и взаимодействует со страницей в собственной авторизованной сессии) это даёт классический канал кражи административной сессии и эскалации до админских прав, под которыми приложение отдаёт CTF-флаг.
## Цели
1. Изучите клиентский JavaScript на странице каталога (DevTools → Sources). Подтвердите, что фрагмент URL декодируется и попадает в DOM **через свойство, которое парсит HTML**, а не через свойство, устанавливающее текстовое содержимое.
2. Сконструируйте URL c фрагментом, который при открытии страницы в браузере жертвы извлечёт `document.cookie` и доставит его на ваш Exploit Server.
3. Доставьте этот URL администратору через форму отчёта; перехватите его сессию; войдите от его имени в админский раздел и заберите CTF-флаг.
## Данные
| Параметр | Значение |
|----------|----------|
| Обычный пользователь | `demo` / `demo` |
| Exploit Server | ссылка «Exploit Server» на панели лабы |