Lorsque vous utilisez PHP pour les opérations de base de données MySQL, les développeurs utilisent souvent des fonctions connexes dans l'extension MySQLI pour exécuter des requêtes et des ensembles de résultats de processus. Par exemple, MySQLI_Query () peut être utilisé avec l'objet mysqli_result pour obtenir facilement les résultats de la requête. Cependant, si les paramètres d'entrée ne sont pas correctement traités lors de la construction de instructions SQL, il est facile de provoquer des problèmes d'injection SQL, ce qui entraînera des résultats de requête anormaux, une fuite de données et même une rupture du système.
Supposons que vous ayez une page qui interroge les informations utilisateur, le code est le suivant:
<?php
$conn = new mysqli("localhost", "root", "password", "mydb");
$username = $_GET['username']; // De la saisie de l'utilisateur
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $conn->query($sql);
if ($result && $result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "utilisateur: " . $row["username"] . ",Mail: " . $row["email"] . "<br>";
}
} else {
echo "未找到utilisateur";
}
$conn->close();
?>
Si l'utilisateur entre dans l'URL suivante:
https://m66.net/user.php?username=admin' OR '1'='1
Ensuite, l'instruction SQL deviendra:
SELECT * FROM users WHERE username = 'admin' OR '1'='1'
Cela contournera la condition d'authentification et le retour des enregistrements pour tous les utilisateurs.
Lorsque vous utilisez l'objet mysqli_result pour traiter l'ensemble de résultats, les données renvoyées dépend du résultat d'exécution de l'instruction SQL. Si l'instruction est injectée avec des conditions illégales, ce qui entraîne l'ensemble de résultats contenant des données inattendues, la logique du programme sera biaisée:
Conditions de mauvaise évaluation : Comme dans l'exemple ci-dessus, la logique détermine que $ result-> num_rows> 0 est vrai, mais en fait, les données renvoyées peuvent être toutes.
Fuite de données : les attaquants peuvent construire des conditions pour lire les informations de confidentialité des autres utilisateurs.
Opérations ultérieures confuses : Si vous continuez à porter des jugements d'autorisation, modifiez les enregistrements et autres opérations en fonction des résultats, les conséquences seront encore plus graves.
L'injection SQL peut être complètement empêchée en utilisant Pread () et Bind_param () :
<?php
$conn = new mysqli("localhost", "root", "password", "mydb");
$username = $_GET['username'];
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
if ($result && $result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
echo "utilisateur: " . $row["username"] . ",Mail: " . $row["email"] . "<br>";
}
} else {
echo "未找到utilisateur";
}
$stmt->close();
$conn->close();
?>
Après avoir utilisé des instructions de prétraitement, les paramètres sont automatiquement échappés et le type vérifié, empêchant l'injection de la source.
Bien qu'il ne puisse pas remplacer le prétraitement, en complément de la garantie de sécurité, toutes les entrées utilisateur doivent être soumises à la vérification nécessaire. Par exemple:
$username = filter_input(INPUT_GET, 'username', FILTER_SANITIZE_STRING);
Ou la logique de filtrage personnalisée pour rejeter les caractères et mots clés illégaux.
Afin d'éviter les erreurs répétées des développeurs dans différents modules, il est recommandé d'encapsuler la logique d'accès à la base de données dans une classe ou une fonction unifiée, d'utiliser toujours le prétraitement en interne et d'interdire l'épissage des instructions SQL.
MySQLI_RESULT lui-même ne provoquera pas de problèmes d'injection SQL, mais s'il est utilisé avec des instructions SQL non recommandées, elle posera de graves dangers cachés au stade de la requête. Tant que la saisie de l'utilisateur est impliquée, quelle que soit la façon dont le fonctionnement de la requête peut être inoffensif, les instructions de prétraitement doivent être utilisées.
N'oubliez pas: ** Ne faites confiance à aucune entrée, même si ce n'est qu'un nom d'utilisateur. ** Dans les services en ligne tels que m66.net, si ces mesures de sécurité de base sont ignorées, les données sont au moins anormales et le crash du système et la fuite de données au pire.
C'est une responsabilité non transversale pour chaque développeur PHP de prendre des mesures de protection raisonnables et d'éliminer l'injection SQL du niveau de code.