Skip to content

Commit

Permalink
Fix/clean path (#45)
Browse files Browse the repository at this point in the history
* Fix - Re-allow Unicode characters
* Fix - Check path length (max 255 bytes per segment)
* Tests - Add testcase for paths containing '..'
  • Loading branch information
nibra authored Mar 2, 2022
1 parent 2b476d6 commit f4be050
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 65 deletions.
2 changes: 0 additions & 2 deletions .drone.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,6 @@ local pipeline(name, phpversion, params) = {
]
},
pipeline("5.3", "5.3", "--prefer-stable"),
pipeline("5.4", "5.4", "--prefer-stable"),
pipeline("5.5", "5.5", "--prefer-stable"),
pipeline("5.6", "5.6", "--prefer-stable"),
pipeline("7.0", "7.0", "--prefer-stable"),
pipeline("7.1", "7.1", "--prefer-stable"),
Expand Down
58 changes: 1 addition & 57 deletions .drone.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,62 +113,6 @@ volumes:
host:
path: /tmp/composer-cache

---
kind: pipeline
name: PHP 5.4

platform:
os: linux
arch: amd64

steps:
- name: composer
image: joomlaprojects/docker-images:php5.4
commands:
- php -v
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache

- name: PHPUnit
image: joomlaprojects/docker-images:php5.4
commands:
- vendor/bin/phpunit

volumes:
- name: composer-cache
host:
path: /tmp/composer-cache

---
kind: pipeline
name: PHP 5.5

platform:
os: linux
arch: amd64

steps:
- name: composer
image: joomlaprojects/docker-images:php5.5
commands:
- php -v
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache

- name: PHPUnit
image: joomlaprojects/docker-images:php5.5
commands:
- vendor/bin/phpunit

volumes:
- name: composer-cache
host:
path: /tmp/composer-cache

---
kind: pipeline
name: PHP 5.6
Expand Down Expand Up @@ -368,6 +312,6 @@ volumes:

---
kind: signature
hmac: 6fa33d7b14ec559e67074903960cc2ea6cc3153fc0fc3840346596dda345543e
hmac: 6b92d54a1ca911a67230ba4707aaad03363d62f357a81081b667f40e6bbade73

...
30 changes: 30 additions & 0 deletions Tests/InputFilterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,12 @@ public function casesGeneric()
'/var/www/html/pub/diplom_labors/2016/2016_Elfimova_O_rpz.pdf',
'From generic cases'
),
'double-dot path' => array(
'path',
'/var/www/html/pub/diplom_labors/../2016_Elfimova_O_rpz.pdf',
'/var/www/html/pub/diplom_labors/../2016_Elfimova_O_rpz.pdf',
'From generic cases'
),
'windows path' => array(
'path',
'C:\Documents\Newsletters\Summer2018.pdf',
Expand Down Expand Up @@ -505,6 +511,30 @@ public function casesGeneric()
'C:\Documents\Newsletters\tmp',
'From generic cases'
),
'non-ascii path' => array(
'path',
'εικόνες',
'εικόνες',
'From generic cases'
),
'symbol path' => array(
'path',
'#+-!$§%&()=,°;<>|',
'#+-!$§%&()=,°;<>|',
'From generic cases'
),
'abs numeric path' => array(
'path',
'/8/86/86753/html/',
'/8/86/86753/html/',
'From generic cases'
),
'rel numeric path' => array(
'path',
'8/86/86753/html/',
'8/86/86753/html/',
'From generic cases'
),
'user_01' => array(
'username',
'&<f>r%e\'d',
Expand Down
51 changes: 45 additions & 6 deletions src/InputFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -1016,23 +1016,62 @@ private function cleanHtml($source)
*/
private function cleanPath($source)
{
$linuxPattern = '/^[A-Za-z0-9_\/-]+[A-Za-z0-9_\.-]*([\\\\\/]+[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/';
// Linux and other Unixoids
$filePattern = '(?:[^\x00\/:*?]{1,255})';
$pathSeparatorPattern = '(?:\/+)';
$rootPattern = '(?:\/)';

if (preg_match($linuxPattern, $source))
if ($this->pathMatches($source, $rootPattern, $pathSeparatorPattern, $filePattern, '/'))
{
return preg_replace('~/+~', '/', $source);
return $source;
}

$windowsPattern = '/^([A-Za-z]:(\\\\|\/))?[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*((\\\\|\/)+[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/';
// Windows
$filePattern = '(?:[^\x00\\\\\/:*"?<>|]{1,255})';
$pathSeparatorPattern = '(?:[\\\\\/])';
$rootPattern = '(?:[A-Za-z]:(\\\\|\/))';

if (preg_match($windowsPattern, $source))
if ($this->pathMatches($source, $rootPattern, $pathSeparatorPattern, $filePattern, '\\'))
{
return preg_replace('~(\\\\|\/)+~', '\\', $source);
return $source;
}

return '';
}

/**
* Fix a path, if and only if it matches the provided patterns.
*
* If a path matches but is longer than 4095 bytes, it is cleared.
*
* @param string $source The path as provided; it gets cleaned in place, if possible.
* @param string $rootPattern The pattern to identify an absolute path (e.g., '/' on Linux, 'C:\' on Windows),
* @param string $pathSeparatorPattern The pattern for valid path separators
* @param string $filePattern The pattern for valid file and directory names
* @param string $pathSeparator The native path separator
*
* @return boolean
*/
private function pathMatches(&$source, $rootPattern, $pathSeparatorPattern, $filePattern, $pathSeparator)
{
$pathPattern = "/^{$rootPattern}?(?:{$filePattern}{$pathSeparatorPattern})*{$filePattern}?$/u";

if (preg_match($pathPattern, $source))
{
$source = preg_replace("/{$pathSeparatorPattern}/", $pathSeparator, $source);

if (strlen($source) > 4095)
{
// Path is too long
$source = '';
}

return true;
}

return false;
}

/**
* Trim filter
*
Expand Down

0 comments on commit f4be050

Please sign in to comment.