Secure web pages with PHP/MySQL
Thursday, 30 March 2006
While there are numerous examples of poorly implemented web applications causing all sorts of security problems, the first step to take when developing in a PHP/Apache environment is to make sure your application always works with register_globals switched off.
The second step is to never trust the user to enter safe data in your applications web forms.
As this guide shows, it’s just too easy for a malicious user to forge a web form and consequently cause the web server to execute commands it never intended to in the first place. That’s why a good, defensive programmer knows that all data submitted by a user must filter out any potentially evil intentions.
For those developers working with the MySQL database, one safe approach is to ensure that you:
- Filter all database data before your present it on the web page.
- Filter all submitted web page data before you run the database query.
To do the former, use the db2form() function, as shown in this example:
$cid = isset($_REQUEST['cid']) ? (int) $_REQUEST['cid'] : 0;
$sql = "select name, address, email from contacts where id='{$cid}'";
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result)) {
$name = db2form($row['name']);
$address = db2form($row['address']);
$email = db2form($row['email']);
printf(
"name=%s address=%s email=%s\n",
$name,
$address,
$email
);
}
To do the latter, use the form2db() function, as shown in this example:
$frm['name'] = form2db($name);
$frm['address'] = form2db($address);
$frm['email'] = form2db($email);
$sql = sprintf(
"update contacts set
name='%s',
address='%s',
email='%s'
where id='%s'",
$frm['name'],
$frm['address'],
$frm['email'],
$cid
);
$result = mysql_query($sql);
The two functions in question which provide the necessary wrapper which ensures that any special characters are “converted” and “escaped”, as necessary:
function db2form($val) {
if (get_magic_quotes_gpc()) {
$val = stripslashes($val);
}
$val = htmlspecialchars(trim($val));
return $val;
}
function form2db($val) {
if (get_magic_quotes_gpc()) {
$val = stripslashes($val);
}
$val = mysql_real_escape_string($val);
return $val;
}
In case you didn’t spot it, note the particular way the variable $cid was extracted in the first example:
$cid = isset($_REQUEST['cid']) ? (int) $_REQUEST['cid'] : 0;
Instead of just assuming that our script is going to be handed a legitimate identifier, we check that it exists where we expect it to and then ensure that it’s a number.
Of course, that’s not all there is to writing secure web applications. Visit the PHP Security Consortium for more ideas.
|