summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Tanghus <thomas@tanghus.net>2012-06-14 13:52:22 +0200
committerThomas Tanghus <thomas@tanghus.net>2012-06-14 13:52:22 +0200
commit625cd822c3cd9d7f382d4c80e06a344f34e66d06 (patch)
treed781815cc23473ba83b883e9a506d909759d6d6c
parent3e339f3d668e57b76bc9e85e7e7cbb8a1b409d85 (diff)
downloadnextcloud-server-625cd822c3cd9d7f382d4c80e06a344f34e66d06.tar.gz
nextcloud-server-625cd822c3cd9d7f382d4c80e06a344f34e66d06.zip
Backport CSRF prevention.
-rw-r--r--core/templates/layout.user.php10
-rw-r--r--lib/json.php12
-rw-r--r--lib/public/json.php7
-rw-r--r--lib/public/util.php16
-rw-r--r--lib/template.php11
-rw-r--r--lib/util.php73
6 files changed, 125 insertions, 4 deletions
diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php
index e9d105ed043..f9d87981359 100644
--- a/core/templates/layout.user.php
+++ b/core/templates/layout.user.php
@@ -24,6 +24,16 @@
echo '/>';
?>
<?php endforeach; ?>
+ <script type="text/javascript">
+ $(function() {
+ var requesttoken = '<?php echo $_['requesttoken']; ?>';
+ $(document).bind('ajaxSend', function(elm, xhr, s){
+ if(requesttoken) {
+ xhr.setRequestHeader('requesttoken', requesttoken);
+ }
+ });
+ });
+ </script>
</head>
<body id="<?php echo $_['bodyid'];?>">
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;
+ }
+ }
}
+