$_SERVER['DOCUMENT_ROOT'] and XSS

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()?

Thanks.

P.S. Am I right in saying to fall prey to a XSS attack you’d need to:

  1. Allow users to store HTML in a database/text file and not sanitise it properly and/or…
  2. 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 :frowning:

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.

Sorry post edited.

Awesome, that makes more sense to me. :slight_smile:

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.

Thank you. So, so long as you htmlspecialchars it, it’s always okay to use?

How accurate is my brief summary of XSS attacks?

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).

Hopefully that helps :slight_smile:

Thanks but if you’re always using double quotes, isn’t ENT_QUOTES pointless? I’ve personally never used single quotes in HTML.

Got you, thanks. :slight_smile:

I thought as such — the main issues come from accepting HTML from users. I can see why using a BBCode type tagging system is advantageous here.

I guess my final question is—and in relation to my previous post—if you’re always using double quotes from HTML attributes, do you ever need to use ENT_QUOTES?

Surely this is fine:

<a href=“page.php?userinput='onmousoever=‘alert(‘XSS’);’”>Link</a>

I don’t want to say it is pointless, but rather your need for it may be less than what it is for other applications. Prime example, applications that need to spit out JavaScript and may use user input within your JavaScript would need to use ENT_QUOTES, as your echo statement may be echo “…<script type=“text/javascript”>alert(‘<user_input>’);</script>…”; and thus single quotes would be dangerous.

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.

Yes, I totally agree. I instinctively do that for JavaScript output.

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.

http://example.com/my_form.php

can be manipulated to

http://example.com/my_form.php/&quot;><script>alert('evil')</script>

Again, htmlspecialchars is nececcary to prevent this. Instead of leaving the form action=“” blank, do something like

action=“<?= htmlspecialchars( $_SERVER[“PHP_SELF”] );?>”

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).

It’s comforting to know that they’re taking positive steps to prevent it. :slight_smile:

Based on what I’ve learnt today I think I’m going to start using ENT_QUOTES from now on. Thanks for your help!

This was just recently posted and is a good resource for when to sanitize the data from $_SERVER

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:

  1. Always be consistent in HTML with your use of single or double quotes
  2. If using single quotes you must use ENT_QUOTES
  3. For scalability try to use ENT_QUOTES anyway though if always using double this isn’t necessary
  4. If you use $_SERVER[‘REQUEST_URI’] or $_SERVER[‘PHP_SELF’] for output always htmlspecialchar it as above
  5. URL vars should be encoded with URL encode and ampersands should be htmlspecialchar’d
  6. Be very, very wary of using HTML supplied by the user
  7. Browsers are getting wise to XSS but don’t count on it

Anything else to add?

Nothing stands out. Your list seems complete :slight_smile:

Thanks again for all your help, I’m wiser for it!

EDIT: I should’ve added for JavaScript output in strings always escape double and single quotes.