Share
## https://sploitus.com/exploit?id=CC02DC93-529C-56EA-80F3-1CE20F705330
# Stored Cross-Site Scripting (XSS) Vulnerability Report

## Executive Summary

This report documents the implementation, exploitation, and mitigation of a **Stored Cross-Site Scripting (XSS)** vulnerability in a vulnerable blog application. The project demonstrates how user input stored in a database (localStorage) can execute malicious JavaScript code when displayed to other users, and implements a defense-in-depth mitigation strategy using both input sanitization and safe output rendering.

---

## 1. Chosen Vulnerability: Stored Cross-Site Scripting (XSS)

### 1.1 Vulnerability Type

**Stored XSS (Persistent XSS)** - Type 2 XSS vulnerability

### 1.2 Description

Stored XSS occurs when malicious scripts are permanently stored on a target server (or client-side storage) and executed when other users view the stored content. Unlike Reflected XSS, the payload persists across sessions and affects all users who view the compromised content.

### 1.3 Risk Level

**HIGH** - Stored XSS is considered more dangerous than Reflected XSS because:

- The attack persists indefinitely
- All users viewing the content are affected
- Can lead to session hijacking, cookie theft, defacement, and malware distribution
- No user interaction required beyond viewing the page

### 1.4 Impact

- **Session Hijacking**: Steal user session cookies
- **Account Takeover**: Perform actions on behalf of users
- **Data Theft**: Extract sensitive information from the page
- **Malware Distribution**: Redirect users to malicious sites
- **Website Defacement**: Modify page content
- **Phishing Attacks**: Create fake login forms

---

## 2. Implementation

### 2.1 Project Structure

```
cyber_sec_project/
โ”œโ”€โ”€ index.html      # Main HTML structure
โ”œโ”€โ”€ script.js       # JavaScript logic (vulnerability & mitigation)
โ””โ”€โ”€ styles.css      # Styling
```

### 2.2 Technologies Used

- **HTML5**: Page structure and form elements
- **JavaScript (ES6+)**: Client-side logic and DOM manipulation
- **localStorage API**: Client-side data persistence (simulating database)
- **DOMPurify Library v3.0.8**: HTML sanitization library (CDN)
- **CSS3**: Styling and responsive design

### 2.3 Vulnerable Code Implementation

#### 2.3.1 Data Storage Mechanism

The application uses `localStorage` to simulate a database, storing blog posts and comments persistently:

```javascript
// Save posts data to localStorage
function savePostsData() {
  localStorage.setItem("postsData", JSON.stringify(postsData));
}

// Load posts data from localStorage or use default
function loadPostsData() {
  const saved = localStorage.getItem("postsData");
  if (saved) {
    return JSON.parse(saved);
  }
  // ... default data
}
```

#### 2.3.2 Vulnerable Comment Submission

The `addComment()` function accepts user input without sanitization:

```javascript
function addComment(event) {
  event.preventDefault();

  const postId = document.getElementById("current-post-id").value;
  let author = document.getElementById("comment-author").value;
  let commentText = document.getElementById("comment-text").value;

  // VULNERABILITY: No input sanitization
  // The comment text is stored and displayed as it is once loaded

  const comment = {
    id: Date.now(),
    author: author, // Unsanitized user input
    text: commentText, // Unsanitized user input
    date: new Date().toLocaleString(),
  };

  // Store the comment (persists in localStorage)
  postsData[postId].comments.push(comment);
  savePostsData();

  // Display comments (vulnerable rendering)
  displayComments(postId);
}
```

**Vulnerability Point**: User input (`author` and `commentText`) is stored directly without validation or sanitization.

#### 2.3.3 Vulnerable Display Function

The `displayComments()` function uses `innerHTML` with unsanitized user content:

```javascript
function displayComments(postId) {
  const commentsContainer = document.getElementById("comments-list");
  const comments = postsData[postId].comments;

  let commentsHTML = "";
  comments.forEach((comment) => {
    // VULNERABILITY: innerHTML with unsanitized user content
    commentsHTML += `
      
        ${comment.author}
        ${comment.text}
        ${comment.date}
      
    `;
  });

  // VULNERABLE: Setting innerHTML with user-controlled content
  commentsContainer.innerHTML = commentsHTML;
}
```

**Vulnerability Point**: Template literals with `innerHTML` allow JavaScript execution. Any HTML/JavaScript in `comment.author` or `comment.text` will be executed.

### 2.4 Why This Implementation is Vulnerable

1. **No Input Validation**: User input is accepted as-is without checking for malicious patterns
2. **Unsafe DOM Manipulation**: Using `innerHTML` with user-controlled data allows script execution
3. **Persistent Storage**: Malicious payloads are stored and persist across sessions
4. **No Output Encoding**: Data is displayed without HTML entity encoding

### 2.5 Important Note: Browser Security and `` Tags

**Modern browsers have built-in XSS protection** that prevents `` tags from executing when inserted via `innerHTML`. This is why `alert('XSS')` may appear to be "sanitized" even in vulnerable mode.

**However, the application is still vulnerable** to other XSS vectors:

- โœ… **Event Handlers**: `` - **WORKS**
- โœ… **SVG with handlers**: `` - **WORKS**
- โœ… **iframe with javascript**: `` - **WORKS**
- โŒ **Script tags**: `alert('XSS')` - **DOESN'T WORK** (browser protection)

This is why the demo payload uses `` instead of `` tags. The vulnerability is real and dangerous - attackers simply need to use event handlers or other HTML elements instead of script tags.

---

## 3. Exploitation

### 3.1 Attack Vector

The vulnerability can be exploited through the comment submission form, where attackers inject malicious JavaScript code.

### 3.2 Exploitation Steps

#### Step 1: Access the Vulnerable Application

1. Open `index.html` in a web browser
2. Navigate to any blog post (e.g., "Ocean Sunset")
3. Scroll to the comments section

#### Step 2: Inject Malicious Payload

In the comment form, enter a malicious payload:

**Example Payload 1: Alert Popup (Event Handler) - โœ… WORKS**

```

```

**Example Payload 2: SVG with onload - โœ… WORKS**

```

```

**Note**: `` tags do NOT work with `innerHTML` due to browser security, but event handlers on HTML elements DO work and are equally dangerous.

#### Step 3: Submit the Comment

1. Enter a name (e.g., "Attacker")
2. Paste the malicious payload in the comment field
3. Click "Post Comment"

#### Step 4: Payload Execution

- The malicious code is stored in `localStorage`
- When the page displays comments, the payload executes automatically
- All users viewing this post will have the script executed in their browser context

### 3.3 Proof of Concept

The application includes a demo payload pre-loaded in Post 2 ("Ocean Sunset"):

```javascript
// Demo malicious comment injected on page load
postsData[2].comments.push({
  id: 2,
  author: "Bassant the attacker",
  text: 'This comment contains a hidden XSS payload that executes when viewed!',
  date: new Date(Date.now() - 3600000).toLocaleString(),
});
```

**To see the vulnerability:**

1. Open the application with `SANITIZATION_MODE = false`
2. Navigate to "Ocean Sunset" post
3. The alert will execute automatically when comments load

## 4. Mitigation Strategy

The project implements a **defense-in-depth** approach with multiple layers of protection:

### 4.1 Mitigation Toggle

A configuration flag controls mitigation:

```javascript
const SANITIZATION_MODE = false; // Set to true to enable mitigation
```

### 4.2 Layer 1: Input Sanitization (DOMPurify)

#### 4.2.1 DOMPurify Library Integration

DOMPurify is loaded via CDN in `index.html`:

```html

```

#### 4.2.2 Input Sanitization Function

The `sanitizeInput()` function uses DOMPurify to sanitize user input before storage:

```javascript
function sanitizeInput(input) {
  // Check if DOMPurify is available (loaded from CDN)
  if (typeof DOMPurify !== "undefined") {
    // DOMPurify: Removes dangerous HTML/scripts but allows safe content
    // ALLOWED_TAGS: [] means no HTML tags allowed (strict mode)
    return DOMPurify.sanitize(input, {
      ALLOWED_TAGS: [], // No HTML tags allowed - treats everything as plain text
      ALLOWED_ATTR: [], // No attributes allowed
    });
  } else {
    // Fallback: Basic sanitization if DOMPurify fails to load
    const tempDiv = document.createElement("div");
    tempDiv.textContent = input; // textContent will auto escapes HTML
    return tempDiv.innerHTML;
  }
}
```

**How it works:**

- DOMPurify parses the input and removes all dangerous HTML elements and attributes
- With `ALLOWED_TAGS: []`, all HTML tags are stripped, leaving only plain text
- HTML entities are properly escaped (e.g., ` {
    // Create elements programmatically to avoid XSS
    const commentDiv = document.createElement("div");
    commentDiv.className = "comment";

    const authorDiv = document.createElement("div");
    authorDiv.className = "comment-author";
    authorDiv.textContent = comment.author; // textContent escapes HTML

    const textDiv = document.createElement("div");
    textDiv.className = "comment-text";
    textDiv.textContent = comment.text; // textContent escapes HTML

    const dateDiv = document.createElement("div");
    dateDiv.className = "comment-date";
    dateDiv.textContent = comment.date;

    // Build DOM tree safely
    commentDiv.appendChild(authorDiv);
    commentDiv.appendChild(textDiv);
    commentDiv.appendChild(dateDiv);

    commentsContainer.appendChild(commentDiv);
  });
}
```

**How it works:**

- `document.createElement()` creates DOM elements programmatically
- `textContent` property treats content as plain text and automatically escapes HTML
- `appendChild()` builds the DOM tree without parsing HTML strings
- No HTML/JavaScript can execute because content is never parsed as HTML

#### 4.3.2 Comparison: Vulnerable vs Safe

**Vulnerable (innerHTML):**

```javascript
container.innerHTML = `${userInput}`;
// If userInput = ""
// Result: Event handler executes โŒ (Script tag wouldn't work due to browser protection)
// If userInput = "alert('XSS')"
// Result: Script tag is stripped by browser, but event handlers still execute โŒ
```

**Safe (textContent):**

```javascript
const div = document.createElement("div");
div.textContent = userInput;
container.appendChild(div);
// If userInput = "alert('XSS')"
// Result: Displayed as text "alert('XSS')" โœ…
```

#### 4.3.3 Application in Display Logic

The safe display function is used when mitigation is enabled:

```javascript
// Refresh comments display
if (SANITIZATION_MODE) {
  displayCommentsSafe(postId); // Safe: uses textContent
} else {
  displayComments(postId); // Vulnerable: uses innerHTML
}
```

**Protection**: Even if malicious data somehow bypasses input sanitization, output sanitization prevents execution.

### 4.4 Defense-in-Depth Benefits

Using both layers provides:

1. **Redundancy**: If one layer fails, the other provides protection
2. **Multiple Attack Vectors Covered**: Protects against both stored and potential reflected XSS
3. **Future-Proof**: If code changes introduce new vulnerabilities, multiple layers reduce risk
4. **Best Practice**: Industry standard approach recommended by OWASP

### 4.5 Enabling Mitigation

To enable mitigation, change one line in `script.js`:

```javascript
// Change from:
const SANITIZATION_MODE = false;

// To:
const SANITIZATION_MODE = true;
```

When enabled:

- โœ… Input is sanitized using DOMPurify before storage
- โœ… Output uses safe DOM manipulation with `textContent`
- โœ… XSS payloads are neutralized at both layers
- โœ… Malicious scripts cannot execute

---

## 5. Testing the Mitigation

### 5.1 Test Procedure

1. **Enable Mitigation**: Set `SANITIZATION_MODE = true` in `script.js`
2. **Clear Storage**: Open browser console and run `localStorage.clear()`
3. **Reload Page**: Refresh the application
4. **Attempt Exploitation**: Try submitting XSS payloads:
   - `` โœ… (Will execute)
   - `` โœ… (Will execute)
   - `alert('XSS')` โŒ (Won't execute - browser protection, but this doesn't mean the app is safe!)
5. **Verify Results**:
   - Payloads should be displayed as plain text
   - No JavaScript execution should occur
   - Alert popups should not appear

### 5.2 Expected Results

**With Mitigation Enabled:**

- โœ… Malicious HTML is stripped or escaped
- โœ… Scripts do not execute
- โœ… Content displays as plain text
- โœ… Application functionality remains intact

**Without Mitigation:**

- โŒ Scripts execute automatically
- โŒ Alert popups appear
- โŒ Potential for cookie theft and session hijacking

## 7. Conclusion

This project successfully demonstrates:

1. โœ… **Vulnerability Implementation**: A realistic Stored XSS vulnerability in a blog application
2. โœ… **Exploitation**: Multiple attack vectors and payload examples
3. โœ… **Mitigation**: Defense-in-depth approach using:
   - **Input Sanitization**: DOMPurify library for robust HTML sanitization

### 7.1 Key Takeaways

- **Stored XSS** is dangerous because payloads persist and affect all users
- **innerHTML** with user input is inherently dangerous
- **Defense-in-depth** provides multiple layers of protection
- **DOMPurify** is an industry-standard sanitization library
- **textContent** is safer than innerHTML for user-generated content

### 7.2 Tools and Techniques Summary

| Component            | Technology/Tool       | Purpose                        |
| -------------------- | --------------------- | ------------------------------ |
| Storage              | localStorage API      | Simulates database persistence |
| Sanitization         | DOMPurify v3.0.8      | HTML sanitization library      |
| Safe Rendering       | textContent + DOM API | Prevents script execution      |
| Vulnerable Rendering | innerHTML             | Demonstrates XSS vulnerability |
| Language             | JavaScript (ES6+)     | Client-side logic              |
| Markup               | HTML5                 | Page structure                 |

---