SQL injection
SQL 注入
描述
SQL 注入是一种漏洞,攻击者将恶意的 SQL 查询注入到输入字段中,从而操纵应用程序 SQL 数据库的行为。通过利用此漏洞,攻击者可以获得对数据库的未经授权的访问,检索、修改或删除敏感数据,或在数据库上执行管理操作。SQL 注入通常是由于未对用户输入进行适当的净化而引起的,这允许攻击者绕过身份验证、执行任意 SQL 命令并利用底层数据库。
示例
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();
?>
建议
为防止 SQL 注入攻击,请考虑以下措施:
-
参数化查询:使用参数化查询或预处理语句来执行 SQL 查询。参数化允许将 SQL 代码与用户输入分开,从而防止注入攻击。
-
输入净化:在将用户输入用于 SQL 查询之前,对其进行验证和净化。通过仅允许预期的字符和格式来实施严格的输入验证。
-
最小特权原则:对数据库用户使用最小特权原则。分配最小的必要权限以限制成功的注入攻击的影响。
-
ORM 和库:利用动态处理 SQL 查询的对象关系映射 (ORM) 库或框架。这些框架通常提供针对注入攻击的内置保护。
示例
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();
?>
链接
标准
- 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