SQL injection
Injection SQL
Description
L'injection SQL est une vulnérabilité où des attaquants injectent des requêtes SQL malveillantes dans des champs de saisie, manipulant ainsi le comportement de la base de données SQL de l'application. En exploitant cette vulnérabilité, les attaquants peuvent obtenir un accès non autorisé à la base de données, récupérer, modifier ou supprimer des données sensibles, ou exécuter des opérations administratives sur la base de données. L'injection SQL survient généralement en raison d'une mauvaise sanitisation des entrées utilisateurs, permettant aux attaquants de contourner l'authentification, d'exécuter des commandes SQL arbitraires et d'exploiter la base de données sous-jacente.
Exemples
import java.sql.*;
public class SQLInjectionDemo {
public static void main(String[] args) {
try {
// Vulnerable Java code prone to SQL Injection
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/database", "username", "password");
Statement stmt = conn.createStatement();
// Vulnerable SQL query without sanitization
String username = args[0];
String password = args[1];
String sql = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'";
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
// User authenticated
} else {
// Invalid credentials
}
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
const mysql = require('mysql');
// Vulnerable Node.js code prone to SQL Injection
const connection = mysql.createConnection({
host: 'localhost',
user: 'username',
password: 'password',
database: 'database'
});
// Vulnerable SQL query without sanitization
const username = req.body.username;
const password = req.body.password;
const sql = `SELECT * FROM users WHERE username='${username}' AND password='${password}'`;
connection.query(sql, (error, results) => {
if (error) throw error;
if (results.length > 0) {
// User authenticated
} else {
// Invalid credentials
}
});
connection.end();
<?php
// Vulnerable PHP code prone to SQL Injection
$conn = new mysqli('localhost', 'username', 'password', 'database');
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Vulnerable SQL query without sanitization
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username='$username' AND password='$password'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// User authenticated
} else {
// Invalid credentials
}
$conn->close();
?>
Recommandation
Pour prévenir les attaques par injection SQL, considérez les mesures suivantes :
-
Requêtes Paramétrées : Utilisez des requêtes paramétrées ou des instructions préparées pour exécuter des requêtes SQL. La paramétrisation permet de séparer le code SQL des entrées utilisateurs, empêchant ainsi les attaques par injection.
-
Sanitisation des Entrées : Validez et sanitisez les entrées utilisateurs avant de les utiliser dans des requêtes SQL. Implémentez une validation stricte des entrées en n'autorisant que les caractères et formats attendus.
-
Principe du Moindre Privilège : Utilisez le principe du moindre privilège pour les utilisateurs de la base de données. Attribuez les permissions minimales nécessaires pour limiter l'impact d'attaques par injection réussies.
-
ORMs et Bibliothèques : Utilisez des bibliothèques de mapping objet-relationnel (ORM) ou des frameworks qui gèrent les requêtes SQL dynamiquement. Ces frameworks fournissent souvent des protections intégrées contre les attaques par injection.
Exemples
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ParametrizedQueryExample {
public static void main(String[] args) {
String username = "userInput"; // User input
String password = "userInput"; // User input
try (Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "username", "password")) {
String query = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement statement = connection.prepareStatement(query);
statement.setString(1, username);
statement.setString(2, password);
ResultSet resultSet = statement.executeQuery();
while (resultSet.next()) {
// Process the results
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
const mysql = require('mysql2/promise');
async function fetchUser(username, password) {
const connection = await mysql.createConnection({
host: 'localhost',
user: 'username',
password: 'password',
database: 'db'
});
const [rows] = await connection.execute('SELECT * FROM users WHERE username = ? AND password = ?', [username, password]);
connection.end();
return rows;
}
// Usage
fetchUser('userInput', 'userInput')
.then(rows => {
// Process the results
})
.catch(err => {
console.error(err);
});
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$db = new mysqli('localhost', 'username', 'password', 'dbname');
if ($stmt = $db->prepare("SELECT * FROM users WHERE username = ? AND password = ?")) {
$stmt->bind_param('ss', $username, $password);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// Process the results
}
$stmt->close();
}
$db->close();
?>
Liens
Normes
- CWE_TOP_25:
- CWE_89
- OWASP_ASVS_L1:
- V5_3_5
- OWASP_ASVS_L2:
- V5_3_5
- OWASP_ASVS_L3:
- V5_3_5
- PCI_STANDARDS:
- REQ_2_2
- REQ_3_5
- REQ_4_2
- REQ_6_2
- REQ_6_3
- REQ_6_4
- REQ_11_3
- SOC2_CONTROLS:
- CC_2_1
- CC_3_4
- CC_4_1
- CC_7_1
- CC_7_2
- CC_7_4
- CC_7_5
- HIPAA_CONTROLS:
- SECURITY212
- SECURITY213
- SECURITY255