CSRF protection

Added a simple CSRF protection
This commit is contained in:
Phyks 2013-08-24 23:53:52 +02:00
parent f468fef559
commit c276d719cd
8 changed files with 59 additions and 27 deletions

2
TODO
View File

@ -1,7 +1,5 @@
* i18n
* Vérification des variables dans les classes + throw exception
* tokens + ban system
* remember me
* htmlspecialchars => on users objects
* handle negative amounts
* Refactor load method to avoir load_* methods !

21
inc/CSRF.inc.php Normal file
View File

@ -0,0 +1,21 @@
<?php
// Generates a token against CSRF
function generate_token($name = '')
{
if(session_id() == '') session_start();
$token = uniqid(rand(), true);
$_SESSION[$name.'_token'] = $token;
$_SESSION[$name.'_token_time'] = time();
return $token;
}
// Checks that the anti-CSRF token is correct
function check_token($time, $name = '')
{
if(session_id() == '') session_start();
if(isset($_SESSION[$name.'_token']) && isset($_SESSION[$name.'_token_time']) && isset($_POST['token']))
if($_SESSION[$name.'_token'] == $_POST['token'])
if($_SESSION[$name.'_token_time'] >= (time() - $time))
return true;
return false;
}

View File

@ -7,6 +7,7 @@
require_once('inc/rain.tpl.class.php');
require_once('inc/functions.php');
require_once('inc/Banc.inc.php');
require_once('inc/CSRF.inc.php');
raintpl::$tpl_dir = 'tpl/';
raintpl::$cache_dir = 'tmp/';
@ -56,7 +57,7 @@
header('location: index.php?do=connect');
exit();
}
// Initialize empty $_GET['do'] if required to avoid error
if(empty($_GET['do'])) {
$_GET['do'] = '';
@ -69,7 +70,7 @@
header('location: index.php');
exit();
}
if(!empty($_POST['login']) && !empty($_POST['password'])) {
if(!empty($_POST['login']) && !empty($_POST['password']) && check_token(600, 'connection')) {
$user = new User();
$user->setLogin($_POST['login']);
if(ban_canLogin() == false) {
@ -101,9 +102,9 @@
}
}
}
$tpl->assign('connection', true);
$tpl->assign('user_post', (!empty($_POST['login'])) ? htmlspecialchars($_POST['login']) : '');
$tpl->draw('connexion');
$tpl->assign('token', generate_token('connection'));
$tpl->draw('connection');
break;
case 'disconnect':
@ -138,20 +139,22 @@
}
if(!empty($_POST['login']) && !empty($_POST['display_name']) && (!empty($_POST['password']) || !empty($_POST['user_id'])) && isset($_POST['admin'])) {
$user = new User();
if(!empty($_POST['user_id'])) {
$user->setId($_POST['user_id']);
}
$user->setLogin($_POST['login']);
$user->setDisplayName($_POST['display_name']);
if(!empty($_POST['password'])) {
$user->setPassword($user->encrypt($_POST['password']));
}
$user->setAdmin($_POST['admin']);
$user->save();
if(check_token('edit_users')) {
$user = new User();
if(!empty($_POST['user_id'])) {
$user->setId($_POST['user_id']);
}
$user->setLogin($_POST['login']);
$user->setDisplayName($_POST['display_name']);
if(!empty($_POST['password'])) {
$user->setPassword($user->encrypt($_POST['password']));
}
$user->setAdmin($_POST['admin']);
$user->save();
header('location: index.php?do=edit_users');
exit();
header('location: index.php?do=edit_users');
exit();
}
}
if(!empty($_GET['user_id']) || $_GET['do'] == 'add_user') {
@ -174,6 +177,7 @@
$tpl->assign('login_post', (!empty($_POST['login']) ? htmlspecialchars($_POST['login']) : ''));
$tpl->assign('display_name_post', (!empty($_POST['display_name']) ? htmlspecialchars($_POST['display_name']) : ''));
$tpl->assign('admin_post', (isset($_POST['admin']) ? (int) $_POST['admin'] : -1));
$tpl->assign('token', generate_token('edit_users'));
$tpl->draw('edit_users');
break;
@ -202,7 +206,7 @@
break;
case 'settings':
if(!empty($_POST['mysql_host']) && !empty($_POST['mysql_login']) && !empty($_POST['mysql_db']) && !empty($_POST['currency']) && !empty($_POST['instance_title']) && !empty($_POST['base_url']) && !empty($_POST['timezone']) && !empty($_POST['email_webmaster'])) {
if(!empty($_POST['mysql_host']) && !empty($_POST['mysql_login']) && !empty($_POST['mysql_db']) && !empty($_POST['currency']) && !empty($_POST['instance_title']) && !empty($_POST['base_url']) && !empty($_POST['timezone']) && !empty($_POST['email_webmaster']) && check_token(600, 'settings')) {
if(!is_writable('data/')) {
$tpl>assign('error', 'The script can\'t write in data/ dir, check permissions set on this folder.');
}
@ -246,6 +250,7 @@
$tpl->assign('mysql_prefix', MYSQL_PREFIX);
$tpl->assign('timezone', @date_default_timezone_get());
$tpl->assign('show_settings', true);
$tpl->assign('token', generate_token('settings'));
$tpl->draw('settings');
break;
@ -271,7 +276,7 @@
if(!empty($_POST['date_year'])) $date_year = $_POST['date_year'];
if(!empty($_POST['users_in'])) $users_in = $_POST['users_in'];
if(!empty($_POST['what']) && !empty($_POST['amount']) && (float) $_POST['amount'] != 0 && !empty($_POST['date_day']) && !empty($_POST['date_month']) && !empty($_POST['date_year']) && !empty($_POST['users_in'])) {
if(!empty($_POST['what']) && !empty($_POST['amount']) && (float) $_POST['amount'] != 0 && !empty($_POST['date_day']) && !empty($_POST['date_month']) && !empty($_POST['date_year']) && !empty($_POST['users_in']) && check_token(600, 'new_invoice')) {
$invoice = new Invoice();
if(!empty($_POST['id']))
@ -312,6 +317,7 @@
$tpl->assign('users_in', (!empty($users_in) ? $users_in : array()));
$tpl->assign('guests', (!empty($guests) ? $guests : array()));
$tpl->assign('id', (!empty($_GET['id']) ? (int) $_GET['id'] : 0));
$tpl->assign('token', generate_token('new_invoice'));
$tpl->draw('new_invoice');
break;

View File

@ -1,4 +1,6 @@
<?php
require_once('inc/CSRF.inc.php');
if(file_exists('data/config.php')) exit("Your Bouffe@Ulm instance is already configured. You should either delete data/config.php to access this page or delete the install.php for security reasons if you are ok with the configuration.");
if(!function_exists("file_get_contents") && !function_exists("file_put_contents")) {
@ -11,7 +13,7 @@
$block_form = true;
}
if(!empty($_POST['mysql_host']) && !empty($_POST['mysql_login']) && !empty($_POST['mysql_db']) && !empty($_POST['admin_login']) && !empty($_POST['admin_password']) && !empty($_POST['currency']) && !empty($_POST['instance_title']) && !empty($_POST['base_url']) && !empty($_POST['timezone']) && !empty($_POST['email_webmaster'])) {
if(!empty($_POST['mysql_host']) && !empty($_POST['mysql_login']) && !empty($_POST['mysql_db']) && !empty($_POST['admin_login']) && !empty($_POST['admin_password']) && !empty($_POST['currency']) && !empty($_POST['instance_title']) && !empty($_POST['base_url']) && !empty($_POST['timezone']) && !empty($_POST['email_webmaster']) && check_token(600, 'install')) {
$mysql_host = $_POST['mysql_host'];
$mysql_login = $_POST['mysql_login'];
$mysql_db = $_POST['mysql_db'];
@ -139,7 +141,7 @@
<p><label for="admin_display_name">Displayed name for admin user : </label><input type="text" name="admin_display_name" id="admin_display_name" <?php echo (!empty($_POST['admin_display_name']) ? 'value="'.htmlspecialchars($_POST['admin_display_name']).'"' : '');?>/></p>
<p><label for="admin_password">Password for the admin : </label><input type="password" name="admin_password" id="admin_password"/> <a href="" onclick="toggle_password('admin_password'); return false;"><img src="img/toggle_password.jpg" alt="Toggle visible"/></a></p>
</fieldset>
<p class="center"><input <?php echo (!empty($block_form)) ? 'disabled ' : '';?>type="submit" value="Install"></p>
<p class="center"><input <?php echo (!empty($block_form)) ? 'disabled ' : '';?>type="submit" value="Install"><input type="hidden" name="token" value="<?php echo generate_token('install');?>"/></p>
</form>
</body>
</html>

View File

@ -6,7 +6,7 @@
<p><label for="login" class="label-block">Username : </label><input type="text" name="login" id="login" value="{$user_post}"/></p>
<p><label for="password" class="label-block">Password : </label><input type="password" name="password" id="password"/></p>
<p><input type="checkbox" name="remember_me" id="remember_me" value="1"/><label for="remember_me"> Remember me ?</label></p>
<p><input type="submit" value="Connect"/></p>
<p><input type="submit" value="Connect"/><input type="hidden" name="token" value="{$token}"/></p>
<p><a href="mailto:{$email_webmaster}?subject={$instance_title}%20password">Forgotten password ?</a></p>
</form>

View File

@ -50,6 +50,7 @@
<p class="center">
<input type="submit" value="{$user_id != -1 ? 'Edit' : 'Add'}"/>
{if condition="$user_id != -1"}<input type="hidden" name="user_id" value="{$user_id}"/>{/if}
<input type="hidden" name="token" value="{$token}"/>
</p>
</form>
@ -58,6 +59,6 @@
<form method="post" action="index.php?do=password" id="edit_password_form">
<p><label for="password" class="label-block">New password : </label><input type="password" id="password" name="password"/></p>
<p><label for="password_confirm" class="label-block">Confirm new password : </label><input type="password" id="password_confirm" name="password_confirm"/></p>
<p class="center"><input type="submit" value="Update"/></p>
<p class="center"><input type="submit" value="Update"/><input type="hidden" name="token" value="{$token}"</p>
</form>
{/if}

View File

@ -38,6 +38,7 @@
<p>
<input type="submit" value="Add"/>
{if condition="$id != 0"}<input type="hidden" name="id" value="{$id}"/>{/if}
<input type="hidden" name="token" value="{$token"}/>
</p>
</form>

View File

@ -8,7 +8,10 @@
<textarea name="notice" rows="15" id="textarea_notice">{$notice}</textarea>
</p>
<p><em>Note :</em> You can use HTML formatting in this form.</p>
<input type="submit" value="Submit"/>
<p>
<input type="submit" value="Submit"/>
<input type="hidden" name="token" value="{$token}"/>
</p>
</form>
{else}
@ -47,7 +50,7 @@
</p>
<p><label for="email_webmaster">Webmaster's email : </label><input type="text" name="email_webmaster" id="email_webmaster" value="{$email_webmaster}"/></p>
</fieldset>
<p class="center"><input type="submit" value="Update settings"></p>
<p class="center"><input type="submit" value="Update settings"><input type="hidden" name="token" value="{$token}"/></p>
</form>
{/if}