7 December 2004

PHP Programmers: Please Learn to Escape Your Data Correctly!

Posted under: at 00:53

I really don’t like the way PHP is heading now, but still PHP is probably used by more web based project than all other languages combined. In my unscientific opinion, PHP programmers tend to make more elementary mistakes than programmers of other languages. This is probably caused by the abundance of poor programming examples on the Internet and in books. One of these mistakes is how to properly escape or quote a string. Improper (or nonexistant) escaping or quoting could cause all sort of security hole we hear almost every week, like SQL injection or Cross Site Scripting. I will offer my insight to vast masses of PHP programmers on how to avoid this problem.

As a general rule of thumb, you should not trust data, especially when the data in question is provided by a web user. You should escape all data before ‘printing’ it. How you escape them depends on the context. Do not enable ‘magic_quotes’. Magic quotes is stupid, it blindly assume your data will be used with database, however that is not always the case. You must ‘quote’ your data, but how to quote them depends on what you are going to do with your data.

Printing a Variable to Browser

The simplest task is to send the content of a variable to web browser. Most of the time you will see example like this: <?php echo $variable ?>. This is very simple but it is also very wrong (if $variable is not already HTML quoted). You will need to escape $variable first by using htmlspecialchars. A better example would be <?php echo htmlspecialchars($variable) ?>. If you need to insert literal HTML code, do that outside escaping. For example: <?php echo "<p>" . htmlspecialchars($variable) . "</p>" ?>.

Printing a Variable as Part of Query String

Sometimes it is needed to pass variables to another PHP script in form of query string, for example: http://example.net/script.php?var=foo. Another wrong example with PHP script: <?php $url = "http://example.net/script.php?var=$somevar" ?>. A better example would be <?php $url = "http://example.net/script.php?var=" . urlencode($somevar) ?>. If you need to print this to web browser (which is likely), you will need to combine this with the HTML quoting above. For example: <?php echo '<a href="/foo.php?var=' . htmlspecialchars(urlencode($somevar)) . '">foo</a>' ?>.

Using a Variable Inside SQL Queries

Another common task is to put variables inside SQL queries. One must be careful here not to make SQL injection hole. A wrong example: <?php $sql = "select * from foo where bar = '$somevar'" ?> when $somevar is not quoted. $somevar needs to be escaped before it is safe to include the variable within SQL context. This example is better written as: <?php $sql = "select * from foo where bar = '". mysql_real_escape_string($somevar) ."'" ?>. This is specific for MySQL, other RDBMS have similar but slightly different escaping style. Yes, I can confirm different RDBMS have different escaping style.

Using a Variable As A Shell Command Argument

It is better to avoid this entirely because PHP’s way to accomplish this doesn’t handle all possible situation. For example, escapeshellarg doesn’t handle empty string. There is apparently no easy way to execute a command line without going through /bin/sh from within PHP. But if you must, you can use something like this: <? passthru('cat ' . escapeshellcmd($filename)) ?>. Of course, you are going to do further sanitation task with $filename, but that’s very specific to each script. A better approach to exec an external program is to create a wrapper script that takes input from environment variables (as opposed from command line arguments). But that’s beyond the scope of this writing.

Conclusion

Doing The Right Thing™ with PHP is a PITA. But they are your scripts, not mine. You are the one who will suffer when some script kiddies decide to exploit your script. You might want to implement your own functions and routine, so that escaping will be much simpler in your situation. Or even better, you might want to learn some other programming language! Wishful thinking, I know.

me, appalled with the state of php scripting today

One Response

Trackback: Use this URI to trackback this entry. Use your web browser's function to copy it to your blog posting.

Comment RSS: You can track conversation in this page by using this page's Comments RSS (XML)

Gravatar: You can have a picture next to each of your comments by getting a Gravatar.

Leave a Comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Warning: Comments carrying links to questionable sites will be removed!