Skip to content
Snippets Groups Projects
Commit 625cd822 authored by Thomas Tanghus's avatar Thomas Tanghus
Browse files

Backport CSRF prevention.

parent 3e339f3d
No related branches found
No related tags found
No related merge requests found
......@@ -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'];?>">
......
......@@ -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
*/
......
......@@ -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
......
......@@ -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());
}
}
......
......@@ -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{
......
......@@ -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 dont 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;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment