Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Php addslashes sql injection still valid?

I know "parameterised queries" is the holy grail. This is not the topic.

There is an old post, that seems to be the reference for all discussions related to sql injections when addslashes is used.

This is the link : http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

My question is : is this Proof of concept still correct ? I tried to test it but the addslashes seems to be working correctly. Did anyone else actually tried this or everybody is taken it for granted ?

  • I added $db->set_charset("GBK");
  • I used gbk_chinese_ci for db/fields
  • The mysql log shows this query
     SELECT *
            FROM   users
        WHERE  username = '�\' OR username = username /*'
        AND    password = 'guess'
    

    so clearly the trick it's not working

    Update : Please read the question I'm asking. I don't care for best practice, I don't need alternatives, I just need to makes sure this is still valid or not.

    Update : Also I would like to remind this POC works for character sets like GBK, SJIS or BIG5 and everybody seems to forget that. Making the titles sound a bit to scary when saying addslashes is not safe.

    Solution : In my case the mysql version 5.5.9-log is not allowing inline comments that are not finised like /*. If I use -- or # it works.

  • like image 263
    johnlemon Avatar asked Feb 27 '11 11:02

    johnlemon


    People also ask

    What is the use of Addslashes in PHP?

    The addslashes() function returns a string with backslashes in front of predefined characters. The predefined characters are: single quote (')

    How do you escape a slash in PHP?

    In PHP, an escape sequence starts with a backslash \ . Escape sequences apply to double-quoted strings. A single-quoted string only uses the escape sequences for a single quote or a backslash.

    Does Mysqli_real_escape_string prevent SQL injection?

    The answer is "No".

    What is real escape string PHP?

    mysqli_real_escape_string(mysqli $mysql , string $string ): string. This function is used to create a legal SQL string that you can use in an SQL statement. The given string is encoded to produce an escaped SQL string, taking into account the current character set of the connection. Caution.


    1 Answers

    It seems working for me.

    mysql:

    mysql> select version();
    +---------------------+
    | version()           |
    +---------------------+
    | 5.0.45-community-nt |
    +---------------------+
    1 row in set (0.00 sec)
    
    mysql> CREATE TABLE users (
        ->     username VARCHAR(32) CHARACTER SET GBK,
        ->     password VARCHAR(32) CHARACTER SET GBK,
        ->     PRIMARY KEY (username)
        -> );
    Query OK, 0 rows affected (0.08 sec)
    
    mysql> insert into users SET username='ewrfg', password='wer44';
    Query OK, 1 row affected (0.02 sec)
    
    mysql> insert into users SET username='ewrfg2', password='wer443';
    Query OK, 1 row affected (0.03 sec)
    
    mysql> insert into users SET username='ewrfg4', password='wer4434';
    Query OK, 1 row affected (0.00 sec)
    

    PHP:

    <pre><?php
    echo "PHP version: ".PHP_VERSION."\n";
    
    mysql_connect();
    mysql_select_db("test");
    mysql_query("SET NAMES GBK");
    
    $_POST['username'] = chr(0xbf).chr(0x27).' OR username = username /*';
    $_POST['password'] = 'guess';
    
    $username = addslashes($_POST['username']);
    $password = addslashes($_POST['password']);
    $sql = "SELECT * FROM  users WHERE  username = '$username' AND password = '$password'";
    $result = mysql_query($sql) or trigger_error(mysql_error().$sql);
    var_dump($username);
    var_dump(mysql_num_rows($result));
    var_dump(mysql_client_encoding());
    
    $username = mysql_real_escape_string($_POST['username']);
    $password = mysql_real_escape_string($_POST['password']);
    $sql = "SELECT * FROM  users WHERE  username = '$username' AND password = '$password'";
    $result = mysql_query($sql) or trigger_error(mysql_error().$sql);
    var_dump($username);
    var_dump(mysql_num_rows($result));
    var_dump(mysql_client_encoding());
    
    mysql_set_charset("GBK");
    $username = mysql_real_escape_string($_POST['username']);
    $password = mysql_real_escape_string($_POST['password']);
    $sql = "SELECT * FROM  users WHERE  username = '$username' AND password = '$password'";
    $result = mysql_query($sql) or trigger_error(mysql_error().$sql);
    var_dump($username);
    var_dump(mysql_num_rows($result));
    var_dump(mysql_client_encoding());
    

    result:

    PHP version: 5.3.3
    string(29) "ї\' OR username = username /*"
    int(3)
    string(6) "latin1"
    string(29) "ї\' OR username = username /*"
    int(3)
    string(6) "latin1"
    string(30) "\ї\' OR username = username /*"
    int(0)
    string(3) "gbk"
    

    Conclusions:

    A second result going to be most surprising for those who chants "you should use mres instead of addslashes!"

    like image 164
    Your Common Sense Avatar answered Sep 22 '22 01:09

    Your Common Sense