Skip to content

Commit d218b22

Browse files
committed
csrf: tighten csrf code paths a little
o restructure session open/close for better visibility o remove potentially insecure "try again" button o remove override for switching csrf off (defer)
1 parent bef4c80 commit d218b22

File tree

2 files changed

+11
-70
lines changed

2 files changed

+11
-70
lines changed

src/www/csrf/csrf-magic.php

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,6 @@
1515

1616
// CONFIGURATION:
1717

18-
/**
19-
* By default, when you include this file csrf-magic will automatically check
20-
* and exit if the CSRF token is invalid. This will defer executing
21-
* csrf_check() until you're ready. You can also pass false as a parameter to
22-
* that function, in which case the function will not exit but instead return
23-
* a boolean false if the CSRF check failed. This allows for tighter integration
24-
* with your system.
25-
*/
26-
$GLOBALS['csrf']['defer'] = false;
27-
2818
/**
2919
* This is the amount of seconds you wish to allow before any token becomes
3020
* invalid; the default is two hours, which should be more than enough for
@@ -117,12 +107,6 @@
117107
*/
118108
$GLOBALS['csrf']['frame-breaker'] = true;
119109

120-
/**
121-
* Whether or not CSRF Magic should be allowed to start a new session in order
122-
* to determine the key.
123-
*/
124-
$GLOBALS['csrf']['auto-session'] = true;
125-
126110
/**
127111
* Whether or not csrf-magic should produce XHTML style tags.
128112
*/
@@ -187,7 +171,6 @@ function csrf_check($fatal = true)
187171
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
188172
return true;
189173
}
190-
csrf_start();
191174
$name = $GLOBALS['csrf']['input-name'];
192175
$ok = false;
193176
$tokens = '';
@@ -232,7 +215,6 @@ function csrf_get_tokens()
232215
} else {
233216
$ip = '';
234217
}
235-
csrf_start();
236218

237219
// These are "strong" algorithms that don't require per se a secret
238220
if (session_id()) {
@@ -259,46 +241,18 @@ function csrf_get_tokens()
259241
return 'invalid';
260242
}
261243

262-
function csrf_flattenpost($data)
263-
{
264-
$ret = array();
265-
foreach ($data as $n => $v) {
266-
$ret = array_merge($ret, csrf_flattenpost2(1, $n, $v));
267-
}
268-
return $ret;
269-
}
270-
function csrf_flattenpost2($level, $key, $data)
271-
{
272-
if (!is_array($data)) {
273-
return array($key => $data);
274-
}
275-
$ret = array();
276-
foreach ($data as $n => $v) {
277-
$nk = $level >= 1 ? $key."[$n]" : "[$n]";
278-
$ret = array_merge($ret, csrf_flattenpost2($level+1, $nk, $v));
279-
}
280-
return $ret;
281-
}
282-
283244
/**
284245
* @param $tokens is safe for HTML consumption
285246
*/
286247
function csrf_callback($tokens)
287248
{
288249
// (yes, $tokens is safe to echo without escaping)
289250
header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden');
290-
$data = '';
291-
foreach (csrf_flattenpost($_POST) as $key => $value) {
292-
if ($key == $GLOBALS['csrf']['input-name']) {
293-
continue;
294-
}
295-
$data .= '<input type="hidden" name="'.htmlspecialchars($key).'" value="'.htmlspecialchars($value).'" />';
296-
}
251+
297252
echo "<html><head><title>CSRF check failed</title></head>
298253
<body>
299254
<p>CSRF check failed. Your form session may have expired, or you may not have
300255
cookies enabled.</p>
301-
<form method='post' action=''>$data<input type='submit' value='Try again' /></form>
302256
<p>Debug: $tokens</p></body></html>
303257
";
304258
}
@@ -398,16 +352,6 @@ function csrf_conf($key, $val)
398352
$GLOBALS['csrf'][$key] = $val;
399353
}
400354

401-
/**
402-
* Starts a session if we're allowed to.
403-
*/
404-
function csrf_start()
405-
{
406-
if ($GLOBALS['csrf']['auto-session'] && session_status() == PHP_SESSION_NONE) {
407-
session_start();
408-
}
409-
}
410-
411355
/**
412356
* Retrieves the secret, and generates one if necessary.
413357
*/
@@ -469,6 +413,4 @@ function csrf_hash($value, $time = null)
469413
ob_start('csrf_ob_handler');
470414
}
471415
// Perform check
472-
if (!$GLOBALS['csrf']['defer']) {
473-
csrf_check();
474-
}
416+
csrf_check();

src/www/guiconfig.inc

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,17 @@ require_once("config.inc");
3434

3535
/* THIS MUST BE ABOVE ALL OTHER CODE */
3636
if (empty($nocsrf)) {
37-
function csrf_startup()
38-
{
39-
csrf_conf('rewrite-js', '/csrf/csrf-magic.js');
40-
$timeout_minutes = isset($config['system']['webgui']['session_timeout']) ? $config['system']['webgui']['session_timeout'] : 240;
41-
csrf_conf('expires', $timeout_minutes * 60);
42-
}
43-
require_once('csrf/csrf-magic.php');
37+
function csrf_startup() {
38+
global $config;
4439

45-
// make sure the session is closed after executing csrf-magic
46-
if (session_status() != PHP_SESSION_NONE) {
47-
session_write_close();
40+
csrf_conf('rewrite-js', '/csrf/csrf-magic.js');
41+
$timeout_minutes = isset($config['system']['webgui']['session_timeout']) ? $config['system']['webgui']['session_timeout'] : 240;
42+
csrf_conf('expires', $timeout_minutes * 60);
4843
}
44+
45+
session_start();
46+
require_once('csrf/csrf-magic.php');
47+
session_write_close();
4948
}
5049

5150
function set_language()

0 commit comments

Comments
 (0)