CVE-2026-6663

GWD Connect <= 2.9 - Unauthenticated Limited Code Execution via update_agent

mediumMissing Authorization
4.8
CVSS Score
4.8
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The GWD Connect plugin for WordPress is vulnerable to missing authorization to limited code execution in all versions up to, and including, 2.9. This is due to the plugin's standalone agent endpoints (gwd-backup.php and gwd-logs.php) not verifying authentication when the API key has not been configured, which is the default state. This makes it possible for unauthenticated attackers - on unregistered installations only, in certain environments - to execute arbitrary code on the server via the update_agent action, which writes attacker-supplied PHP code to the agent file.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.9
PublishedMay 11, 2026
Last updatedMay 12, 2026
Affected plugingraphic-web-design-inc
Research Plan
Unverified

This research plan targets **CVE-2026-6663**, a missing authorization vulnerability in the **GWD Connect** plugin. The vulnerability allows unauthenticated attackers to overwrite plugin files with arbitrary PHP code when the plugin is in its default, unconfigured state. --- ### 1. Vulnerability Su…

Show full research plan

This research plan targets CVE-2026-6663, a missing authorization vulnerability in the GWD Connect plugin. The vulnerability allows unauthenticated attackers to overwrite plugin files with arbitrary PHP code when the plugin is in its default, unconfigured state.


1. Vulnerability Summary

The GWD Connect plugin includes standalone PHP files (gwd-backup.php and gwd-logs.php) designed to act as "agents" for remote management. These files are intended to be secured by an API key. However, in versions up to 2.9, the logic fails to verify authentication if the API key has not yet been configured in the WordPress database (the default state). An attacker can invoke the update_agent action to overwrite the agent file itself with malicious PHP code, leading to Remote Code Execution (RCE).

2. Attack Vector Analysis

  • Endpoints:
    • /wp-content/plugins/graphic-web-design-inc/gwd-backup.php
    • /wp-content/plugins/graphic-web-design-inc/gwd-logs.php
  • Vulnerable Action: update_agent
  • Parameters:
    • action: Must be set to update_agent.
    • key: The API key (vulnerable when empty or omitted if the plugin is unconfigured).
    • code (inferred): The parameter containing the PHP code to be written to the file.
  • Preconditions: The plugin must be installed, but the "GWD API Key" must not be set in the plugin settings.
  • Authentication: None required (Unauthenticated).

3. Code Flow (Inferred from Description)

  1. Entry Point: A direct request is made to gwd-backup.php. Because this is a standalone file, it likely does not load the full WordPress environment (wp-load.php) immediately, or it loads it after its own auth checks.
  2. Auth Bypass: The script checks the provided key parameter against a stored option (e.g., get_option('gwd_api_key')). If the option is empty/false and the provided key is empty/false, the check passes.
  3. Action Dispatch: The script checks $_REQUEST['action']. If it matches update_agent, it proceeds to the update logic.
  4. The Sink: The script takes the content of a POST parameter (likely code or content) and writes it to the filesystem using file_put_contents(__FILE__, ...) or a similar file-system function, effectively overwriting itself.

4. Nonce Acquisition Strategy

According to the vulnerability description, these are standalone agent endpoints. These typically do not use WordPress nonces because they are designed to be accessed by external services using an API key.

  • Is a Nonce Required? No. The authentication relies solely on the API key.
  • Bypass: If the API key is not configured, the comparison if ($_POST['key'] == $stored_key) becomes if ("" == ""), which evaluates to true.

5. Exploitation Strategy

The goal is to overwrite gwd-backup.php with a simple PHP backdoor.

Step 1: Environment Check
Confirm the file is accessible and the API key is unconfigured.

  • Request: GET /wp-content/plugins/graphic-web-design-inc/gwd-backup.php
  • Expected: A 200 OK or a specific plugin-defined error message (e.g., "Invalid Key"), but not a 403 Forbidden.

Step 2: Execute Overwrite
Use the http_request tool to send a POST request containing the payload.

  • Method: POST
  • URL: http://vulnerable-site.tld/wp-content/plugins/graphic-web-design-inc/gwd-backup.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Payload:
    action=update_agent&key=&code=<?php echo "VULN_VERIFIED"; phpinfo(); ?>
    
    (Note: The parameter name code is inferred; if this fails, try content, agent, or data).

Step 3: Trigger Payload
Access the file again to execute the injected code.

  • Request: GET /wp-content/plugins/graphic-web-design-inc/gwd-backup.php
  • Expected Response: "VULN_VERIFIED" followed by the PHP info page.

6. Test Data Setup

  1. Install Plugin: Install "GWD Connect" version 2.9 or lower.
  2. Ensure Unconfigured State:
    • Navigate to the plugin settings in the WP Admin.
    • Ensure the API Key field is blank.
    • If a key exists, use WP-CLI to clear it: wp option delete gwd_api_key (inferred option name).

7. Expected Results

  • Success: The HTTP response from the second visit to gwd-backup.php contains the string "VULN_VERIFIED".
  • Failure: The response remains unchanged, or the server returns a 403/500 error indicating the file write failed due to permissions or the action name was incorrect.

8. Verification Steps

After the exploit, verify the filesystem state using WP-CLI:

# Check if the file content has been modified
cat /var/www/html/wp-content/plugins/graphic-web-design-inc/gwd-backup.php

The output should be exactly the payload sent in Step 2.

9. Alternative Approaches

If the update_agent action does not use the code parameter:

  1. Grep for Sinks: Search the plugin folder for file_put_contents or fwrite to identify the correct parameter name.
    grep -rn "file_put_contents" /var/www/html/wp-content/plugins/graphic-web-design-inc/
    
  2. Try gwd-logs.php: The vulnerability is reported in both files. If one has restricted permissions, the other might be writable.
  3. Variable Override: If the plugin uses extract($_POST), attempt to overwrite the configuration variable directly in the request.
Research Findings
Static analysis — not yet PoC-verified

Summary

The GWD Connect plugin for WordPress contains standalone agent files (gwd-backup.php and gwd-logs.php) that fail to validate authentication if the API key has not been configured. An unauthenticated attacker can exploit this default state to invoke the 'update_agent' action, allowing them to overwrite the agent file with arbitrary PHP code.

Vulnerable Code

// wp-content/plugins/graphic-web-design-inc/gwd-backup.php

$stored_key = get_option('gwd_api_key');
if ($_REQUEST['key'] == $stored_key) {
    if ($_REQUEST['action'] == 'update_agent') {
        $code = $_REQUEST['code'];
        file_put_contents(__FILE__, $code);
    }
}

Security Fix

--- wp-content/plugins/graphic-web-design-inc/gwd-backup.php
+++ wp-content/plugins/graphic-web-design-inc/gwd-backup.php
@@ -1,6 +1,6 @@
 $stored_key = get_option('gwd_api_key');
 
-if ($_REQUEST['key'] == $stored_key) {
+if (!empty($stored_key) && $_REQUEST['key'] === $stored_key) {
     if ($_REQUEST['action'] == 'update_agent') {
         $code = $_REQUEST['code'];
         file_put_contents(__FILE__, $code);

Exploit Outline

To exploit this vulnerability, an attacker targets the standalone agent endpoints at /wp-content/plugins/graphic-web-design-inc/gwd-backup.php or gwd-logs.php. By sending a POST request with the 'action' parameter set to 'update_agent' and an empty 'key' parameter, the attacker can bypass authentication on installations where the API key has not yet been configured. The attacker includes the desired PHP payload in the 'code' parameter (or similar, such as 'content'), which the script writes directly into its own file. Subsequent requests to the agent file will execute the injected PHP code with the privileges of the web server.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.