Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

does PHP mysql_real_escape_string() protect database name?

I know that mysql_real_escape_string()
prepends backslashes to the following characters: \x00, \n, \r, \, ', " and \x1a

I know how this protects a query from injection into something like a variable in a where clause. But here's a scenario I am unsure of:

$query = "SELECT * FROM $db WHERE 1";

If $db is taken from a user input, then the user could insert something like:
$db = 'RealDatabase WHERE 1; DELETE FROM RealDatabase WHERE 1; SELECT FROM RealDatabase';

From my understanding, mysql_real_escape_string() would not affect this string, making the final query: $query = "SELECT * FROM RealDatabase WHERE 1; DELETE FROM RealDatabase WHERE 1; SELECT FROM RealDatabase WHERE 1";

which would delete the database. Is there another level of protection I am unaware of?

like image 261
Brian Avatar asked Dec 22 '22 06:12

Brian


2 Answers

The level of protection you are looking for is supplied by backticks:

"SELECT * FROM `$db` WHERE 1";

Backticks are used to qualify identifiers that could otherwise be ambiguous (ie. MySQL reserved words), and if you are accepting user input or have variably-named columns or databases, you absolutely should use backticks, or I can promise that you will run into trouble in the future. For example, what if you had a system where a temporary field name was created with some user input, only it turned out the field ended up being named update?

"SELECT field1,field2,update FROM table;"

It fails miserably. However:

"SELECT `field`,`field2`,`update` FROM table"

works just fine. (This is actually a real example from a system I worked on a few years ago that had this problem).

This solves your problem in terms of putting in bad SQL. For instance, the following query will simply return an "unknown column" error, where test; DROP TABLE test is the injected attack code:

"SELECT * FROM `test; DROP TABLE test`;"

Be careful though: SQL Injection is still possible with backticks!

For instance, if your $db variable contained data that had a backtick in it, you could still inject some SQL in the normal way. If you're using variable data for database and field names, you should strip it of all backticks before putting it into your statement, and then qualifying it with backticks once inside.

$db = str_replace('`','',$db);
$sql = "SELECT * FROM `$db` WHERE 1";

I utilize a database wrapper which has separate functions for sanitizing data and sanitizing database identifiers, and this is what the latter does :)

like image 54
zombat Avatar answered Dec 28 '22 11:12

zombat


You should really look into binding your SQL queries.

This will protect you from basically all SQL injection. It boils down to this:

(taken from PHP.net)

$stmt = mssql_init('NewUserRecord');

// Bind the field names
mssql_bind($stmt, '@username',  'Kalle',  SQLVARCHAR,  false,  false,  60);

// Execute
mssql_execute($stmt);

And PHP has support for binded queries on basically all databases. Oh and of course you should still sanitize all input & output(display).

More info: - http://php.net/manual/en/function.mssql-bind.php

like image 22
mr-sk Avatar answered Dec 28 '22 11:12

mr-sk