User Controlled Primary Key
ID |
php.user_controlled_primary_key |
Severity |
high |
Resource |
Misconfiguration |
Language |
Php |
Tags |
CWE:566, NIST.SP.800-53, PCI-DSS:6.5.6 |
Description
This vulnerability arises when an application uses user-supplied input to control primary key values for database queries or operations, which may lead to unauthorized data access or modification.
Rationale
When user input is directly used to build database queries, including primary keys, it can result in unauthorized access or manipulation of protected data.
This problem is particularly dangerous when primary keys are integers or predictable values, as it enables users to perform unintended actions like accessing records that belong to other users, potentially exposing or corrupting sensitive information.
For example, consider this PHP code snippet:
<?php
// Capture and sanitize input
$userId = $_POST['user_id'];
$newFirstName = $_POST['first_name'];
// Connect to the database using PDO
$dbConnection = new PDO("mysql:host=$serverName;dbname=$databaseName", $dbUsername, $dbPassword);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Prepare SQL statement and bind parameters securely
$pdoStatement = $dbConnection->prepare("UPDATE Users SET first_name = :first_name WHERE user_id = :user_id");
$pdoStatement->bindParam(':user_id', $userId, PDO::PARAM_INT);
$pdoStatement->bindParam(':first_name', $newFirstName, PDO::PARAM_STR);
// Execute the statement
$pdoStatement->execute();
// Connect to the database using MySQLi
$mysqliConnection = mysqli_connect("example.com", "username", "userpassword", "databasename");
// Prepare SQL statement and bind parameters securely
$mysqliStatement = mysqli_prepare($mysqliConnection, "UPDATE Users SET first_name = ? WHERE user_id = ?");
mysqli_stmt_bind_param($mysqliStatement, "si", $newFirstName, $userId);
// Execute the statement
if (mysqli_stmt_execute($mysqliStatement)) {
// Handle success
} else {
// Handle error
}
// Close connections if necessary
mysqli_stmt_close($mysqliStatement);
mysqli_close($mysqliConnection);
?>
In this example, the userId
parameter is user controlled, which may allow a user to access data of any user simply by changing the userId
value.
Remediation
To mitigate the risks of CWE-566, it’s essential to avoid constructing database queries using user-supplied input directly or allow user input to control database primary key values. Best practices include:
If the SQL query is constructed without relying on user-controlled input, such as through the use of parameterized SQL, attackers cannot access unauthorized records.
Configuration
The detector has the following configurable parameters:
-
sources
, that indicates the source kinds to check. -
neutralizations
, that indicates the neutralization kinds to check.
Unless you need to change the default behavior, you typically do not need to configure this detector.
References
-
CWE-566 : Authorization Bypass Through User-Controlled SQL Primary Key.