Lab Difficulty: Apprentice
Topic: Cross-Site Scripting (Reflected)
The objective of this lab is to perform a Reflected Cross-Site Scripting
(XSS) attack. The vulnerability exists within the HTML <link> tag used
for canonical URL definition. The goal is to inject a payload that
executes the alert function.
Identification of Reflection Point
We started by navigating to the blog posts and observing how the URL parameters affect the HTML source. The application uses a “canonical” link tag to help search engines understand the preffered URL for a page.
Upon inspecting the source code for a post (e.g., /post?postId=4), we
noticed that the entire URL, including query parameters, is reflected inside
the href attribute of the <link rel="canonical"> tag.
Vulnerability Assessment
The reflection occurs inside a single-quoted string:
<link rel="canonical" href='.../post?postId=4'/>
If the application fails to sanitise single quotes, we can break out of
the href attribute. However, since this tag resides in the <head>
section of the HTML document and is not a visible element, standard event
handlers like onmouseover or onfocus will not trigger automatically or
via mouse interaction.
To exploit this, we need an attribute that allows user interaction via the
keyboard. The accesskey attribute is suitable here, as it allows us to
assign a keyboard shortcut to the element.
Payload Construction
We crafted a payload to:
Break Out: Use a single quote ' to close the href attribute.
Add Interaction: Inject the accesskey='x' attribute. This allows us to
target the hidden element by pressing a key combination (e.g., ALT+X on
Windows, CTRL+ALT+X on macOS).
Add Trigger: Inject onclick='alert(1)'. When the access key is pressed,
the “click” event fires, executing our JavaScript.
Payload:
' accesskey='x' onclick='alert(1)
Full URL:
/?postId=3&x=' accesskey='x' onclick='alert(1)
Execution
We sent the request via Burp Suite to verify the injection structure.
As seen in the response:
<link rel="canonical" href='...postId=3&x=' accesskey='x' onclick='alert(1)'/>