From bbb954fd8dfb51856405b6cb7f3717cf7633e866 Mon Sep 17 00:00:00 2001
From: tbrehm <t.brehm@ispconfig.org>
Date: Wed, 04 Apr 2012 02:30:25 -0400
Subject: [PATCH] Extended path checks for ftp and shell users.

---
 server/plugins-available/ftpuser_base_plugin.inc.php   |   12 ++++++++++++
 server/plugins-available/shelluser_base_plugin.inc.php |   14 ++++++++++++++
 interface/web/sites/shell_user_edit.php                |    2 ++
 interface/web/sites/ftp_user_edit.php                  |    2 ++
 interface/web/sites/lib/lang/en_shell_user.lng         |    2 ++
 interface/web/sites/lib/lang/en_ftp_user.lng           |    2 ++
 6 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/interface/web/sites/ftp_user_edit.php b/interface/web/sites/ftp_user_edit.php
index 337fe16..f6d0288 100644
--- a/interface/web/sites/ftp_user_edit.php
+++ b/interface/web/sites/ftp_user_edit.php
@@ -106,6 +106,8 @@
 		
 		if(isset($this->dataRecord['username']) && trim($this->dataRecord['username']) == '') $app->tform->errorMessage .= $app->tform->lng('username_error_empty').'<br />';
 		if(isset($this->dataRecord['username']) && empty($this->dataRecord['parent_domain_id'])) $app->tform->errorMessage .= $app->tform->lng('parent_domain_id_error_empty').'<br />';
+		if(isset($this->dataRecord['dir']) && stristr($this->dataRecord['dir'],'..')) $app->tform->errorMessage .= $app->tform->lng('dir_dot_error').'<br />';
+		if(isset($this->dataRecord['dir']) && stristr($this->dataRecord['dir'],'./')) $app->tform->errorMessage .= $app->tform->lng('dir_slashdot_error').'<br />';
 		
 		parent::onSubmit();
 	}
diff --git a/interface/web/sites/lib/lang/en_ftp_user.lng b/interface/web/sites/lib/lang/en_ftp_user.lng
index 88c644e..4598b03 100644
--- a/interface/web/sites/lib/lang/en_ftp_user.lng
+++ b/interface/web/sites/lib/lang/en_ftp_user.lng
@@ -26,4 +26,6 @@
 $wb['directory_error_notinweb'] = 'Directory not inside of web root directory.';
 $wb["parent_domain_id_error_empty"] = 'No website selected.';
 $wb["quota_size_error_regex"] = 'Quota: enter a -1 for unlimited or a number > 0';
+$wb['dir_dot_error'] = 'No .. in path allowed.';
+$wb['dir_slashdot_error'] = 'No ./ in path allowed.';
 ?>
diff --git a/interface/web/sites/lib/lang/en_shell_user.lng b/interface/web/sites/lib/lang/en_shell_user.lng
index e05fd25..b703ad0 100644
--- a/interface/web/sites/lib/lang/en_shell_user.lng
+++ b/interface/web/sites/lib/lang/en_shell_user.lng
@@ -21,4 +21,6 @@
 $wb["limit_shell_user_txt"] = 'The max number of shell users is reached.';
 $wb["parent_domain_id_error_empty"] = 'No website selected.';
 $wb["ssh_rsa_txt"] = 'SSH-RSA Public Key (for key-based logins)';
+$wb['dir_dot_error'] = 'No .. in path allowed.';
+$wb['dir_slashdot_error'] = 'No ./ in path allowed.';
 ?>
diff --git a/interface/web/sites/shell_user_edit.php b/interface/web/sites/shell_user_edit.php
index bb93bf2..e09d8dd 100644
--- a/interface/web/sites/shell_user_edit.php
+++ b/interface/web/sites/shell_user_edit.php
@@ -111,6 +111,8 @@
 		
 		if(isset($this->dataRecord['username']) && trim($this->dataRecord['username']) == '') $app->tform->errorMessage .= $app->tform->lng('username_error_empty').'<br />';
 		if(isset($this->dataRecord['username']) && empty($this->dataRecord['parent_domain_id'])) $app->tform->errorMessage .= $app->tform->lng('parent_domain_id_error_empty').'<br />';
+		if(isset($this->dataRecord['dir']) && stristr($this->dataRecord['dir'],'..')) $app->tform->errorMessage .= $app->tform->lng('dir_dot_error').'<br />';
+		if(isset($this->dataRecord['dir']) && stristr($this->dataRecord['dir'],'./')) $app->tform->errorMessage .= $app->tform->lng('dir_slashdot_error').'<br />';
 		
 		if(isset($this->dataRecord['ssh_rsa'])) $this->dataRecord['ssh_rsa'] = trim($this->dataRecord['ssh_rsa']);
 		
diff --git a/server/plugins-available/ftpuser_base_plugin.inc.php b/server/plugins-available/ftpuser_base_plugin.inc.php
index 42edbb5..8cd2aa2 100644
--- a/server/plugins-available/ftpuser_base_plugin.inc.php
+++ b/server/plugins-available/ftpuser_base_plugin.inc.php
@@ -74,6 +74,12 @@
       
       $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($data['new']['parent_domain_id']));
       
+	  //* Check if the resulting path is inside the docroot
+	  if(substr(realpath($data['new']['dir']),0,strlen($web['document_root'])) != $web['document_root']) {
+		$app->log('User dir is outside of docroot.',LOGLEVEL_WARN);
+		return false;
+	  }
+	  
       exec('mkdir -p '.escapeshellcmd($data['new']['dir']));
       exec('chown '.escapeshellcmd($web["system_user"]).':'.escapeshellcmd($web['system_group']).' '.$data['new']['dir']);
       
@@ -90,6 +96,12 @@
       
       $web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($data['new']['parent_domain_id']));
       
+	  //* Check if the resulting path is inside the docroot
+	  if(substr(realpath($data['new']['dir']),0,strlen($web['document_root'])) != $web['document_root']) {
+		$app->log('User dir is outside of docroot.',LOGLEVEL_WARN);
+		return false;
+	  }
+	  
       exec('mkdir -p '.escapeshellcmd($data['new']['dir']));
       exec('chown '.escapeshellcmd($web["system_user"]).':'.escapeshellcmd($web['system_group']).' '.$data['new']['dir']);
       
diff --git a/server/plugins-available/shelluser_base_plugin.inc.php b/server/plugins-available/shelluser_base_plugin.inc.php
index f411251..5c41863 100755
--- a/server/plugins-available/shelluser_base_plugin.inc.php
+++ b/server/plugins-available/shelluser_base_plugin.inc.php
@@ -72,6 +72,13 @@
 		
 		$app->uses('system');
 		
+		//* Check if the resulting path is inside the docroot
+		$web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($data['new']['parent_domain_id']));
+		if(substr(realpath($data['new']['dir']),0,strlen($web['document_root'])) != $web['document_root']) {
+			$app->log('Directory of the shell user is outside of website docroot.',LOGLEVEL_WARN);
+			return false;
+		}
+		
 		if($app->system->is_user($data['new']['puser'])) {
 			// Get the UID of the parent user
 			$uid = intval($app->system->getuid($data['new']['puser']));
@@ -121,6 +128,13 @@
 		
 		$app->uses('system');
 		
+		//* Check if the resulting path is inside the docroot
+		$web = $app->db->queryOneRecord("SELECT * FROM web_domain WHERE domain_id = ".intval($data['new']['parent_domain_id']));
+		if(substr(realpath($data['new']['dir']),0,strlen($web['document_root'])) != $web['document_root']) {
+			$app->log('Directory of the shell user is outside of website docroot.',LOGLEVEL_WARN);
+			return false;
+		}
+		
 		if($app->system->is_user($data['new']['puser'])) {
 			// Get the UID of the parent user
 			$uid = intval($app->system->getuid($data['new']['puser']));

--
Gitblit v1.9.1