Life SlashBoot The Internet Unices Web Development
This article last updated: Monday, 28 August 2006

Defend in depth

First rule of web development and probably the most important in the modern climate of severe hostility on the Internet. This should be your mantra and the ever present, foremost thought in your mind, when developing PHP scripts for use on the Internet.

Simple

Simplicity is the best policy when developing your PHP scripts. Always look to develop your scripts to be readable, commenting liberally. Complicity can often mask or obfuscate potential problems, logic errors, bugs and vulnerabilities in your code. Unless you absolutely must squeeze every processor cycle out of your servers, the simplest and most straight forward code, is usually the best. With proper planning, you can shape your system to allow for simple functions and loops, whilst still maintaining efficiency in execution times.

Multiple layers of defence

Think of a handful of ways that you can implement added security and authentication into your system, then make every effort to implement at least two, preferably three, of them.

Make every effort not to expose meaningful information in authorisation systems. If you must store values in insecure places like user cookies and also accept values from those sources, then make sure that the exposed data is at worst a hash of what you have stored on the server, never the data itself and preferably a time limited token.

Trust no-one

Any data that you accept from the outside world, be it through GET parameters, POST values, COOKIE values, treat as tainted. Untaint and only act on known and to be expected, values. Use switch/case constructs to filter for expected values, wherever possible. At the very least check data types and allowed characters. A simple method is to keep with numbers as references, which allows for simple is_numeric($value) tests.

When you are untainting data, you are ensuring that the data that is acted upon is clean and free of possible exploits. This can be achieved in a number of ways, such as the switch / case constructs I mention above, where you are setting a value according to what you are supplied. It is the newly set value that you pass on through your web application. Other methods include stripping out characters that may be used in exploits, such as semi-colons, quotes and others. A common form of untainting data is the mysql_real_escape_string() PHP function, which makes any changes necessary to strings, to ensure that they cannot be used in SQL injection attacks. It simply escapes characters that have special meaning in SQL queries, to make sure that they have no effect. When untainting or filtering data for general use, you may want to use a regular expression to test that data fits what you are expecting. Another useful method is simple switch / case or if conditional tests, that set a value depending on the data received. It is this newly set value that you then act upon, so you are not blindly using data or values supplied from the outside world.

Escape to safety

Escape all output. Make sure that you are making efforts to control what becomes output for your scripts. Output means not only what gets output to the visitor's browser, but what gets written on the server, be it in data files directly, or into database files, which have a structure of their own, that you will always be trying to protect from any malicious corruption.

Luckily PHP has database type dependant functions, which can make short work of ensuring that your SQL queries remain clean and uncorrupted. MySQL users can use mysql_real_escape_string($string) to untaint data for safe database inserts and scupper SQL injection attacks. Although I don't encourage allowing your web based scripts to interact with the shell, there is also the escapshellarg() and escapeshellcmd() which look for semi-colons, backticks and so on. Read up on these and similar commands over at the PHP.net site, for more details.

Escaping, filtering, untainting, it's all in the same vein and something that you should be comfortable with, if you are allowing the world to use scripts on your site. Remember, there's some devious buggers out there. Some are very clever and resourceful, you can't beat them all, but you can do your best. With luck, you'll develop systems that are secure enough to repel all but the most skilled and determined attackers, who are likely to be after far bigger fish than yourself. That's my philosophy on it, anyway.

Inspecting the output

Another useful tip I can offer, is to make use of the output buffering facilities offered in PHP scripting. This has many uses but from a security perspective I suggest inspecting the output of your scripts, before it is output to the browser. For example, source code exposure is a real problem and the ingenuity of some attackers, or an as yet undiscovered flaw in the scripting engine, could allow somebody to see your source code, which might expose passwords for databases, or at least the structure of databases or file locations. To protect against this, we could insert a longish, very obscure string into our scripts, includes and other files that we don't want broadcast to visitors. Make this string something that is not going to be reproduced by chance, in the legitimate content of your site, we don't want to be creating false positive alerts. Just drop this marker string in as a comment, so as not to interfere with the script's normal operation and then using the output buffer, we can check for the existence of the marker string, before the output is sent to the browser. Ideally we would strip stuff out, but if somebody has gotten far enough to be outputting the content of our scripts, it is safer to just halt the operation and alert yourself, or another admin for the site. Make sure you log as much as possible and hopefully you can learn how they were doing it, what they were doing and maybe even who was doing it. Output buffers can be another tool in your security chest and the more the merrier, from a defence in depth perspective.

Post a comment:




No HTML allowed except for plain <b>, <i>, <s>, <u> & <p> tags. NO uBB code ([b] ... [/b] style tags) are allowed and comments containing [URL] ... [/URL] tags are automatically rejected as spam.
|
URL and email address are optional, email address is never displayed.
Like this page? Furl it | del.icio.us | Spurl it
GeoLocator Contact Sitemap
Standards for a better web Valid XHTML Strict CSS inside Valid RSS2.0 feeds used on this site
Hosted by BristolGeek