From f989b8060b24784980a1003e998f07938ef657d0 Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 17:05:00 +0200 Subject: [PATCH 01/19] always verify csrf token for resource-modifying requests, that is post, put, patch, delete --- includes/functions.php | 20 ++++++++++++++++++++ index.php | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/includes/functions.php b/includes/functions.php index 06ef2e0f..316665d3 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -82,6 +82,26 @@ function CSRFValidate() } } +/** +* Should the request be CSRF-validated? +*/ +function csrfValidateRequest() +{ + $request_method = strtolower($_SERVER['REQUEST_METHOD']); + return in_array($request_method, [ "post", "put", "patch", "delete" ]); +} + +/** +* Handle invalid CSRF +*/ +function handleInvalidCSRFToken() +{ + header('HTTP/1.1 500 Internal Server Error'); + header('Content-Type: text/plain'); + echo 'Invalid CSRF token'; + exit; +} + /** * Test whether array is associative */ diff --git a/index.php b/index.php index 8189e175..e8af838a 100755 --- a/index.php +++ b/index.php @@ -39,6 +39,10 @@ include_once('includes/about.php'); $output = $return = 0; $page = $_GET['page']; +if (csrfValidateRequest() && !CSRFValidate()) { + handleInvalidCSRFToken(); +} + if (empty($_SESSION['csrf_token'])) { if (function_exists('mcrypt_create_iv')) { $_SESSION['csrf_token'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); From 87fe8948b8bec0d1b13174dbd15de392d163852b Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 17:05:41 +0200 Subject: [PATCH 02/19] remove splattered, duplicated csrf validation code since we do that always and early, now. --- ajax/networking/gen_int_config.php | 2 +- ajax/networking/get_int_config.php | 2 +- ajax/networking/get_ip_summary.php | 2 +- ajax/networking/save_int_config.php | 2 +- includes/admin.php | 46 +++++----- includes/configure_client.php | 2 +- includes/dhcp.php | 138 +++++++++++++--------------- includes/hostapd.php | 36 +++----- includes/system.php | 10 +- 9 files changed, 104 insertions(+), 136 deletions(-) diff --git a/ajax/networking/gen_int_config.php b/ajax/networking/gen_int_config.php index d0f59ff3..8d042991 100644 --- a/ajax/networking/gen_int_config.php +++ b/ajax/networking/gen_int_config.php @@ -3,7 +3,7 @@ session_start(); include_once('../../includes/config.php'); include_once('../../includes/functions.php'); -if(isset($_POST['generate']) && isset($_POST['csrf_token']) && CSRFValidate()) { +if(isset($_POST['generate'])) { $cnfNetworking = array_diff(scandir(RASPI_CONFIG_NETWORKING, 1),array('..','.','dhcpcd.conf')); $cnfNetworking = array_combine($cnfNetworking,$cnfNetworking); $strConfFile = ""; diff --git a/ajax/networking/get_int_config.php b/ajax/networking/get_int_config.php index d29ee735..d39f12b3 100644 --- a/ajax/networking/get_int_config.php +++ b/ajax/networking/get_int_config.php @@ -4,7 +4,7 @@ include_once('../../includes/config.php'); include_once('../../includes/functions.php'); -if(isset($_POST['interface']) && isset($_POST['csrf_token']) && CSRFValidate()) { +if(isset($_POST['interface'])) { $int = preg_replace('/[^a-z0-9]/', '', $_POST['interface']); if(!file_exists(RASPI_CONFIG_NETWORKING.'/'.$int.'.ini')) { touch(RASPI_CONFIG_NETWORKING.'/'.$int.'.ini'); diff --git a/ajax/networking/get_ip_summary.php b/ajax/networking/get_ip_summary.php index 810c6265..3383337d 100644 --- a/ajax/networking/get_ip_summary.php +++ b/ajax/networking/get_ip_summary.php @@ -2,7 +2,7 @@ session_start(); include_once('../../includes/functions.php'); -if(isset($_POST['interface']) && isset($_POST['csrf_token']) && CSRFValidate()) { +if(isset($_POST['interface'])) { $int = preg_replace('/[^a-z0-9]/','',$_POST['interface']); exec('ip a s '.$int,$intOutput,$intResult); $intOutput = array_map('htmlentities', $intOutput); diff --git a/ajax/networking/save_int_config.php b/ajax/networking/save_int_config.php index 77fcd865..e8b4f4d1 100644 --- a/ajax/networking/save_int_config.php +++ b/ajax/networking/save_int_config.php @@ -2,7 +2,7 @@ session_start(); include_once('../../includes/config.php'); include_once('../../includes/functions.php'); - if(isset($_POST['interface']) && isset($_POST['csrf_token']) && CSRFValidate()) { + if(isset($_POST['interface'])) { $int = $_POST['interface']; $cfg = []; $file = $int.".ini"; diff --git a/includes/admin.php b/includes/admin.php index b335f6be..22353461 100755 --- a/includes/admin.php +++ b/includes/admin.php @@ -6,34 +6,30 @@ function DisplayAuthConfig($username, $password) { $status = new StatusMessages(); if (isset($_POST['UpdateAdminPassword'])) { - if (CSRFValidate()) { - if (password_verify($_POST['oldpass'], $password)) { - $new_username=trim($_POST['username']); - if ($_POST['newpass'] !== $_POST['newpassagain']) { - $status->addMessage('New passwords do not match', 'danger'); - } elseif ($new_username == '') { - $status->addMessage('Username must not be empty', 'danger'); - } else { - if (!file_exists(RASPI_ADMIN_DETAILS)) { - $tmpauth = fopen(RASPI_ADMIN_DETAILS, 'w'); - fclose($tmpauth); - } - - if ($auth_file = fopen(RASPI_ADMIN_DETAILS, 'w')) { - fwrite($auth_file, $new_username.PHP_EOL); - fwrite($auth_file, password_hash($_POST['newpass'], PASSWORD_BCRYPT).PHP_EOL); - fclose($auth_file); - $username = $new_username; - $status->addMessage('Admin password updated'); - } else { - $status->addMessage('Failed to update admin password', 'danger'); - } - } + if (password_verify($_POST['oldpass'], $password)) { + $new_username=trim($_POST['username']); + if ($_POST['newpass'] !== $_POST['newpassagain']) { + $status->addMessage('New passwords do not match', 'danger'); + } elseif ($new_username == '') { + $status->addMessage('Username must not be empty', 'danger'); } else { - $status->addMessage('Old password does not match', 'danger'); + if (!file_exists(RASPI_ADMIN_DETAILS)) { + $tmpauth = fopen(RASPI_ADMIN_DETAILS, 'w'); + fclose($tmpauth); + } + + if ($auth_file = fopen(RASPI_ADMIN_DETAILS, 'w')) { + fwrite($auth_file, $new_username.PHP_EOL); + fwrite($auth_file, password_hash($_POST['newpass'], PASSWORD_BCRYPT).PHP_EOL); + fclose($auth_file); + $username = $new_username; + $status->addMessage('Admin password updated'); + } else { + $status->addMessage('Failed to update admin password', 'danger'); + } } } else { - error_log('CSRF violation'); + $status->addMessage('Old password does not match', 'danger'); } } ?> diff --git a/includes/configure_client.php b/includes/configure_client.php index 8c3f08b3..d1640041 100755 --- a/includes/configure_client.php +++ b/includes/configure_client.php @@ -53,7 +53,7 @@ function DisplayWPAConfig() if (isset($_POST['connect'])) { $result = 0; exec('sudo wpa_cli -i ' . RASPI_WPA_CTRL_INTERFACE . ' select_network '.strval($_POST['connect'])); - } elseif (isset($_POST['client_settings']) && CSRFValidate()) { + } elseif (isset($_POST['client_settings'])) { $tmp_networks = $networks; if ($wpa_file = fopen('/tmp/wifidata', 'w')) { fwrite($wpa_file, 'ctrl_interface=DIR=' . RASPI_WPA_CTRL_INTERFACE . ' GROUP=netdev' . PHP_EOL); diff --git a/includes/dhcp.php b/includes/dhcp.php index cc5133c1..82e80bec 100755 --- a/includes/dhcp.php +++ b/includes/dhcp.php @@ -12,64 +12,60 @@ function DisplayDHCPConfig() $status = new StatusMessages(); if (isset($_POST['savedhcpdsettings'])) { - if (CSRFValidate()) { - $errors = ''; - define('IFNAMSIZ', 16); - if (!preg_match('/^[a-zA-Z0-9]+$/', $_POST['interface']) || - strlen($_POST['interface']) >= IFNAMSIZ) { - $errors .= _('Invalid interface name.').'
'.PHP_EOL; + $errors = ''; + define('IFNAMSIZ', 16); + if (!preg_match('/^[a-zA-Z0-9]+$/', $_POST['interface']) || + strlen($_POST['interface']) >= IFNAMSIZ) { + $errors .= _('Invalid interface name.').'
'.PHP_EOL; + } + + if (!preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/', $_POST['RangeStart']) && + !empty($_POST['RangeStart'])) { // allow ''/null ? + $errors .= _('Invalid DHCP range start.').'
'.PHP_EOL; + } + + if (!preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/', $_POST['RangeEnd']) && + !empty($_POST['RangeEnd'])) { // allow ''/null ? + $errors .= _('Invalid DHCP range end.').'
'.PHP_EOL; + } + + if (!ctype_digit($_POST['RangeLeaseTime']) && $_POST['RangeLeaseTimeUnits'] !== 'infinite') { + $errors .= _('Invalid DHCP lease time, not a number.').'
'.PHP_EOL; + } + + if (!in_array($_POST['RangeLeaseTimeUnits'], array('m', 'h', 'd', 'infinite'))) { + $errors .= _('Unknown DHCP lease time unit.').'
'.PHP_EOL; + } + + $return = 1; + if (empty($errors)) { + $config = 'interface='.$_POST['interface'].PHP_EOL. + 'dhcp-range='.$_POST['RangeStart'].','.$_POST['RangeEnd']. + ',255.255.255.0,'; + if ($_POST['RangeLeaseTimeUnits'] !== 'infinite') { + $config .= $_POST['RangeLeaseTime']; } - if (!preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/', $_POST['RangeStart']) && - !empty($_POST['RangeStart'])) { // allow ''/null ? - $errors .= _('Invalid DHCP range start.').'
'.PHP_EOL; - } + $config .= $_POST['RangeLeaseTimeUnits'].PHP_EOL; - if (!preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/', $_POST['RangeEnd']) && - !empty($_POST['RangeEnd'])) { // allow ''/null ? - $errors .= _('Invalid DHCP range end.').'
'.PHP_EOL; - } - - if (!ctype_digit($_POST['RangeLeaseTime']) && $_POST['RangeLeaseTimeUnits'] !== 'infinite') { - $errors .= _('Invalid DHCP lease time, not a number.').'
'.PHP_EOL; - } - - if (!in_array($_POST['RangeLeaseTimeUnits'], array('m', 'h', 'd', 'infinite'))) { - $errors .= _('Unknown DHCP lease time unit.').'
'.PHP_EOL; - } - - $return = 1; - if (empty($errors)) { - $config = 'interface='.$_POST['interface'].PHP_EOL. - 'dhcp-range='.$_POST['RangeStart'].','.$_POST['RangeEnd']. - ',255.255.255.0,'; - if ($_POST['RangeLeaseTimeUnits'] !== 'infinite') { - $config .= $_POST['RangeLeaseTime']; + for ($i=0; $i < count($_POST["static_leases"]["mac"]); $i++) { + $mac = trim($_POST["static_leases"]["mac"][$i]); + $ip = trim($_POST["static_leases"]["ip"][$i]); + if ($mac != "" && $ip != "") { + $config .= "dhcp-host=$mac,$ip".PHP_EOL; } - - $config .= $_POST['RangeLeaseTimeUnits'].PHP_EOL; - - for ($i=0; $i < count($_POST["static_leases"]["mac"]); $i++) { - $mac = trim($_POST["static_leases"]["mac"][$i]); - $ip = trim($_POST["static_leases"]["ip"][$i]); - if ($mac != "" && $ip != "") { - $config .= "dhcp-host=$mac,$ip".PHP_EOL; - } - } - - file_put_contents("/tmp/dhcpddata", $config); - system('sudo cp /tmp/dhcpddata '.RASPI_DNSMASQ_CONFIG, $return); - } else { - $status->addMessage($errors, 'danger'); } - if ($return == 0) { - $status->addMessage('Dnsmasq configuration updated successfully', 'success'); - } else { - $status->addMessage('Dnsmasq configuration failed to be updated.', 'danger'); - } + file_put_contents("/tmp/dhcpddata", $config); + system('sudo cp /tmp/dhcpddata '.RASPI_DNSMASQ_CONFIG, $return); } else { - error_log('CSRF violation'); + $status->addMessage($errors, 'danger'); + } + + if ($return == 0) { + $status->addMessage('Dnsmasq configuration updated successfully', 'success'); + } else { + $status->addMessage('Dnsmasq configuration failed to be updated.', 'danger'); } } @@ -77,36 +73,28 @@ function DisplayDHCPConfig() $dnsmasq_state = ($dnsmasq[0] > 0); if (isset($_POST['startdhcpd'])) { - if (CSRFValidate()) { - if ($dnsmasq_state) { - $status->addMessage('dnsmasq already running', 'info'); - } else { - exec('sudo /etc/init.d/dnsmasq start', $dnsmasq, $return); - if ($return == 0) { - $status->addMessage('Successfully started dnsmasq', 'success'); - $dnsmasq_state = true; - } else { - $status->addMessage('Failed to start dnsmasq', 'danger'); - } - } + if ($dnsmasq_state) { + $status->addMessage('dnsmasq already running', 'info'); } else { - error_log('CSRF violation'); + exec('sudo /etc/init.d/dnsmasq start', $dnsmasq, $return); + if ($return == 0) { + $status->addMessage('Successfully started dnsmasq', 'success'); + $dnsmasq_state = true; + } else { + $status->addMessage('Failed to start dnsmasq', 'danger'); + } } } elseif (isset($_POST['stopdhcpd'])) { - if (CSRFValidate()) { - if ($dnsmasq_state) { - exec('sudo /etc/init.d/dnsmasq stop', $dnsmasq, $return); - if ($return == 0) { - $status->addMessage('Successfully stopped dnsmasq', 'success'); - $dnsmasq_state = false; - } else { - $status->addMessage('Failed to stop dnsmasq', 'danger'); - } + if ($dnsmasq_state) { + exec('sudo /etc/init.d/dnsmasq stop', $dnsmasq, $return); + if ($return == 0) { + $status->addMessage('Successfully stopped dnsmasq', 'success'); + $dnsmasq_state = false; } else { - $status->addMessage('dnsmasq already stopped', 'info'); + $status->addMessage('Failed to stop dnsmasq', 'danger'); } } else { - error_log('CSRF violation'); + $status->addMessage('dnsmasq already stopped', 'info'); } } else { if ($dnsmasq_state) { diff --git a/includes/hostapd.php b/includes/hostapd.php index 6912bd92..0da1c795 100755 --- a/includes/hostapd.php +++ b/includes/hostapd.php @@ -22,34 +22,22 @@ function DisplayHostAPDConfig() exec("ip -o link show | awk -F': ' '{print $2}'", $interfaces); if (isset($_POST['SaveHostAPDSettings'])) { - if (CSRFValidate()) { - SaveHostAPDConfig($arrSecurity, $arrEncType, $arr80211Standard, $interfaces, $status); - } else { - error_log('CSRF violation'); - } + SaveHostAPDConfig($arrSecurity, $arrEncType, $arr80211Standard, $interfaces, $status); } elseif (isset($_POST['StartHotspot'])) { - if (CSRFValidate()) { - $status->addMessage('Attempting to start hotspot', 'info'); - if ($arrHostapdConf['WifiAPEnable'] == 1) { - exec('sudo /etc/raspap/hostapd/servicestart.sh --interface uap0 --seconds 3', $return); - } else { - exec('sudo /etc/raspap/hostapd/servicestart.sh --seconds 5', $return); - } - foreach ($return as $line) { - $status->addMessage($line, 'info'); - } + $status->addMessage('Attempting to start hotspot', 'info'); + if ($arrHostapdConf['WifiAPEnable'] == 1) { + exec('sudo /etc/raspap/hostapd/servicestart.sh --interface uap0 --seconds 3', $return); } else { - error_log('CSRF violation'); + exec('sudo /etc/raspap/hostapd/servicestart.sh --seconds 5', $return); + } + foreach ($return as $line) { + $status->addMessage($line, 'info'); } } elseif (isset($_POST['StopHotspot'])) { - if (CSRFValidate()) { - $status->addMessage('Attempting to stop hotspot', 'info'); - exec('sudo /etc/init.d/hostapd stop', $return); - foreach ($return as $line) { - $status->addMessage($line, 'info'); - } - } else { - error_log('CSRF violation'); + $status->addMessage('Attempting to stop hotspot', 'info'); + exec('sudo /etc/init.d/hostapd stop', $return); + foreach ($return as $line) { + $status->addMessage($line, 'info'); } } diff --git a/includes/system.php b/includes/system.php index 4b27c1d9..746963c9 100755 --- a/includes/system.php +++ b/includes/system.php @@ -63,13 +63,9 @@ function DisplaySystem() $status = new StatusMessages(); if (isset($_POST['SaveLanguage'])) { - if (CSRFValidate()) { - if (isset($_POST['locale'])) { - $_SESSION['locale'] = $_POST['locale']; - $status->addMessage('Language setting saved', 'success'); - } - } else { - error_log('CSRF violation'); + if (isset($_POST['locale'])) { + $_SESSION['locale'] = $_POST['locale']; + $status->addMessage('Language setting saved', 'success'); } } From 20bb9fe42f5f9018e93a041948421065ca6cf885 Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 17:22:03 +0200 Subject: [PATCH 03/19] add csrf meta tag (for use with xhr, for example) --- includes/functions.php | 9 +++++++++ index.php | 1 + 2 files changed, 10 insertions(+) diff --git a/includes/functions.php b/includes/functions.php index 316665d3..31790d5b 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -67,6 +67,15 @@ function CSRFToken() '; +} + /** * * Validate CSRF Token diff --git a/index.php b/index.php index e8af838a..f204ea12 100755 --- a/index.php +++ b/index.php @@ -64,6 +64,7 @@ $theme_url = 'dist/css/'.htmlspecialchars($theme, ENT_QUOTES); + From ce3ec131a6978654e10a4b7d980b4d187230cf46 Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 17:26:30 +0200 Subject: [PATCH 04/19] add csrf token header to all resource-modifying xhr --- js/custom.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/custom.js b/js/custom.js index 7d8875bf..96b1f163 100644 --- a/js/custom.js +++ b/js/custom.js @@ -162,6 +162,15 @@ function setupBtns() { }); } +$.ajaxSetup({ + beforeSend: function(xhr, settings) { + var csrfToken = $('meta[name=csrf_token]').attr('content'); + if (/^(POST|PATCH|PUT|DELETE)$/i.test(settings.type)) { + xhr.setRequestHeader("X-CSRF-Token", csrfToken); + } + } +}); + $().ready(function(){ csrf = $('#csrf_token').val(); pageCurrent = window.location.href.split("?")[1].split("=")[1]; From 0967a53152173acefbfec3df2b4b7cf23cf7f5c8 Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 17:28:03 +0200 Subject: [PATCH 05/19] validate token value from csrf token header if supplied and not overridden by post request param --- includes/functions.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/includes/functions.php b/includes/functions.php index 31790d5b..5facfe76 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -83,7 +83,19 @@ function CSRFMetaTag() */ function CSRFValidate() { - if (hash_equals($_POST['csrf_token'], $_SESSION['csrf_token'])) { + $post_token = $_POST['csrf_token']; + $header_token = $_SERVER['HTTP_X_CSRF_TOKEN']; + + if (empty($post_token) && empty($header_token)) { + return false; + } + + $request_token = $post_token; + if (empty($post_token)) { + $request_token = $header_token; + } + + if (hash_equals($_SESSION['csrf_token'], $request_token)) { return true; } else { error_log('CSRF violation'); From d53517a34afff6cb91cff56753bd6172cd582440 Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 17:36:34 +0200 Subject: [PATCH 06/19] removed useless line of code --- index.php | 1 - 1 file changed, 1 deletion(-) diff --git a/index.php b/index.php index f204ea12..bbb6603d 100755 --- a/index.php +++ b/index.php @@ -50,7 +50,6 @@ if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(openssl_random_pseudo_bytes(32)); } } -$csrf_token = $_SESSION['csrf_token']; if (!isset($_COOKIE['theme'])) { $theme = "custom.css"; From b9e9b7fe39ab913efc794cb60a4e2af1dfc0fb5e Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 17:38:33 +0200 Subject: [PATCH 07/19] move csrf token initialization into function --- includes/functions.php | 14 ++++++++++++++ index.php | 8 +------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index 5facfe76..24da797f 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -54,6 +54,20 @@ function safefilerewrite($fileName, $dataToSave) } } +/** +* Saves a CSRF token in the session +*/ +function ensureCSRFSessionToken() +{ + if (empty($_SESSION['csrf_token'])) { + if (function_exists('mcrypt_create_iv')) { + $_SESSION['csrf_token'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); + } else { + $_SESSION['csrf_token'] = bin2hex(openssl_random_pseudo_bytes(32)); + } + } +} + /** * * Add CSRF Token to form diff --git a/index.php b/index.php index bbb6603d..ce91ea77 100755 --- a/index.php +++ b/index.php @@ -43,13 +43,7 @@ if (csrfValidateRequest() && !CSRFValidate()) { handleInvalidCSRFToken(); } -if (empty($_SESSION['csrf_token'])) { - if (function_exists('mcrypt_create_iv')) { - $_SESSION['csrf_token'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); - } else { - $_SESSION['csrf_token'] = bin2hex(openssl_random_pseudo_bytes(32)); - } -} +ensureCSRFSessionToken(); if (!isset($_COOKIE['theme'])) { $theme = "custom.css"; From b38dbb82ab248e838aaf024adc7d1a7e9eead0d2 Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 19:57:35 +0200 Subject: [PATCH 08/19] do net send csrf tokens individually with post xhr since we set it in a `beforeSend` callback --- js/custom.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/js/custom.js b/js/custom.js index 96b1f163..8cdcdcdd 100644 --- a/js/custom.js +++ b/js/custom.js @@ -19,7 +19,7 @@ function createNetmaskAddr(bitCount) { } function loadSummary(strInterface) { - $.post('/ajax/networking/get_ip_summary.php',{interface:strInterface,csrf_token:csrf},function(data){ + $.post('/ajax/networking/get_ip_summary.php',{interface:strInterface},function(data){ jsonData = JSON.parse(data); console.log(jsonData); if(jsonData['return'] == 0) { @@ -50,7 +50,7 @@ function setupTabs() { } function loadCurrentSettings(strInterface) { - $.post('/ajax/networking/get_int_config.php',{interface:strInterface,csrf_token:csrf},function(data){ + $.post('/ajax/networking/get_int_config.php',{interface:strInterface},function(data){ jsonData = JSON.parse(data); $.each(jsonData['output'],function(i,v) { var int = v['interface']; @@ -102,7 +102,6 @@ function saveNetworkSettings(int) { } }); arrFormData['interface'] = int; - arrFormData['csrf_token'] = csrf; $.post('/ajax/networking/save_int_config.php',arrFormData,function(data){ //console.log(data); var jsonData = JSON.parse(data); @@ -113,7 +112,6 @@ function saveNetworkSettings(int) { function applyNetworkSettings() { var int = $(this).data('int'); arrFormData = {}; - arrFormData['csrf_token'] = csrf; arrFormData['generate'] = ''; $.post('/ajax/networking/gen_int_config.php',arrFormData,function(data){ console.log(data); @@ -172,7 +170,6 @@ $.ajaxSetup({ }); $().ready(function(){ - csrf = $('#csrf_token').val(); pageCurrent = window.location.href.split("?")[1].split("=")[1]; pageCurrent = pageCurrent.replace("#",""); $('#side-menu').metisMenu(); From 490cb14acd39e58dd633533cbcf572e309a50aa8 Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 20:06:33 +0200 Subject: [PATCH 09/19] removing superfluous call to CSRFToken() which just put the hidden input onto the page for js to have access to it. this is now handled with a meta tag. --- includes/networking.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/includes/networking.php b/includes/networking.php index 9b728d06..9c330af7 100755 --- a/includes/networking.php +++ b/includes/networking.php @@ -16,8 +16,6 @@ function DisplayNetworkingConfig() foreach ($interfaces as $interface) { exec("ip a show $interface", $$interface); } - - CSRFToken(); ?>
From 7898dc24c84d72357391c3babe5ebe13e918e063 Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 20:14:37 +0200 Subject: [PATCH 10/19] mcrypt_create_iv is deprecated, openssl_random_pseudo_bytes depends on openssl. php7 has the platform-independent `random_bytes` to generate "cryptographically secure" random data. use that for csrf token. --- includes/functions.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index 24da797f..66d87116 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -60,11 +60,7 @@ function safefilerewrite($fileName, $dataToSave) function ensureCSRFSessionToken() { if (empty($_SESSION['csrf_token'])) { - if (function_exists('mcrypt_create_iv')) { - $_SESSION['csrf_token'] = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); - } else { - $_SESSION['csrf_token'] = bin2hex(openssl_random_pseudo_bytes(32)); - } + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } } From 964dc00fab4ff7f7ec7c10ca07b2083c7686b7ed Mon Sep 17 00:00:00 2001 From: glaszig Date: Tue, 30 Jul 2019 20:15:10 +0200 Subject: [PATCH 11/19] generate a new csrf token for each request --- includes/functions.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index 66d87116..07d48efa 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -59,9 +59,7 @@ function safefilerewrite($fileName, $dataToSave) */ function ensureCSRFSessionToken() { - if (empty($_SESSION['csrf_token'])) { - $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); - } + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } /** From 2f6dc2cc0594ae8e3f5019b76e31e8d23b461653 Mon Sep 17 00:00:00 2001 From: glaszig Date: Thu, 1 Aug 2019 12:48:56 +0200 Subject: [PATCH 12/19] remove superfluous semi-colon --- includes/functions.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index 07d48efa..b3f8b19d 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -70,8 +70,7 @@ function ensureCSRFSessionToken() function CSRFToken() { ?> - + Date: Thu, 1 Aug 2019 13:01:03 +0200 Subject: [PATCH 13/19] improve CSRFToken() implementation --- includes/functions.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index b3f8b19d..b3b8f996 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -69,9 +69,8 @@ function ensureCSRFSessionToken() */ function CSRFToken() { -?> - -'; } /** From 0a255e8b499d0e725dc6a4ed3594698b6a22d4dc Mon Sep 17 00:00:00 2001 From: glaszig Date: Thu, 1 Aug 2019 13:03:59 +0200 Subject: [PATCH 14/19] don't write the csrf token field to the output buffer but return and echo it --- includes/admin.php | 2 +- includes/configure_client.php | 2 +- includes/functions.php | 2 +- includes/hostapd.php | 2 +- includes/system.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/includes/admin.php b/includes/admin.php index 22353461..f867705c 100755 --- a/includes/admin.php +++ b/includes/admin.php @@ -40,7 +40,7 @@ function DisplayAuthConfig($username, $password)

showMessages(); ?>

- +
diff --git a/includes/configure_client.php b/includes/configure_client.php index d1640041..458676ac 100755 --- a/includes/configure_client.php +++ b/includes/configure_client.php @@ -182,7 +182,7 @@ function DisplayWPAConfig()
- +