WRInaute occasionnel
Bonjour,
La semaine dernière, l'un des sites que je gère a subi une injection SQL. Il y a environ 4-5 ans, je suis passé aux requêtes préparées (mysqli/pdo), mais il reste encore quelques codes qui contiennent parfois des $variable directement dans la commande query.
Du coup, j'ai corrigé le problème en passant ce code (oublié) en requête préparée et j'ai installé Modsecurity qui sert justement à filtrer les requêtes comme ça
Au début de cette semaine, j'ai reproduit toutes les failles d'injection, donc pour ce faire, j'ai imaginé une query comme celle-ci en php, elle est un peu arrangée pour qu'elle soit simple à comprendre :
Du coup, à la place de $test, j'ai testé cette liste :
Test 1 :
(ça retourne la liste des tables de la base de données. Ce genre de commande peut retourner la liste des tables, bases de données, les colonnes d'une table...)
Test 2 :
(ça retourne les noms des colonnes de la table accounts)
Test 3 :
(ça retourne le pseudo, le mot de passe, et le statut de confirmation)
Test 4 :
- Du code JavaScript ou PHP (<script>, <?php) injecté est impossible à générer, il y a des erreurs PHP.
Test 5 :
(avec OR id=1 il se connecte sur l'id 1 sans mot de passe)
Test 6 :
- Faire attention à LOAD_FILE() qui sert à afficher le contenu d'un fichier sur le serveur. Faire aussi attention à INTO OUTFILE qui permet d'écrire un fichier à partir d'une commande SQL. Chez moi, les deux ne fonctionnent pas, surtout avec l'utilisateur du compte
Test 7 :
- Les commandes qu'un hacker peut ajouter en préfixe sont : UNION, SELECT, OR, AND, ORDER, LIMIT, LOAD_FILE(), INTO OUTFILE ....
Les commandes les plus dangereuses d'un hack SQL, ce sont surtout celles du Test 3 et du Test 6
J'ai questionné ChatGPT pour savoir ce que ça générait comme code une fois que la commande est envoyée avec $_POST ($_POST est un exemple), les réponses :
1)
Query avec variable directement injectée (VULNÉRABLE)
Exemple de code:
On envoie :
?id=1 OR 1=1
Il génère directement :
2)
Query avec mysqli_real_escape_string (PARTIELLEMENT SÉCURISÉ)
Exemple:
On envoie :
' OR 1=1 --
Il génère :
3)
Requête préparée (SÉCURISÉ)
Exemple:
On envoie :
' OR 1=1 --
Il génère :
Pour sécuriser tout ça, j'ai dû désactiver display_errors dans php.ini, c'est une habitude que je dois prendre
Pour afficher les erreurs, il suffit ensuite d'ajouter ceci tout en haut de chaque fichier php en mode dev :
Il faut le mettre à 0 (désactivé) en prod.
Le désactiver est important, ça permet d'éviter d'aider les hackeurs qui lisent les erreurs.
J'ai aussi appris à utiliser Modsecurity qui permet de sécuriser les requêtes SQL injectables. Il était simple à mettre en oeuvre. Le plus difficile c'est qu'il est sévére au début, et il faut lui mettre des exceptions dont c'était pas facile à comprendre, mais ça va c'est pas plus difficile que de réparer une voiture.
En testant tout ça, ça m'a permis de comprendre comment fonctionnent les queries avec les GET, POST, etc., ce qui améliore mon expérience ainsi que ma compréhension du fonctionnement de SQL et des hacks par injection SQL sur de nombreux sites.
Pour ceux qui n'ont jamais testé ni reproduit les injections SQL et qui lisent ceci, j'espère que j'ai bien expliqué.
La semaine dernière, l'un des sites que je gère a subi une injection SQL. Il y a environ 4-5 ans, je suis passé aux requêtes préparées (mysqli/pdo), mais il reste encore quelques codes qui contiennent parfois des $variable directement dans la commande query.
Du coup, j'ai corrigé le problème en passant ce code (oublié) en requête préparée et j'ai installé Modsecurity qui sert justement à filtrer les requêtes comme ça
Au début de cette semaine, j'ai reproduit toutes les failles d'injection, donc pour ce faire, j'ai imaginé une query comme celle-ci en php, elle est un peu arrangée pour qu'elle soit simple à comprendre :
PHP:
query("SELECT username FROM accounts WHERE username = '$user' $test LIMIT 1");
Du coup, à la place de $test, j'ai testé cette liste :
Test 1 :
SQL:
UNION SELECT schema_name FROM information_schema.schemata
Test 2 :
SQL:
UNION SELECT column_name FROM information_schema.columns WHERE table_name = 'accounts');
Test 3 :
SQL:
UNION SELECT CONCAT(username, ' ', password, ' ', confirmation) FROM accounts
Test 4 :
- Du code JavaScript ou PHP (<script>, <?php) injecté est impossible à générer, il y a des erreurs PHP.
Test 5 :
SQL:
OR 1=1
SQL:
OR id=1
Test 6 :
- Faire attention à LOAD_FILE() qui sert à afficher le contenu d'un fichier sur le serveur. Faire aussi attention à INTO OUTFILE qui permet d'écrire un fichier à partir d'une commande SQL. Chez moi, les deux ne fonctionnent pas, surtout avec l'utilisateur du compte
Test 7 :
- Les commandes qu'un hacker peut ajouter en préfixe sont : UNION, SELECT, OR, AND, ORDER, LIMIT, LOAD_FILE(), INTO OUTFILE ....
Les commandes les plus dangereuses d'un hack SQL, ce sont surtout celles du Test 3 et du Test 6
J'ai questionné ChatGPT pour savoir ce que ça générait comme code une fois que la commande est envoyée avec $_POST ($_POST est un exemple), les réponses :
1)
Exemple de code:
PHP:
$id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $id";
$result = mysqli_query($conn, $query);
?id=1 OR 1=1
Il génère directement :
SQL:
SELECT * FROM users WHERE id = 1 OR 1=1
2)
Exemple:
PHP:
$user = mysqli_real_escape_string($conn, $_POST['user']);
$query = "SELECT * FROM users WHERE username = '$user'";
' OR 1=1 --
Il génère :
SQL:
SELECT * FROM users WHERE username = '\' OR 1=1 --'
3)
Exemple:
PHP:
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['user']);
$stmt->execute();
$result = $stmt->get_result();
' OR 1=1 --
Il génère :
SQL:
SELECT * FROM users WHERE username = "' OR 1=1 --"
Pour sécuriser tout ça, j'ai dû désactiver display_errors dans php.ini, c'est une habitude que je dois prendre
Code:
display_errors = Off
Pour afficher les erreurs, il suffit ensuite d'ajouter ceci tout en haut de chaque fichier php en mode dev :
Code:
ini_set('display_errors', 1);
Il faut le mettre à 0 (désactivé) en prod.
Le désactiver est important, ça permet d'éviter d'aider les hackeurs qui lisent les erreurs.
J'ai aussi appris à utiliser Modsecurity qui permet de sécuriser les requêtes SQL injectables. Il était simple à mettre en oeuvre. Le plus difficile c'est qu'il est sévére au début, et il faut lui mettre des exceptions dont c'était pas facile à comprendre, mais ça va c'est pas plus difficile que de réparer une voiture.
En testant tout ça, ça m'a permis de comprendre comment fonctionnent les queries avec les GET, POST, etc., ce qui améliore mon expérience ainsi que ma compréhension du fonctionnement de SQL et des hacks par injection SQL sur de nombreux sites.
Pour ceux qui n'ont jamais testé ni reproduit les injections SQL et qui lisent ceci, j'espère que j'ai bien expliqué.
Dernière édition: