SQL Injection là gì? Cách Phòng Ch?ng T?n C?ng SQL Injection.
Nguy?n Th? Tùng
? Backend Developer at CGT Media | Let's Connect! | #WeCommit100xHabit ?
SQL Injection là m?t lo?i l? h?ng b?o m?t web x?y ra khi m?t k? t?n c?ng có th? chèn ho?c "tiêm" các l?nh SQL ??c h?i và o m?t truy v?n SQL h?p l?. ?i?u nà y có th? cho phép k? t?n c?ng th?c hi?n các hà nh ??ng kh?ng mong mu?n trên c? s? d? li?u c?a ?ng d?ng, ch?ng h?n nh? truy c?p d? li?u nh?y c?m, thay ??i ho?c xóa d? li?u, và th?m chà th?c hi?n các l?nh qu?n tr?.
VÃ d? 1 v? SQL Injection
Gi? s? b?n có m?t ?ng d?ng web v?i m?t form ??ng nh?p ??n gi?n. Ng??i dùng nh?p tên ng??i dùng và m?t kh?u, và ?ng d?ng th?c hi?n truy v?n SQL sau ?? xác th?c ng??i dùng:
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $sql);
N?u ng??i dùng nh?p ' OR '1'='1?và o tr??ng tên ng??i dùng và b?t k? th? gì và o tr??ng m?t kh?u, truy v?n SQL s? tr? thà nh:
SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '';
Ph?n ' OR '1'='1' lu?n lu?n ?úng, vì v?y truy v?n s? tr? v? t?t c? các hà ng trong b?ng users, cho phép k? t?n c?ng ??ng nh?p mà kh?ng c?n bi?t m?t kh?u th?c s?.
VÃ d? 2 v? SQL Injection
M?t cau query nh? sau:
$name = "Nguyen The Tung'; DELETE FROM SINHVIEN; -- ";
mysql_query("SELECT * FROM CUSTOMERS WHERE name='{$name}' ");
Phan tÃch l?nh SQL ???c ta:
Khi giá tr? c?a $name là "Nguyen The Tung'; DELETE FROM SINHVIEN; -- ", truy v?n SQL s? tr? thà nh:
SELECT * FROM CUSTOMERS WHERE name='Tung'; DELETE FROM SINHVIEN; -- ';
?o?n m? trên s? ???c phan tÃch nh? sau:
- SELECT * FROM CUSTOMERS WHERE name='Nguyen The Tung': Tìm t?t c? các hà ng trong b?ng CUSTOMERS có c?t name là 'Nguyen The Tung'.
- DELETE FROM SINHVIEN: Xóa t?t c? các hà ng trong b?ng SINHVIEN.
- -- ': B? qua ph?n còn l?i c?a cau l?nh SQL.
Cách ng?n ng?a
Cách ng?n ng?a SQL Injection ? và d? 1:
- S? d?ng Prepared Statements (Cau l?nh chu?n b? s?n)
Prepared Statements tách bi?t d? li?u ??u và o c?a ng??i dùng kh?i m? SQL, giúp ng?n ng?a SQL Injection.
Ly do Prepared Statements ng?n ng?a SQL Injection
- Tách bi?t m? SQL và d? li?u ??u và o: Khi b?n s? d?ng Prepared Statements, b?n ?ang tách bi?t ph?n c?u trúc c?a cau l?nh SQL kh?i d? li?u ??u và o. ?i?u nà y có ngh?a là các d? li?u ??u và o s? kh?ng bao gi? ???c coi là m?t ph?n c?a m? SQL.
- X? ly d? li?u ??u và o an toà n: PDO s? t? ??ng thoát (escape) các ky t? ??c bi?t trong d? li?u ??u và o. ?i?u nà y ng?n ch?n vi?c chèn các ?o?n m? ??c h?i và o cau l?nh SQL.
- C? ??nh c?u trúc cau l?nh SQL: Cau l?nh SQL ???c xác ??nh tr??c (prepared) và kh?ng thay ??i d?a trên d? li?u ??u và o. Do ?ó, kh?ng có cách nà o ?? d? li?u ??u và o thay ??i m?c ?Ãch c?a cau l?nh SQL ban ??u.
VÃ d? v?i MySQLi:
$stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->bind_param("ss", $username, $password);
$stmt->execute();
$result = $stmt->get_result();
VÃ d? v?i PDO:
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username AND password = :password");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);
$stmt->execute();
$result = $stmt->fetch();
- S? d?ng ORM (Object-Relational Mapping)
S? d?ng ORM nh? Eloquent (Laravel) ho?c Doctrine (Symfony) ?? t? ??ng hóa vi?c t?o các truy v?n an toà n.
VÃ d? v?i Eloquent (Laravel):
$user = User::where('username', $username)->where('password', $password)->first();
3. Escaping ??u và o ng??i dùng
S? d?ng các hà m thoát ky t? (escaping functions) ?? x? ly d? li?u ??u và o c?a ng??i dùng.
VÃ d? v?i MySQLi:
$username = mysqli_real_escape_string($conn, $_POST['username']);
$password = mysqli_real_escape_string($conn, $_POST['password']);
VÃ d? v?i PDO:
PDO t? ??ng thoát ky t? khi s? d?ng prepared statements.
- S? d?ng các th? vi?n b?o m?t
S? d?ng các th? vi?n ho?c framework ?? ???c ch?ng minh là an toà n ?? x? ly các truy v?n SQL.
B?ng cách s? d?ng các bi?n pháp trên, b?n có th? gi?m thi?u nguy c? SQL Injection và b?o v? c? s? d? li?u c?a mình kh?i các t?n c?ng .
Cách ng?n ng?a SQL Injection ? và d? 2:
?? ng?n ng?a SQL Injection, b?n nên s? d?ng Prepared Statements ho?c các th? vi?n cung c?p các hà m an toà n ?? th?c thi các truy v?n SQL. D??i ?ay là cách là m ?i?u ?ó.
S? d?ng MySQLi v?i Prepared Statements
// K?t n?i ??n c? s? d? li?u
$conn = new mysqli($servername, $username, $password, $dbname);
// Ki?m tra k?t n?i
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Chu?n b? cau l?nh
$stmt = $conn->prepare("SELECT * FROM CUSTOMERS WHERE name = ?");
$stmt->bind_param("s", $name);
// Th?c thi cau l?nh
$stmt->execute();
// L?y k?t qu?
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['name'];
}
// ?óng cau l?nh và k?t n?i
$stmt->close();
$conn->close();
S? d?ng PDO v?i Prepared Statements
// K?t n?i ??n c? s? d? li?u
try {
$pdo = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Chu?n b? cau l?nh
$stmt = $pdo->prepare("SELECT * FROM CUSTOMERS WHERE name = :name");
$stmt->bindParam(':name', $name);
// Th?c thi cau l?nh
$stmt->execute();
// L?y k?t qu?
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row['name'];
}
} catch(PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
// ?óng k?t n?i
$pdo = null;
Vi?c s? d?ng Prepared Statements giúp ng?n ch?n SQL Injection b?ng cách ??m b?o r?ng d? li?u ??u và o c?a ng??i dùng ???c x? ly ?úng cách và kh?ng th? th?c thi nh? m?t ph?n c?a cau l?nh SQL. ?i?u nà y giúp b?o v? ?ng d?ng c?a b?n kh?i các cu?c t?n c?ng tiêm nhi?m SQL và b?o v? c? s? d? li?u c?a b?n kh?i b? truy c?p ho?c thay ??i trái phép.
Data Engineering | Database Optimization | Data/Risk Analyst in Finance | Expert in MicrosoftExcel
10 个月bà i vi?t tam huy?t quá, c?m ?n anh r?t nhi?u vì ?? chia s?