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