Skip navigation.

Newbies Beware! Not so good advice...

DB Hoopla | Wonky Code

Thanks to Mike for sending in this WTF on a tutorial about PHP and MySQL security. Every PHP developer should know about the hazards of SQL injection. In fact it is important enough to be an offical part of the PHP documentation.

Perhaps the author who wrote this tutorial should have read the manual before declaring that PHP and MySQL doesn't allow SQL injection vulnerabilities any more and providing some pretty moot examples. Here is an excerpt from the article that describes how SQL Injections can happen.

How could hackers manipulate the form values to drop the whole database? Well it's pretty simple they just add a semicolon (which ends a query) then add the SQL statement ;DROP DATABASE mysql , or any other query they want.

Here's the provided code example:

= "INSERT INTO user (host, user, password, select_priv, insert_priv, update_ priv) VALUES ('localhost', 'someuser;drop database mysql;', PASSWORD('$password'), 'Y', 'Y', 'Y')";

Ack! Can that be any more wrong? First mysql_query() will only run one query at a time. Even if an attacker managed to inject an unexpected semicolon, the worst that could happen is the query would fail and confuse an application without adequate error checking. Semicolons more a part of mysql clients rather than actual SQL syntax. I don't think semicolon injection is a major security problem. If an application doesn't have adequate error handling it might fail but other than that there's really no security hazards to the database.

Secondly 'someuser;dropdatabase mysql;' would be interpreted as a string and there is no security problem there. The semicolons will have no effect other than creating a pretty ugly username.

SQL injection vulnerabilities usually occur from lazy coding. All data going into a database should be totally checked and cleaned. Writting data checking code is pretty tedious which is why it is often skipped. Here are some guidelines to follow for accepting data from users for the database:

  • Don't trust any data that comes from the user ment for the database.
    • Be especially paranoid about database ID's submitted throwugh $_GET because these can be easily modified.
    • Heck, be especially paranoid about any database data submitted through $_GET!
  • Run all string data through addslashes()
  • Make sure integers are actually integers, floats are floats, etc. Reformat them, explicitly cast them to the proper types, do the minimum necessary to ensure clean data for the database.
  • Make sure you have business rules for your data.
  • Check data validity before it goes into the database. Make sure it conforms to a proper set of business rules.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

I would recommend either usin

I would recommend either using prepared statements (if such a mechanism is available to you) or building your queries with sprintf plus mysql_escape_string(), like the following example:
$query = sprintf("select foo, bar from baz where quux = '%s'",mysql_escape_string($bla));

Hi,Have you contacted the a


Have you contacted the author of this tutorial about this issue? And is this the only issue that's not so good about this tutorial(s)? As it happens I saw this tutorial a few days ago, and it seemed very informative for me. As a novice in php/mysql programming, it's difficult to distinguish the 'good' from the 'bad' tutorials.


er ... the rss feed is STILL

er ... the rss feed is STILL broken. this one is showing twice, the previous one four times...

addslashes() is only useful

addslashes() is only useful with databases which allow more then the standard escaping feature for quotes. Typical PHP thinking. There's no \' in the standard!

When it comes to numbers, I'v

When it comes to numbers, I've started using floatval() for converting text strings to float values and intval() to get the integer. That ensures that I get the right kind of value for my MySQL commands instead of getting exactly what the user has typed in. Regarding string values, I've gone from using addslashes() to mysql_escape_string() ever since I discovered the latter.

Still, the person who wrote that tutorial must be naive when it comes to security, especially when simply stating that "SQL injection is not a problem with PHP anymore". Security risks also arise when programmers don't do their job properly by means of correct error handling.

mysql_escape_string() is de

mysql_escape_string() is deprecated as of php 4.3.0. Use mysql_real_escape_string() instead.


Thanks for the tip, GrumpySim

Thanks for the tip, GrumpySimon. I'll do that.

My database usage is not st

My database usage is not strickly MySQL so I use many different items.

From addslashes, htmlentities, strtr($data, array('(' => '(', ')' => ')')), utf8decode, and striptags.

I guess when it comes to my data i am really sensitive in what goes in and out. I use many checking levels by first ensuring the data is of the correct type then type casting it. For instance is_numberic($_POST['var']) and then using $var= (int) $_POST['var'] i could use settype but when i was running them through a series of tests it seemed that settype took longer than a type cast.

Not quite sure why it would take longer without looking at the actual source. Also for quoting you could add an additional function like:

function quote($str){
if (get_magic_quotes_gpc()) {
$str = str_replace('\\"','"',$str);
return $str;
$str = str_replace("\\\0", "\0", str_replace('\\\\', '\\',$str));
return "'".str_replace("'",'\\',$str)."'";

heh... The coolest thing on

heh... The coolest thing on #php is, that there was one guy, who claimed, that stripslashes() (not addslashes) prevents SQL injections...

Well... I had weirder conversations...


See for specific information about preventing sql injection attacks in mysql.

Post new comment


  • Web and e-mail addresses are automatically converted into links.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <pre> <p> <br /> <br>