whenpenguinsattack.com

Sunday, March 19, 2006

php security mistakes - part 2

By Justin Silverton

In one of my previous articles, I mentioned the top 5 security mistakes made in PHP. This article is a follow-up, with some more common security mistakes.

System Calls

In PHP, there are different ways to execute system calls. The system(), exec(), and passthru() all allow you to execute operating-system commands from within your scripts.

Each of these functions, if not checked, can also allow a malicious user to exploit your system and execute commands that could possible access private files and information.

Protecting your system from this attack

The input from the user, no matter the context, should never be trusted. PHP provides two functions, escapeshellarg() and escapeshellcmd().

The escapeshellarg() function is designed to remove or otherwise eliminate any potentially harmful characters received from user input for use as arguments to system commands (in our case, the zip command).

The syntax for this function is as follows:escapeshellarg($command)
where $command is the input to clean, and the return value is the cleaned string. When executed, this function will add single quotes around the string and escape (add a slash in front of) any single quotes that exist in the string.

escapeshellcmd() is similar to this function, except it will only escape characters that have a special meaning to the underlying operating system. If user input will be used as part of the argument list for a system call, the escapeshellarg() function is always the better choice.

File Uploads

PHP will create a file with the uploaded content, but will not check whether the filename is valid, or if the type and size are correct

A user could potentially create his own form specifying the name of some other file that contains sensitive information and submit it, resulting in the processing of that other file.

Solution

use move_uploaded_file() or is_uploaded_file(). However, there are some other problems with user-uploaded files and check the $_FILES super global array to make sure that the user has uploaded the correct file type/size.


Including Files

In PHP you can include local or remote files by using include(), include_once(), require() and require_once(). It allows you to have separate files for classes, reused code and so on, increasing the maintainability and readability of your code.

The concept of including remote files is dangerous in itself, though, because the remote site could be compromised or the network connection could be spoofed. In either scenario, you are injecting unknown and possibly hostile code directly into your script.

Another issue to think about when including files, is if a file that is included is dependent on user input. This poses a potential securty issue, which can be fixed by verifying and cleaning incoming varialbes.

Conclusion

Don't trust any incoming variables ($_GET,$_POST, or $_COOKIE). These can all be set by a malicious user and possibly compromise the securty of your system.

4 Comments:

  • Could this be any more common sense, even to the point of not even worth mentioning?

    By Anonymous Anonymous, at 5:05 PM  

  • Yes, most are common sense, but that does not stop many PHP programmers from writing insecure apps.

    By Blogger justin silverton, at 5:10 PM  

  • Your are saying not to trust $_GET, $_POST, can you set an example on how best to do this,

    Sorry it might be a newbie question.

    By Anonymous Anonymous, at 9:40 PM  

  • Don't worry about it. Ask any question you want and I will try to help you out as best I can.

    When I say not to trust $_GET or $_POST, it means if you are passing the data directly to anything outside of PHP.

    Below is an example script file that I have used for securing all posts values. (you could just save the script in a file such as secure_posts.php" and include it in any file that you wanted to secure your incoming posts (it would work for gets as well).

    I wasn't executing commands directly from PHP, so it doesn't check for that, but it could be added in the SecureValue() function.

    all posts and gets are each an associative array, so I just cycle through every value and clean the value.

    function SecureValue(&$value) {
    $MaxValueLength = 255;

    //sets a limit on the incoming value, 255

    $value = substr($value,0,$MaxValueLength);
    //strip the value of html
    $value = strip_tags($value);
    //escape value so it will be safe to submit to a mysql database
    $value = mysql_real_escape_string($value);

    //return the new, safe value
    return $value;
    }

    //all names of the associative post array
    $post_key_array = array_keys($_POST);
    //the total size of the array so we can iterate through each value
    $post_key_size = sizeof($post_key_array);

    //cycle through all POST variables and secure them
    for ($count=0;$count<$post_key_size;$count++)
    SecureValue($_POST["$post_key_array[$count]"]);

    By Blogger justin silverton, at 10:09 PM  

Post a Comment

Links to this post:

Create a Link

<< Home