35

I've been learning more about XSS (for the unfamiliar, Excess XSS is a great resource). I opted to get my hands dirty and give Reflected XSS a try on a local environment. I set up a very simple vulnerable PHP page running on Apache2 which takes a URL parameter and dumps the contents into the page:

<!DOCTYPE html>
<html>
<head>
    <title>VULNERABLE WEBSITE</title>
</head>
<body style="background-color:#98FB98">
    <h1>VULNERABLE WEBSITE</h1>
    <p>Search results for <?php echo $_GET['query']; ?>:</p>
</body>
</html>

Then, I attempted to get 'malicious' JavaScript embedded into the page using a URL such as the following:

http://localhost:8082/?query=<script>alert('Hello!');</script>

I found that the browsers themselves prevented this from happening. In Firefox, this took me to a Google Search page. In Chromium, the XSS was specifically detected and blocked:

enter image description here

So, going from theory to practice, I am now wondering: is Reflected XSS still a relevant security concern today?

This obviously does not apply to Persistent XSS where the malicious content is served directly by the website itself.

Anders
  • 64,406
  • 24
  • 178
  • 215
Gigi
  • 1,280
  • 1
  • 11
  • 12
  • 4
    There was a [bypass](http://blog.portswigger.net/2016/04/edge-xss-filter-bypass.html) in Edge, not sure if it's fixed. For now, apps shouldn't rely on the filters, so reflective XSS is still relevant. – paj28 Jul 02 '17 at 08:16
  • 9
    Just search for [bypass XSS auditor](https://www.google.com/search?q=bypass+xss+auditor) or similar and you'll find lots of hits. XSS auditor and similar are just heuristics which need to have a high performance and a very low false positive rate (otherwise they would block innocent responses) and with these restrictions they are not able to block everything malicious. – Steffen Ullrich Jul 02 '17 at 08:40
  • It is still relevant and it works in Firefox. And XSS Auditors can be easily bypassed. And checking if there is some XSS can be also done with some simple h1 tag, not just the often used script tag. – Daniel Ruf Jul 02 '17 at 11:16
  • Just to mention it, midpersistent XSS (using localstorage, cookies, ...) is also not so rare. – Daniel Ruf Jul 02 '17 at 11:18
  • 1
    Consider those who can't afford to update the OS/browser due to their requirement, especially on workplace environment. Also, [Is Chrome completely secure against Reflected XSS?](https://security.stackexchange.com/q/53474) proves that reflected XSS still works on the latest Chrome. – Andrew T. Jul 02 '17 at 17:28
  • 2
    I co-wrote Excess XSS and had this same question when I researched reflected XSS and browsers had already started to implement filters like these. This is a great question and I might update the tutorial with the insights provided here. – Jakob Jul 03 '17 at 18:20

8 Answers8

21

Reflected XSS is not only by GET. It can be by POST too. And they are not prevented always by the browsers. And of course, is still relevant.

A couple of definitions:

And from Checkmarx knowledge base, it says: "The most commonly found XSS". Extracted from here. So if is the most commonly found I guess is still relevant.

OscarAkaElvis
  • 5,185
  • 3
  • 17
  • 48
  • 5
    Just a note re the "most commonly found" - one of the main reasons for asking this question is that when reading about something, it's hard to determine whether that source is out of date and whether security has caught up. – Gigi Jul 02 '17 at 12:00
  • Oh believe me, nowadays is still the most commonly found I think. – OscarAkaElvis Jul 02 '17 at 12:02
  • @Gigi true point. Thats what happens to the internet. It gets old and articles on it get older. – Xatenev Jul 04 '17 at 07:52
  • "believe me" and "i think" are somewhat mutually exclusive if you ask me. You are completely right though, it's still the most common vulnerability in ALL web languages. – J.A.K. Jul 04 '17 at 12:43
  • How is reflected XSS done via POST? I thought reflected XSS is done by including malicious script in the querystring of a link, which you can't do with POST. – Gigi Jul 04 '17 at 19:24
  • 1
    Easy. You can insert the evil javascript on a field of a POST form for example. If the server is not sanitizing the data correctly, it can be reflected and executed somewhere on the website. It depends of the website but is very common. – OscarAkaElvis Jul 04 '17 at 21:35
17

Yes, all forms of XSS are still relevant today.

The particular attack that you tried was obvious for the browser to heuristically find, but the code generated by more subtle injections might not be. What if I change the submission URL of a form because the developer used <form action="{$_SERVER['PHP_SELF']}"? What if I change your error message to a confirmation message? What if I change the SHA1 hash displayed of a Linux distro that you've downloaded?

Never rely on client-side features (web browsers in particular) to provide security for your users.

dotancohen
  • 3,698
  • 3
  • 24
  • 34
  • 3
    Can you do any of those using a **reflected** XSS attack? – Gigi Jul 02 '17 at 12:58
  • @Gigi: That depends entirely on the service that I'm attacking. If I attack enough sites, I'll find those whose reflected values are valuable for my purposes. For instance, I could redirect an HTTPS login for to an HTTP image which I can then MitM, or I can display the file hash of a _different_ linux distro causing the user to reject the distro he just downloaded. He'll then continue using his older, unpatched distro "to be on the safe side". – dotancohen Jul 02 '17 at 13:02
  • 1
    @Gigi, if some, eg, GET variable is used in attributes like `action` (as above) or one of the various JS hooks (eg, `onclick`), then you could have arbitrary JS code that doesn't need a ` – Kat Jul 04 '17 at 20:32
9

The most common and trivial cases of reflected XSS — where you literally output exactly what was provided (<?php echo $_GET['query']; ?>) and it runs as-is — are not practically relevant in modern browsers by default, no.

However, "reflected XSS" as a category is a bit broader than that. It also includes cases where the input is encoded in some way. One example I've seen in the wild is reflection of base64-encoded HTML, such as <?php echo base64_decode($_GET['query']); ?>. Browser filters probably won't catch that.

You also need to consider cases where the code doesn't run on its own, but there is some other JavaScript that will cause it to be run later. The most common way this can happen is a client-side templating library that interprets expressions in what would otherwise be static text. For example, consider this case where dyn- attributes are evaluated client-side with some model data:

<img dyn-src="model.get('<?php echo $_GET['name']; ?>')" />
<script>
  let model = { something... };
  for (let el of document.querySelectorAll('[dyn-src]')) {
    el.src = eval(el.getAttribute('dyn-src'));
  }
</script>

This allows a form of reflected XSS with something like ?name=', alert('xss'), ', which browsers also probably won't catch.

Jeremy
  • 1
  • 1
  • 1
  • 11
5

Reflected XSS is still relevant because not every browser implements the same filters in the same way, some times a bypass is discovered for some implementations, therefore the auditor may not block it.

Some sites don't have the X-XSS-Protection header enabled, so those sites are vulnerable too

And, as said in other answer, the payload may be delivered through POST instead of GET, preventing the auditor from blocking the malicious injection

Finally, even if everything is configured correctly and there is no known bypass for the filter implementation, it is just a filter. It blocks certain reflected XSS but as there are false positives there are too false negatives, therefore the payload remains undetected

Mr. E
  • 1,954
  • 9
  • 18
  • It's worth a mention that a lack of an `X-XSS-Protection` header is interpreted as "Turn on the XSS filter". If you want the XSS filter off then you specifically have to send `X-XSS-Protection: 0;`. Browsers are designed to turn the XSS filtering on by default for any browser that doesn't specifically state to turn it off, where as your answer implies that the XSS filter is off by default unless told to be on. – Conor Mancone Sep 01 '17 at 14:48
2

Yes.

For one thing, Firefox doesn't yet have an XSS filter, so reflected attacks can be executed on this browser.

Also, DOM-based XSS bypasses browser filters. This is not strictly categorised as "reflected XSS", however the end-result is the same.

Another thing to bear in mind is that browser XSS auditors do not constitute a security boundary. From Google:

No, XSS auditor bypasses don't constitute Chrome security vulnerabilities (which is why this bug is flagged SecSeverity-None). You can find our severity guidelines here: http://dev.chromium.org/developers/severity-guidelines

To clarify a bit more, the XSS auditor is a defense-in-depth mechanism to protect our users against some common XSS vulnerabilities in web sites. We know for a fact it can't catch all possible XSS variants, and those it does catch still need to be fixed on the affected site. So, the auditor is really an additional safety-net for our users, but not intended as a strong security mechanism.

There are bypasses found in such browser mechanisms all the time. IE example here. And, in opposition to another answer on here, filters do attempt to block POST requests too. However, you can never rely on these filters to block all XSS.

The upshot is that you should mitigate XSS on your web application through the use of output encoding, input filtering/validation (if possible) and hopefully a strong Content Security Policy.

Input filtering and validation can sometimes be tricky, however if you're taking input where the only valid input is say numbers and letters, if you want a secure application it is a good idea to restrict character sets to only those useful. Of course, this is not possible if you're running a Stack Overflow style site where you are allowing code snippets and such that make use of a large character set.

Remember that reflected XSS requires a user to follow, or be redirected to, a URL. Therefore it sometimes needs a bit of "social engineering" from an attacker to exploit. I usually classify reflected XSS as a medium risk vulnerability unless it can be automatically exploited from within the application (say an automatic redirect somewhere) or if the application itself is particularly sensitive.

SilverlightFox
  • 33,408
  • 6
  • 67
  • 178
  • Actually, I showed in my answer that attempting to include script tags in a querystring just doesn't work in Firefox. – Gigi Jul 04 '17 at 11:37
  • 1
    You said it didn't work when you tried, however maybe you made a mistake in pasting the payload? [This link](http://rob-sec-1.com/xss_test.php?query=%3Cscript%3Ealert(document.cookie)%3C/script%3E) works for me. – SilverlightFox Jul 04 '17 at 11:47
  • Yes, it works for me too. Not sure what happened. I'm pretty sure I used the same URL between Chromium and Firefox. Only difference is that I was testing in Linux, and now I'm on Windows. – Gigi Jul 04 '17 at 15:51
  • If it directs you to Google search then the browser hasn't detected it as a URL. Firefox is attempting to search for your keywords instead. Maybe it had a leading tab or bullet point. Anyway, my answer demonstrates that reflected XSS is still a risk. – SilverlightFox Jul 04 '17 at 15:53
1

Yes:

  • Not fixing known security vulnerabilities is always a bad idea, but also...
  • The major browsers that attempted to block reflected XSS, are considering to retire the technology.

I understand where this question is coming from, but the technology is unfortunately not perfect and almost never stops a determined attacker:

In the past 3 months we surveyed all internal XSS bugs that triggered the XSSAuditor and were able to find bypasses to all of them.

That is the team at Chromium, announcing they advice Chrome to remove the XSSAuditor. The reason given is this:

We haven't found any evidence the XSSAuditor stops any XSS, and instead we have been experiencing difficulty explaining to developers at scale, why they should fix the bugs even when the browser says the attack was stopped.

And not only does it make developers wonder whether they should apply fixes, it also makes security testers do their work less well. Since they have a hard time justifying how it is a risk without finding a (sometimes time-consuming) bypass:

Furthermore, we've surveyed security pentesters and found out some do not report vulnerabilities unless they can find a bypass of the XSSAuditor, which means that defense teams end up being handicapped even more than attackers (as defense teams since defense teams need to scale up their remediation efforts, while attackers only need something that works).

Microsoft is less forthcoming about their reasoning, but also announced last June that they will retire the XSS Filter:

Retired XSS Filter: We are retiring the XSS filter in Microsoft Edge beginning in today’s build. Our customers remain protected thanks to modern standards like Content Security Policy, which provide more powerful, performant, and secure mechanisms to protect against content injection attacks, with high compatibility across modern browsers.

Another good blog post on the topic is this one: https://portswigger.net/daily-swig/xss-protection-disappears-from-microsoft-edge
For example, it links to research that shows the XSS Filter in MSIE sometimes leads to vulnerabilities that would otherwise not have been exploitable.

Luc
  • 31,973
  • 8
  • 71
  • 135
  • From your link: "Note this is a proposal *to* the Chrome team, not *from* the Chrome team"; it's also currently marked as "WontFix". So they probably don't want to retire the XSSAuditor (Microsoft will retire their filter though); the link still contains good arguments why XSS is relevant even with a filter. – tim Nov 07 '18 at 16:36
  • Good answer. I'm surprised at the decision to remove XSS protection from browsers though. It may not be perfect, but it likely protects a large number of clueless people from very simple and dangerous attacks. Just because it's harder to justify additional efforts in security doesn't mean the basic protection is bad. – Gigi Nov 08 '18 at 23:08
0

Yes, this is still relevant. You can try follow for your sample:

http://localhost:8082/?query=<svg onload="alert('Hello!')"/>
-1

There is also no reason that someone intending a hack will not just use a browser that does not have the XSS protection built in. Even if there is no old browser that will work, they can always get the source of newer ones and leave out those protections.

It's always a bad idea to rely on client-side restrictions to stop any sort of exploit. The client is not under your control, and never will be. The hacker can always modify their own computer.

trlkly
  • 162
  • 5