2017-10-20 8 views
1

Je veux faire la requête SQL suivante dans CakePHP 3.4.7:Lorsque vous devez absolument échapper manuellement SQL dans CakePHP 3.4.7

DROP DATABASE $databasename 

J'ai trouvé que cela ne fonctionne pas:

$conn->execute("DROP DATABASE :databasename", ['databasename' => $databasename]); 

... parce que MySQL n'accepte pas les noms de base de données et de table en tant que paramètres dans les états préparés (voir Can PHP PDO Statements accept the table or column name as parameter?)

Je ne peux pas utiliser la classe Désinfecter de CakePHP parce qu'elle a été désapprouvée dans CakePHP 3 (https://book.cakephp.org/3.0/en/appendices/3-0-migration-guide.html#sanitize)

Je ne peux pas utiliser mysqli :: real_escape_string parce AFAIK il n'y a pas l'objet mysqli ...

Quelqu'un sait-il des alternatives?

+1

Escaping ne fonctionnerait pas parce que ce serait pour les guillemets, les guillemets ne sont pas pour les tables/colonnes. Vous pouvez faire une liste blanche des termes autorisés, puis les transmettre. – chris85

+0

Je suppose que dans mon cas, je ne devrais vraiment m'inquiéter de l'insertion de points-virgules? Mais je pensais aussi à aller sur la liste blanche. –

+0

Je suppose que vous avez une liste de bases de données qui peuvent être supprimées. Tu ne peux pas juste vérifier si le terme est dans cette liste? – arilia

Répondre

1

Il est décevant de ne pas pouvoir compter sur le code de quelqu'un d'autre pour la sécurité, car avouons-le, la grande majorité des gens ne se soucient pas de la sécurité. Mieux vaut compter sur ces bibliothèques! Mais, dans les cas où vous ne pouvez pas, comme cela peut-être, envisager une petite liste blanche de possibilités pour le contenu que vous attendez. Pensez à ce que vous attendez de voir et appliquez-le. Dans mon esprit, je m'attendrais à un nom de base de données uniquement de lettres alphabétiques et peut-être des traits de soulignement. Cela ne couvrira évidemment pas toutes les valeurs de noms de tables possibles (par exemple, les noms de bases de données peuvent aussi avoir des nombres), mais c'est votre situation qui détermine ce qui compte. Dans cet esprit, une routine de nettoyage possible peut être une simple regex qui impose que le nom passé n'a pas d'espace, commence par une lettre, a peut-être plus de lettres ou de traits de soulignement et ne peut pas dépasser 16 caractères:

if (! preg_match('/^[A-z][A-z_]{0,15}$/', $databasename)) { 
    # database name does not pass the project standards of alpha 
    # letters and underscores only. Likely crack attempt. 
    die('No way, Joker!'); # or something more appropriate. 
} 

ce n'est pas l'exhaustivité offerte par les pilotes DB, mais il est simple, facile à lire, et travaillera pour> 90% de tous les noms de base de données là-bas. Avec la vérification de bon sens ci-dessus passé, alors vous pouvez écrire le-dangereux généralement considéré comme méthode qui-est-sûre en ce cas chaîne SQL directement:

$conn->execute("DROP DATABASE $databasename");