Permalink
Browse files

Use global request tokens and automatically protect all POST requests

  • Loading branch information...
1 parent 61e96cd commit 5499336feff22f682448dd99cc00a9b36701fcd1 @thomascube thomascube committed Jul 21, 2009
View
@@ -2,7 +2,7 @@
/*
+-------------------------------------------------------------------------+
| RoundCube Webmail IMAP Client |
- | Version 0.3-20090702 |
+ | Version 0.3-20090721 |
| |
| Copyright (C) 2005-2009, RoundCube Dev. - Switzerland |
| |
@@ -143,11 +143,16 @@
// check client X-header to verify request origin
if ($OUTPUT->ajax_call) {
- if (!$RCMAIL->config->get('devel_mode') && !rc_request_header('X-RoundCube-Referer')) {
+ if (!$RCMAIL->config->get('devel_mode') && rc_request_header('X-RoundCube-Request') != $RCMAIL->get_request_token()) {
header('HTTP/1.1 404 Not Found');
die("Invalid Request");
}
}
+// check request token in POST form submissions
+else if (!empty($_POST) && !$RCMAIL->check_request()) {
+ $OUTPUT->show_message('invalidrequest', 'error');
+ $OUTPUT->send($RCMAIL->task);
+}
// not logged in -> show login page
@@ -872,33 +872,29 @@ public function shutdown()
/**
* Generate a unique token to be used in a form request
*
- * @param string Request identifier
* @return string The request token
*/
- public function get_request_token($key)
+ public function get_request_token()
{
- if (!$this->request_tokens[$key])
- $_SESSION['request_tokens'][$key] = $this->request_tokens[$key] = md5(uniqid($key . rand(), true));
+ $key = $this->task;
- return $this->request_tokens[$key];
+ if (!$_SESSION['request_tokens'][$key])
+ $_SESSION['request_tokens'][$key] = md5(uniqid($key . rand(), true));
+
+ return $_SESSION['request_tokens'][$key];
}
/**
* Check if the current request contains a valid token
*
- * @param string Request identifier
+ * @param int Request method
* @return boolean True if request token is valid false if not
*/
- public function check_request($key, $mode = RCUBE_INPUT_POST)
+ public function check_request($mode = RCUBE_INPUT_POST)
{
$token = get_input_value('_token', $mode);
- $valid = !(empty($token) || $_SESSION['request_tokens'][$key] != $token);
-
- if ($valid)
- unset($_SESSION['request_tokens'][$key]);
-
- return $valid;
+ return !empty($token) && $_SESSION['request_tokens'][$this->task] == $token;
}
@@ -59,6 +59,7 @@ public function __construct($task, $framed = false)
//$this->framed = $framed;
$this->set_env('task', $task);
+ $this->set_env('request_token', $this->app->get_request_token());
// load the correct skin (in case user-defined)
$this->set_skin($this->config['skin']);
@@ -325,6 +326,9 @@ public function write($template = '')
$js = $this->framed ? "if(window.parent) {\n" : '';
$js .= $this->get_js_commands() . ($this->framed ? ' }' : '');
$this->add_script($js, 'head_top');
+
+ // make sure all <form> tags have a valid request token
+ $template = preg_replace_callback('/<form\s+([^>]+)>/Ui', array($this, 'alter_form_tag'), $template);
// call super method
parent::write($template, $this->config['skin_path']);
@@ -514,7 +518,24 @@ private function parse_conditions($input)
*/
private function check_condition($condition)
{
- return eval("return (".$this->parse_expression($condition).");");
+ return eval("return (".$this->parse_expression($condition).");");
+ }
+
+
+ /**
+ *
+ */
+ private function alter_form_tag($matches)
+ {
+ $out = $matches[0];
+ $attrib = parse_attrib_string($matches[1]);
+
+ if (strtolower($attrib['method']) == 'post') {
+ $hidden = new html_hiddenfield(array('name' => '_token', 'value' => $this->app->get_request_token()));
+ $out .= "\n" . $hidden->show();
+ }
+
+ return $out;
}
@@ -957,10 +978,6 @@ public function request_form($attrib, $content = '')
$hidden->add(array('name' => '_action', 'value' => $attrib['action']));
}
- // generate request token
- $request_key = $attrib['request'] ? $attrib['request'] : $attrib['action'];
- $hidden->add(array('name' => '_token', 'value' => $this->app->get_request_token($request_key)));
-
unset($attrib['task'], $attrib['request']);
$attrib['action'] = './';
View
@@ -55,7 +55,7 @@ function rcube_webmail()
// set jQuery ajax options
jQuery.ajaxSetup({ cache:false,
error:function(request, status, err){ ref.http_error(request, status, err); },
- beforeSend:function(xmlhttp){ xmlhttp.setRequestHeader('X-RoundCube-Referer', bw.get_cookie('roundcube_sessid')); }
+ beforeSend:function(xmlhttp){ xmlhttp.setRequestHeader('X-RoundCube-Request', ref.env.request_token); }
});
// set environment variable(s)
@@ -5,7 +5,7 @@
| program/steps/addressbook/save.inc |
| |
| This file is part of the RoundCube Webmail client |
- | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland |
+ | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
@@ -22,14 +22,6 @@
$cid = get_input_value('_cid', RCUBE_INPUT_POST);
$return_action = empty($cid) ? 'add' : 'show';
-// check request token and exit if invalid
-if (!$RCMAIL->check_request('save.'.intval($cid), RCUBE_INPUT_POST))
-{
- $OUTPUT->show_message('invalidrequest', 'error');
- rcmail_overwrite_action($return_action);
- return;
-}
-
// cannot edit record
if ($CONTACTS->readonly)
{
@@ -5,7 +5,7 @@
| program/steps/settings/save_identity.inc |
| |
| This file is part of the RoundCube Webmail client |
- | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland |
+ | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
@@ -26,12 +26,6 @@ $a_html_cols = array('signature');
$a_boolean_cols = array('standard', 'html_signature');
$updated = $default_id = false;
-// check request token
-if (!$RCMAIL->check_request('save-identity.'.intval(get_input_value('_iid', RCUBE_INPUT_POST)), RCUBE_INPUT_POST)) {
- $OUTPUT->show_message('invalidrequest', 'error');
- rcmail_overwrite_action('identities');
- return;
-}
// check input
if (empty($_POST['_name']) || (empty($_POST['_email']) && IDENTITIES_LEVEL != 1 && IDENTITIES_LEVEL != 3))
{
@@ -5,7 +5,7 @@
| program/steps/settings/save_prefs.inc |
| |
| This file is part of the RoundCube Webmail client |
- | Copyright (C) 2005-2007, RoundCube Dev. - Switzerland |
+ | Copyright (C) 2005-2009, RoundCube Dev. - Switzerland |
| Licensed under the GNU GPL |
| |
| PURPOSE: |
@@ -19,13 +19,6 @@
*/
-// check request token and exit if invalid
-if (!$RCMAIL->check_request('save-prefs', RCUBE_INPUT_POST)) {
- $OUTPUT->show_message('invalidrequest', 'error');
- rcmail_overwrite_action('preferences');
- return;
-}
-
$a_user_prefs = array(
'language' => isset($_POST['_language']) ? get_input_value('_language', RCUBE_INPUT_POST) : $CONFIG['language'],
'timezone' => isset($_POST['_timezone']) ? (is_numeric($_POST['_timezone']) ? floatval($_POST['_timezone']) : get_input_value('_timezone', RCUBE_INPUT_POST)) : $CONFIG['timezone'],

0 comments on commit 5499336

Please sign in to comment.