đ Description
The purpose of this challenge is to use CSS code to manipulate the page to execute an Cross Site Scripting (XSS) that you created.
The challenge allows us to load an external CSS file.
Source Code:
|
|
Source code review
|
|
The :root
selector is a special CSS selector that allows you to define global CSS variables for a web page.
|
|
We have three buttons that respectively call the Description
function with parameters âhacker
, âdeveloper
, or âbug
.
The Description
function retrieves the description of the associated parameters from the DOM (:root
) and stores it in the txt
variable.
Then it appends it to the innerHTML
of the ‘desc’ tag using template literals (${txt}
).
đľď¸ Proof of Concept
If a input is reflected inside template literals you can embed JS expressions using ${ ... }
Here’s an example with ${<img src=x onerror=alert()>}
:
|
|
So, if we can control the description of each attribute of the :root
tag, we will be able to execute JavaScript using the JavaScript template ${txt}
.
How to overwrite :root tag ?
It is not possible to “overwrite” the :root
tag, but it is possible to override it.
There are two ways to achieve this. The first one is by using the !important
declaration.
|
|
In CSS, the !important
declaration is used to give a specific CSS rule the highest priority, overriding any other conflicting styles. When applied to an attribute in the :root
selector, an attribute with !important
will take precedence over an attribute without it.
The second way is to declare a under tag :root on :root.
|
|
The reason why :root:root
is prioritized over :root
is because :root:root
is more specific in its targeting. When two selectors have the same specificity, the last selector in the stylesheet takes precedence.
The two different ways would result in the following when any of the three buttons is clicked:
đ Remediation
To protect against XSS attacks when using JavaScript template ${}
syntax, you can take the following measures:
- Sanitize input: Use a sanitization function to remove or escape any special characters that could be interpreted as HTML or JavaScript code. This ensures that user input is treated as plain text rather than executable code.
- Validate and filter input: Implement server-side input validation to ensure that only expected values are accepted. Apply appropriate filters to reject or sanitize any potentially malicious or incorrect input.
- Implement Content Security Policy (CSP): Set up a proper Content Security Policy on your web server to restrict allowed content sources and prevent the execution of unauthorized scripts.
To prevent CSS override injection, you can implement the following measures:
- Escape User-Generated Content: When displaying user-generated content that may contain CSS, properly escape and sanitize the content to prevent any unintended execution of CSS code. Use appropriate encoding techniques or libraries specific to the output context (HTML, CSS, etc.).
- Limit CSS File Inclusion: Only allow the inclusion of CSS files from trusted sources. Avoid dynamically generating URLs or allowing arbitrary file inclusion based on user input.
Conclusion
The challenge was really interesting as it demonstrated the priority of CSS selectors and the ability to override existing styles. It also highlighted the potential security vulnerabilities when using JavaScript templates ${}
.
Thanks to the author for this awesome challenge!