Cross-Site Scripting (XSS)
Cross-Site Scripting (XSS)
Description
Cross-site-scripting (XSS) vulnerabilities occur when unsanitized user-controlled input is served to the user.
XSS vulnerabilities bypass same-Origin-Policy, which is a core principle of web security. SOP ensures that a page
from http://evil.com
can't access the content of a page from http://bank.com
.
XSS is commonly separated into three families
- Reflected: the user-controlled input is directly reflected in the page response
- Stored: the user-controlled input is stored on the server side, for instance, in a database, and is later returned to user
- DOM-based: the user-controlled input is injected on the client-side to the DOM, triggering the injection of malicious JavaScript
XSS vulnerabilities allow an attacker to perform a variety of malicious actions, like exfiltration of personal data, including user session or account information; perform actions on behalf of the user.
Examples
import javax.servlet.http.*;
import java.io.*;
public class VulnerableXSS extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String userInput = request.getParameter("input");
String page = "<html><body><h2>User Input: " + userInput + "</h2></body></html>";
PrintWriter out = response.getWriter();
out.println(page);
}
}
const express = require('express');
const app = express();
app.get('/vulnerable', (req, res) => {
const userInput = req.query.input;
res.send(`<html><body><h2>User Input: ${userInput}</h2></body></html>`);
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
<!DOCTYPE html>
<html>
<head>
<title>XSS Vulnerability</title>
</head>
<body>
<h1>Welcome to the Vulnerable Page</h1>
<p>Search for a product:</p>
<form action="/search">
<input type="text" name="query" placeholder="Enter product name">
<input type="submit" value="Search">
</form>
<p>Search results:</p>
<div id="results">
<!-- Display search results here -->
<?php
// Vulnerable code - directly echoing user input without sanitization
$query = $_GET['query'];
echo "<p>You searched for: " . $query . "</p>";
?>
</div>
</body>
</html>
Recommendation
In general, cases, preventing XSS vulnerabilities requires 2-step protection:
- Input validation: user-controlled input should be validated to forbid all unauthorized characters, phone number For instance, only numbers; names should only contain alphabetical characters, etc.
- Output encoding: all input shown to the user is encoded correctly using proven standard API. Use of a safe template engines with native support for output encoding and secure defaults are highly recommended.
Examples
import org.apache.commons.text.StringEscapeUtils;
import javax.servlet.http.*;
import java.io.*;
public class SecureXSSWithLibrary extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String userInput = request.getParameter("input");
String sanitizedInput = StringEscapeUtils.escapeHtml4(userInput);
String page = "<html><body><h2>User Input: " + sanitizedInput + "</h2></body></html>";
PrintWriter out = response.getWriter();
out.println(page);
}
}
const express = require('express');
const app = express();
const { escape } = require('html-escaper'); // Using 'html-escaper' library
app.get('/secure', (req, res) => {
const userInput = req.query.input;
const sanitizedInput = escape(userInput);
res.send(`<html><body><h2>User Input: ${sanitizedInput}</h2></body></html>`);
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
<!DOCTYPE html>
<html>
<head>
<title>Secure Page</title>
</head>
<body>
<h1>Welcome to the Secure Page</h1>
<p>Search for a product:</p>
<form action="/search">
<input type="text" name="query" placeholder="Enter product name">
<input type="submit" value="Search">
</form>
<p>Search results:</p>
<div id="results">
<!-- Display sanitized search results here -->
<?php
// Sanitizing user input before displaying
$query = $_GET['query'];
echo "<p>You searched for: " . htmlspecialchars($query, ENT_QUOTES, 'UTF-8') . "</p>";
?>
</div>
</body>
</html>
Links
- CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
- CWE-80: Improper Neutralization of Script-Related HTML Tags in a Web Page (Basic XSS)
- CWE-116: Improper Encoding or Escaping of Output
- CWE-159: Failure to Sanitize Special Element
Standards
- OWASP_ASVS_L1:
- V5_2_1
- V5_3_1
- V13_1_1
- OWASP_ASVS_L2:
- V5_2_1
- V1_5_4
- V5_3_1
- V13_1_1
- OWASP_ASVS_L3:
- V5_2_1
- V1_5_4
- V5_3_1
- V13_1_1
- PCI_STANDARDS:
- REQ_2_2
- REQ_6_2
- REQ_6_3
- REQ_6_4
- REQ_11_3
- SOC2_CONTROLS:
- CC_2_1
- CC_4_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5