Vulnérabilités des injections SQL lors de l'utilisation de modèles SQL de Zend Framework

15

Lors de la jonction de tables, j'utilise des modèles SQL de Zend Framework. À titre d'exemple, j'ai modifié mon code actuel, mais je pense que vous obtiendrez le point:

$this->getSelect()->join(
                      array('sections' => $sectionsTableName),
                      'main_table.banner_id = pages.banner_id',
                      array()
                    )
                  ->where("sections.section= '$section' OR sections.section = '0' OR (sections.section = '6' AND ? LIKE main_table.url)",$url)
                  ->group('main_table.banner_id'); 

La page est chargée avec ajax et le paramètre $ section est envoyé en tant que paramètre GET ( www.example.com/controllerName/index/display/3?paremeter1=example&section=www.example2.com).

Voici maintenant le problème si quelqu'un effectue quelque chose comme ceci:

www.example.com/controllerName/index/display/3?paremeter1=example&url=(SELECT 3630 FROM(SELECT COUNT(*),CONCAT(0x7170786a71,(SELECT (ELT(3630=3630,1))),0x717a716b71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)

De cette façon, l'utilisateur peut vider la base de données entière. Les données ne seront pas affichées, mais SQL effectuera toujours un vidage qui peut entraîner une surcharge sql.

Des questions:

  1. Quelle est la meilleure façon de prévenir un tel scénario?
  2. Maintenant, je suis inquiet pour les clients précédents. Est-il possible avec ce code de faire encore plus de risques, comme supprimer ou modifier une table? Je suppose que non parce que vous ne pouvez pas mettre d'autre instruction que SELECT dans la sous-sélection afin que DELETE produise une erreur de syntaxe sql. Ai-je raison?

MISE À JOUR: Mon exemple n'est pas une bonne illustration de l'injection SQL car il y a des sections «signe autour de $ et donc il ne sera pas possible de faire l'injection. Quoi qu'il en soit, cela serait possible lorsque vous attendez une valeur entière et lorsque vous ne filtrez pas l'entrée entière. Voir mon commentaire ci-dessous.

JohnyFree
la source
1
Vous pouvez utiliser: $db = Mage::getSingleton('core/resource')->getConnection('core_read');et $db->quote()même dans votre cas, regardez $db->quoteInto. Si $thisest une ressource, vous pouvez le faire: $this->getConnection('core_read')->quoteInto()si elle est une collection que vous pourriez faire: $this->getResource()->getConnection('core_read')->quoteInto(). le long de ces lignes. Si cela vous guide vers votre objectif.
ash
Je viens de réaliser que ce scénario n'est possible que si la valeur est un entier. Si la valeur est varchar, alors il y aura toujours 'signe avant (signe et donc (SELECTou quoi que ce soit d'autre sera juste une chaîne et ne fonctionnera pas. Lorsque le champ est entier, il 'n'est pas nécessaire et cela rend possible un tel scénario. Mais l'entier doit toujours être filtré avec intval()donc ce n'est pas non plus un problème.
JohnyFree
Et si vous commencez par fermer le '? Alors ' AND (SELECT ...) '? Soit dit en passant, je ne pense pas que Zend ne cite pas cela ... Et si vous utilisez des liaisons, PDO s'en occupera. "sections.section= '$section'"
N'utilisez
@ 7ochem dans ce cas, vous DEVEZ lier le paramètre en utilisant? et "deviendra \". Mais si vous utilisez une valeur entière, vous ne devez pas la lier car vous pouvez la nettoyer en utilisant la fonction php intval () et «quelque chose deviendra 0.
JohnyFree

Réponses:

8

Validez votre entrée!

Aussi bien et autant que possible.

Quelques suggestions pour votre validation:

  1. Vérifiez la longueur de la variable que vous obtenez via le paramètre GET. Il n'est pas nécessaire d'accepter une longue chaîne sans fin.

  2. Validez pour un nom de domaine. Quel type de format ont vos noms de domaine attendus? Est-ce toujours www.mydomain.tld? Créez une expression régulière qui vérifie une correspondance ou (mieux) une utilisation Zend_Validate_Hostname:

    $validator = new Zend_Validate_Hostname();
    if ($validator->isValid($hostname)) {
        //hostname is valid - continue
    }
  3. Liste blanche: savez-vous à quels noms de domaine s'attendre? Vous pouvez créer une liste de domaines autorisés et les comparer. Laissez tomber le reste.

    $allowedDomains = array('www.domain1.tld','www.domain2.tld');
  4. Liste noire des noms de domaine et / ou des caractères: Si vous attendez un nom de domaine, il n'est pas nécessaire d'accepter d'autres caractères que az et 0-9 et "." (sauf si vous travaillez avec des noms de domaine spéciaux).

Anna Völkl
la source