Tuesday, January 27, 2009

PHP Security issues

Avoid Using Variables When Accessing Files

Code:
include($lib_dir . "functions.inc");
include($page);

Issue:
The user could set the $lib_dir or $page variables and include files such as /etc/passwd or remote files such as http://www.some-site.com/whatever.php with malicious code. This malicious code could potentially delete files, corrupt databases, or change the values of variables used to track authentication status.

Fixes or Improvements:

Avoid using variables as file names. The $lib_dir variable above could be replaced with a value defined by the PHP define function.

1. Check the file name against a list of valid file names. For example,
$valid_pages = array(
"apage.php" => "",
"another.php" => "",
"more.php" => "");

if (!isset($valid_pages[$page])) {
// Abort the script
// You should probably write a log message here too
die ("Invalid request");
}

2. If you must really use a variable from the browser, check the variable's value using code like the following:

if (!(eregi("^[a-z_./]*$", $page) && !eregi("\\.\\.", $page))) {
// Abort the script
// You should probably write a log message here too
die("Invalid request");
}

3. Use the allow_url_fopen and open_basedir configuration variables to limit the locations where files can be opened from.


Escape characters in SQL statements


A common mistake is to use a variable value supplied by the user or the URL in an SQL query without escaping special characters. Consider the following fragment of code from a script designed to authenticate a username and password entered in a HTML form:
$query = "SELECT * FROM users WHERE username='" . $username . "'
AND password='" . $password . "'";

// the record exists function is defined elsewhere
if (record_exists($query)) {
echo "Access granted";
} else {
echo "Access denied";
}

Issue :

his code would work when accessed using check.php?username=admin&password=x. However, if the code were accessed using check.php?username=admin&password=a%27+OR+1%3Di%271 (and if magic_quotes_gpc were disabled) then the password condition becomes Password='a' or 1='1' so that the admin user record would always be returned regardless of the password it contained.

Fixes or Improvements:

1. This problem is partly avoided when the magic_quotes_gpc variable is on in the php.ini file, meaning that PHP will escape quotes in GET, POST, and cookie data using the \ character.
2. Use the built-in addslashes function or a similar function to escape quotes and backslashes in SQL statements with backslashes.
3. If you are using variables which you expect to contain numbers in your SQL statement, ensure that they really do contain numbers. You can use various built-in PHP functions including sprintf, ereg and is_long, to perform this check.


Do Not Trust Global Variables

// Assume $article_id is set by the URL
if ($article_id == 0) {
$guest_ok = true;
}

if (!$guest_ok) {
// Check user is authenticated using a function defined elsewhere
check_auth();
}

Issue:
This code may appear to work, because the $guest_ok variable will generally be initialized to false. However, if a malicious user includes guest_ok=1 in the URL, he will be granted access to any article in the system.

Fixes or Improvements
• Disable register_globals in your php.ini file. After making this change, you will need to use the $_GET and $_POST arrays to access GET and POST inputs instead of using global variables. This can be tedious, but also far more secure.
• If a "Remember My Login" function is required, include a password or a hard to guess random identifier in the cookie. (A "Remember My Login" function can still produce other holes such as malicious user who shares a machine with a legitimate user to gain access.)
• Write code to initialize all global variables. The previous code fragment could be improved by initializing $guest_ok to false at the start of the script.
• Ensure session variables really do come from the session and not from a malicious user.

Avoid False Uploads


File uploads can suffer from a severe case of the untrusted global variables problem that is worth considering as an additional problem. When a file is uploaded, a PHP script is given a variable that provides the name of the temporary file where PHP saves the uploaded file. However, the user could construct a URL that sets this variable to a malicious value such as /etc/passwd and not upload a file. The responding script may then copy that file to an accessible location or display the file's contents to the user.

Escape HTML Characters in text

What happens if somebody puts a blink tag in a posting to a discussion board? If you don't escape HTML characters in text either before you save or display it, all subsequent text on the page could be blinking. More severe versions of this attack are also possible; for example an attacker could write JavaScript that takes the browser to a competitor's site.

Fixes or Improvements
• Escape HTML appropriately either before you save it or before you display it. You can use PHP's built-in functions htmlspecialchars or htmlentities for this purpose.
• If you want untrusted users to use HTML for formatting, you should perform validation to restrict the available HTML tags to a basic tags set.

No comments:

Post a Comment