From 08c514b1cd4a8414a284aea38658e5c2488d75c1 Mon Sep 17 00:00:00 2001 From: LAUMAILLE Nils <298792@dom2.ad.sys> Date: Tue, 14 Jun 2016 17:46:11 +0200 Subject: [PATCH 1/2] 2.1.26 Fixing bug with CSRFP and DUO enabled --- duo.load.php | 55 ++++++++++++++++++++++---------------------- sources/checks.php | 6 ++--- sources/identify.php | 14 +++++++---- 3 files changed, 40 insertions(+), 35 deletions(-) diff --git a/duo.load.php b/duo.load.php index 542a2cba1..219a7c3b0 100644 --- a/duo.load.php +++ b/duo.load.php @@ -23,7 +23,7 @@ include $_SESSION['settings']['cpassman_dir'].'/includes/settings.php'; -/* +/* ** This page contains the javascript call for DUOSecurity api ** It loads the expected iFrame where user gives his DUO credentials ** It sends the request to the DUO server @@ -31,33 +31,34 @@ ?> \ No newline at end of file diff --git a/sources/checks.php b/sources/checks.php index 7906a80ff..e80bf8650 100644 --- a/sources/checks.php +++ b/sources/checks.php @@ -16,13 +16,13 @@ $pagesRights = array( "user" => array( - "home", "items", "find", "kb", "favourites", "suggestion", "folders" + "home", "items", "find", "kb", "favourites", "suggestion", "folders", "duo_check" ), "manager" => array( - "home", "items", "find", "kb", "favourites", "suggestion", "folders", "manage_roles", "manage_folders", "manage_views", "manage_users" + "home", "items", "find", "kb", "favourites", "suggestion", "folders", "manage_roles", "manage_folders", "manage_views", "manage_users", "duo_check" ), "admin" => array( - "home", "items", "find", "kb", "favourites", "suggestion", "folders", "manage_roles", "manage_folders", "manage_views", "manage_users", "manage_settings", "manage_main" + "home", "items", "find", "kb", "favourites", "suggestion", "folders", "manage_roles", "manage_folders", "manage_views", "manage_users", "manage_settings", "manage_main", "duo_check" ) ); diff --git a/sources/identify.php b/sources/identify.php index a36648e82..30ca84b2e 100644 --- a/sources/identify.php +++ b/sources/identify.php @@ -31,6 +31,7 @@ // This step creates the DUO request encrypted key include $_SESSION['settings']['cpassman_dir'].'/includes/settings.php'; + // load library require_once $_SESSION['settings']['cpassman_dir'].'/includes/libraries/Authentication/DuoSecurity/Duo.php'; $sig_request = Duo::signRequest(IKEY, SKEY, AKEY, $_POST['login']); @@ -45,8 +46,11 @@ ); } + // load csrfprotector + $csrfp_config = include $_SESSION['settings']['cpassman_dir'].'/includes/libraries/csrfp/libs/csrfp.config.php'; + // return result - echo '[{"sig_request" : "'.$sig_request.'"}]'; + echo '[{"sig_request" : "'.$sig_request.'" , "csrfp_token" : "'.$csrfp_config['CSRFP_TOKEN'].'" , "csrfp_key" : "'.$COOKIE[$csrfp_config['CSRFP_TOKEN']].'"}]'; } elseif ($_POST['type'] == "identify_duo_user_check") { // this step is verifying the response received from the server @@ -76,7 +80,7 @@ // increment counter of login attempts if (empty($_SESSION["pwd_attempts"])) $_SESSION["pwd_attempts"] = 1; else $_SESSION["pwd_attempts"] ++; - + // manage brute force if ($_SESSION["pwd_attempts"] <= 3) { // identify the user through Teampass process @@ -84,13 +88,13 @@ } elseif (isset($_SESSION["next_possible_pwd_attempts"]) && time() > $_SESSION["next_possible_pwd_attempts"] && $_SESSION["pwd_attempts"] > 3) { $_SESSION["pwd_attempts"] = 1; // identify the user through Teampass process - identifyUser($_POST['data']); + identifyUser($_POST['data']); } else { $_SESSION["next_possible_pwd_attempts"] = time() + 10; echo '[{"error" : "bruteforce_wait"}]'; return false; } - + } elseif ($_POST['type'] == "store_data_in_cookie") { // not used any more (only development purpose) if ($_POST['key'] != $_SESSION['key']) { @@ -818,7 +822,7 @@ function identifyUser($sentData) "Identified : " . $return . "\n\n" ); } - + // manage bruteforce if ($_SESSION["pwd_attempts"] > 2) { $_SESSION["next_possible_pwd_attempts"] = time() + 10; From e0d965208be59da7a1208bee5234cdf415258d6d Mon Sep 17 00:00:00 2001 From: "nils@teampass.net" Date: Tue, 14 Jun 2016 20:51:45 +0200 Subject: [PATCH 2/2] 2.1.26 #1229 CSRFProtector message while DUO is enabled --- changelog.md | 1 + duo.load.php | 2 +- .../csrfp/libs/csrf/csrfprotector.php | 26 ++--- .../csrfp/libs/csrfp.config.sample.php | 2 +- install/upgrade_ajax.php | 1 + install/upgrade_run_2.1.26.php | 10 +- load.php | 103 ++++++++---------- sources/checks.php | 6 +- sources/identify.php | 2 +- 9 files changed, 69 insertions(+), 84 deletions(-) diff --git a/changelog.md b/changelog.md index a8d8c841c..89dfdaae5 100644 --- a/changelog.md +++ b/changelog.md @@ -14,6 +14,7 @@ Last changes #1241 OTV visible more than one time #1238 Fix for upgrade.php where mysql_result() command were still not replaced #1235 Import from Keepass: missing items with the same title + #1229 CSRFProtector message while DUO is enabled #1225 Unable to Access OTV Link #1224 Fixed errors in export_to_html_format #1211 No FA code sent from home page diff --git a/duo.load.php b/duo.load.php index 219a7c3b0..11412aa6a 100644 --- a/duo.load.php +++ b/duo.load.php @@ -52,7 +52,7 @@ function(data) { Duo.init({ 'host': '', 'sig_request': data[0].sig_request, - 'post_action': "index.php?page=duo_check&"+data[0].csrfp_token+"="+data[0].csrfp_key + 'post_action': "index.php?page=items&type=duo_check&"+data[0].csrfp_token+"="+data[0].csrfp_key }); $("#duo_login").val($("#login").val()); diff --git a/includes/libraries/csrfp/libs/csrf/csrfprotector.php b/includes/libraries/csrfp/libs/csrf/csrfprotector.php index a9861d26e..a9135c38d 100644 --- a/includes/libraries/csrfp/libs/csrf/csrfprotector.php +++ b/includes/libraries/csrfp/libs/csrf/csrfprotector.php @@ -176,15 +176,12 @@ public static function authorizePost() //#todo this method is valid for same origin request only, //enable it for cross origin also sometime //for cross origin the functionality is different - if ($_SERVER['REQUEST_METHOD'] === 'POST') { - - //set request type to POST - self::$requestType = "POST"; - + if (!static::isURLallowed()) { + //currently for same origin only - if (!(isset($_POST[self::$config['CSRFP_TOKEN']]) + if (!(isset($_GET[self::$config['CSRFP_TOKEN']]) && isset($_SESSION[self::$config['CSRFP_TOKEN']]) - && (self::isValidToken($_POST[self::$config['CSRFP_TOKEN']])) + && (self::isValidToken($_GET[self::$config['CSRFP_TOKEN']])) )) { //action in case of failed validation @@ -192,12 +189,15 @@ public static function authorizePost() } else { self::refreshToken(); //refresh token for successfull validation } - } else if (!static::isURLallowed()) { - + } else if ($_SERVER['REQUEST_METHOD'] === 'POST') { + + //set request type to POST + self::$requestType = "POST"; + //currently for same origin only - if (!(isset($_GET[self::$config['CSRFP_TOKEN']]) + if (!(isset($_POST[self::$config['CSRFP_TOKEN']]) && isset($_SESSION[self::$config['CSRFP_TOKEN']]) - && (self::isValidToken($_GET[self::$config['CSRFP_TOKEN']])) + && (self::isValidToken($_POST[self::$config['CSRFP_TOKEN']])) )) { //action in case of failed validation @@ -205,7 +205,7 @@ public static function authorizePost() } else { self::refreshToken(); //refresh token for successfull validation } - } + } } /* @@ -487,7 +487,7 @@ private static function getCurrentUrl() } } - return $request_scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']; + return $request_scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; } /* diff --git a/includes/libraries/csrfp/libs/csrfp.config.sample.php b/includes/libraries/csrfp/libs/csrfp.config.sample.php index 575a6a698..dc611c575 100644 --- a/includes/libraries/csrfp/libs/csrfp.config.sample.php +++ b/includes/libraries/csrfp/libs/csrfp.config.sample.php @@ -17,5 +17,5 @@ "disabledJavascriptMessage" => "This site attempts to protect users against Cross-Site Request Forgeries attacks. In order to do so, you must have JavaScript enabled in your web browser otherwise this site will fail to work correctly for you. See details of your web browser for how to enable JavaScript.", - "verifyGetFor" => array() + "verifyGetFor" => array("*page=items&type=duo_check*") ); diff --git a/install/upgrade_ajax.php b/install/upgrade_ajax.php index 6156a5fdd..832cad7d3 100644 --- a/install/upgrade_ajax.php +++ b/install/upgrade_ajax.php @@ -582,6 +582,7 @@ function tableExists($tablename, $database = false) $newdata = str_replace('"tokenLength" => "25"', '"tokenLength" => "50"', $newdata); $jsUrl = $_SESSION['fullurl'].'/includes/libraries/csrfp/js/csrfprotector.js'; $newdata = str_replace('"jsUrl" => ""', '"jsUrl" => "'.$jsUrl.'"', $newdata); + $newdata = str_replace('"verifyGetFor" => array()', '"verifyGetFor" => array("*page=items&type=duo_check*")', $newdata); file_put_contents("../includes/libraries/csrfp/libs/csrfp.config.php", $newdata); diff --git a/install/upgrade_run_2.1.26.php b/install/upgrade_run_2.1.26.php index 1e7187d43..b5f4d5758 100644 --- a/install/upgrade_run_2.1.26.php +++ b/install/upgrade_run_2.1.26.php @@ -159,9 +159,9 @@ function tableExists($tablename, $database = false) // check that API doesn't exist $tmp = mysqli_fetch_row(mysqli_query($dbTmp, "SELECT COUNT(*) FROM `".$_SESSION['tbl_prefix']."users` WHERE id = '9999999'")); if ($tmp[0] == 0 || empty($tmp[0])) { - mysqli_query($dbTmp, - "INSERT INTO `".$_SESSION['tbl_prefix']."users` (`id`, `login`, `read_only`) VALUES ('9999999', 'API', '1')" - ); + mysqli_query($dbTmp, + "INSERT INTO `".$_SESSION['tbl_prefix']."users` (`id`, `login`, `read_only`) VALUES ('9999999', 'API', '1')" + ); } @@ -180,13 +180,13 @@ function tableExists($tablename, $database = false) // add Estonian $tmp = mysqli_fetch_row(mysqli_query($dbTmp, "SELECT COUNT(*) FROM `".$_SESSION['tbl_prefix']."languages` WHERE name = 'estonian'")); if ($tmp[0] == 0 || empty($tmp[0])) { - mysqli_query($dbTmp, "INSERT INTO `".$_SESSION['tbl_prefix']."languages` VALUES (null, 'estonian', 'Estonian', 'ee', 'ee.png')"); + mysqli_query($dbTmp, "INSERT INTO `".$_SESSION['tbl_prefix']."languages` VALUES (null, 'estonian', 'Estonian', 'ee', 'ee.png')"); } // remove Estonia $tmp = mysqli_fetch_row(mysqli_query($dbTmp, "SELECT COUNT(*) FROM `".$_SESSION['tbl_prefix']."languages` WHERE name = 'estonia'")); if ($tmp[0] == 0 || empty($tmp[0])) { - mysqli_query($dbTmp, "DELETE FROM `".$_SESSION['tbl_prefix']."languages` WHERE name = 'estonia'"); + mysqli_query($dbTmp, "DELETE FROM `".$_SESSION['tbl_prefix']."languages` WHERE name = 'estonia'"); } // ensure CSRFP config file is ready diff --git a/load.php b/load.php index 0e916f15b..90641a9bd 100644 --- a/load.php +++ b/load.php @@ -257,9 +257,9 @@ function (){ ); } else if (data[0].value == "false_onetimepw") { $("#connection_error").html("'.$LANG['bad_onetime_password'].'").show(); - } else if (data[0].pwd_attempts >=3 ||data[0].error == "bruteforce_wait") { - // now user needs to wait 10 secs before new passwd - $("#connection_error").html("'.$LANG['error_bad_credentials_more_than_3_times'].'").show(); + } else if (data[0].pwd_attempts >=3 ||data[0].error == "bruteforce_wait") { + // now user needs to wait 10 secs before new passwd + $("#connection_error").html("'.$LANG['error_bad_credentials_more_than_3_times'].'").show(); } else if (data[0].error == "bad_credentials") { $("#connection_error").html("'.$LANG['error_bad_credentials'].'").show(); } else if (data[0].error == "ga_code_wrong") { @@ -267,8 +267,8 @@ function (){ } else { $("#connection_error").html("'.$LANG['error_bad_credentials'].'").show(); } - - $("#ajax_loader_connexion").hide(); + + $("#ajax_loader_connexion").hide(); }, "json" ); @@ -430,7 +430,7 @@ function refreshListLastSeenItems() key : "'.$_SESSION["key"].'" }, function(data) { - data = $.parseJSON(data); + data = $.parseJSON(data); //check if format error if (data.error == "") { if (data.text == null) { @@ -440,10 +440,10 @@ function(data) { } // rebuild menu $("#menu_last_seen_items").menu("refresh"); - // show notification - if (data.existing_suggestions != 0) { - blink("#menu_button_suggestion", -1, 500, "ui-state-error"); - } + // show notification + if (data.existing_suggestions != 0) { + blink("#menu_button_suggestion", -1, 500, "ui-state-error"); + } } else { $("#main_info_box_text").html(data.error); setTimeout(function(){$("#main_info_box").effect( "fade", "slow" );}, 1000); @@ -455,25 +455,7 @@ function(data) { // DUO box - identification function loadDuoDialog() { - /* - // save data connection - $.post( - "sources/identify.php", - { - type : "store_data_in_cookie", - data : prepareExchangedData($("#duo_data").val(), "encode", "'.$_SESSION['key'].'>"), - key : "'.$_SESSION['key'].'" - }, - function(data) { - if (data[0].error == "something_wrong") { - - } - }, - "json" - ); - */ - - // show dialog + // show dialog $("#dialog_duo").dialog({ width: 600, height: 500, @@ -496,6 +478,7 @@ function loadDuoDialogWait() title: "DUO Security - please wait ..." }).dialog("open"); } + function ChangeMyPass() { if ($("#new_pw").val() != "" && $("#new_pw").val() == $("#new_pw2").val()) { @@ -608,7 +591,7 @@ function(data) { $("#main *, #footer *, #icon_last_items *, #top *, button, .tip").tooltipster({ maxWidth: 400, contentAsHTML: true, - multiple: true + multiple: true }); $("#user_session").val(sessionStorage.password); @@ -715,7 +698,7 @@ function() { title: "'.$LANG['home_personal_saltkey_label'].'", open: function( event, ui ) { $("#input_personal_saltkey").val("'.addslashes(str_replace(""", '"', $_SESSION['my_sk'])).'"); - console.log("'.addslashes(str_replace(""", '"', $_SESSION['my_sk'])).'"); + console.log("'.addslashes(str_replace(""", '"', $_SESSION['my_sk'])).'"); }, buttons: { "'.$LANG['save_button'].'": function() { @@ -768,7 +751,7 @@ function(data) { $("#div_change_personal_saltkey_wait").show(); var data_to_share = "{\"sk\":\"" + sanitizeString($("#new_personal_saltkey").val()) + "\", \"old_sk\":\"" + sanitizeString($("#old_personal_saltkey").val()) + "\"}"; - $("#div_change_personal_saltkey_wait_progress").html(" 0%"); + $("#div_change_personal_saltkey_wait_progress").html(" 0%"); //Send query $.post( @@ -946,8 +929,8 @@ function getSelectedValue(id) }); $("#new_pw").bind({ "score.simplePassMeter" : function(jQEvent, score) { - $("#pw_strength_value").val(score); - } + $("#pw_strength_value").val(score); + } }).change({ "score.simplePassMeter" : function(jQEvent, score) { $("#pw_strength_value").val(score); @@ -957,32 +940,32 @@ function getSelectedValue(id) // get list of last items refreshListLastSeenItems(); - // prevent usage of symbols in Personal saltkey - $(".text_without_symbols").bind("keydown", function (event) { - switch (event.keyCode) { - case 8: // Backspace - case 9: // Tab - case 13: // Enter - case 37: // Left - case 38: // Up - case 39: // Right - case 40: // Down - break; - default: - var regex = new RegExp("^[a-zA-Z0-9.,/#&$@()%*]+$"); - var key = event.key; - if (!regex.test(key)) { - $("#set_personal_saltkey_warning").html("'.addslashes($LANG['character_not_allowed']).'").stop(true,true).show().fadeOut(1000); - event.preventDefault(); - return false; - } - if (key !== "Alt" && key !== "Control" && key !== "Shift") $("#set_personal_saltkey_last_letter").html(key).stop(true,true).show().fadeOut(1400); - break; - } - }).bind("paste",function(e){ - $("#set_personal_saltkey_warning").html("'.addslashes($LANG['error_not_allowed_to']).'").stop(true,true).show().fadeOut(1000); - e.preventDefault(); - }); + // prevent usage of symbols in Personal saltkey + $(".text_without_symbols").bind("keydown", function (event) { + switch (event.keyCode) { + case 8: // Backspace + case 9: // Tab + case 13: // Enter + case 37: // Left + case 38: // Up + case 39: // Right + case 40: // Down + break; + default: + var regex = new RegExp("^[a-zA-Z0-9.,/#&$@()%*]+$"); + var key = event.key; + if (!regex.test(key)) { + $("#set_personal_saltkey_warning").html("'.addslashes($LANG['character_not_allowed']).'").stop(true,true).show().fadeOut(1000); + event.preventDefault(); + return false; + } + if (key !== "Alt" && key !== "Control" && key !== "Shift") $("#set_personal_saltkey_last_letter").html(key).stop(true,true).show().fadeOut(1400); + break; + } + }).bind("paste",function(e){ + $("#set_personal_saltkey_warning").html("'.addslashes($LANG['error_not_allowed_to']).'").stop(true,true).show().fadeOut(1000); + e.preventDefault(); + }); setTimeout(function() { NProgress.done(); $(".fade").removeClass("out"); }, 1000); });'; diff --git a/sources/checks.php b/sources/checks.php index e80bf8650..7906a80ff 100644 --- a/sources/checks.php +++ b/sources/checks.php @@ -16,13 +16,13 @@ $pagesRights = array( "user" => array( - "home", "items", "find", "kb", "favourites", "suggestion", "folders", "duo_check" + "home", "items", "find", "kb", "favourites", "suggestion", "folders" ), "manager" => array( - "home", "items", "find", "kb", "favourites", "suggestion", "folders", "manage_roles", "manage_folders", "manage_views", "manage_users", "duo_check" + "home", "items", "find", "kb", "favourites", "suggestion", "folders", "manage_roles", "manage_folders", "manage_views", "manage_users" ), "admin" => array( - "home", "items", "find", "kb", "favourites", "suggestion", "folders", "manage_roles", "manage_folders", "manage_views", "manage_users", "manage_settings", "manage_main", "duo_check" + "home", "items", "find", "kb", "favourites", "suggestion", "folders", "manage_roles", "manage_folders", "manage_views", "manage_users", "manage_settings", "manage_main" ) ); diff --git a/sources/identify.php b/sources/identify.php index 30ca84b2e..6292fafdb 100644 --- a/sources/identify.php +++ b/sources/identify.php @@ -50,7 +50,7 @@ $csrfp_config = include $_SESSION['settings']['cpassman_dir'].'/includes/libraries/csrfp/libs/csrfp.config.php'; // return result - echo '[{"sig_request" : "'.$sig_request.'" , "csrfp_token" : "'.$csrfp_config['CSRFP_TOKEN'].'" , "csrfp_key" : "'.$COOKIE[$csrfp_config['CSRFP_TOKEN']].'"}]'; + echo '[{"sig_request" : "'.$sig_request.'" , "csrfp_token" : "'.$csrfp_config['CSRFP_TOKEN'].'" , "csrfp_key" : "'.$_COOKIE[$csrfp_config['CSRFP_TOKEN']].'"}]'; } elseif ($_POST['type'] == "identify_duo_user_check") { // this step is verifying the response received from the server