Trouver des vulnérabilités par SQL injection dans les Bug Bounty

Les vulnérabilités par injection SQL sont l’une des principales menaces de sécurité pour les applications web. Les attaquants utilisent des entrées utilisateur malveillantes pour exécuter des instructions SQL non autorisées et accéder à des informations sensibles ou même prendre le contrôle du système. Les vulnérabilités par injection SQL se produisent lorsque les développeurs n’utilisent pas de paramètres de requête sécurisés et concatènent directement les entrées utilisateur dans les requêtes SQL. Les conséquences d’une injection SQL réussie peuvent être graves, notamment la perte de données, la violation de la confidentialité et l’altération du système. Il est donc important de prendre des mesures de sécurité pour prévenir les vulnérabilités par injection SQL, telles que l’utilisation de paramètres de requête sécurisés, les instructions préparées et la validation des entrées utilisateur.

Comment vérifier un logiciel pour une faille SQL injection

1. Choisir le paramètre à vérifier

🔹 paramètres dans le URL
🔹 contenu POST
🔹 HTTP Headers
🔹 Cookies

Cela peut être n’importe lequel paramètre. Commençons par les paramètres de type entier

2. Si le paramètre est entier, un calcul sera fait

🔹 user_id=1338-1

Si vous êtes chanceux et que l’injection SQL a fonctionné, vous verrez le résultat user_id=1337

3. Essayez d’ajouter des symboles à la fin du paramètre

🔹 ‘ (guillement simple)
🔹 ” (guillement)
🔹 ; (point-virgule)

Observer la réponse. S’il y a un erreur, il y a probablement possibilité d’injection SQL

4. Essayez d’ajouter un autre symbole pour voir si l’erreur disparaît

🔹 login=admin (status: 200)
🔹 login=admin’ (status: 500)
🔹 login=admin” (status: 200)

En SQL, la séquence d’échappement pour un guillement simple est un deuxième guillement simple. Pour un guillement, c’est un deuxième guillement.

Essayer des fonctions SQL

Int
🔹 user_id=1337 AND 1=1 (status: 200)
🔹 user_id=1337 AND 2=1 (status: 500)

Text
🔹 login=admin’ AND ‘A’=’A (status: 200)
🔹 login=admin’ AND ‘A’=’B (status: 500)

JSON int
🔹{“user_id”:”1337 AND 1=1″} (status: 200)

Essayer de combiner des commentaires SQL avec des fonctions SQL

Int
🔹user_id=1337 AND 1=1 — (status: 200)

Text
🔹login=admin’ AND ‘A’=’A’ — (status: 200)

JSON int
🔹{“user_id”:”1337 AND 1=1 –“} (status: 200)

JSON text
🔹{“login”:”admin’ AND ‘A’=’A’ –“} (status: 200)

Utilisez ces logiciels pour une découverte automatisée des SQL Injection

🔹 sqlmap
🔹 r0oth3x49/ghauri (github)

Rappelez-vous que vous ne devriez extraire aucune information confidentielle. Essayer d’obtenir la version de la base de données comme preuve. Vous devez obtenir l’autorisation de l’entreprise pour continuer si vous souhaitez pousser plus loin.

Vous pouvez utiliser ce DB fiddle pour tester différentes requêtes SQL et le comportement.

Éditer la requête SQL à droite et cliquez RUN pour voir la façon dont celle-ci est exécutée et obtenir le résultat en bas.

https://www.db-fiddle.com/f/mZ2ftcLLzZLbrEELn38hjQ/0

Se protéger contre les attaques SQL en Python

import mysql.connector
from mysql.connector import Error

def get_user(username):
    try:
        connection = mysql.connector.connect(host='localhost',
                                             database='users',
                                             user='user',
                                             password='password')

        cursor = connection.cursor(prepared=True)

        sql_query = """SELECT * FROM user WHERE username = %s"""

        cursor.execute(sql_query, (username,))

        result = cursor.fetchone()

        return result

    except Error as e:
        print(f"Error while connecting to MySQL: {e}")
    finally:
        if (connection.is_connected()):
            cursor.close()
            connection.close()
            print("MySQL connection is closed")

Dans cet exemple, nous utilisons un paramètre de requête sécurisé, %s, pour la requête SQL, au lieu de concaténer directement la valeur d’entrée de l’utilisateur dans la requête. Cela empêche les attaquants d’injecter des instructions SQL malveillantes dans la requête.

Nous utilisons également la méthode prepared=True du curseur pour activer les instructions préparées, qui pré-compilent la requête SQL et la lient au paramètre de requête sécurisé. Cela améliore les performances et offre une sécurité supplémentaire.

Enfin, nous utilisons un bloc try-except-finally pour gérer les exceptions et fermer correctement la connexion à la base de données, même en cas d’erreur.

Protéger son code PHP contre les SQL injection

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Création de la connexion
$conn = new mysqli($servername, $username, $password, $dbname);

// Vérification de la connexion
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

// Utilisation de la requête préparée pour éviter l'injection SQL
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $username);

// Assignation de la variable $username à une valeur d'entrée utilisateur
$username = $_POST['username'];

// Exécution de la requête
$stmt->execute();
$result = $stmt->get_result();

// Traitement des résultats
while ($row = $result->fetch_assoc()) {
  echo "Username: " . $row["username"] . "<br>";
}

// Fermeture de la connexion
$stmt->close();
$conn->close();
?>

Dans cet exemple, nous utilisons des requêtes préparées pour éviter l’injection SQL. La requête préparée utilise un marqueur de paramètre, “?” dans la requête SQL, qui est lié à une variable de paramètre en utilisant la méthode bind_param(). Cela permet de séparer clairement les requêtes SQL des données utilisateur et de garantir que les données sont traitées en toute sécurité.

Ensuite, nous récupérons la valeur de l’entrée utilisateur, $username, à partir de la variable $_POST['username'], qui contient les données soumises par l’utilisateur via un formulaire. Ensuite, nous exécutons la requête préparée en appelant la méthode execute() sur l’objet $stmt.

Enfin, nous traitons les résultats et fermons la connexion à la base de données en utilisant les méthodes fetch_assoc(), close(), et close(), respectivement. En utilisant des requêtes préparées, nous pouvons empêcher efficacement les attaques par injection SQL et garantir que les données de l’utilisateur sont traitées en toute sécurité.

Autres ressources

Attaques avec SQLmap

Leave a Reply