You are on page 1of 6

T +44 1273 906 908 E hi@addedbytes.

com
Skip Navigation
Home Blog Writing Secure PHP, Part 2
Jump to: Top.
Home
Work
What We Do
Our Previous Work
What Our Customers Say
Store
Blog
Latest Posts
Articles
Code
Recommended
Most Popular
Blog Writing Secure PHP, Part 2
Learn how to improve your security a little further with the second part of this PHP tutorial.
In Writing Secure PHP, I covered a few of the most common security holes in websites. It's time to move
on, though, to a few more advanced techniques for securing a website. As techniques for 'breaking into' a
site or crashing a site become more advanced, so must the methods used to stop those attacks.
[Writing Secure PHP is a series. Part 1, Part 3 and Part 4 are currently also available.]
File Systems
Most hosting environments are very similar, and rather predictable. Many web developers are also very
predictable. It doesn't take a genius to guess that a site's includes (and most dynamic sites use an includes
directory for common files) is an www.website.com/includes/. If the site owner has allowed directory
listing on the server, anyone can navigate to that folder and browse files.
Imagine for a second that you have a database connection script, and you want to connect to the database
from every page on your site. You might well place that in your includes folder, and call it something like
connect.inc. However, this is very predictable - many people do exactly this. Worst of all, a file with the
extension ".inc" is usually rendered as text and output to the browser, rather than processed as a PHP
script - meaning if someone were to visit that file in a browser, they'll be given your database login
information.
Placing important files in predictable places with predictable names is a recipe for disaster. Placing them
outside the web root can help to lessen the risk, but is not a foolproof solution. The best way to protect
your important files from vulnerabilities is to place them outside the web root, in an unusually-named
Writing Secure PHP, Part 2 - Web Development in Brighton - Added Bytes http://www.addedbytes.com/articles/writing-secure-php/writing-secure...
1 of 6 4/28/2014 11:19 AM
folder, and to make sure that error reporting is set to off (which should make life difficult for anyone
hoping to find out where your important files are kept). You should also make sure directory listing is not
allowed, and that all folders have a file named "index.html" in (at least), so that nobody can ever see the
contents of a folder.
Never, ever, give a file the extension ".inc". If you must have ".inc" in the extension, use the extension
".inc.php", as that will ensure the file is processed by the PHP engine (meaning that anything like a
username and password is not sent to the user). Always make sure your includes folder is outside your
web root, and not named something obvious. Always make sure you add a blank file named "index.html"
to all folders like include or image folders - even if you deny directory listing yourself, you may one day
change hosts, or someone else may alter your server configuration - if directory listing is allowed, then
your index.html file will make sure the user always receives a blank page rather than the directory listing.
As well, always make sure directory listing is denied on your web server (easily done with .htaccess or
httpd.conf).
------
Out of sheer curiosity, shortly after writing this section of this tutorial, I decided to see how many sites I
could find in a few minutes vulnerable to this type of attack. Using Google and a few obvious search
phrases, I found about 30 database connection scripts, complete with usernames and passwords. A little
more hunting turned up plenty more open include directories, with plenty more database connections and
even FTP details. All in, it took about ten minutes to find enough information to cause serious damage to
around 50 sites, without even using these vulnerabilities to see if it were possible to cause problems for
other sites sharing the same server.
-----
Login Systems
Most site owners now require an online administration area or CMS (content management system), so
that they can make changes to their site without needing to know how to use an FTP client. Often, these
are placed in predictable locations (as covered in the last article), however placing an administration area
in a hard-to-find location isn't enough to protect it.
Most CMSes allow users to change their password to anything they choose. Many users will pick an
easy-to-remember word, often the name of a loved one or something similar with special significance to
them. Attackers will use something called a "dictionary attack" (or "brute force attack") to break this kind
of protection. A dictionary attack involves entering each word from the dictionary in turn as the password
until the correct one is found.
The best way to protect against this is threefold. First, you should add a turing test to a login page. Have a
randomly generated series of letters and numbers on the page that the user must enter to login. Make sure
this series changes each time the user tries to login, that it is an image (rather than simple text), and that it
cannot be identified by an optical character recognition script.
Second, add in a simple counter. If you detect a certain number of failed logins in a row, disable logging
in to the administration area until it is reactivated by someone responsible. If you only allow each
potential attacker a small number of attempts to guess a password, they will have to be very lucky indeed
to gain access to the protected area. This might be inconvenient for authentic users, however is usually a
price worth paying.
Finally, make sure you track IP addresses of both those users who successfully login and those who don't.
Writing Secure PHP, Part 2 - Web Development in Brighton - Added Bytes http://www.addedbytes.com/articles/writing-secure-php/writing-secure...
2 of 6 4/28/2014 11:19 AM
If you spot repeated attempts from a single IP address to access the site, you may consider blocking
access from that IP address altogether.
Database Users
One excellent way to make sure that even if you have a problem with someone accessing your database
who shouldn't be able to, you can limit the damage they can cause. Modern databases like MySQL and
SQL Server allow you to control what a user can and cannot do. You can give users (or not) permission to
create data, edit, delete, and more using these permissions. Usually, I try and ensure that I only allow
users to add and edit data.
If a site requires an item be deleted, I will usually set the front end of the site to only appear to delete the
item. For example, you could have a numeric field called "item_deleted", and set it to 1 when an item is
deleted. You can then use that to prevent users seeing these items. You can then purge these later if
required, yourself, while not giving your users "delete" permissions for the database. If a user cannot
delete or drop tables, neither can someone who finds out the user login to the database (though obviously
they can still do damage).
Powerful Commands
PHP contains a variety of commands with access to the operating system of the server, and that can
interact with other programs. Unless you need access to these specific commands, it is highly
recommended that you disable them entirely.
For example, the eval() function allows you to treat a string as PHP code and execute it. This can be a
useful tool on occasion. However, if using the eval() function on any input from the user, the user could
cause all sorts of problems. You could be, without careful input validation, giving the user free reign to
execute whatever commands he or she wants.
There are ways to get around this. Not using eval() is a good start. However, the php.ini file gives you a
way to completely disable certain functions in PHP - "disable_functions". This directive of the php.ini file
takes a comma-separated list of function names, and will completely disable these in PHP. Commonly
disabled functions include ini_set(), exec(), fopen(), popen(), passthru(), readfile(), file(), shell_exec() and
system().
It may be (it usually is) worth enabling safe_mode on your server. This instructs PHP to limit the use of
functions and operators that can be used to cause problems. If it is possible to enable safe_mode and still
have your scripts function, it is usually best to do so.
Finally, Be Completely and Utterly Paranoid
Much as I hate to bring this point up again, it still holds true (and always will). Most of the above
problems can be avoided through careful input validation. Some become obvious points to address when
you assume everyone is out to destroy your site. If you are prepared for the worst, you should be able to
deal with anything.
Ready for more? Try Writing Secure PHP, Part 3.
Writing Secure PHP, Part 2 - Web Development in Brighton - Added Bytes http://www.addedbytes.com/articles/writing-secure-php/writing-secure...
3 of 6 4/28/2014 11:19 AM
37 Comments

Jeff Majors
That's why all my includes end with .php as .inc can be exposed as text files in browsers. I
don't see the point of adding .inc.php though. Just stating, "inc_db.php" is informative and
you sort them naturally.



Dougall
Excellent article.
However I agree with Jamie from Canada above, it *is* safe to use .inc files (and indeed an
/include dir) if you set up your htaccess rules so they are not visible externally (or alternatively
you can place them outside the apache docroot).
In the following article Rasmus Lerdoff (the original author of PHP) uses this approach (and
there is a dicsussion of this exact issue in the comments, see #37 and onwards):
http://toys.lerdorf.com/archiv...



Fredrik
Thank you for these articles, a very good read!
A note about using .htaccess files to restrict access, if you go from Apache to Lighttpd like I
just did, they stop working since Lighttpd doesn't seem to support them. You need to set, for
example, url.access-deny in your lighttpd.conf instead.


Erick
You mention adding a delete indicator on a record. I go beyond that on every table. I add:
update_datetime
update_user_id
create_datetime
create_user_id
delete_datetime
delete_user_id
Then, anything that is done is logged. At least the last execution of any of those. If you need
more granularity in something, then create a table that logs extended or historical information.


Sandor
never trust user data, should we trust a webpage as well :-)


Writing Secure PHP, Part 2 - Web Development in Brighton - Added Bytes http://www.addedbytes.com/articles/writing-secure-php/writing-secure...
4 of 6 4/28/2014 11:19 AM
Writing Secure PHP, Part 2, by Dave Child, was posted on 22 March 2005 and has been tagged with
security, webdev, development, programming, mysql, php, web, work and imported.
Thoughts from a Brighton geek about web development, marketing, freelancing, entrepreneurship and
fatherhood. Probably not in that order.
Feeds
RSS (Full)
RSS (Partial)
More Feeds
Newsletter
Name
Email
Topics
PHP
E-commerce
Security
Online Marketing
Freelancing
For Beginners
More
Latest Posts
Articles
Code
Recommended
Most Popular
Hi! I'm Dave and I'm a freelance PHP developer from Brighton, UK. I build awesome e-commerce and
CMS websites using platforms like Magento, MODX, Drupal and OpenCart. I'm available for projects
starting in June.
Check out my Services and Portfolio or get in touch!
Services
Website Development
- Magento Website Development
- MODX Website Development
- OpenCart Website Development
- TomatoCart Website Development
- Wordpress Website Development
- Drupal Website Development
Writing Secure PHP, Part 2 - Web Development in Brighton - Added Bytes http://www.addedbytes.com/articles/writing-secure-php/writing-secure...
5 of 6 4/28/2014 11:19 AM
2003 2014 Added Bytes Ltd (Company 8026399)
Creative Commons License | Privacy Policy | Tags | Site Map
- Bespoke Website Development
Online Marketing
- Search Engine Optimisation
- Social Media Marketing
Magento Extensions
- Store Locator for Magento
- Discontinued Products for Magento
- Mass Redirect for Magento
Quick Links
- Blog
- Cheat Sheets
Contact Added Bytes
Phone: +44 (0) 1273 906908
Twitter: @AddedBytes
Email: hi@addedbytes.com
Writing Secure PHP, Part 2 - Web Development in Brighton - Added Bytes http://www.addedbytes.com/articles/writing-secure-php/writing-secure...
6 of 6 4/28/2014 11:19 AM

You might also like