Day 8 of breaking web applications on purpose.

Let me ask you something:

When you upload a file… Do you trust that it's just a file?

Or do you assume the server actually checked it properly?

Welcome to Stored XSS via File Upload.

This one isn't about forms. It isn't about URL parameters. It isn't even about headers.

It's about abusing trust.

🎯 The Setup

The application allows users to upload image files.

After upload:

  • The file is stored on the server.
  • It is displayed back inside the browser.
  • No deep validation is performed.
  • No re-encoding happens.

Now here's the real question:

πŸ‘‰ What if the "image" contains executable content?

🧠 The Dangerous Assumption

Developers often validate uploads like this:

  • Check file extension (.jpg, .png, etc.)
  • Check MIME type
  • Accept file
  • Store it
  • Display it

But they forget something critical:

Browsers don't care about your intentions.

They care about content.

If executable content exists and is rendered…

It executes.

πŸ’£ The Conceptual Payload

Instead of uploading a clean image, we upload a crafted file containing client-side executable content.

Example idea:

An SVG file (which is XML-based) containing embedded JavaScript.

Or an image file that includes HTML/JS content interpreted by the browser.

Once uploaded and rendered by the application:

The embedded script executes automatically.

No clicking required.

No extra interaction.

Just viewing the uploaded file triggers it.

⚑ Why This Works

Because:

  • The server accepts the file.
  • The file is stored.
  • The file is served back to users.
  • The browser parses and executes embedded script.

The application does not:

  • Re-encode the file.
  • Strip active content.
  • Restrict script execution.
  • Serve from a sandboxed domain.

So the uploaded file becomes a stored attack vector.

🧠 Real-World Analogy

Imagine a security checkpoint that only checks:

"Does this look like a picture?"

But never checks:

"What's hidden inside it?"

So someone hides malware inside a framed painting.

The guard sees a frame.

But doesn't inspect the canvas.

That's what weak file validation looks like.

πŸ’₯ Why This Is More Serious Than Basic XSS

Because:

  • The payload is stored server-side.
  • It affects every user who views it.
  • It can target administrators.
  • It can spread automatically.

Now imagine replacing an alert with:

  • Cookie exfiltration
  • Admin session hijacking
  • Silent account takeover
  • Credential harvesting overlay
  • Malicious script injection

This turns into:

Stored persistent client-side compromise.

πŸ”₯ The Question You Should Be Asking

When testing file uploads, do you ask:

  • Can I upload SVG?
  • Can I upload files with embedded script?
  • Is the file re-encoded server-side?
  • Is it served from a separate domain?
  • Is CSP enforced?

Or do you just test .php shells?

Client-side exploitation via uploads is often overlooked.

But in real bug bounties?

It pays.

πŸ›‘οΈ Proper Remediation

To fix properly:

βœ… Restrict allowed formats to safe raster images (JPEG, PNG). ❌ Disallow SVG unless absolutely necessary. βœ… Re-encode images server-side (strip active content). βœ… Serve uploaded files from a separate static domain. βœ… Disable inline script execution via strict CSP:

Content-Security-Policy: script-src 'self' object-src 'none'

Security rule:

If users can upload it, attackers can weaponize it.

Always assume that.

🎯 Day 8 Takeaway

You didn't inject into a form.

You didn't modify a URL.

You uploaded a file.

And the file became your payload.

The application trusted content. The browser executed it. And the vulnerability persisted.

This is where XSS stops being "just alerts."

And starts becoming full compromise potential.

We've now completed the entire XSS chain.

From reflected. To stored. To DOM. To attribute injection. To headers. To protocol abuse. To file-based execution.

Next?

We leave JavaScript.

And start attacking the database.

And that's where things get destructive.

None
LESSGOOO πŸ”₯