Assuming register globals if off (I never ran PHP with it on even back in the day) is $_SERVER[‘REQUEST_URI’] ever not safe to use in a XSS context? If guess if you need to use it wouldn’t htmlspecialchars() work? If not, can someone give me an example where $_SERVER[‘REQUEST_URI’] could cause XSS injection even with htmlspecialchars()?
P.S. Am I right in saying to fall prey to a XSS attack you’d need to:
Allow users to store HTML in a database/text file and not sanitise it properly and/or…
Not escape user input data properly
Also, you’re more likely to suffer XSS if you use cookie-based authentication. If not, you’d need to rely on them getting a link to a user so they can steal their cookie (harder to do).
And you can further prevent it with HTTP only cookies (which seem to be well supported now).
Is that right?
EDIT: Sorry! Long day, I’m tired, I meant REQUEST_URI
Out of curiosity, why would you be writing $_SERVER[‘DOCUMENT_ROOT’] to the browser? As doesn’t it contain the full local path (/var/www/…/myproject/myfile.php)? I’d test it out locally right now, but my environment seems to have bombed due to a few upgrades over the last couple of days.
So the short answer is yes, one could craft an XSS exploit to REQUEST_URI. This actually happened to Discourse not that long ago (they are a Ruby app, but same concept applies to all web languages). The person passed the following /’ onmouseover=“alert(‘XSS’);” to the app and when they wrote it out without sanitizing it, it wrote: <a href=‘/’ onmouseover=“alert(‘XSS’);”>…link text here…</a>
You can see how that may be used for nefarious purposes. So utilizing htmlspecialchars is a good idea.
Yes, but you may need to use ENT_QUOTES to ensure you are protected (from the example I gave you). As I believe the documentation states single quotes are only converted when ENT_QUOTES is set.
Also using htmlentities may be preferred as it it will cover a lot more (it converts all characters that have entity equivalents), but that could also be detrimental too depending on what URL characters you need to maintain (so be sure to test it).
XSS has nothing to do with storing user input (though to impact more than themselves, they do need a way to persist that data and show it to others), it has everything to do with sending user input to the browser (with validating/sanitizing it first).
WARNING: DON’T DO THIS
So I could create a basic form that has a text area, ask the user to input text, and behind the scenes have
<?php echo $_POST['user_input']; ?>
Granted, it is negligible to some degree, as it won’t be persisted (unless the user finds a way to persist it to others users), but it still exists.
XSS is permitting a user to inject a script, image, whatever, onto your site that is then automatically triggered by a user via loading the data, mousing over the data, clicking on it, whatever.
The biggest rule to ever learn is NEVER trust user input. Always scrutinize it. Validate it when it is passed in before storing it, perform htmlspecialchars or htmlentities on it when you write it to the page. If you need to support HTML tags, create a white list and only support those by stripping out all other tags not supported.
If you support image URLs be sure to strip out any additional attributes they may try to embed with an img tag (you can start to see how complicated it gets when you want to support HTML).
So the key take away is test it. Try and see if introducing them in your input causes your HTML to be invalid. If it is, then you want to protect against them, as there is a good chance there is a security hole there waiting to happen.
Right, but be cautious that your code may change to one day need to use single quotes and thus introduce a problem. The goal is to keep yourself as protected from day 1 as you can be. I like to use a HTML validator and run various user inputs through my forms, and send their output to the validator. If the HTML can be made invalid, I know I need to scrutinize it a lot more as someone smarter than I will likely find a way to abuse it.
You have to be careful if the form processing is done on the same file as the script executing this (e.g., form action=“”).
In those scenarios, the form does not need to be submitted, simply passing arguments to the URL will suffice.
I’ve just been playing around and tried to do a XSS injection using <a href=‘<?= htmlspecialchars($_SERVER[‘REQUEST_URI’]) ?>’>Test</a> Even with single quotes I could not get it to do a XSS injection in Safari or Firefox. Safari generated an error saying that the XSS auditor refused to execute it whereas Firefox automatically encoded the single quotes. That’s pretty cool, do most modern browsers have built-in XSS prevention now?
While that is highly unlikely I like your mindset as that tends to be how I think. If you’re not allowing HTML (I only ever allow clients to using HTML WYSIWYG) from users then is XSS quite low risk? When outputting non-HTML do you always use ENT_QUOTES? I appreciate your input and am thinking I should start using it — even if it is not needed right now.
That is news to me, I didn’t even realize Safari did that…
I tend to always use ENT_QUOTES, as I rarely have a valid reason for permitting single quotes in a form that requires them not to be escaped and in those rare situations, I question if I’m going about it correctly or if I made a fundamental flaw and should redesign my current process (I usually redesign my process).
That’s great, thanks. There was a similar post on Stack Overflow.
One of the article I’ve read was pointing to being wary of using user input for tag names and attribute names. I would almost certainly never do that. In most cases it would only ever be form action of a href.
The lesson for me is:
Always be consistent in HTML with your use of single or double quotes
If using single quotes you must use ENT_QUOTES
For scalability try to use ENT_QUOTES anyway though if always using double this isn’t necessary
If you use $_SERVER[‘REQUEST_URI’] or $_SERVER[‘PHP_SELF’] for output always htmlspecialchar it as above
URL vars should be encoded with URL encode and ampersands should be htmlspecialchar’d
Be very, very wary of using HTML supplied by the user
Browsers are getting wise to XSS but don’t count on it