if (user_auth()) {
$access = true;
}
if ($access) {
do_sensitive_things();
}
This could be exploited by tacking an ?access=true
to the
end of the url, and the if ($access)
test would be passed
despite the user_auth()
function returning false. This
hole could be closed easily by adding a $access = false;
at
the top of the script, but not all security holes are this easy to spot.
Thankfully, PHP now defaults the register_globals
option to
off. This setting would pass the access variable sent by the url to the
script as $_GET[access]
rather than just
$access
. This closes off many of these types of
vulnerabilities, but when writing PHP code, especially code for
distribution, you should never assume that this option will be set
correctly, and always initialize your PHP variables. Users in a shared
hosting environment may not have the ability to set these options to
their most secure setting.
- Always initialize PHP variables before using them.
- Always set
register_globals
to off, but never write code that assumes this setting. - You can use the
ini_get()
function to determine ifregister_globals
is set at runtime.
Another common cause of PHP application holes is improper sanitization
of user provided data. For example, if you allow a user to fill out a
form and then pass data from a field on that form to a function like
system()
or exec()
the data could contain
something malicious, like an ; rm -rf *
command tacked onto it.
- Never trust user provided data.
- Beware functions that launch system commands, think long and hard about checking any data that is passed to them.
Another related but common security flaw in PHP applications is a SQL
injection vulnerability. The magic_quotes_gpc
option can
mitigate this, but as with register_globals
you should not
assume this setting is on.
For example, in your PHP script you might ask the user for a user id and password, and then check for the user by passing the database a query.
SELECT * FROM users WHERE name='$username' AND pass='$password';
However, if the user logging in is malicious and devious, he may enter
the following as his password:
' OR '1'='1
This causes your query to become:
SELECT * FROM users WHERE name='known_user' AND pass='' OR '1'='1';
The user has just logged in with no password, and your application has
been penetrated. To avoid this, check for the status of
magic_quotes_gpc()
using the ini_get()
function and if it is disabled, pass all user input that must be
included in a query through addslashes()
. This will escape
the single or double quotes in the user input with backslashes, thereby
thwarting the attempted SQL injection attack.
- Use
magic_quotes_gpc
, but don't assume it is on or depend on it. - The
addslashes()
function should be used on user data passed to SQL queries. - Again, you simply cannot trust user provided data.
The PHP online manual
contains an entire
chapter on PHP security. It's an excellent resource, and goes into
much more detail on the PHP security issues I've discussed in this
article. Until next time, stay secure, and don't blindly trust any user
provided data.
--
Pax Dickinson has over ten years of experience in systems administration and software development on a wide variety of hardware and software platforms. He is currently employed by Guardian Digital as a systems programmer where he develops and implements security solutions using EnGarde Secure Linux. His experience includes UNIX and Windows systems engineering and support at Prudential Insurance, Guardian Life Insurance, Philips Electronics and a wide variety of small business consulting roles.