
CVE-2024–27630 Reference
In Savane v3.12 and prior, a lack of validation on the file_id parameter when deleting a file from /bugs/index.php leads to an Insecure Direct Object Reference (IDOR) vulnerability that can cause an authenticated administrator of a group with a bug tracker to arbitrarily delete file attachments of any bug tracker, leading to a lack of availability of these files. Since the file IDs increment with each new upload, it is possible to create a script that iteratively deletes all file attachments on the server by file_id.
CWE Classification: CWE-639: Authorization Bypass Through User-Controlled Key
Reported By: Ally Petitt
Affected Product: Savane
Affected Versions: 3.12 and prior
The function responsible for deleting file attachments on bug trackers is trackers_data_delete_file(), which is defined in the code block below.
frontend/php/include/trackers/data.php:2417
function trackers_data_delete_file ($group_id, $item_id, $file_id)
{
global $sys_trackers_attachments_dir;
# Make sure the attachment belongs to the group.
$res = db_execute ("
SELECT bug_id from " . ARTIFACT . " WHERE bug_id = ? AND group_id = ?",
[$item_id, $group_id]
);
if (db_numrows ($res) <= 0)
{
# TRANSLATORS: the argument is item id (a number).
$msg = sprintf (
_("Item #%s doesn't belong to project"), $item_id
);
fb ($msg, 1);
return;
}
$result = false;
# Delete the attachment.
if (unlink ("$sys_trackers_attachments_dir/$file_id"))
$result = db_execute ("
DELETE FROM trackers_file WHERE item_id = ? AND file_id = ?",
[$item_id, $file_id]
);
The function begins with a SQL query to verify that the group that the bug ID specified in item_id is in the group that the attacker is a part of, known as the $group_id. The function fails to check whether the file_id is part of the group as well, meaning that as long as the item_id cooresponds to a valid bug in the attacker's group, the attacker can modify the file_id to point to any file within the upload directory /var/lib/savane/trackers_attachments.
Additionally, this function is only reachable for bug tracker admins.
frontend/php/bugs/index.php:586
case 'delete_file':
# Remove an attached file.
if ($is_trackeradmin)
{
trackers_data_delete_file($group_id, $item_id, $item_file_id);
# Unset previous settings and return to the item.
$depends_search = $reassign_change_project_search = $add_cc
= $input_file = $changed = $vfl = $details = null;
include '../include/trackers_run/mod.php';
}
else
exit_permission_denied ();
break;
These steps demonstrate deleting one file that is unauthorized, however, note that an attacker could automate the deletion of all files by their ID since they are predictable.
40231 was uploaded by the victim:root@60ae93fe131f:/var/lib/savane/trackers_attachments# ls
40226 40227 40230 40231
Visit the homepage of the group that the attacker is an admin of. Then, visit Bugs > Browse and note a valid Item ID on the leftmost column of the table. This ID will be used in the next step.
As the attacker, make a get request to the path /bugs/index.php?func=delete_file&item_id=<ATTACKER_ITEM_ID>&item_file_id=<FILE_ID_TO_DELETE>.
In my case, this looks like http://172.17.0.2:7890/bugs/index.php?func=delete_file&item_id=50697&item_file_id=40231.
Verify that the victim’s file (from a group the attacker doesn’t have privileges on) has been deleted. For example:
root@60ae93fe131f:/var/lib/savane/trackers_attachments# ls
40226 40227 40230
Upgrade to Savane version 3.13 or higher. The patch can be found here.