From 4b9329a0f204c190f9cae6c072c9827d05d269e6 Mon Sep 17 00:00:00 2001 From: tbrehm Date: Fri, 8 Jun 2012 12:06:41 +0000 Subject: [PATCH] Implemented: FS#2112 - Set u / i attributes on system web folders This option can be enabled under System > Server config and is named "Web folder protection". --- install/tpl/server.ini.master | 1 + .../web/admin/form/server_config.tform.php | 6 ++++++ .../web/admin/lib/lang/en_server_config.lng | 1 + .../admin/templates/server_config_web_edit.htm | 6 ++++++ server/lib/classes/system.inc.php | 16 ++++++++++++++++ server/plugins-available/apache2_plugin.inc.php | 17 ++++++++++++++--- .../cron_jailkit_plugin.inc.php | 6 ++++++ .../shelluser_base_plugin.inc.php | 7 +++++++ .../shelluser_jailkit_plugin.inc.php | 15 +++++++++++++++ 9 files changed, 72 insertions(+), 3 deletions(-) diff --git a/install/tpl/server.ini.master b/install/tpl/server.ini.master index 49b9e3ce2..eaeff0210 100644 --- a/install/tpl/server.ini.master +++ b/install/tpl/server.ini.master @@ -76,6 +76,7 @@ set_folder_permissions_on_update=y add_web_users_to_sshusers_group=y connect_userid_to_webid=n connect_userid_to_webid_start=10000 +web_folder_protection=n [dns] bind_user=root diff --git a/interface/web/admin/form/server_config.tform.php b/interface/web/admin/form/server_config.tform.php index 09334c749..e08d1cc08 100644 --- a/interface/web/admin/form/server_config.tform.php +++ b/interface/web/admin/form/server_config.tform.php @@ -462,6 +462,12 @@ $form["tabs"]['web'] = array( 'default' => 'y', 'value' => array(0 => 'n', 1 => 'y') ), + 'web_folder_protection' => array( + 'datatype' => 'VARCHAR', + 'formtype' => 'CHECKBOX', + 'default' => 'y', + 'value' => array(0 => 'n', 1 => 'y') + ), 'add_web_users_to_sshusers_group' => array( 'datatype' => 'VARCHAR', 'formtype' => 'CHECKBOX', diff --git a/interface/web/admin/lib/lang/en_server_config.lng b/interface/web/admin/lib/lang/en_server_config.lng index b14f34dd9..c32657b21 100644 --- a/interface/web/admin/lib/lang/en_server_config.lng +++ b/interface/web/admin/lib/lang/en_server_config.lng @@ -165,4 +165,5 @@ $wb["awstats_settings_txt"] = 'AWStats Settings'; $wb["firewall_txt"] = 'Firewall'; $wb["mailbox_quota_stats_txt"] = 'Mailbox quota statistics'; $wb["enable_ip_wildcard_txt"] = 'Enable IP wildcard (*)'; +$wb["web_folder_protection_txt"] = 'Web folder protection'; ?> \ No newline at end of file diff --git a/interface/web/admin/templates/server_config_web_edit.htm b/interface/web/admin/templates/server_config_web_edit.htm index 40750038b..349ddcdcf 100644 --- a/interface/web/admin/templates/server_config_web_edit.htm +++ b/interface/web/admin/templates/server_config_web_edit.htm @@ -116,6 +116,12 @@ {tmpl_var name='set_folder_permissions_on_update'} +
+

{tmpl_var name='web_folder_protection_txt'}

+
+ {tmpl_var name='web_folder_protection'} +
+

{tmpl_var name='add_web_users_to_sshusers_group_txt'}

diff --git a/server/lib/classes/system.inc.php b/server/lib/classes/system.inc.php index c43a0ccd1..323ffe504 100644 --- a/server/lib/classes/system.inc.php +++ b/server/lib/classes/system.inc.php @@ -1281,6 +1281,22 @@ class system{ return false; } } + + function web_folder_protection($document_root,$protect) { + global $app,$conf; + + //* load the server configuration options + $app->uses('getconf'); + $web_config = $app->getconf->get_server_config($conf['server_id'], 'web'); + + if($protect == true && $web_config['web_folder_protection'] == 'y') { + //* Add protection + if($document_root != '' && $document_root != '/' && strlen($document_root) > 6 && !stristr($document_root,'..')) exec('chattr +i '.escapeshellcmd($document_root)); + } else { + //* Remove protection + if($document_root != '' && $document_root != '/' && strlen($document_root) > 6 && !stristr($document_root,'..')) exec('chattr -i '.escapeshellcmd($document_root)); + } + } } ?> diff --git a/server/plugins-available/apache2_plugin.inc.php b/server/plugins-available/apache2_plugin.inc.php index a6157ada8..c441a6a7c 100644 --- a/server/plugins-available/apache2_plugin.inc.php +++ b/server/plugins-available/apache2_plugin.inc.php @@ -366,6 +366,9 @@ class apache2_plugin { } } } + + //* Remove protection of old folders + $app->system->web_folder_protection($data['old']['document_root'],false); //* Move the site data $tmp_docroot = explode('/',$data['new']['document_root']); @@ -414,7 +417,7 @@ class apache2_plugin { if(!is_dir($data['new']['document_root'].'/ssl')) exec('mkdir -p '.$data['new']['document_root'].'/ssl'); if(!is_dir($data['new']['document_root'].'/cgi-bin')) exec('mkdir -p '.$data['new']['document_root'].'/cgi-bin'); if(!is_dir($data['new']['document_root'].'/tmp')) exec('mkdir -p '.$data['new']['document_root'].'/tmp'); - + // 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']); @@ -593,10 +596,11 @@ class apache2_plugin { } } - - //* If the security level is set to high if(($this->action == 'insert' && $data['new']['type'] == 'vhost') or ($web_config['set_folder_permissions_on_update'] == 'y' && $data['new']['type'] == 'vhost')) { + + $app->system->web_folder_protection($data['new']['document_root'],false); + if($web_config['security_level'] == 20) { $this->_exec('chmod 751 '.escapeshellcmd($data['new']['document_root'])); @@ -673,6 +677,9 @@ class apache2_plugin { $this->_exec('chown '.$username.':'.$groupname.' '.escapeshellcmd($data['new']['document_root'].'/web')); } } + + //* 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 if(!@is_file($data['new']['document_root'].'/log/error.log')) exec('touch '.escapeshellcmd($data['new']['document_root']).'/log/error.log'); @@ -1217,7 +1224,9 @@ class apache2_plugin { if(!is_file($data['new']['document_root'].'/.htpasswd_stats') || $data['new']['stats_password'] != $data['old']['stats_password']) { if(trim($data['new']['stats_password']) != '') { $htp_file = 'admin:'.trim($data['new']['stats_password']); + $app->system->web_folder_protection($data['new']['document_root'],false); file_put_contents($data['new']['document_root'].'/.htpasswd_stats',$htp_file); + $app->system->web_folder_protection($data['new']['document_root'],true); chmod($data['new']['document_root'].'/.htpasswd_stats',0755); unset($htp_file); } @@ -1280,6 +1289,8 @@ class apache2_plugin { // load the server configuration options $app->uses('getconf'); $web_config = $app->getconf->get_server_config($conf['server_id'], 'web'); + + $app->system->web_folder_protection($data['new']['document_root'],false); //* Check if this is a chrooted setup if($web_config['website_basedir'] != '' && @is_file($web_config['website_basedir'].'/etc/passwd')) { diff --git a/server/plugins-available/cron_jailkit_plugin.inc.php b/server/plugins-available/cron_jailkit_plugin.inc.php index 2e5f06eea..1e4713846 100644 --- a/server/plugins-available/cron_jailkit_plugin.inc.php +++ b/server/plugins-available/cron_jailkit_plugin.inc.php @@ -116,6 +116,8 @@ class cron_jailkit_plugin { $this->app = $app; $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit'); + $app->system->web_folder_protection($parent_domain['document_root'],false); + $this->_update_website_security_level(); $this->_setup_jailkit_chroot(); @@ -126,6 +128,8 @@ class cron_jailkit_plugin { exec($command); $this->_update_website_security_level(); + + $app->system->web_folder_protection($parent_domain['document_root'],true); } $app->log("Jailkit Plugin (Cron) -> insert username:".$parent_domain['system_user'],LOGLEVEL_DEBUG); @@ -182,12 +186,14 @@ class cron_jailkit_plugin { $this->app = $app; $this->jailkit_config = $app->getconf->get_server_config($conf["server_id"], 'jailkit'); + $app->system->web_folder_protection($parent_domain['document_root'],false); $this->_update_website_security_level(); $this->_setup_jailkit_chroot(); $this->_add_jailkit_user(); $this->_update_website_security_level(); + $app->system->web_folder_protection($parent_domain['document_root'],true); } $app->log("Jailkit Plugin (Cron) -> update username:".$parent_domain['system_user'],LOGLEVEL_DEBUG); diff --git a/server/plugins-available/shelluser_base_plugin.inc.php b/server/plugins-available/shelluser_base_plugin.inc.php index 5c4186338..a56ec6d72 100755 --- a/server/plugins-available/shelluser_base_plugin.inc.php +++ b/server/plugins-available/shelluser_base_plugin.inc.php @@ -80,6 +80,10 @@ class shelluser_base_plugin { } if($app->system->is_user($data['new']['puser'])) { + + //* Remove webfolder protection + $app->system->web_folder_protection($web['document_root'],false); + // Get the UID of the parent user $uid = intval($app->system->getuid($data['new']['puser'])); if($uid > $this->min_uid) { @@ -114,6 +118,9 @@ class shelluser_base_plugin { exec($command); $app->log("Disabling shelluser temporarily: ".$command,LOGLEVEL_DEBUG); } + + //* Add webfolder protection again + $app->system->web_folder_protection($web['document_root'],true); } else { $app->log("UID = $uid for shelluser:".$data['new']['username']." not allowed.",LOGLEVEL_ERROR); diff --git a/server/plugins-available/shelluser_jailkit_plugin.inc.php b/server/plugins-available/shelluser_jailkit_plugin.inc.php index 671ae62c1..6ffe8e87a 100755 --- a/server/plugins-available/shelluser_jailkit_plugin.inc.php +++ b/server/plugins-available/shelluser_jailkit_plugin.inc.php @@ -71,6 +71,7 @@ class shelluser_jailkit_plugin { global $app, $conf; $app->uses('system'); + $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$this->data['new']['parent_domain_id']); if($app->system->is_user($data['new']['username'])) { @@ -79,6 +80,8 @@ class shelluser_jailkit_plugin { */ if ($data['new']['chroot'] == "jailkit") { + $app->system->web_folder_protection($web['document_root'],false); + // load the server configuration options $app->uses("getconf"); $this->data = $data; @@ -98,6 +101,7 @@ class shelluser_jailkit_plugin { exec($command); $this->_update_website_security_level(); + $app->system->web_folder_protection($web['document_root'],true); } $app->log("Jailkit Plugin -> insert username:".$data['new']['username'],LOGLEVEL_DEBUG); @@ -113,6 +117,7 @@ class shelluser_jailkit_plugin { global $app, $conf; $app->uses('system'); + $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$this->data['new']['parent_domain_id']); if($app->system->is_user($data['new']['username'])) { @@ -121,6 +126,8 @@ class shelluser_jailkit_plugin { */ if ($data['new']['chroot'] == "jailkit") { + $app->system->web_folder_protection($web['document_root'],false); + // load the server configuration options $app->uses("getconf"); $this->data = $data; @@ -136,6 +143,8 @@ class shelluser_jailkit_plugin { $this->_setup_ssh_rsa(); $this->_update_website_security_level(); + + $app->system->web_folder_protection($web['document_root'],true); } $app->log("Jailkit Plugin -> update username:".$data['new']['username'],LOGLEVEL_DEBUG); @@ -155,6 +164,8 @@ class shelluser_jailkit_plugin { $app->uses('system'); + $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".$this->data['old']['parent_domain_id']); + if ($data['old']['chroot'] == "jailkit") { $app->uses("getconf"); @@ -165,6 +176,8 @@ class shelluser_jailkit_plugin { //commented out proved to be dangerous on config errors //exec('rm -rf '.$data['old']['dir'].$jailkit_chroot_userhome); + $app->system->web_folder_protection($web['document_root'],false); + if(@is_dir($data['old']['dir'].$jailkit_chroot_userhome)) { $command = 'userdel -f'; $command .= ' '.escapeshellcmd($data['old']['username']); @@ -172,6 +185,8 @@ class shelluser_jailkit_plugin { $app->log("Jailkit Plugin -> delete chroot home:".$data['old']['dir'].$jailkit_chroot_userhome,LOGLEVEL_DEBUG); } + $app->system->web_folder_protection($web['document_root'],true); + } $app->log("Jailkit Plugin -> delete username:".$data['old']['username'],LOGLEVEL_DEBUG); -- GitLab