web-dev-qa-db-fra.com

Injections SQL utilisant Jfactory :: getDBO et setQuery ()

$db = JFactory::getDBO();
$searchP = JRequest::getVar('key');
$sql = "SELECT name FROM people LIKE " . "'%" . $searchP . "%'";

$db->setQuery($sql);
$fileR = $db->loadObjectList();

SetQuery () lève-t-il une erreur pour avoir deux instructions SQL dans la même chaîne?

Par exemple, selon mon code, est-il possible d'exécuter une commande drop table en transmettant ce paramètre de requête ou quelque chose de similaire:

key=a'; DROP TABLE people; # 

En outre, en utilisant quelque chose comme

$db = JFactory::getDBO();
$query = $db->getQuery(true); 
$query ->setLimit('1');
$query ->select($db->quoteName('name'));
$query ->from($db->quoteName('people'));
$query ->like($db->quoteName($searchP));
$db->setQuery($query);

empêcher l'injection puisque la limite de requête de l'objet de requête est définie sur 1?

5
Jay Shri

Vous n'aurez pas à vous soucier des attaques par injection SQL si vous utilisez les fonctions quote() (ou q()) et quoteName() (ou qn()) méthodes de manière appropriée.

De https://docs.joomla.org/Secure_coding_guidelines#Secure_on_search

Sécurisé pour la recherche

Une attention particulière doit être portée aux clauses LIKE qui contiennent le caractère générique%, car elles nécessitent une évasion spéciale afin d'éviter d'éventuelles attaques par déni de service. Les clauses LIKE peuvent être traitées comme ceci:

// Construit le terme de recherche en échappant à la chaîne fournie par l'utilisateur et, si nécessaire, en ajoutant manuellement les caractères génériques%.

$search = '%' . $db->escape( $search, true ) . '%' );

// Construit la requête SQL en veillant à supprimer le comportement par défaut de Quote afin d'éviter le double échappement.

$query = 'SELECT  * FROM #__table WHERE `field` LIKE ' . $db->quote( $search, false );

->like(), dans la mesure où j'ai effectué des recherches, n'existe pas. Donc, sur la base de la recommandation de documentation ci-dessus et en supposant que vous souhaitiez effectuer une recherche dans la colonne name, je vous suggère le bloc de code suivant:

$db = JFactory::getDBO();
$query = $db->getQuery(true)
            ->select($db->qn('name'))
            ->from($db->qn('people'))
            ->where($db->qn('name') . ' LIKE ' . $db->q('%' . $db->escape($searchP, true) . '%', false));
$db->setQuery($query);

Lors de l'exécution d'une requête LIKE, il est souvent logique de recevoir plusieurs lignes de données dans l'ensemble de résultats. Puisque je crois que vous utilisiez simplement la méthode setLimit() à titre de précaution de sécurité, je vais l'enlever afin d'améliorer les requêtes.


Malgré ce que commentaire de inf3rno indique, il n'y a pas de méthode bind() disponible selon la dernière documentation . (J'ai testé l'extrait de toute façon en utilisant à la fois :needle Et ? Comme espaces réservés et j'ai reçu: Erreur fatale: appel de la fonction membre bind () sur null) I J'aurais aimé que ce ne soit pas le cas, car avant d'entrer dans Joomla-land, j'utilisais des instructions préparées avec des espaces réservés pour TOUTES les données externes/non fiables alimentées par mes requêtes.

n article pertinent de Lodder de 2014 concernant les déclarations préparées dans Joomla.

L'intention/effet de la méthode quote (escape ()) dans le bloc de code ci-dessus est de garantir que, quelle que soit la chaîne transmise à la requête, cette chaîne est toujours traitée comme une valeur unique dans l'expression. Cela ressemble à l'équivalent de mysqli_real_escape() (mais je n'ai pas vérifié sous le capot Joomla). Malheureusement, de nombreux développeurs StackOverflow marquent mysqli_real_escape() comme non optimale et recommandent plutôt des instructions préparées avec des espaces réservés. Je mettrai à jour tous mes projets Joomla dès que la méthode bind() sera disponible.


J'ai exécuté le test suivant sur mon Joomla 3.8.6:

$needle = "key=a'; INSERT INTO [... redacted query that would be successful on its own ...]; #";
try {
    $db = JFactory::getDbo();
    $sql = "SELECT [redacted] FROM [redacted] WHERE [redacted] LIKE " . "'%" . $needle . "%'";
    $db->setQuery($sql);
    var_export($db->loadAssocList());
} catch (Exception $e) {
    echo $e->getMessage();
}

et reçu:

1064 Vous avez une erreur dans votre syntaxe SQL; Consultez le manuel correspondant à la version de votre serveur MySQL pour connaître la syntaxe à utiliser près de 'INSERT INTO.

Cela indique que la méthode setQuery() de Joomla s'étouffera avec plusieurs requêtes.

6
mickmackusa