fix(security): remove JWT role extraction without signature, add OTP replay protection, fix user enumeration
This commit is contained in:
@@ -54,14 +54,12 @@ if ($count > 0) {
|
|||||||
]);
|
]);
|
||||||
// jsonError("Incorrect password.");
|
// jsonError("Incorrect password.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The user does not exist
|
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
"status" => "Failure",
|
"status" => "Failure",
|
||||||
"data" => "User does not exist."
|
"data" => "Invalid credentials."
|
||||||
]);
|
]);
|
||||||
// jsonError("User does not exist.");
|
}
|
||||||
}
|
$con = null;
|
||||||
$conn->close();
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -18,17 +18,7 @@ if (empty($receiver)) {
|
|||||||
|
|
||||||
$user_type = filterRequest("user_type");
|
$user_type = filterRequest("user_type");
|
||||||
|
|
||||||
$authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? (function_exists('apache_request_headers') ? (apache_request_headers()['Authorization'] ?? null) : null);
|
// user_type is taken from request only (JWT not trusted without signature verification)
|
||||||
if (!empty($authHeader) && preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
|
|
||||||
$jwtToken = $matches[1];
|
|
||||||
$tokenParts = explode('.', $jwtToken);
|
|
||||||
if (count($tokenParts) === 3) {
|
|
||||||
$payload = json_decode(base64_decode($tokenParts[1]), true);
|
|
||||||
if (isset($payload['role'])) {
|
|
||||||
$user_type = $payload['role'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$country = filterRequest("country"); // Egypt | Syria | Jordan
|
$country = filterRequest("country"); // Egypt | Syria | Jordan
|
||||||
$method = filterRequest("method"); // whatsapp | sms | voice | flash_call | bearer_send
|
$method = filterRequest("method"); // whatsapp | sms | voice | flash_call | bearer_send
|
||||||
|
|||||||
@@ -23,17 +23,7 @@ if (empty($token_code)) {
|
|||||||
$user_type = filterRequest("user_type");
|
$user_type = filterRequest("user_type");
|
||||||
$context = filterRequest("context"); // token_change | login (default)
|
$context = filterRequest("context"); // token_change | login (default)
|
||||||
|
|
||||||
$authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? (function_exists('apache_request_headers') ? (apache_request_headers()['Authorization'] ?? null) : null);
|
// user_type is taken from request only (JWT not trusted without signature verification)
|
||||||
if (!empty($authHeader) && preg_match('/Bearer\s(\S+)/', $authHeader, $matches)) {
|
|
||||||
$jwtToken = $matches[1];
|
|
||||||
$tokenParts = explode('.', $jwtToken);
|
|
||||||
if (count($tokenParts) === 3) {
|
|
||||||
$payload = json_decode(base64_decode($tokenParts[1]), true);
|
|
||||||
if (isset($payload['role'])) {
|
|
||||||
$user_type = $payload['role'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($phone_number)) {
|
if (empty($phone_number)) {
|
||||||
jsonError("Phone number is required.");
|
jsonError("Phone number is required.");
|
||||||
@@ -75,7 +65,7 @@ try {
|
|||||||
if ($user_type === 'admin') {
|
if ($user_type === 'admin') {
|
||||||
$sql = "SELECT * FROM token_verification_admin
|
$sql = "SELECT * FROM token_verification_admin
|
||||||
WHERE phone_number = :phone AND token = :token
|
WHERE phone_number = :phone AND token = :token
|
||||||
AND expiration_time >= NOW()";
|
AND expiration_time >= NOW() AND verified = 0";
|
||||||
$stmt = $con->prepare($sql);
|
$stmt = $con->prepare($sql);
|
||||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||||
$stmt->bindParam(':token', $encryptedToken, PDO::PARAM_STR);
|
$stmt->bindParam(':token', $encryptedToken, PDO::PARAM_STR);
|
||||||
@@ -103,7 +93,7 @@ try {
|
|||||||
} elseif ($user_type === 'service') {
|
} elseif ($user_type === 'service') {
|
||||||
$sql = "SELECT `id` FROM `phone_verification_service`
|
$sql = "SELECT `id` FROM `phone_verification_service`
|
||||||
WHERE `phone_number` = :phone AND `token_code` = :token
|
WHERE `phone_number` = :phone AND `token_code` = :token
|
||||||
AND `expiration_time` > NOW()";
|
AND `expiration_time` > NOW() AND `is_verified` = 0";
|
||||||
$stmt = $con->prepare($sql);
|
$stmt = $con->prepare($sql);
|
||||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||||
$stmt->bindParam(':token', $encryptedToken, PDO::PARAM_STR);
|
$stmt->bindParam(':token', $encryptedToken, PDO::PARAM_STR);
|
||||||
@@ -124,7 +114,7 @@ try {
|
|||||||
$sql = "SELECT `id` FROM `token_verification_driver`
|
$sql = "SELECT `id` FROM `token_verification_driver`
|
||||||
WHERE `phone_number` = :phone
|
WHERE `phone_number` = :phone
|
||||||
AND `token` = :token
|
AND `token` = :token
|
||||||
AND `expiration_time` > NOW()";
|
AND `expiration_time` > NOW() AND `verified` = 0";
|
||||||
|
|
||||||
$stmt = $con->prepare($sql);
|
$stmt = $con->prepare($sql);
|
||||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||||
@@ -147,7 +137,7 @@ try {
|
|||||||
$sql = "SELECT `id` FROM `phone_verification`
|
$sql = "SELECT `id` FROM `phone_verification`
|
||||||
WHERE `phone_number` = :phone
|
WHERE `phone_number` = :phone
|
||||||
AND `token_code` = :token
|
AND `token_code` = :token
|
||||||
AND `expiration_time` > NOW()";
|
AND `expiration_time` > NOW() AND `is_verified` = 0";
|
||||||
|
|
||||||
$stmt = $con->prepare($sql);
|
$stmt = $con->prepare($sql);
|
||||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||||
@@ -172,7 +162,7 @@ try {
|
|||||||
$sql = "SELECT `id` FROM `token_verification`
|
$sql = "SELECT `id` FROM `token_verification`
|
||||||
WHERE `phone_number` = :phone
|
WHERE `phone_number` = :phone
|
||||||
AND `token` = :token
|
AND `token` = :token
|
||||||
AND `expiration_time` > NOW()";
|
AND `expiration_time` > NOW() AND `verified` = 0";
|
||||||
|
|
||||||
$stmt = $con->prepare($sql);
|
$stmt = $con->prepare($sql);
|
||||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||||
@@ -195,7 +185,7 @@ try {
|
|||||||
$sql = "SELECT `id` FROM `phone_verification_passenger`
|
$sql = "SELECT `id` FROM `phone_verification_passenger`
|
||||||
WHERE `phone_number` = :phone
|
WHERE `phone_number` = :phone
|
||||||
AND `token` = :token
|
AND `token` = :token
|
||||||
AND `expiration_time` > NOW()";
|
AND `expiration_time` > NOW() AND `verified` = 0";
|
||||||
|
|
||||||
$stmt = $con->prepare($sql);
|
$stmt = $con->prepare($sql);
|
||||||
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
$stmt->bindParam(':phone', $encryptedPhone, PDO::PARAM_STR);
|
||||||
|
|||||||
Reference in New Issue
Block a user