From 625cd822c3cd9d7f382d4c80e06a344f34e66d06 Mon Sep 17 00:00:00 2001 From: Thomas Tanghus Date: Thu, 14 Jun 2012 13:52:22 +0200 Subject: [PATCH] Backport CSRF prevention. --- core/templates/layout.user.php | 10 +++++ lib/json.php | 12 ++++++ lib/public/json.php | 7 ++++ lib/public/util.php | 16 ++++++++ lib/template.php | 11 +++-- lib/util.php | 73 ++++++++++++++++++++++++++++++++++ 6 files changed, 125 insertions(+), 4 deletions(-) diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php index e9d105ed04..f9d8798135 100644 --- a/core/templates/layout.user.php +++ b/core/templates/layout.user.php @@ -24,6 +24,16 @@ echo '/>'; ?> + diff --git a/lib/json.php b/lib/json.php index f3bbe9ac89..dfc0a7b894 100644 --- a/lib/json.php +++ b/lib/json.php @@ -41,6 +41,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 */ diff --git a/lib/public/json.php b/lib/public/json.php index 439721ac6c..69a6992545 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 2abffba4c4..bffe07da3f 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 e908c76bfa..fd2cb34a4a 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 49f658f3c0..c47a7e5d84 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