summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gohr <andi@splitbrain.org>2007-08-29 22:15:38 +0200
committerAndreas Gohr <andi@splitbrain.org>2007-08-29 22:15:38 +0200
commit634d7150e59d03e4a4987164bfe9948fb8828c70 (patch)
tree93357ea3c0c54840cf5ef040ecbc75ddbb3a5b66
parent0e1a261ed103bc8f11934d76ec8c7ec412f02220 (diff)
downloadrpg-634d7150e59d03e4a4987164bfe9948fb8828c70.tar.gz
rpg-634d7150e59d03e4a4987164bfe9948fb8828c70.tar.bz2
CSRF prevention for admin plugins
This patch adds a session based token to all form in the default action plugins. The validity of the token is checked before any administrative function is executed aiming to protect DokuWiki's admin functions from Cross-site request forgery (CSRF) attacks. Another patch will follow to add the same functionality on other, less critical functions. More details on CSRF attacks can be found at http://en.wikipedia.org/wiki/Cross-site_request_forgery darcs-hash:20070829201538-7ad00-d0770224a3351fd8e38968e3a9d8e73520482445.gz
-rw-r--r--inc/common.php38
-rw-r--r--inc/plugin.php4
-rw-r--r--lib/plugins/acl/admin.php7
-rw-r--r--lib/plugins/config/admin.php2
-rw-r--r--lib/plugins/plugin/admin.php7
-rw-r--r--lib/plugins/revert/admin.php3
-rw-r--r--lib/plugins/usermanager/admin.php8
7 files changed, 63 insertions, 6 deletions
diff --git a/inc/common.php b/inc/common.php
index e812d181d..73e8e9369 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -53,6 +53,44 @@ function stripctl($string){
}
/**
+ * Return a secret token to be used for CSRF attack prevention
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @link http://en.wikipedia.org/wiki/Cross-site_request_forgery
+ * @link http://christ1an.blogspot.com/2007/04/preventing-csrf-efficiently.html
+ * @return string
+ */
+function getSecurityToken(){
+ return md5(auth_cookiesalt().session_id());
+}
+
+/**
+ * Check the secret CSRF token
+ */
+function checkSecurityToken($token=null){
+ if(is_null($token)) $token = $_REQUEST['sectok'];
+ if(getSecurityToken() != $token){
+ msg('Security Token did not match. Possible CSRF attack.',-1);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Print a hidden form field with a secret CSRF token
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ */
+function formSecurityToken($print=true){
+ $ret = '<input type="hidden" name="sectok" value="'.getSecurityToken().'" />'."\n";
+ if($print){
+ echo $ret;
+ }else{
+ return $ret;
+ }
+}
+
+/**
* Return info about the current document as associative
* array.
*
diff --git a/inc/plugin.php b/inc/plugin.php
index d7dea4130..763b57bf2 100644
--- a/inc/plugin.php
+++ b/inc/plugin.php
@@ -155,7 +155,7 @@ class DokuWiki_Plugin {
return $conf;
}
-
+
/**
* Loads a given helper plugin (if enabled)
*
@@ -163,7 +163,7 @@ class DokuWiki_Plugin {
*
* @param $name name of plugin to load
* @param $msg message to display in case the plugin is not available
- *
+ *
* @return object helper plugin object
*/
function loadHelper($name, $msg){
diff --git a/lib/plugins/acl/admin.php b/lib/plugins/acl/admin.php
index 172c13af3..dd50bfb39 100644
--- a/lib/plugins/acl/admin.php
+++ b/lib/plugins/acl/admin.php
@@ -78,7 +78,9 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin {
if($user == '@all') $user = '@ALL'; //special group! (now case insensitive)
$perm = (int) $perm;
if($perm > AUTH_DELETE) $perm = AUTH_DELETE;
- //FIXME sanitize scope!!!
+
+ // check token
+ if(!checkSecurityToken()) return;
//nothing to do?
if(empty($cmd) || empty($scope) || empty($user)) return;
@@ -295,6 +297,7 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin {
ptln(' <input type="hidden" name="do" value="admin" />',4);
ptln(' <input type="hidden" name="page" value="acl" />',4);
ptln(' <input type="hidden" name="acl_cmd" value="save" />',4);
+ formSecurityToken();
//scope select
ptln($this->lang['acl_perms'],4);
@@ -374,6 +377,7 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin {
// update form
ptln('<td class="centeralign">',4);
ptln(' <form method="post" action="'.wl($ID).'"><div class="no">',4);
+ formSecurityToken();
ptln(' <input type="hidden" name="do" value="admin" />',4);
ptln(' <input type="hidden" name="page" value="acl" />',4);
ptln(' <input type="hidden" name="acl_cmd" value="save" />',4);
@@ -392,6 +396,7 @@ class admin_plugin_acl extends DokuWiki_Admin_Plugin {
$ask .= $id.' '.$conf['name'].' '.$conf['perm'];
ptln('<td class="centeralign">',4);
ptln(' <form method="post" action="'.wl($ID).'" onsubmit="return confirm(\''.str_replace('\\\\n','\\n',addslashes($ask)).'\')"><div class="no">',4);
+ formSecurityToken();
ptln(' <input type="hidden" name="do" value="admin" />',4);
ptln(' <input type="hidden" name="page" value="acl" />',4);
ptln(' <input type="hidden" name="acl_cmd" value="delete" />',4);
diff --git a/lib/plugins/config/admin.php b/lib/plugins/config/admin.php
index 26880b390..f251eac7d 100644
--- a/lib/plugins/config/admin.php
+++ b/lib/plugins/config/admin.php
@@ -58,6 +58,7 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin {
global $ID;
if (!$this->_restore_session()) return $this->_close_session();
+ if (!checkSecurityToken()) return $this->_close_session();
if (!isset($_REQUEST['save']) || ($_REQUEST['save'] != 1)) return $this->_close_session();
if (is_null($this->_config)) { $this->_config = new configuration($this->_file); }
@@ -111,6 +112,7 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin {
ptln('<div class="success">'.$this->getLang('updated').'</div>');
ptln('<form action="'.wl($ID).'" method="post">');
+ formSecurityToken();
$this->_print_h1('dokuwiki_settings', $this->getLang('_header_dokuwiki'));
$undefined_settings = array();
diff --git a/lib/plugins/plugin/admin.php b/lib/plugins/plugin/admin.php
index 5172568a3..5845f5183 100644
--- a/lib/plugins/plugin/admin.php
+++ b/lib/plugins/plugin/admin.php
@@ -116,6 +116,11 @@ class admin_plugin_plugin extends DokuWiki_Admin_Plugin {
$this->plugin = '';
}
+ if(($this->cmd != 'manage' || $this->plugin != '') && !checkSecurityToken()){
+ $this->cmd = 'manage';
+ $this->plugin = '';
+ }
+
// create object to handle the command
$class = "ap_".$this->cmd;
if (!class_exists($class)) $class = 'ap_manage';
@@ -181,6 +186,7 @@ class ap_manage {
ptln(' <fieldset class="hidden">',4);
ptln(' <input type="hidden" name="do" value="admin" />');
ptln(' <input type="hidden" name="page" value="plugin" />');
+ formSecurityToken();
ptln(' </fieldset>');
ptln(' <fieldset>');
ptln(' <legend>'.$this->lang['download'].'</legend>');
@@ -199,6 +205,7 @@ class ap_manage {
ptln(' <fieldset class="hidden">');
ptln(' <input type="hidden" name="do" value="admin" />');
ptln(' <input type="hidden" name="page" value="plugin" />');
+ formSecurityToken();
ptln(' </fieldset>');
$this->html_pluginlist();
diff --git a/lib/plugins/revert/admin.php b/lib/plugins/revert/admin.php
index d148779d6..c96328981 100644
--- a/lib/plugins/revert/admin.php
+++ b/lib/plugins/revert/admin.php
@@ -67,7 +67,7 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin {
$this->_searchform();
- if(is_array($_REQUEST['revert'])){
+ if(is_array($_REQUEST['revert']) && checkSecurityToken()){
$this->_revert($_REQUEST['revert'],$_REQUEST['filter']);
}elseif(isset($_REQUEST['filter'])){
$this->_list($_REQUEST['filter']);
@@ -133,6 +133,7 @@ class admin_plugin_revert extends DokuWiki_Admin_Plugin {
echo '<hr /><br />';
echo '<form action="" method="post">';
echo '<input type="hidden" name="filter" value="'.hsc($filter).'" />';
+ formSecurityToken();
$recents = getRecents(0,$this->max_lines);
echo '<ul>';
diff --git a/lib/plugins/usermanager/admin.php b/lib/plugins/usermanager/admin.php
index 4d9288116..b32e8daf6 100644
--- a/lib/plugins/usermanager/admin.php
+++ b/lib/plugins/usermanager/admin.php
@@ -170,6 +170,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
ptln("<p>".sprintf($this->lang['nonefound'],$this->_auth->getUserCount())."</p>");
}
ptln("<form action=\"".wl($ID)."\" method=\"post\">");
+ formSecurityToken();
ptln(" <table class=\"inline\">");
ptln(" <thead>");
ptln(" <tr>");
@@ -268,6 +269,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
}
ptln("<form action=\"".wl($ID)."\" method=\"post\">",$indent);
+ formSecurityToken();
ptln(" <table class=\"inline\">",$indent);
ptln(" <thead>",$indent);
ptln(" <tr><th>".$this->lang["field"]."</th><th>".$this->lang["value"]."</th></tr>",$indent);
@@ -334,7 +336,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
}
function _addUser(){
-
+ if (!checkSecurityToken()) return false;
if (!$this->_auth->canDo('addUser')) return false;
list($user,$pass,$name,$mail,$grps) = $this->_retrieveUser();
@@ -362,7 +364,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
* Delete user
*/
function _deleteUser(){
-
+ if (!checkSecurityToken()) return false;
if (!$this->_auth->canDo('delUser')) return false;
$selected = $_REQUEST['delete'];
@@ -386,6 +388,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
* Edit user (a user has been selected for editing)
*/
function _editUser($param) {
+ if (!checkSecurityToken()) return false;
if (!$this->_auth->canDo('UserMod')) return false;
$user = cleanID(preg_replace('/.*:/','',$param));
@@ -407,6 +410,7 @@ class admin_plugin_usermanager extends DokuWiki_Admin_Plugin {
* Modify user (modified user data has been recieved)
*/
function _modifyUser(){
+ if (!checkSecurityToken()) return false;
if (!$this->_auth->canDo('UserMod')) return false;
// get currently valid user data