Skip to content

Commit 5af0cfd

Browse files
author
Till Brehm
committed
Extended the CSRF check.
1 parent 3f19613 commit 5af0cfd

File tree

15 files changed

+165
-3
lines changed

15 files changed

+165
-3
lines changed

interface/lib/classes/auth.inc.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,56 @@ public function crypt_password($cleartext_password) {
201201
$salt.="$";
202202
return crypt($cleartext_password, $salt);
203203
}
204+
205+
public function csrf_token_get($form_name) {
206+
/* CSRF PROTECTION */
207+
// generate csrf protection id and key
208+
$_csrf_id = uniqid($form_name . '_'); // form id
209+
$_csrf_key = sha1(uniqid(microtime(true), true)); // the key
210+
if(!isset($_SESSION['_csrf'])) $_SESSION['_csrf'] = array();
211+
if(!isset($_SESSION['_csrf_timeout'])) $_SESSION['_csrf_timeout'] = array();
212+
$_SESSION['_csrf'][$_csrf_id] = $_csrf_key;
213+
$_SESSION['_csrf_timeout'][$_csrf_id] = time() + 3600; // timeout hash in 1 hour
214+
215+
return array('csrf_id' => $_csrf_id,'csrf_key' => $_csrf_key);
216+
}
217+
218+
public function csrf_token_check() {
219+
global $app;
220+
221+
if(isset($_POST) && is_array($_POST)) {
222+
$_csrf_valid = false;
223+
if(isset($_POST['_csrf_id']) && isset($_POST['_csrf_key'])) {
224+
$_csrf_id = trim($_POST['_csrf_id']);
225+
$_csrf_key = trim($_POST['_csrf_key']);
226+
if(isset($_SESSION['_csrf']) && isset($_SESSION['_csrf'][$_csrf_id]) && isset($_SESSION['_csrf_timeout']) && isset($_SESSION['_csrf_timeout'][$_csrf_id])) {
227+
if($_SESSION['_csrf'][$_csrf_id] === $_csrf_key && $_SESSION['_csrf_timeout'] >= time()) $_csrf_valid = true;
228+
}
229+
}
230+
if($_csrf_valid !== true) {
231+
$app->log('CSRF attempt blocked. Referer: ' . (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : 'unknown'), LOGLEVEL_WARN);
232+
$app->error($app->lng('err_csrf_attempt_blocked'));
233+
}
234+
$_SESSION['_csrf'][$_csrf_id] = null;
235+
$_SESSION['_csrf_timeout'][$_csrf_id] = null;
236+
unset($_SESSION['_csrf'][$_csrf_id]);
237+
unset($_SESSION['_csrf_timeout'][$_csrf_id]);
238+
239+
if(isset($_SESSION['_csrf_timeout']) && is_array($_SESSION['_csrf_timeout'])) {
240+
$to_unset = array();
241+
foreach($_SESSION['_csrf_timeout'] as $_csrf_id => $timeout) {
242+
if($timeout < time()) $to_unset[] = $_csrf_id;
243+
}
244+
foreach($to_unset as $_csrf_id) {
245+
$_SESSION['_csrf'][$_csrf_id] = null;
246+
$_SESSION['_csrf_timeout'][$_csrf_id] = null;
247+
unset($_SESSION['_csrf'][$_csrf_id]);
248+
unset($_SESSION['_csrf_timeout'][$_csrf_id]);
249+
}
250+
unset($to_unset);
251+
}
252+
}
253+
}
204254

205255
}
206256

interface/lib/classes/tform.inc.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,12 +386,17 @@ function getHTML($record, $tab, $action = 'NEW') {
386386

387387
/* CSRF PROTECTION */
388388
// generate csrf protection id and key
389-
$_csrf_id = uniqid($this->formDef['name'] . '_');
389+
/*$_csrf_id = uniqid($this->formDef['name'] . '_');
390390
$_csrf_value = sha1(uniqid(microtime(true), true));
391391
if(!isset($_SESSION['_csrf'])) $_SESSION['_csrf'] = array();
392392
if(!isset($_SESSION['_csrf_timeout'])) $_SESSION['_csrf_timeout'] = array();
393393
$_SESSION['_csrf'][$_csrf_id] = $_csrf_value;
394394
$_SESSION['_csrf_timeout'][$_csrf_id] = time() + 3600; // timeout hash in 1 hour
395+
*/
396+
$csrf_token = $app->auth->csrf_token_get($this->formDef['name']);
397+
$_csrf_id = $csrf_token['csrf_id'];
398+
$_csrf_value = $csrf_token['csrf_key'];
399+
395400
$this->formDef['tabs'][$tab]['fields']['_csrf_id'] = array(
396401
'datatype' => 'VARCHAR',
397402
'formtype' => 'TEXT',
@@ -669,6 +674,7 @@ function encode($record, $tab, $dbencode = true) {
669674
//$this->errorMessage = '';
670675

671676
/* CSRF PROTECTION */
677+
672678
if(isset($_POST) && is_array($_POST)) {
673679
$_csrf_valid = false;
674680
if(isset($_POST['_csrf_id']) && isset($_POST['_csrf_key'])) {

interface/web/admin/language_add.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@
6565
$app->tpl->setVar('error', $error);
6666

6767
if(isset($_POST['lng_new']) && strlen($_POST['lng_new']) == 2 && $error == '') {
68+
69+
//* CSRF Check
70+
$app->auth->csrf_token_check();
71+
6872
$lng_new = $_POST['lng_new'];
6973
if(!preg_match("/^[a-z]{2}$/i", $lng_new)) die('unallowed characters in language name.');
7074

@@ -94,6 +98,11 @@
9498

9599
$app->tpl->setVar('msg', $msg);
96100

101+
//* SET csrf token
102+
$csrf_token = $app->auth->csrf_token_get('language_add');
103+
$app->tpl->setVar('_csrf_id',$csrf_token['csrf_id']);
104+
$app->tpl->setVar('_csrf_key',$csrf_token['csrf_key']);
105+
97106
//* load language file
98107
$lng_file = 'lib/lang/'.$_SESSION['s']['language'].'_language_add.lng';
99108
include $lng_file;

interface/web/admin/language_complete.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@
6767
// Export the language file
6868
if(isset($_POST['lng_select']) && $error == '') {
6969

70+
//* CSRF Check
71+
$app->auth->csrf_token_check();
72+
7073
// complete the global langauge file
7174
merge_langfile(ISPC_LIB_PATH."/lang/".$selected_language.".lng", ISPC_LIB_PATH."/lang/en.lng");
7275

@@ -157,6 +160,11 @@ function merge_langfile($langfile, $masterfile) {
157160

158161
$app->tpl->setVar('msg', $msg);
159162

163+
//* SET csrf token
164+
$csrf_token = $app->auth->csrf_token_get('language_merge');
165+
$app->tpl->setVar('_csrf_id',$csrf_token['csrf_id']);
166+
$app->tpl->setVar('_csrf_key',$csrf_token['csrf_key']);
167+
160168
//* load language file
161169
$lng_file = 'lib/lang/'.$_SESSION['s']['language'].'_language_complete.lng';
162170
include $lng_file;

interface/web/admin/language_edit.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555

5656
//* Save data
5757
if(isset($_POST['records']) && is_array($_POST['records'])) {
58+
59+
//* CSRF Check
60+
$app->auth->csrf_token_check();
61+
5862
$file_content = "<?php\n";
5963
foreach($_POST['records'] as $key => $val) {
6064
$val = stripslashes($val);
@@ -93,6 +97,11 @@
9397
unset($wb);
9498
}
9599

100+
//* SET csrf token
101+
$csrf_token = $app->auth->csrf_token_get('language_edit');
102+
$app->tpl->setVar('_csrf_id',$csrf_token['csrf_id']);
103+
$app->tpl->setVar('_csrf_key',$csrf_token['csrf_key']);
104+
96105

97106
//* load language file
98107
$lng_file = 'lib/lang/'.$_SESSION['s']['language'].'_language_edit.lng';

interface/web/admin/language_import.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ function validate_line($line) {
129129

130130
// Export the language file
131131
if(isset($_FILES['file']['name']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
132+
133+
//* CSRF Check
134+
$app->auth->csrf_token_check();
135+
132136
$lines = file($_FILES['file']['tmp_name']);
133137
// initial check
134138
$parts = explode('|', $lines[0]);
@@ -183,6 +187,11 @@ function validate_line($line) {
183187
$app->tpl->setVar('msg', $msg);
184188
$app->tpl->setVar('error', $error);
185189

190+
//* SET csrf token
191+
$csrf_token = $app->auth->csrf_token_get('language_import');
192+
$app->tpl->setVar('_csrf_id',$csrf_token['csrf_id']);
193+
$app->tpl->setVar('_csrf_key',$csrf_token['csrf_key']);
194+
186195
//* load language file
187196
$lng_file = 'lib/lang/'.$_SESSION['s']['language'].'_language_import.lng';
188197
include $lng_file;

interface/web/admin/remote_action_ispcupdate.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666

6767
//* Note: Disabled post action
6868
if (1 == 0 && isset($_POST['server_select'])) {
69+
70+
//* CSRF Check
71+
$app->auth->csrf_token_check();
72+
6973
$server = $_POST['server_select'];
7074
$servers = array();
7175
if ($server == '*') {
@@ -95,6 +99,11 @@
9599

96100
$app->tpl->setVar('msg', $msg);
97101

102+
//* SET csrf token
103+
$csrf_token = $app->auth->csrf_token_get('ispupdate');
104+
$app->tpl->setVar('_csrf_id',$csrf_token['csrf_id']);
105+
$app->tpl->setVar('_csrf_key',$csrf_token['csrf_key']);
106+
98107
$app->tpl->setVar($wb);
99108

100109
$app->tpl_defaults();

interface/web/admin/remote_action_osupdate.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@
6262
* If the user wants to do the action, write this to our db
6363
*/
6464
if (isset($_POST['server_select'])) {
65+
66+
//* CSRF Check
67+
$app->auth->csrf_token_check();
68+
6569
$server = $_POST['server_select'];
6670
$servers = array();
6771
if ($server == '*') {
@@ -91,6 +95,11 @@
9195

9296
$app->tpl->setVar('msg', $msg);
9397

98+
//* SET csrf token
99+
$csrf_token = $app->auth->csrf_token_get('osupdate');
100+
$app->tpl->setVar('_csrf_id',$csrf_token['csrf_id']);
101+
$app->tpl->setVar('_csrf_key',$csrf_token['csrf_key']);
102+
94103
$app->tpl->setVar($wb);
95104

96105
$app->tpl_defaults();

interface/web/client/client_message.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@
5151

5252
//* Save data
5353
if(isset($_POST) && count($_POST) > 1) {
54-
54+
55+
//* CSRF Check
56+
$app->auth->csrf_token_check();
57+
5558
//* Check values
5659
if(!preg_match("/^\w+[\w\.\-\+]*\w{0,}@\w+[\w.-]*\w+\.[a-zA-Z0-9\-]{2,30}$/i", $_POST['sender'])) $error .= $wb['sender_invalid_error'].'<br />';
5760
if(empty($_POST['subject'])) $error .= $wb['subject_invalid_error'].'<br />';
@@ -161,6 +164,11 @@
161164
}
162165
$app->tpl->setVar('message_variables', trim($message_variables));
163166

167+
//* SET csrf token
168+
$csrf_token = $app->auth->csrf_token_get('client_message');
169+
$app->tpl->setVar('_csrf_id',$csrf_token['csrf_id']);
170+
$app->tpl->setVar('_csrf_key',$csrf_token['csrf_key']);
171+
164172
$app->tpl->setVar('okmsg', $msg);
165173
$app->tpl->setVar('error', $error);
166174

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
<tmpl_dyninclude name="content_tpl">
1+
<tmpl_dyninclude name="content_tpl">
2+
<input type="hidden" name="_csrf_id" value="{tmpl_var name='_csrf_id'}" />
3+
<input type="hidden" name="_csrf_key" value="{tmpl_var name='_csrf_key'}" />

0 commit comments

Comments
 (0)