Skip to content

Commit

Permalink
fix possible privilege escalation from customer to root when specifyi…
Browse files Browse the repository at this point in the history
…ng custom error documents in directory-options

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
  • Loading branch information
d00p committed Jan 28, 2023
1 parent bd5b99d commit 0034681
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 12 deletions.
15 changes: 7 additions & 8 deletions lib/Froxlor/Api/Commands/DirOptions.php
Expand Up @@ -157,16 +157,15 @@ public function add()
* this functions validates a given value as ErrorDocument
* refs #267
*
* @param
* string error-document-string
* @param string $errdoc
* @param bool $throw_exception
*
* @return string error-document-string
*
*/
private function correctErrorDocument($errdoc = null, $throw_exception = false)
private function correctErrorDocument(string $errdoc, $throw_exception = false)
{
if ($errdoc !== null && $errdoc != '') {
if (trim($errdoc) != '') {
// not a URL
if ((strtoupper(substr($errdoc, 0, 5)) != 'HTTP:' && strtoupper(substr($errdoc, 0, 6)) != 'HTTPS:') || !Validate::validateUrl($errdoc)) {
// a file
Expand All @@ -176,22 +175,22 @@ private function correctErrorDocument($errdoc = null, $throw_exception = false)
if (!substr($errdoc, 0, 1) == '/') {
$errdoc = '/' . $errdoc;
}
} else {
} elseif (preg_match('/^"([^\r\n\t\f\0"]+)"$/', $errdoc)) {
// a string (check for ending ")
// string won't work for lighty
if (Settings::Get('system.webserver') == 'lighttpd') {
Response::standardError('stringerrordocumentnotvalidforlighty', '', $throw_exception);
} elseif (substr($errdoc, -1) != '"') {
$errdoc .= '"';
}
} else {
Response::standardError('invaliderrordocumentvalue', '', $throw_exception);
}
} else {
if (Settings::Get('system.webserver') == 'lighttpd') {
Response::standardError('urlerrordocumentnotvalidforlighty', '', $throw_exception);
}
}
}
return $errdoc;
return trim($errdoc);
}

/**
Expand Down
12 changes: 8 additions & 4 deletions lib/Froxlor/FileDir.php
Expand Up @@ -147,9 +147,9 @@ public static function makeCorrectDir($dir)
*/
public static function makeSecurePath($path)
{
// check for bad characters, some are allowed with escaping
// check for bad characters, some are allowed with escaping,
// but we generally don't want them in our directory-names,
// thx to aaronmueller for this snipped
// thx to aaronmueller for this snippet
$badchars = [
':',
';',
Expand All @@ -161,7 +161,11 @@ public static function makeSecurePath($path)
'$',
'~',
'?',
"\0"
"\0",
"\n",
"\r",
"\t",
"\f"
];
foreach ($badchars as $bc) {
$path = str_replace($bc, "", $path);
Expand Down Expand Up @@ -606,7 +610,7 @@ public static function removeImmutable(string $filename)
}

/**
*
*
* @return array|false
*/
public static function getFilesystemQuota()
Expand Down
1 change: 1 addition & 0 deletions lng/de.lng.php
Expand Up @@ -837,6 +837,7 @@
'notrequiredpasswordcomplexity' => 'Die vorgegebene Passwort-Komplexität wurde nicht erfüllt.<br />Bitte kontaktieren Sie Ihren Administrator, wenn Sie Fragen zur Komplexitäts-Vorgabe haben.',
'stringerrordocumentnotvalidforlighty' => 'Ein Text als Fehlerdokument funktioniert leider in LigHTTPd nicht, bitte geben Sie einen Pfad zu einer Datei an',
'urlerrordocumentnotvalidforlighty' => 'Eine URL als Fehlerdokument funktioniert leider in LigHTTPd nicht, bitte geben Sie einen Pfad zu einer Datei an',
'invaliderrordocumentvalue' => 'Der angegebene Wert für das Fehlederdokument ist keine gültige Datei, URL oder Text-Zeile.',
'intvaluetoolow' => 'Die angegebene Zahl ist zu klein (Feld "%s")',
'intvaluetoohigh' => 'Die angegebene Zahl ist zu groß (Feld "%s")',
'phpfpmstillenabled' => 'PHP-FPM ist derzeit aktiviert. Bitte deaktivieren Sie es, um FCGID zu aktivieren',
Expand Down
1 change: 1 addition & 0 deletions lng/en.lng.php
Expand Up @@ -905,6 +905,7 @@
'notrequiredpasswordcomplexity' => 'The specified password-complexity was not satisfied.<br />Please contact your administrator if you have any questions about the complexity-specification',
'stringerrordocumentnotvalidforlighty' => 'A string as ErrorDocument does not work in lighttpd, please specify a path to a file',
'urlerrordocumentnotvalidforlighty' => 'An URL as ErrorDocument does not work in lighttpd, please specify a path to a file',
'invaliderrordocumentvalue' => 'The value given as ErrorDocument does not seem to be a valid file, URL or string.',
'intvaluetoolow' => 'The given number is too low (field %s)',
'intvaluetoohigh' => 'The given number is too high (field %s)',
'phpfpmstillenabled' => 'PHP-FPM is currently active. Please deactivate it before activating FCGID',
Expand Down
45 changes: 45 additions & 0 deletions tests/Extras/DirOptionsTest.php
Expand Up @@ -191,4 +191,49 @@ public function testCustomerDirOptionsDelete()
$this->expectExceptionMessage("Directory option with id #1 could not be found");
DirOptions::getLocal($admin_userdata, $data)->get();
}

public function testCustomerDirOptionsAddMalformed()
{
global $admin_userdata;

// get customer
$json_result = Customers::getLocal($admin_userdata, array(
'loginname' => 'test1'
))->get();
$customer_userdata = json_decode($json_result, true)['data'];

$data = [
'path' => '/testmalformed',
'error404path' => '/"'.PHP_EOL.'something/../../../../weird 404.html'.PHP_EOL.'#'
];
$json_result = DirOptions::getLocal($customer_userdata, $data)->add();
$result = json_decode($json_result, true)['data'];
$expected = '/"something/././././weird\ 404.html#';
$this->assertEquals($expected, $result['error404path']);
}

public function testCustomerDirOptionsAddMalformedInvalid()
{
global $admin_userdata;

// get customer
$json_result = Customers::getLocal($admin_userdata, array(
'loginname' => 'test1'
))->get();
$customer_userdata = json_decode($json_result, true)['data'];

$data = [
'path' => '/testmalformed',
'error404path' => '"'.PHP_EOL.'IncludeOptional /something/else/'.PHP_EOL.'#'
];
$this->expectExceptionMessage("The value given as ErrorDocument does not seem to be a valid file, URL or string.");
DirOptions::getLocal($customer_userdata, $data)->add();

$data = [
'path' => '/testmalformed',
'error404path' => '"something"oh no a quote within the string"'
];
$this->expectExceptionMessage("The value given as ErrorDocument does not seem to be a valid file, URL or string.");
DirOptions::getLocal($customer_userdata, $data)->add();
}
}

0 comments on commit 0034681

Please sign in to comment.