2

Is there any situation where an XSS attack can be performed via the PHP $_SERVER['REQUEST_URI'] variable? For those unfamiliar with it: It contains the complete URL used to access that website, without the domain name, and with some special characters encoded.

For example, take this piece of code. We already have a <, and are not even using ":

echo '<form action=' . $_SERVER['REQUEST_URI'] . ' method="post"></form>';

If I visit localhost/myscript.php?foo onhover=alert(1) the result is:

<form action=/myscript.php?foo%20onhover=alert(1) method="post">
  • Is there any way to inject a space? I tried + and similar characters, but it did not work.
  • If there is a way, would it also be possible if quotes were used around the action?
  • If it is not possible, can you think of any scenario where $_SERVER['REQUEST_URI'] could be used to perform an XSS attack? Or any other attack for that matter?

// edit: To summarize the answers (in case someone doesn't read all the comments): With current browsers, it doesn't seem that an attack is possible via REQUEST_URI. But one shouldn't rely on browser to sanitize user input, so REQUEST_URI should still be sanitized server side.

2 Answers 2

3

PHP does not encode characters when setting $_SERVER['REQUEST_URI']. Any URL-encoding you may see is performed client-side (e. g. in your browser).

So all you have to do is use a different HTTP client which sends the raw URL with no prior encoding. For example, cURL will do this. While literal spaces aren't allowed within a URL, it's perfectly possible to inject angle brackets, terminate the current <form> tag and create a new script element.

8
  • Thanks, you seem to be correct that the browser adds encoding, not PHP (although it's a bit odd that it isn't happening for PHP_SELF then). But I wasn't able to inject >, it gets encoded as %3E, so I can't use it in an attack either.
    – tim
    Commented Mar 21, 2015 at 17:20
  • Who encoded the angle bracket? Which tool did you use? I've just made an example attack with cURL, and it worked flawlessly. The reason why PHP_SELF contains no percent-encoded characters is because it's actually the decoded version of the URL. You can verify that by performing the encoding yourself: In the result, all encoding sequences are replaced with their underlying character.
    – Fleche
    Commented Mar 21, 2015 at 17:36
  • a browser again (it sounded as if you suggested that < will not be encoded, because you proposed it as an alternative to a space, which I can also use with curl). I think if I have to use curl, it's not really a realistic attack. The main motivation for my question was to find out if REQUEST_URI has to be sanitized in any way, which doesn't seem to be the case then?
    – tim
    Commented Mar 21, 2015 at 18:00
  • 4
    @AlfredArmstrong The premise of XSS is that you inject scripting into a web page that someone else loads (typically in a browser). Messing with the response of a cURL request is pretty useless since cURL doesn't parse HTML and it doesn't execute JavaScript. XSS attacks tend to essentially require a browser.
    – Corbin
    Commented Mar 21, 2015 at 18:49
  • 1
    You're right that the curl not being a realistic attack thing is still misguided though... For example, a new consumer-targeted browser could come out tomorrow that doesn't encode URLs (which would be against the HTTP spec), and then suddenly users of that browser are susceptible to this (currently pretty much theoretical) XSS attack. In other words (@tim) it's not currently meaningful in any existing popular browser, but it could be next week or 5 years from now.
    – Corbin
    Commented Mar 21, 2015 at 18:57
0

You could use a little PHP to reinject the space from the URL encoder. Some thing like...

$action = implode(' ', explode('%20', $_SERVER['REQUEST_URI'])); echo '<form action=' . $action . ' method="post"></form>';

2
  • 2
    The point of XSS is that you do not have access to the server-side code.
    – Simon
    Commented Mar 22, 2015 at 3:59
  • Yes, but you can use server-side code to prevent it. You could use something more to the effect of <form action=' . $action . ' onhover= ... This would only grab the URL
    – Nektro
    Commented Mar 22, 2015 at 11:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .