Smart Slider 3 <= 3.5.1.36 - Authenticated (Administrator+) Path Traversal to Arbitrary File Read via 'src'/'srcset' Attribute in HTML Export
Description
The Smart Slider 3 plugin for WordPress is vulnerable to Directory Traversal in all versions up to, and including, 3.5.1.36 via the replaceHTMLImage function. This makes it possible for authenticated attackers, with administrator-level access and above, to read the contents of arbitrary files on the server, which can contain sensitive information.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=3.5.1.36What Changed in the Fix
Changes introduced in v3.5.1.37
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-9197 ## 1. Vulnerability Summary **CVE-2026-9197** is a high-severity Path Traversal vulnerability in the **Smart Slider 3** plugin for WordPress (versions <= 3.5.1.36). The vulnerability exists within the HTML Export functionality, specifically in the proces…
Show full research plan
Exploitation Research Plan - CVE-2026-9197
1. Vulnerability Summary
CVE-2026-9197 is a high-severity Path Traversal vulnerability in the Smart Slider 3 plugin for WordPress (versions <= 3.5.1.36). The vulnerability exists within the HTML Export functionality, specifically in the processing of src and srcset attributes. When a slider is exported as HTML, the plugin attempts to "localize" images referenced in the slides by reading them from the server's filesystem and bundling them into the export package (typically a ZIP file).
Because the plugin fails to properly validate that the paths extracted from these attributes are restricted to the allowed media directories, an authenticated Administrator can create a slide containing an image with a path traversal payload (e.g., ../../../../wp-config.php). During export, the plugin's replaceHTMLImage function (inferred sink) reads the contents of the target file and includes it in the resulting ZIP file, allowing for arbitrary file disclosure.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin.phporwp-admin/admin-ajax.php - Action:
nextend_ajaxwithn2actionset to a slider export controller (e.g.,exportorexport-html). - Payload Location: The
backgroundImageparameter or an image layer'ssrcattribute within a slide's configuration data. - Authentication: Authenticated Administrator+ access is required.
- Preconditions: A slider must exist or be created, and the attacker must be able to edit its slides to include the traversal payload.
3. Code Flow
- Entry Point: The administrator initiates an export of a slider (likely via the "Export" tab in the Smart Slider 3 dashboard).
- Controller: The request is handled by a controller inheriting from
Nextend\Framework\Controller\Admin\AdminAjaxController. - Export Logic: The controller instantiates
Nextend\SmartSlider3\BackupSlider\ExportSlider. - Slide Processing: The
create()method inExportSlider.phpiterates through slides and their layers. - Image Identification: The code identifies image URLs via the
srcorsrcsetattributes in the slide's HTML/JSON data. - Path Resolution: The plugin calls
ResourceTranslator::toPath($image)to convert the URL into a filesystem path. - The Sink: The
replaceHTMLImagefunction (as per CVE description) or the logic insideExportSlider::create()(around line 147) callsfile_get_contents($file)on the resolved path without sufficient validation against the WordPress root or images directory. - Output: The content of the traversed file is written into the export ZIP package.
4. Nonce Acquisition Strategy
Smart Slider 3 uses a centralized AJAX handling system. The nonce is typically localized in the WordPress admin dashboard for the plugin.
- Navigate to Dashboard: Use
browser_navigateto go to the Smart Slider 3 main page:wp-admin/admin.php?page=smart-slider-3. - Extract Nonce: The nonce is stored in the
window.nextendorwindow.n2global JavaScript objects. - JavaScript Execution:
// Command for PoC agent browser_eval("window.n2?.ajaxNonce || window.nextend?.ajaxNonce") - Fallback: If the above objects are not found, check for the script localization key:
browser_eval("window._N2?.ajaxNonce")
5. Exploitation Strategy
Step 1: Create a Malicious Slider and Slide
The attacker first creates a slider and adds a slide containing the traversal payload.
- URL:
http://example.com/wp-admin/admin-ajax.php - Method: POST
- Parameters:
action:nextend_ajaxn2action:SlideCreatesliderId:[TARGET_SLIDER_ID]nonce:[EXTRACTED_NONCE]slideData: A JSON-encoded string representing the slide. ThebackgroundImageor a layer's image attribute must contain the payload:../../../../../../wp-config.php.
Step 2: Trigger the HTML Export
Once the slide is saved, the attacker triggers the export process that processes the malicious path.
- URL:
http://example.com/wp-admin/admin-ajax.php - Method: POST
- Parameters:
action:nextend_ajaxn2action:SliderExport(orExportHTMLif available)sliderId:[TARGET_SLIDER_ID]nonce:[EXTRACTED_NONCE]format:html(to trigger the HTML image replacement logic)
Step 3: Retrieve the File
The response will be a ZIP file (or a link to one). Download the ZIP and examine the images/ directory.
- Expected File Path inside ZIP:
images/wp-config.php(The plugin typically flattens the directory structure into animages/folder during export).
6. Test Data Setup
- Plugin State: Ensure Smart Slider 3 version 3.5.1.36 is installed and active.
- Slider: Create a simple slider via
wp-clior the UI to get a validsliderId. - Target File: Ensure
wp-config.phpexists in the standard WordPress root. - Admin User: Perform all actions as an administrator.
7. Expected Results
- The export process completes successfully.
- The downloaded ZIP archive contains a file named
wp-config.php(or a similar name depending on howbasename()handles the traversed path). - The contents of the file match the server's
wp-config.php, including database credentials and security salts.
8. Verification Steps
- Inspect ZIP: Use a CLI tool to list the contents of the generated export:
unzip -l export_file.zip | grep wp-config - Verify Content: Extract and read the file to confirm it is not just an empty file or error message:
unzip -p export_file.zip images/wp-config.php | head -n 20
9. Alternative Approaches
- Blind Read: If the ZIP generation is restricted or the extension check is enforced for
.php, attempt to read files that mimic allowed extensions, such as.svgfiles that might contain sensitive data or.logfiles. - Direct Browse: If the export fails, test the
ControllerAjaxBrowse::actionIndexendpoint identified in the source files. While restricted bystrpos($path, $root) !== 0, certain configurations or symlink behaviors might allow directory listing via thepathparameter:action:nextend_ajaxn2action:BrowseIndexpath:../../../../
Summary
The Smart Slider 3 plugin is vulnerable to authenticated path traversal via its HTML Export functionality. Administrators can embed path traversal sequences in image source attributes within a slider, causing the plugin to read arbitrary server files and bundle them into the generated export ZIP file.
Vulnerable Code
// Nextend/SmartSlider3/BackupSlider/ExportSlider.php line 381 public function replaceHTMLImage($found) { $path = Filesystem::absoluteURLToPath(self::addProtocol($found[2])); if (substr($path, 0, 5) === "data:") { return $found[0]; } if (strpos($path, Filesystem::getBasePath()) !== 0) { $imageUrl = Url::relativetoabsolute($path); $path = Filesystem::absoluteURLToPath($imageUrl); } if ($path == $found[2]) { return $found[0]; } if (Filesystem::fileexists($path)) { if (!isset($this->imageTranslation[$path])) { $fileName = strtolower(basename($path)); while (in_array($fileName, $this->usedNames)) { $fileName = $this->uniqueCounter . $fileName; $this->uniqueCounter++; } $this->usedNames[] = $fileName; $this->imageTranslation[$path] = $fileName; $this->files[] = array( $path, 'images/' . $fileName ); } return str_replace($found[2], 'images/' . $fileName, $found[0]); } else { return $found[0]; } }
Security Fix
@@ -379,21 +379,21 @@ } public function replaceHTMLImage($found) { - $path = Filesystem::absoluteURLToPath(self::addProtocol($found[2])); + $resource = ResourceTranslator::urlToResource(self::addProtocol($found[2])); - if (substr($path, 0, 5) === "data:") { + if (substr($resource, 0, 5) === "data:") { return $found[0]; } - if (strpos($path, Filesystem::getBasePath()) !== 0) { - $imageUrl = Url::relativetoabsolute($path); - $path = Filesystem::absoluteURLToPath($imageUrl); - } - - if ($path == $found[2]) { + if (!ResourceTranslator::isResource($resource) || preg_match('#(^|/)\.\.(/|$)#', $resource)) { return $found[0]; } - if (Filesystem::fileexists($path)) { + + $path = ResourceTranslator::toPath($resource); + + if ($this->isAllowedExportFile($path)) { + $path = realpath($path); + if (!isset($this->imageTranslation[$path])) { $fileName = strtolower(basename($path)); while (in_array($fileName, $this->usedNames)) { @@ -408,9 +408,38 @@ } return str_replace($found[2], 'images/' . $fileName, $found[0]); - } else { - return $found[0]; } + + return $found[0]; + } + + private function isAllowedExportFile($path) { + + $realPath = realpath($path); + + if (!$realPath || !is_file($realPath)) { + return false; + } + + $extension = strtolower(pathinfo($realPath, PATHINFO_EXTENSION)); + + $allowedExtensions = array( + 'jpg', + 'jpeg', + 'png', + 'gif', + 'mp4', + 'mp3', + 'svg', + 'webp', + 'avif' + ); + + if (!in_array($extension, $allowedExtensions, true)) { + return false; + } + + return true; }
Exploit Outline
1. Login as an Administrator and obtain the AJAX nonce from the dashboard (typically via the `window.n2` object). 2. Create or edit a slider using the `nextend_ajax` action and `SlideCreate` n2action. 3. In the slide configuration data, set an image attribute (like `backgroundImage`) to a path traversal payload pointing to a sensitive file (e.g., `../../../../wp-config.php`). 4. Trigger the slider export process by sending an AJAX request with `n2action` set to `SliderExport` (or equivalent HTML export action) and the `format` set to `html`. 5. Download the resulting ZIP package. The contents of the targeted file (e.g., database credentials from `wp-config.php`) will be stored within the `images/` directory inside the archive.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.