Day 5 of breaking web applications on purpose.

Last attack we broke out of an <a href="">.

Today?

We break out of an <img src="">.

And this one is sneakier.

Because the developer thought they were safe.

They removed < and >.

Game over, right?

Not even close.

🎯 The Setup

The application has a gallery page.

It takes a parameter from the URL:

?img=1

And renders something like:

<img src="1.jpg">

Simple.

Clean.

Harmless.

But here's the real question:

πŸ‘‰ What happens if we inject a quote inside the src attribute?

🧠 Think Like a Browser

Browsers don't "see" input the way humans do.

They see structure.

If the application builds this:

echo '<img src="' . $_GET['img'] . '.jpg">'

Then whatever we put inside img= becomes part of the HTML attribute.

So if we inject:

1" onerror="alert('imgXSS')

The final HTML becomes:

<img src="1" onerror="alert('imgXSS')".jpg">

Pause.

Look at that carefully.

We just:

  • Closed the src attribute with "
  • Injected a new attribute: onerror
  • Attached JavaScript to it

No <script> tag needed.

No angle brackets.

Just context breaking.

πŸ’£ The Payload

1" onerror="alert('imgXSS')

Encoded in URL:

?img=1"%20onerror="alert('imgXSS')

Now ask yourself:

Why does this execute?

⚑ Why This Works

Because the image source becomes invalid:

src="1"

The browser tries to load image 1.

It fails.

When an image fails to load, the onerror event fires.

And what did we attach to it?

JavaScript.

So the browser executes:

alert('imgXSS')

But in the real world?

Replace that alert with:

  • document.cookie exfiltration
  • Silent form submission
  • Admin session theft
  • Redirect to phishing page
  • Injected keylogger

Now it's not a popup.

It's a breach.

🧠 Real-World Analogy

Imagine a security guard checking bags at an airport.

He only checks for knives.

So you bring liquid explosives.

He says:

"No knives detected. You're good."

That's blacklist-based filtering.

The developer removed < and >.

But forgot about:

  • "
  • Event handlers
  • Attribute context
  • Browser parsing behavior

Security isn't about removing characters.

It's about understanding context.

🧨 Why This Is More Dangerous Than It Looks

Because developers often believe:

"We filtered script tags."

But XSS isn't about <script>.

It's about execution context.

If you can:

  • Break HTML structure
  • Inject attributes
  • Control event handlers

You control execution.

πŸ›‘οΈ Proper Fix (Not the Fake Fix)

Bad Fix:

  • Remove < and >.

Still vulnerable.

Good Fix:

  • Escape quotes using:

htmlspecialchars($value, ENT_QUOTES, 'UTF-8');

  • Whitelist allowed values (e.g., only numbers 1–4).
  • Implement Content Security Policy:

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

  • Avoid injecting raw input into attributes at all.

Security rule:

Never trust user input inside HTML attributes. Ever.

πŸ”₯ The Bigger Question

When you test XSS, do you only try:

<script>alert(1)</script>

Or do you test:

  • Attribute context?
  • Event handlers?
  • Broken tags?
  • Quote injection?
  • URL schemes?
  • JavaScript protocol?

Most beginners stop at <script>.

Real attackers don't.

🎯 Day 5 Takeaway

You didn't inject a script tag.

You didn't touch backend logic.

You just:

  • Closed a quote
  • Added an event
  • Let the browser do the rest

And the browser happily executed your payload.

Because browsers trust structure.

And the developer trusted you.

That's the real vulnerability.

Next, we escalate from reflected attribute injection…

to persistence.

Because what happens when your payload doesn't disappear?

That's when things get serious.

LESSGOOO πŸ”₯

None
LESSGOOO πŸ”₯