Severity: High
Vulnerability Type: Reflected XSS/CSP Bypass/Client-Side Template Injection
Target: Web Security Academy Blog-Search Functionality
A Reflected Cross-Site Scripting (XSS) vulnerability was identified in the blog search functionality.
The application uses AngularJS and implements a Content Security Policy (CSP)
to prevent inline script execution. However, the application reflects user
input into the HTML body where AngularJS is active. An attacker can inject
specific HTML directives (ng-focus) that the AngularJS framework executes.
By combining this with a specific URL fragment to force element focus and an
AngularJS sandbox escape payload, an attacker can bypass the CSP and execute
arbitrary JavaScript on the victim’s browser immediately upon page load.
2.1 Target identification & Reflection
The search function reflects the user’s input directly into the HTML page. The
response headers confirm that the application is protected by a CSP that
disallows inline scripts (script-src 'self').
However, an analysis of the loaded scripts revealed the presence of AngularJS (v1.4.4).
2.2 Exploitation Strategy
Standard XSS payloads (like <script>) are blocked by the CSP. However,
AngularJS parses HTML attributes starting with ng- (directives) and
executes them within its own context, which is “trusted” by the CSP because
the Angular library itself is loaded from a trusted source ('self').
The Attack Chain:
Injection: Inject an HTML element (<input>) with an AngularJS event
listener (ng-focus).
Trigger: Use the URL fragment identifier (#x) to tell the browser to
automatically “focus” on our injected element (id=x) as soon as the page
loads.
Sandbox Escape: Inside the ng-focus event, use an expression that breaks
out of the AngularJS sandbox to call alert().
2.3. Payload Construction
The following payload was constructed to achieve execution:
<input id=x ng-focus=$event.composedPath()|orderBy:'(z=alert)(document.cookie)'>
id=x: Sets the element ID so we can target it with the URL fragment.
ng-focus: The directive that executes code when the element receives focus.
$event.composedPath() | orderBy:...: This specific chain is a known
sandbox escape for this version of AngularJS. It manipulates an array (the
event path) and passes it to the orderBy filter, which allows function
calls (like alert) to be executed during the sorting process.
2.4 Execution
When the victim visits the malicious URL constructed on the exploit server, the browser loads the page, focuses the injected input field, and triggers the XSS payload, displaying the session cookie.
The impact is rated as High.
CSP Bypass: The attack demonstrates that the current CSP is ineffective against library-based attacks (Client-Side Template Injection).
Zero-Interaction: The use of the autofocus or URL fragment technique
means the victim does not need to interact with the page (other than
loading it) for the code to execute.
Session Compromise: Arbitrary JavaScript execution allows for session hijacking (cookie theft) or redirection to malicious sites.
To mitigate this vulnerability:
Update AngularJS: The application is using an outdated version of AngularJS. Migrate to a modern, supported framework (Angular 2+, React, Vue) that does not rely on this type of sandbox.
Context-Aware Encoding: Strictly encode all user-supplied data reflected in the HTML body.
Disable ng-app: If possible, do not place the ng-app directive on the
<body> or <html> tag. Limit the scope of AngularJS to specific
containers that do not contain reflected user input.
CSP Refinement: Consider using CSP Level 3 features like strict-dynamic
with nonces, though this is difficult to implement with legacy AngularJS.