Synopsis
Snipe-IT is an open-source IT asset management application developed by Grokability, Inc. The endpoint that cancels asset checkout requests, POST /account/request/{itemType}/{itemId}/{cancel_by_admin?}/{requestingUser?}, trusts two user-controlled URL path parameters without performing a server-side authorization check. The cancel_by_admin segment is treated as a boolean, and because any non-empty value is truthy in PHP it bypasses the request-ownership check (isRequestedBy()) through a logical OR, while the requestingUser segment selects whose checkout request is canceled. As a result, any authenticated user can cancel any other user's pending checkout request without holding an administrative role. Asset and user identifiers are sequential integers, so an attacker can iterate over them to cancel every pending checkout request in the system, disrupting the asset-request workflow for all users. Snipe-IT does not permit self-registration, so exploitation requires a legitimate (or compromised) low-privileged account.
Solution
Upgrade to Snipe-IT v8.6.0 or later. In v8.6.0 the endpoint verifies that the authenticated user holds an administrative role before honoring the cancel_by_admin flag, and only an administrator may cancel another user's checkout request.
Proof of Concept
if (($item_request = $item->isRequestedBy($user)) || $cancel_by_admin) {
$item->cancelRequest($requestingUser);
After authenticating as any standard (non-admin) user and obtaining a valid CSRF token, the attacker cancels a specific victim's request by sending:
POST /account/request/asset/{assetId}/1/{victimUserId} HTTP/1.1
Host: <snipe-it-host>
Cookie: <attacker session cookie>
Content-Type: application/x-www-form-urlencoded
_token=<attacker CSRF token>
The 1 in the path sets cancel_by_admin to a truthy value, bypassing the ownership check, and {victimUserId} identifies whose request is canceled. An equivalent minimal request:
curl -b cookies.txt -X POST "http://TARGET:8000/account/request/asset/1/1/2" -d "_token=CSRF_TOKEN"
Because asset and user IDs are sequential, iterating over combinations (POST /account/request/asset/{1..N}/1/{1..M}) blindly cancels all pending checkout requests without prior knowledge of valid IDs. The endpoint returns HTTP 302 or HTTP 500 regardless of whether a matching request existed; the cancellation is committed to the database before the notification step, so the response code does not indicate success. Confirmation requires inspecting the database:
SELECT id, user_id, canceled_at FROM checkout_requests WHERE canceled_at IS NOT NULL;
Disclosure Timeline
All information within TRA advisories is provided “as is”, without warranty of any kind, including the implied warranties of merchantability and fitness for a particular purpose, and with no guarantee of completeness, accuracy, or timeliness. Individuals and organizations are responsible for assessing the impact of any actual or potential security vulnerability.
Tenable takes product security very seriously. If you believe you have found a vulnerability in one of our products, we ask that you please work with us to quickly resolve it in order to protect customers. Tenable believes in responding quickly to such reports, maintaining communication with researchers, and providing a solution in short order.
For more details on submitting vulnerability information, please see our Vulnerability Reporting Guidelines page.
If you have questions or corrections about this advisory, please email [email protected]
Tenable One
Request a demo
The world’s leading AI-powered exposure management platform.
Thank You
Thank you for your interest in Tenable One.
A representative will be in touch soon.
Form ID: 7469
Form Name: one-eval
Form Class: c-form form-panel__global-form c-form--mkto js-mkto-no-css js-form-hanging-label c-form--hide-comments
Form Wrapper ID: one-eval-form-wrapper
Confirmation Class: one-eval-confirmform-modal
Simulate Success