Security-critical fix: Nginx directory protection did not prevent access to
PHP scripts Although the implemented direction protection posed a prompt when accessing the http://...com/protectedir/ it was still possible to call http://...com/protectedir/script.php This vulnerability emerges from the precedence order of "location" statements. The RegEx matching the PHP script is triggered before the directory protection is evaluated. As a result, the PHP script is interpreted and path parsing stops due to the circumflex (see http://nginx.org/en/docs/http/ngx_http_core_module.html#location). The fix involves adding a PHP parsing snippet to every protected block. In order to prevent PHP-related config params repeatedly, the required section is referenced using a prefix.
This commit is contained in:
@@ -271,6 +271,8 @@ class nginx extends HttpConfigBase {
|
||||
&& !is_dir(Settings::Get('system.apacheconf_vhost')))
|
||||
|| is_dir(Settings::Get('system.apacheconf_vhost'))
|
||||
) {
|
||||
$domain['nonexistinguri'] = '/' . md5(uniqid(microtime(), 1)) . '.htm';
|
||||
|
||||
// Create non-ssl host
|
||||
$this->nginx_data[$vhost_filename].= $this->getVhostContent($domain, false);
|
||||
if ($domain['ssl'] == '1' || $domain['ssl_redirect'] == '1') {
|
||||
@@ -681,6 +683,9 @@ class nginx extends HttpConfigBase {
|
||||
if ($single['path'] == '/') {
|
||||
$path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n";
|
||||
$path_options .= "\t\t" . 'auth_basic_user_file ' . makeCorrectFile($single['usrf']) . ';'."\n";
|
||||
$path_options .= "\t\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n";
|
||||
$path_options .= "\t\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n";
|
||||
$path_options .= "\t\t" . '}' . "\n";
|
||||
// remove already used entries so we do not have doubles
|
||||
unset($htpasswds[$idx]);
|
||||
}
|
||||
@@ -741,6 +746,9 @@ class nginx extends HttpConfigBase {
|
||||
$path_options .= "\t" . 'location ' . makeCorrectDir($single['path']) . ' {' . "\n";
|
||||
$path_options .= "\t\t" . 'auth_basic "' . $single['authname'] . '";' . "\n";
|
||||
$path_options .= "\t\t" . 'auth_basic_user_file ' . makeCorrectFile($single['usrf']) . ';'."\n";
|
||||
$path_options .= "\t\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n";
|
||||
$path_options .= "\t\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n";
|
||||
$path_options .= "\t\t" . '}' . "\n";
|
||||
$path_options .= "\t".'}' . "\n";
|
||||
}
|
||||
//}
|
||||
@@ -805,6 +813,10 @@ class nginx extends HttpConfigBase {
|
||||
$phpopts = '';
|
||||
if ($domain['phpenabled'] == '1') {
|
||||
$phpopts = "\tlocation ~ \.php {\n";
|
||||
$phpopts .= "\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n";
|
||||
$phpopts .= "\t" . '}' . "\n\n";
|
||||
|
||||
$phpopts .= "\tlocation @php {\n";
|
||||
$phpopts .= "\t\tfastcgi_split_path_info ^(.+\.php)(/.+)\$;\n";
|
||||
$phpopts .= "\t\tinclude ".Settings::Get('nginx.fastcgiparams').";\n";
|
||||
$phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;\n";
|
||||
|
||||
@@ -25,6 +25,10 @@ class nginx_phpfpm extends nginx
|
||||
$phpconfig = $php->getPhpConfig((int)$domain['phpsettingid']);
|
||||
|
||||
$php_options_text = "\t" . 'location ~ ^(.+?\.php)(/.*)?$ {' . "\n";
|
||||
$php_options_text .= "\t\t" . 'try_files ' . $domain['nonexistinguri'] . ' @php;' . "\n";
|
||||
$php_options_text .= "\t" . '}' . "\n\n";
|
||||
|
||||
$php_options_text .= "\t" . 'location @php {' . "\n";
|
||||
$php_options_text .= "\t\t" . 'try_files $1 = 404;' . "\n\n";
|
||||
$php_options_text .= "\t\t" . 'include ' . Settings::Get('nginx.fastcgiparams') . ";\n";
|
||||
$php_options_text .= "\t\t" . 'fastcgi_split_path_info ^(.+\.php)(/.+)\$;' . "\n";
|
||||
|
||||
Reference in New Issue
Block a user