Như các nhận xét ở trên gợi ý, bạn nên sử dụng các tham số truy vấn để bảo vệ bản thân khỏi việc đưa vào SQL.
Bạn đã yêu cầu một ví dụ về cách bất cứ điều gì độc hại có thể được thực hiện. Trong thực tế, nó thậm chí không cần phải độc hại. Bất kỳ chuỗi vô tội nào chứa dấu nháy đơn hợp pháp có thể phá vỡ truy vấn SQL của bạn. Chèn SQL độc hại tận dụng điểm yếu đó.
Điểm yếu được khắc phục bằng cách giữ các giá trị động tách biệt khỏi truy vấn SQL của bạn cho đến sau khi truy vấn được phân tích cú pháp. Chúng tôi sử dụng trình giữ chỗ tham số truy vấn trong chuỗi SQL, sau đó sử dụng prepare()
để phân tích cú pháp và sau đó kết hợp các giá trị khi bạn execute()
truy vấn đã chuẩn bị. Bằng cách đó, nó vẫn an toàn.
Đây là cách tôi viết hàm của bạn. Tôi đang giả định sử dụng PDO hỗ trợ các tham số truy vấn được đặt tên. Tôi khuyên bạn nên sử dụng PDO thay vì Mysqli.
function updateProfile( $vars, $userId ) {
$db = new Database();
$safeArray = [
"gradYear",
"emailAddress",
"token",
"iosToken",
"country",
"birthYear",
"userDescription",
];
// Filter $vars to include only keys that exist in $safeArray.
$data = array_intersect_keys($vars, array_flip($safeArray));
// This might result in an empty array if none of the $vars keys were valid.
if (count($data) == 0) {
trigger_error("Error: no valid columns named in: ".print_r($vars, true));
$response = ["response" => 400, "title" => "no valid fields found"];
return $response;
}
// Build list of update assignments for SET clause using query parameters.
// Remember to use back-ticks around column names, in case one conflicts with an SQL reserved keyword.
$updateAssignments = array_map(function($column) { return "`$column` = :$column"; }, array_keys($data));
$updateString = implode(",", $updateAssignments);
// Add parameter for WHERE clause to $data.
// This must be added after $data is used to build the update assignments.
$data["userIdWhere"] = $userId;
$sqlStatement = "update users set $updateString where userId = :userIdWhere";
$stmt = $db->prepare($sqlStatement);
if ($stmt === false) {
$err = $db->errorInfo();
trigger_error("Error: {$err[2]} preparing SQL query: $sqlStatement");
$response = ["response" => 500, "title" => "database error, please report it to the site administrator"];
return $response;
}
$ok = $stmt->execute($data);
if ($ok === false) {
$err = $stmt->errorInfo();
trigger_error("Error: {$err[2]} executing SQL query: $sqlStatement");
$response = ["response" => 500, "title" => "database error, please report it to the site administrator"];
return $response;
}
$response = ["response" => 200, "title" => "update successful"];
return $response;
}