PHP Security - Introduction

Keeping Things Separate

One area wherethere is the potential for security issues with your PHP is where you have things jumbled together - for example data jumbled inside database statements or inside HTML. The code you use to resolve this is output processing that should be placed as close as possible to where the actual SQL or HTML is being processed.

The preferred solution to resolving these issues is to not jumble them together in a single statement but to keep them separate. Where it is impossible to completely separate them we need to "escape" the data so that it is treated specifically as data. We need to ensure that it is not possible to inject SQL into an SQL command via data or HTML into a web page via data except in those specific situations where we need the script to allow it and even then we need to make sure that what can be injected is limited to specifically what we wish to allow.

With database calls involving mySQL databases you can completely separate the SQL and the data it needs to reference in the majority of cases by using PREPARE and BIND statements instead of QUERY statements. About the only time that can't be easily done is where you need to specify the table name via a data field or build the SQL using data. To do this you need to either use the mysqli_ interface to the database instead of the mysql_ one or you need to use PDO. Either of these options will allow you to use a PREPARE statement containing the SQL and a BIND statement containing the data and there is therefore no possibility whatever for the data to be misinterpreted.

If you need to be able to specify the table name via the data then most likely there are only a small number of values that it will be allowed to be and so using an if or switch statement to specifically test the allowed values when building the prepare statement takes care of the alternatives without allowing the actual data field to be inserted into the SQL. A similar solution should be considered for where you need flexibility within the SQL itself since in almost all cases the number of alternatives that are valid will be limited.

Unfortunately HTML does not have a facility for separating the data the way that SQL does and so the alternative of "escaping" the data is the best alternative that we have available in this situation. Any data that is being written out in HTML can be escaped using the htmlspecialchars() function. This specifically converts those characters that HTML gives special meaning to into the corresponding entity codes so that the characters display in the web page instead of being treated as HTML. If none of those characters are allowed to appear in the data in the first place then the strip_tags() function can be used to strip those characters out of the field completely so as to ensure that those characters do not appear in the data at all - your input validation should have already checked this but using this function on the output as well can't hurt. Another function htmlentities() is also available to use if you specifically need to convert other characters in the data into entity codes in addition to those that can be confused for HTML - you only really need to use this one where you want to convert characters into HTML entity codes.

MySQL does have escape functions as well mysql_real_escape_string and mysqli_real_escape_string and if you find it impossible to use PREPARE and BIND then using one of these functions instead is better than nothing. These functions are not required when PREPARE and BIND are used though since you only need to escape data when it is jumbled with something else and there isn't anything jumbled with the data in a BIND statement.

The one other thing to remember when "escaping" data is that this process is specific to whatever it is that the data will be mixed with and so the escaping needs to be done at the time of the output processing and needs to be kept completely separate from your input processing where you validate the data coming in. There is little point in validating in input field and then passing it through htmlspecialchars() before writing it to a database as that then meains that the data is invalid for use anywhere except if being written insecurely into HTML where the appropriate output processing is not performed.


This article written by Stephen Chapman, Felgall Pty Ltd.

go to top

FaceBook Follow
Twitter Follow