What is Cross-Site Scripting (XSS)?

Security

Cross-Site Scripting (XSS)

Cross-Site Scripting (XSS) is a type of security vulnerability that allows an attacker to inject malicious scripts into a web page viewed by other users. These scripts can then be executed within the user's browser, potentially leading to unauthorized actions, data theft, or other harmful activities.

This category of attack is called an injection attack where we're basically like, putting content in a place that is designed for text, we can trick the system into treating it as code and executing it.

We're allowing our content to become code and to be executed. Allow attackers to read data, or perform operation on user's behalf.

Here's a practical example of an XSS vulnerability in React:

// ❌ Vulnerable to XSS
function CommentDisplay({ userComment }) {
return (
<div
dangerouslySetInnerHTML={{ __html: userComment }}
/>
);
}

// Example attack:
const maliciousComment = `
<img src="invalid-image" onerror="alert('Your data has been stolen!')" />
<script>sendDataToAttacker('cookie: ' + document.cookie)</script>
`;

// ✅ Safe way to handle user content
function SafeCommentDisplay({ userComment }) {
return <div>{userComment}</div>;
}

In the example above, using dangerouslySetInnerHTML with unsanitized user input creates an XSS vulnerability. An attacker could inject malicious scripts that steal cookies, session tokens, or perform actions on behalf of the user. React's default behavior of escaping content inside JSX curly braces ({}) helps prevent XSS attacks, which is why the SafeCommentDisplay version is secure.

More than 30% of sites are vulnerable to this kind of thing in one way or another.

  • Stored XSS - COde that executes attacker's script is persisted
  • Reflected XSS - Transient response from server causes script to execute (i.e, a validation error)
  • DOM Based XSS - No server involvement is required (i.e pass code in via query params)
  • Blind XSS - Exploits vulnerability in another app (log reader), that attacker can't see or access under normal means

XSS Danger Zones

  • User-generated rich text (i.e WYSIWYG)
  • Embedded content
  • Anywhere users have control over URL
  • Anywhere user input is reflected back (i.e coudn't find)
  • Query Parameters rendered into DOM
  • element.innerHTML = ?

Defending against XSS

  • We should never trust raw user data and we should not put raw user data in these places
    • Directly in a script
    • In an HTML comment
    • In an attribute name
    • In a tag name
    • Directly in a style block
  • We should sanitize the raw user data using a library called DOMPurify, we need to keep user values as values and not as code.
00:00