Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP: using prepared statements and protecting against SQL injection vs escape

I do understand that the prepared statements is the ultimate way to seek protection against the SQL injection. However, they provide coverage in a limited fashion; for example, in cases where I let the user to decide how the order by operation to be ( i.e, is it ASC or DESC? etc ), I get no coverage there with the prepared statements.

I understand that I can map the user input to a pre-defined white list for that. But, this is only possible when a whitelist can be created or guessed thoroughly beforehand.

For example, in the cases I mention above ( the ASC, or DESC ), this can easily be mapped and verified against a list of accepted values. But isn't there a situation where the portion of the SQL statement cannot be verified against a white list?

If such a situation exists, then what's the recommended approach?

If I were to escape the user_input using the underlying database's built-in escape utility (such as mysqL_real_escape_string for mysql) across the board, where would I fail?

I'm asking this question with the assumption that I always construct my sql statements with quoted values - even for integers...

Let's take a look at the following example and reflect upon it..

select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}

Assume all vars are user supplied.

If I were to mysql_real_escape_string all the variables in the above SQL ( as opposed to using prepared statements which covers me only half-way forcing me to come up whitelists for the other half that it cannot help), wouldn't it be equally safe (and easier to code)? If not, in which input scenario escape utility would fail?

$fields       = mysql_escape($fields);
$table        = mysql_escape($table);
$age          = mysql_escape($age);
$orderby_pref = mysql_escape($orderby_pref);

select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref}
like image 480
Average Joe Avatar asked Jul 12 '12 15:07

Average Joe


People also ask

Does prepared statement prevent SQL injection?

Prepared statements are very useful against SQL injections, because parameter values, which are transmitted later using a different protocol, need not be correctly escaped. If the original statement template is not derived from external input, SQL injection cannot occur.

Is escaping enough to prevent SQL injection?

Character Escaping Pre-cleansing input data by “escaping” characters tells SQL values that they should be treated as a string, rather than as a command. Escaping special characters doesn't guarantee SQL injection prevention, but it reduces the risk significantly. Here is an example of how character escaping works.

Does PHP prevent SQL injection?

Another approach for avoiding SQL injections is using PHP Prepared Statements. A prepared statement is a feature in PHP which enables users to execute similar SQL queries efficiently and repeatedly.

What is the advantage of prepared statement in PHP?

Prepared statements offer two major benefits: The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query.


2 Answers

You always need to use white-lists for stuff like table- or column names, whether you use prepared statements or the mysql escape functions.

The problem is that table names and column names are not quoted in single or double quotes, so if you use a function that specifically quotes these characters (and some more of course...), it will do nothing for your table name.

Consider the table name my_table; DELETE * FROM mysql; SELECT * FROM my_table. Nothing in this string will get escaped by mysql's escape functions but it is definitely a string you would want to check against a white-list.

Apart from that the mysql escape functions have a problem with character sets that can render them useless, so you are always better off with prepared statements.

like image 87
jeroen Avatar answered Oct 05 '22 23:10

jeroen


You could use PDO and your life will get easier ... :

    #   Order
    switch(strtoupper($Order)){
        default:
        case 'ASC':
            $Order = 'ASC';
            break;

        case 'DESC':
            $Order = 'DESC';
            break;
    }

    #   ID
    $ID = 39;
    $Username = 'David';

    #   Query
    $Query = $this->DB->Main->prepare('SELECT * FROM Table WHERE ID = :ID AND Username = :Username ORDER BY HellBob '.$Order);
    $Query->bindValue(':ID', $ID, PDO::PARAM_INT);
    $Query->bindValue(':Username', $Username, PDO::PARAM_STR);

    #   All good ?
    if(!$Query->execute()){
        exit('Error');
    }

    // Results
    $Row = $Query->fetch(PDO::FETCH_ASSOC);

You don't have to worry about quotes or SQL injections. You can use simple "white list" as you mention to get variable into your query.

like image 30
David Bélanger Avatar answered Oct 05 '22 23:10

David Bélanger