Stored XSS Vulnerability Demonstration
localStorage and displayed using innerHTML
without sanitization, allowing JavaScript payloads to execute when comments are rendered.
None
localStorage - persist after page reload and browser restart
(0 comments stored)
This lab sets demo cookies on page load. When the XSS payload executes
alert(document.cookie), it displays all non-HttpOnly cookies.
This lab also demonstrates how XSS can inject a username into the page when untrusted input is inserted without proper sanitization.
// DANGER: Using innerHTML with unsanitized user input
function displayComments() {
const comments = JSON.parse(localStorage.getItem('comments')) || [];
const container = document.getElementById('commentsContainer');
let html = '';
comments.forEach(comment => {
// VULNERABLE: Direct HTML injection
html += `<div>${comment.text}</div>`;
});
container.innerHTML = html; // XSS HERE!
}
// FIX 1: Use textContent (Recommended)
function displayCommentsSecure() {
const comments = JSON.parse(localStorage.getItem('comments')) || [];
const container = document.getElementById('commentsContainer');
container.innerHTML = '';
comments.forEach(comment => {
const div = document.createElement('div');
div.textContent = comment.text; // Safe!
container.appendChild(div);
});
}
// FIX 2: HTML Entity Encoding
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(//g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
HttpOnly flag to prevent JavaScript accessSecure flag for HTTPS-only transmissionSameSite=Strict to prevent CSRFContent-Security-Policy headers
No comments yet. Be the first to comment!