Critical Stored XSS Exploit Demo to Capture Key strokes on test site called PinewoodStore

Hello everyone,

Today we would be discussing about Stored XSS and how this vulnerability is exploited by bad actors. We would also analyze vulnerable source code from PinewoodStore, a Vulnerable Web I created to Demo different vulnerabilities.

📌 Definition: What is Stored XSS?

Stored Cross-Site Scripting (Stored XSS) is a type of web security vulnerability where malicious scripts are permanently stored on a web server and later executed when other users visit the affected page. Unlike Reflected XSS, where the attack payload is part of a request and executed immediately, Stored XSS remains persistent, making it far more dangerous.

🛑 Impact of Stored XSS:

  • Attackers can steal user credentials (e.g., session cookies).
  • Deface web pages or inject fake forms for phishing.
  • Perform actions on behalf of authenticated users (CSRF-like attacks).
  • Capture keystrokes and track user input (keylogging).

⚠️ Stored XSS Vulnerability in PinewoodStore Web App

Let’s analyze a real-world Stored XSS vulnerability in the PinewoodStore web application, specifically in the CommentController.java source code.

📌 Vulnerable Source Code: CommentController.java

package com.enoch.auth2.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import com.enoch.auth2.model.Comment;
import com.enoch.auth2.repository.CommentRepository;

import java.util.List;

@Controller
@RequestMapping("/comments")
public class CommentController {

    @Autowired
    private CommentRepository commentRepository;

    @GetMapping
    public String getComments(Model model) {
        List comments = commentRepository.findAll();
        model.addAttribute("comments", comments);
        return "comments";
    }

    @PostMapping("/add")
    public String addComment(@RequestParam String name, @RequestParam String email, @RequestParam String comment) {
        Comment newComment = new Comment(name, email, comment);
        commentRepository.save(newComment);
        return "redirect:/comments";
    }
}

📌 Where is the Vulnerability?

🔴 Issue 1: Lack of Input Sanitization

  • The addComment method directly saves user input (name, email, comment) into the database without sanitizing it.
  • If an attacker submits a comment containing malicious JavaScript, it will be stored in the database and executed every time a user loads the comments page.

🔴 Issue 2: Unescaped Output in the View (Thymeleaf/HTML Template)

  • The retrieved comments are directly displayed on the webpage (comments.html).
  • If the template does not properly escape HTML and JavaScript, malicious scripts will execute on the client’s browser.

🚀 Exploiting the Stored XSS in PinewoodStore

1️⃣ Attack Execution

An attacker submits the following malicious comment using the /comments/add endpoint:

Name: Attacker  
Email: attacker@example.com  
Comment: 

2️⃣ What Happens Next?

  • The server stores the comment without sanitizing it.
  • When another user visits the /comments page, the

    How It Works?

    1. This script listens for any key pressed on the webpage.
    2. Every keystroke is sent to the attacker’s server (attacker.com).
    3. This allows the attacker to capture sensitive data, including usernames, passwords, and search queries.

    💀 Real-World Impact:

    • Attackers can steal login credentials by logging what users type.
    • Sensitive information, such as credit card numbers and personal messages, can be compromised.
    • Users remain unaware that their keystrokes are being tracked.

    💡 How to Fix Stored XSS?

    Sanitize Input Before Storing
    Use HTML encoding to escape