REPORT / 01
Analysis Report · Folder Analysis cache/phastpress_3.7 → cache/phastpress_3.8 — CVE-2025-14388
Shared security patch analysis results
02 ·
Lifecycle actions
cancel · resume · skip · regenerate
03 ·
Share this analysis
copy link · embed report
03 ·
CVE Security Analysis & Writeups
ai-generated · per cve
Comprehensive security analysis generated by AI for each confirmed CVE match. Click on a CVE to view the detailed writeup including vulnerability background, technical details, patch analysis, and PoC guide.
CVE-2025-14388
NVD
AI-Generated Analysis
05 ·
Findings
filter · search · paginate
Showing 0 to 0 of 0 results
sdk/phast.php
AI: 1 vulnerabilities
1 true positive
CVE-2025-14388
--- cache/phastpress_3.7/sdk/phast.php 2025-12-24 00:33:38.277283981 +0000+++ cache/phastpress_3.8/sdk/phast.php 2025-12-24 00:35:47.101256335 +0000@@ -9596,22 +9596,22 @@ } private function guard(\Kibo\Phast\ValueObjects\URL $url, callable $cb) {- if (!in_array($this->getExtensionForURL($url), self::getAllowedExtensions())) {- return false;- } $file = $this->getFileForURL($url); if ($file === false) { return false; }+ if (!in_array($this->getExtension($file), self::getAllowedExtensions())) {+ return false;+ } return $cb($file); }- private function getExtensionForURL(\Kibo\Phast\ValueObjects\URL $url)+ private function getExtension($file) {- $dotPosition = strrpos($url->getDecodedPath(), '.');+ $dotPosition = strrpos($file, '.'); if ($dotPosition === false) { return ''; }- return strtolower(substr($url->getDecodedPath(), $dotPosition + 1));+ return strtolower(substr($file, $dotPosition + 1)); } private function getFileForURL(\Kibo\Phast\ValueObjects\URL $url) {
AI Analysis
Vulnerability Existed: yes
TRUE POSITIVE
Path Traversal / Improper Input Validation - CWE-22 - sdk/phast.php lines 9596-9620
Old Code:
```php
private function guard(\Kibo\Phast\ValueObjects\URL $url, callable $cb)
{
if (!in_array($this->getExtensionForURL($url), self::getAllowedExtensions())) {
return false;
}
$file = $this->getFileForURL($url);
if ($file === false) {
return false;
}
return $cb($file);
}
private function getExtensionForURL(\Kibo\Phast\ValueObjects\URL $url)
{
$dotPosition = strrpos($url->getDecodedPath(), '.');
if ($dotPosition === false) {
return '';
}
return strtolower(substr($url->getDecodedPath(), $dotPosition + 1));
}
```
Fixed Code:
```php
private function guard(\Kibo\Phast\ValueObjects\URL $url, callable $cb)
{
$file = $this->getFileForURL($url);
if ($file === false) {
return false;
}
if (!in_array($this->getExtension($file), self::getAllowedExtensions())) {
return false;
}
return $cb($file);
}
private function getExtension($file)
{
$dotPosition = strrpos($file, '.');
if ($dotPosition === false) {
return '';
}
return strtolower(substr($file, $dotPosition + 1));
}
```
Explanation:
This fix addresses a critical security vulnerability in the file extension validation logic. The original code validated the extension based on the URL's decoded path (`$url->getDecodedPath()`) before resolving the actual file path. This allowed an attacker to bypass the extension whitelist through URL encoding or path traversal techniques (e.g., `file.php%2e.jpg` or `file.php/..`) where the decoded URL path would appear to have an allowed extension, but the actual resolved file (`$file`) would be a different type.
The fix corrects this by:
1. First resolving the actual file path via `getFileForURL($url)`
2. Then validating the extension of the resolved file path (`getExtension($file)`)
3. Only proceeding with the callback if both the file exists AND has an allowed extension
This ensures that the extension validation is performed on the actual file path that will be processed, not on a potentially manipulated URL representation, preventing path traversal and extension validation bypass attacks.
CVE Analysis Results:
CVE-2025-14388: Yes
View CVE Description
The PhastPress plugin for WordPress is vulnerable to Unauthenticated Arbitrary File Read via null byte injection in all versions up to, and including, 3.7. This is due to a discrepancy between the extension validation in `getExtensionForURL()` which operates on URL-decoded paths, and `appendNormalized()` which strips everything after a null byte before constructing the filesystem path. This makes it possible for unauthenticated attackers to read arbitrary files from the webroot, including wp-config.php, by appending a double URL-encoded null byte (%2500) followed by an allowed extension (.txt) to the file path.
Showing 1 to 1 of 1 results