From d87f76019fc231ec20d95126a7fee0487e7be5f0 Mon Sep 17 00:00:00 2001 From: tbrehm <t.brehm@ispconfig.org> Date: Tue, 14 Aug 2012 14:56:20 +0000 Subject: [PATCH] - Added new web folder named private to web folder layout. The folder is intended to store data that shall not be visible in the web directory, it is owned by the user of the web. - Changed ownership of web root directory to root user in all security modes to prevent symlink attacks. - Apache log files are now owned by user root. - Improved functions in system library. --- server/lib/classes/system.inc.php | 28 ++++++- .../plugins-available/apache2_plugin.inc.php | 76 ++++++------------- 2 files changed, 48 insertions(+), 56 deletions(-) diff --git a/server/lib/classes/system.inc.php b/server/lib/classes/system.inc.php index 7a78a2b040..14b9413c2a 100644 --- a/server/lib/classes/system.inc.php +++ b/server/lib/classes/system.inc.php @@ -617,7 +617,12 @@ class system{ return false; } if(file_exists($file)) { - return chown($file, $owner); + if(@chown($file, $owner)) { + return true; + } else { + $app->log("chown failed: $file : $owner",LOGLEVEL_DEBUG); + return false; + } } } @@ -628,7 +633,12 @@ class system{ return false; } if(file_exists($file)) { - return chgrp($file, $group); + if(@chgrp($file, $group)) { + return true; + } else { + $app->log("chgrp failed: $file : $group",LOGLEVEL_DEBUG); + return false; + } } } @@ -639,7 +649,12 @@ class system{ $app->log("Action aborted, file is a symlink: $file",LOGLEVEL_WARN); return false; } - return chmod($file, $mode); + if(@chmod($file, $mode)) { + return true; + } else { + $app->log("chmod failed: $file : $mode",LOGLEVEL_DEBUG); + return false; + } } function file_put_contents($filename, $data, $allow_symlink = false) { @@ -676,7 +691,12 @@ class system{ $app->log("Action aborted, file is a symlink: $dirname",LOGLEVEL_WARN); return false; } - return mkdir($dirname); + if(@mkdir($dirname)) { + return true; + } else { + $app->log("mkdir failed: $dirname",LOGLEVEL_DEBUG); + return false; + } } function unlink($file) { diff --git a/server/plugins-available/apache2_plugin.inc.php b/server/plugins-available/apache2_plugin.inc.php index 9e00a0f86c..6c72d29360 100644 --- a/server/plugins-available/apache2_plugin.inc.php +++ b/server/plugins-available/apache2_plugin.inc.php @@ -433,6 +433,8 @@ class apache2_plugin { //print_r($data); // Check if the directories are there and create them if necessary. + $app->system->web_folder_protection($data['new']['document_root'],false); + if(!is_dir($data['new']['document_root'].'/web')) $app->system->mkdirpath($data['new']['document_root'].'/web'); if(!is_dir($data['new']['document_root'].'/web/error') and $data['new']['errordocs']) $app->system->mkdirpath($data['new']['document_root'].'/web/error'); //if(!is_dir($data['new']['document_root'].'/log')) exec('mkdir -p '.$data['new']['document_root'].'/log'); @@ -441,6 +443,16 @@ class apache2_plugin { if(!is_dir($data['new']['document_root'].'/tmp')) $app->system->mkdirpath($data['new']['document_root'].'/tmp'); if(!is_dir($data['new']['document_root'].'/webdav')) $app->system->mkdirpath($data['new']['document_root'].'/webdav'); + //* Create the new private directory + if(!is_dir($data['new']['document_root'].'/private')) { + $app->system->mkdirpath($data['new']['document_root'].'/private'); + $app->system->chmod($data['new']['document_root'].'/private',0710); + $app->system->chown($data['new']['document_root'].'/private',$username); + $app->system->chgrp($data['new']['document_root'].'/private',$groupname); + } + + $app->system->web_folder_protection($data['new']['document_root'],true); + // Remove the symlink for the site, if site is renamed if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) { if(is_dir('/var/log/ispconfig/httpd/'.$data['old']['domain'])) exec('rm -rf /var/log/ispconfig/httpd/'.$data['old']['domain']); @@ -459,21 +471,6 @@ class apache2_plugin { $app->log('Creating symlink: ln -s /var/log/ispconfig/httpd/'.$data['new']['domain'].' '.$data['new']['document_root'].'/log',LOGLEVEL_DEBUG); } - /* - // Create the symlink for the logfiles - // This does not work as vlogger cannot log trough symlinks. - if($this->action == 'update' && $data['old']['domain'] != '' && $data['new']['domain'] != $data['old']['domain']) { - if(is_dir($data['old']['document_root'].'/log')) exec('rm -rf '.$data['old']['document_root'].'/log'); - if(is_link('/var/log/ispconfig/httpd/'.$data['old']['domain'])) $app->system->unlink('/var/log/ispconfig/httpd/'.$data['old']['domain']); - } - - // Create the symlink for the logfiles - if(!is_dir($data['new']['document_root'].'/log')) exec('mkdir -p '.$data['new']['document_root'].'/log'); - if(!is_link('/var/log/ispconfig/httpd/'.$data['new']['domain'])) { - exec('ln -s '.$data['new']['document_root'].'/log /var/log/ispconfig/httpd/'.$data['new']['domain']); - $app->log('Creating symlink: ln -s '.$data['new']['document_root'].'/log /var/log/ispconfig/httpd/'.$data['new']['domain'],LOGLEVEL_DEBUG); - } - */ // Get the client ID $client = $app->dbmaster->queryOneRecord('SELECT client_id FROM sys_group WHERE sys_group.groupid = '.intval($data['new']['sys_groupid'])); @@ -624,19 +621,16 @@ class apache2_plugin { $app->system->web_folder_protection($data['new']['document_root'],false); + //* Check if we have the new private folder and create it if nescessary + if(!is_dir($data['new']['document_root'].'/private')) $app->system->mkdir($data['new']['document_root'].'/private'); + if($web_config['security_level'] == 20) { - $app->system->chmod($data['new']['document_root'],0751); + $app->system->chmod($data['new']['document_root'],0755); $app->system->chmod($data['new']['document_root'].'/web',0710); $app->system->chmod($data['new']['document_root'].'/webdav',0710); + $app->system->chmod($data['new']['document_root'].'/private',0710); $app->system->chmod($data['new']['document_root'].'/ssl',0755); - - /* - $this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root'])); - $this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root']).'/*'); - $this->_exec('chmod 710 '.escapeshellcmd($data['new']['document_root'].'/web')); - $this->_exec('chmod 755 '.escapeshellcmd($data['new']['document_root'].'/ssl')); - */ // make tmp directory writable for Apache and the website users $app->system->chmod($data['new']['document_root'].'/tmp',0777); @@ -669,16 +663,8 @@ class apache2_plugin { $app->system->add_user_to_group($groupname, escapeshellcmd($web_config['user'])); //* Chown all default directories - /* - $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'])); - $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/cgi-bin')); - $this->_exec('chown root:'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/log')); - $this->_exec('chown root:root '.escapeshellcmd($data['new']['document_root'].'/ssl')); - $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/tmp')); - $this->_exec('chown -R '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/web')); - */ - $app->system->chown($data['new']['document_root'],$username); - $app->system->chgrp($data['new']['document_root'],$groupname); + $app->system->chown($data['new']['document_root'],'root'); + $app->system->chgrp($data['new']['document_root'],'root'); $app->system->chown($data['new']['document_root'].'/cgi-bin',$username); $app->system->chgrp($data['new']['document_root'].'/cgi-bin',$groupname); if(realpath($data['new']['document_root'].'/log') == '/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log') { @@ -697,22 +683,8 @@ class apache2_plugin { $app->system->chgrp($data['new']['document_root'].'/web/stats',$groupname); $app->system->chown($data['new']['document_root'].'/webdav',$username); $app->system->chgrp($data['new']['document_root'].'/webdav',$groupname); - - - /* - * Workaround for jailkit: If jailkit is enabled for the site, the - * website root has to be owned by the root user and we have to chmod it to 755 then - */ - - //* Check if there is a jailkit user or cronjob for this site - $tmp = $app->db->queryOneRecord('SELECT count(shell_user_id) as number FROM shell_user WHERE parent_domain_id = '.$data['new']['domain_id']." AND chroot = 'jailkit'"); - $tmp2 = $app->db->queryOneRecord('SELECT count(id) as number FROM cron WHERE parent_domain_id = '.$data['new']['domain_id']." AND `type` = 'chrooted'"); - if($tmp['number'] > 0 || $tmp2['number'] > 0) { - $app->system->chmod($data['new']['document_root'],0755); - $app->system->chown($data['new']['document_root'],'root'); - $app->system->chgrp($data['new']['document_root'],'root'); - } - unset($tmp); + $app->system->chown($data['new']['document_root'].'/private',$username); + $app->system->chgrp($data['new']['document_root'].'/private',$groupname); // If the security Level is set to medium } else { @@ -755,10 +727,10 @@ class apache2_plugin { //* Protect web folders $app->system->web_folder_protection($data['new']['document_root'],true); - // Change the ownership of the error log to the owner of the website + // Change the ownership of the error log to the root user if(!@is_file('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log')) exec('touch '.escapeshellcmd('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log')); - $app->system->chown('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log',$username); - $app->system->chgrp('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log',$groupname); + $app->system->chown('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log','root'); + $app->system->chgrp('/var/log/ispconfig/httpd/'.$data['new']['domain'].'/error.log','root'); //* Write the custom php.ini file, if custom_php_ini fieled is not empty -- GitLab