diff options
author | Thomas Tanghus <thomas@tanghus.net> | 2012-06-14 13:52:22 +0200 |
---|---|---|
committer | Thomas Tanghus <thomas@tanghus.net> | 2012-06-14 13:52:22 +0200 |
commit | 625cd822c3cd9d7f382d4c80e06a344f34e66d06 (patch) | |
tree | d781815cc23473ba83b883e9a506d909759d6d6c /lib | |
parent | 3e339f3d668e57b76bc9e85e7e7cbb8a1b409d85 (diff) | |
download | nextcloud-server-625cd822c3cd9d7f382d4c80e06a344f34e66d06.tar.gz nextcloud-server-625cd822c3cd9d7f382d4c80e06a344f34e66d06.zip |
Backport CSRF prevention.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/json.php | 12 | ||||
-rw-r--r-- | lib/public/json.php | 7 | ||||
-rw-r--r-- | lib/public/util.php | 16 | ||||
-rw-r--r-- | lib/template.php | 11 | ||||
-rw-r--r-- | lib/util.php | 73 |
5 files changed, 115 insertions, 4 deletions
diff --git a/lib/json.php b/lib/json.php index f3bbe9ac899..dfc0a7b894e 100644 --- a/lib/json.php +++ b/lib/json.php @@ -42,6 +42,18 @@ class OC_JSON{ } /** + * @brief Check an ajax get/post call if the request token is valid. + * @return json Error msg if not valid. + */ + public static function callCheck(){ + if( !OC_Util::isCallRegistered()){ + $l = OC_L10N::get('core'); + self::error(array( 'data' => array( 'message' => $l->t('Token expired. Please reload page.') ))); + exit(); + } + } + + /** * Check if the user is a admin, send json error msg if not */ public static function checkAdminUser(){ diff --git a/lib/public/json.php b/lib/public/json.php index 439721ac6ce..69a69925457 100644 --- a/lib/public/json.php +++ b/lib/public/json.php @@ -53,6 +53,13 @@ class JSON { return(\OC_JSON::checkLoggedIn()); } + /** + * @brief Check an ajax get/post call if the request token is valid. + * @return json Error msg if not valid. + */ + public static function callCheck(){ + return(\OC_JSON::callCheck()); + } /** * @brief Send json success msg diff --git a/lib/public/util.php b/lib/public/util.php index 2abffba4c4a..bffe07da3f8 100644 --- a/lib/public/util.php +++ b/lib/public/util.php @@ -249,6 +249,22 @@ class Util { return(\OC_Hook::emit( $signalclass, $signalname, $params )); } + /** + * Register an get/post call. This is important to prevent CSRF attacks + * TODO: write example + */ + public static function callRegister(){ + return(\OC_Util::callRegister()); + } + + + /** + * Check an ajax get/post call if the request token is valid. exit if not. + * Todo: Write howto + */ + public static function callCheck(){ + return(\OC_Util::callCheck()); + } } diff --git a/lib/template.php b/lib/template.php index e908c76bfad..fd2cb34a4a9 100644 --- a/lib/template.php +++ b/lib/template.php @@ -155,11 +155,13 @@ class OC_Template{ $this->renderas = $renderas; $this->application = $app; $this->vars = array(); + if($renderas == 'user') { + $this->vars['requesttoken'] = OC_Util::callRegister(); + } $this->l10n = OC_L10N::get($app); - header('X-Frame-Options: Sameorigin'); - header('X-XSS-Protection: 1; mode=block'); - header('X-Content-Type-Options: nosniff'); - + header('X-Frame-Options: Sameorigin'); + header('X-XSS-Protection: 1; mode=block'); + header('X-Content-Type-Options: nosniff'); $this->findTemplate($name); } @@ -355,6 +357,7 @@ class OC_Template{ if( $this->renderas == "user" ){ $page = new OC_Template( "core", "layout.user" ); $page->assign('searchurl',OC_Helper::linkTo( 'search', 'index.php' )); + $page->assign('requesttoken', $this->vars['requesttoken']); if(array_search(OC_APP::getCurrentApp(),array('settings','admin','help'))!==false){ $page->assign('bodyid','body-settings'); }else{ diff --git a/lib/util.php b/lib/util.php index 49f658f3c0e..c47a7e5d84c 100644 --- a/lib/util.php +++ b/lib/util.php @@ -331,4 +331,77 @@ class OC_Util { } exit(); } + + /** + * @brief Register an get/post call. This is important to prevent CSRF attacks + * Todo: Write howto + * @return $token Generated token. + */ + public static function callRegister(){ + //mamimum time before token exires + $maxtime=(60*60); // 1 hour + + // generate a random token. + $token=mt_rand(1000,9000).mt_rand(1000,9000).mt_rand(1000,9000); + + // store the token together with a timestamp in the session. + $_SESSION['requesttoken-'.$token]=time(); + + // cleanup old tokens garbage collector + // only run every 20th time so we donīt waste cpu cycles + if(rand(0,20)==0) { + foreach($_SESSION as $key=>$value) { + // search all tokens in the session + if(substr($key,0,12)=='requesttoken') { + if($value+$maxtime<time()){ + // remove outdated tokens + unset($_SESSION[$key]); + } + } + } + } + // return the token + return($token); + } + + /** + * @brief Check an ajax get/post call if the request token is valid. + * @return boolean False if request token is not set or is invalid. + */ + public static function isCallRegistered(){ + //mamimum time before token exires + $maxtime=(60*60); // 1 hour + if(isset($_GET['requesttoken'])) { + $token=$_GET['requesttoken']; + }elseif(isset($_POST['requesttoken'])){ + $token=$_POST['requesttoken']; + }elseif(isset($_SERVER['HTTP_REQUESTTOKEN'])){ + $token=$_SERVER['HTTP_REQUESTTOKEN']; + }else{ + //no token found. + return false; + } + if(isset($_SESSION['requesttoken-'.$token])) { + $timestamp=$_SESSION['requesttoken-'.$token]; + if($timestamp+$maxtime<time()){ + return false; + }else{ + //token valid + return true; + } + }else{ + return false; + } + } + + /** + * @brief Check an ajax get/post call if the request token is valid. exit if not. + * Todo: Write howto + */ + public static function callCheck(){ + if(!OC_Util::isCallRegistered()) { + exit; + } + } } + |