changed CSRF token handling from GET to POST

This commit is contained in:
Roland Gruber 2018-03-14 20:06:09 +01:00
parent ca358b3975
commit 993751c7ff
8 changed files with 62 additions and 51 deletions

View File

@ -642,19 +642,20 @@ class htmlInputField extends htmlElement {
'; ';
} }
if ($this->checkPasswordStrength) { if ($this->checkPasswordStrength) {
$tokenSuffix = '?' . getSecurityTokenName() . '=' . getSecurityTokenValue(); $query = '?noselfservice=1';
if (isSelfService()) { if (isSelfService()) {
$tokenSuffix .= '&selfservice=1'; $query = '?selfservice=1';
} }
$ajaxPath = "../templates/misc/ajax.php" . $tokenSuffix; $ajaxPath = "../templates/misc/ajax.php";
if (is_file("../../templates/misc/ajax.php")) { if (is_file("../../templates/misc/ajax.php")) {
$ajaxPath = "../../templates/misc/ajax.php" . $tokenSuffix; $ajaxPath = "../../templates/misc/ajax.php";
} }
elseif (is_file("../../../templates/misc/ajax.php")) { elseif (is_file("../../../templates/misc/ajax.php")) {
$ajaxPath = "../../../templates/misc/ajax.php" . $tokenSuffix; $ajaxPath = "../../../templates/misc/ajax.php";
} }
$ajaxPath .= $query;
echo '<script type="text/javascript"> echo '<script type="text/javascript">
checkPasswordStrength("' . $this->fieldName . '", "' . $ajaxPath . '"); checkPasswordStrength("' . $this->fieldName . '", "' . $ajaxPath . '", "' . getSecurityTokenName() . '", "' . getSecurityTokenValue() . '");
</script> </script>
'; ';
} }

View File

@ -2,10 +2,9 @@
use LAM\TYPES\ConfiguredType; use LAM\TYPES\ConfiguredType;
use \LAM\TYPES\TypeManager; use \LAM\TYPES\TypeManager;
/* /*
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2017 Roland Gruber Copyright (C) 2003 - 2018 Roland Gruber
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -1278,8 +1277,8 @@ class accountContainer {
$passwordButton = new htmlButton('accountContainerPassword', _('Set password')); $passwordButton = new htmlButton('accountContainerPassword', _('Set password'));
$passwordButton->setIconClass('passwordButton'); $passwordButton->setIconClass('passwordButton');
$passwordButton->setOnClick('passwordShowChangeDialog(\'' . _('Set password') . '\', \'' . _('Ok') . '\', \'' $passwordButton->setOnClick('passwordShowChangeDialog(\'' . _('Set password') . '\', \'' . _('Ok') . '\', \''
. _('Cancel') . '\', \'' . _('Set random password') . '\', \'../misc/ajax.php?function=passwordChange&' . _('Cancel') . '\', \'' . _('Set random password') . '\', \'../misc/ajax.php?function=passwordChange\',\''
. getSecurityTokenName() . '=' . getSecurityTokenValue() . '\');'); . getSecurityTokenName() . '\',\'' . getSecurityTokenValue() . '\');');
$leftButtonGroup->addElement($passwordButton); $leftButtonGroup->addElement($passwordButton);
} }
$table->addElement($leftButtonGroup); $table->addElement($leftButtonGroup);

View File

@ -1,11 +1,10 @@
<?php <?php
use \LAM\TYPES\TypeManager; use \LAM\TYPES\TypeManager;
/* /*
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2006 Tilo Lutz Copyright (C) 2003 - 2006 Tilo Lutz
2005 - 2017 Roland Gruber 2005 - 2018 Roland Gruber
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -2954,9 +2953,10 @@ class inetOrgPerson extends baseModule implements passwordService {
"action": "delete", "action": "delete",
"id": id "id": id
}; };
jQuery.post(\'../misc/ajax.php?selfservice=1&module=inetOrgPerson&scope=user' var data = {jsonInput: actionJSON};
. '&' . getSecurityTokenName() . '=' . getSecurityTokenValue() data["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
. '\', {jsonInput: actionJSON}, function(data) {inetOrgPersonDeleteCertificateHandleReply(data);}, \'json\'); jQuery.post(\'../misc/ajax.php?selfservice=1&module=inetOrgPerson&scope=user\',
data, function(data) {inetOrgPersonDeleteCertificateHandleReply(data);}, \'json\');
} }
function inetOrgPersonDeleteCertificateHandleReply(data) { function inetOrgPersonDeleteCertificateHandleReply(data) {
@ -2970,6 +2970,8 @@ class inetOrgPerson extends baseModule implements passwordService {
function inetOrgPersonUploadCert(elementID) { function inetOrgPersonUploadCert(elementID) {
var uploadStatus = document.getElementById(\'inetOrgPerson_upload_status_cert\'); var uploadStatus = document.getElementById(\'inetOrgPerson_upload_status_cert\');
var params = { action: \'ajaxCertUpload\' };
params["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
var uploader = new qq.FineUploader({ var uploader = new qq.FineUploader({
element: document.getElementById(elementID), element: document.getElementById(elementID),
listElement: uploadStatus, listElement: uploadStatus,
@ -2977,9 +2979,7 @@ class inetOrgPerson extends baseModule implements passwordService {
endpoint: \'../misc/ajax.php?selfservice=1&module=inetOrgPerson&scope=user' endpoint: \'../misc/ajax.php?selfservice=1&module=inetOrgPerson&scope=user'
. '&' . getSecurityTokenName() . '=' . getSecurityTokenValue() . '\', . '&' . getSecurityTokenName() . '=' . getSecurityTokenValue() . '\',
forceMultipart: true, forceMultipart: true,
params: { params: params
action: \'ajaxCertUpload\'
}
}, },
multiple: false, multiple: false,
callbacks: { callbacks: {

View File

@ -3,10 +3,9 @@ use \LAM\PDF\PDFTable;
use \LAM\PDF\PDFTableCell; use \LAM\PDF\PDFTableCell;
use \LAM\PDF\PDFTableRow; use \LAM\PDF\PDFTableRow;
/* /*
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2005 - 2017 Roland Gruber Copyright (C) 2005 - 2018 Roland Gruber
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -392,9 +391,10 @@ class ldapPublicKey extends baseModule {
for (c = 0; c < count; c++) { for (c = 0; c < count; c++) {
actionJSON["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val(); actionJSON["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val();
} }
jQuery.post(\'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user' var data = {jsonInput: actionJSON};
. '&' . getSecurityTokenName() . '=' . getSecurityTokenValue() data["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
. '\', {jsonInput: actionJSON}, function(data) {ldapPublicKeyDeleteKeyHandleReply(data);}, \'json\'); jQuery.post(\'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user\',
data, function(data) {ldapPublicKeyDeleteKeyHandleReply(data);}, \'json\');
} }
function ldapPublicKeyDeleteKeyHandleReply(data) { function ldapPublicKeyDeleteKeyHandleReply(data) {
@ -413,9 +413,11 @@ class ldapPublicKey extends baseModule {
for (c = 0; c < count; c++) { for (c = 0; c < count; c++) {
actionJSON["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val(); actionJSON["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val();
} }
var data = {jsonInput: actionJSON};
data["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
jQuery.post(\'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user' jQuery.post(\'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user'
. '&' . getSecurityTokenName() . '=' . getSecurityTokenValue() . '&' . getSecurityTokenName() . '=' . getSecurityTokenValue()
. '\', {jsonInput: actionJSON}, function(data) {ldapPublicKeyAddKeyHandleReply(data);}, \'json\'); . '\', data, function(data) {ldapPublicKeyAddKeyHandleReply(data);}, \'json\');
} }
function ldapPublicKeyAddKeyHandleReply(data) { function ldapPublicKeyAddKeyHandleReply(data) {
@ -435,12 +437,12 @@ class ldapPublicKey extends baseModule {
for (c = 0; c < count; c++) { for (c = 0; c < count; c++) {
parameters["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val(); parameters["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val();
} }
parameters["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
var uploader = new qq.FineUploader({ var uploader = new qq.FineUploader({
element: document.getElementById(elementID), element: document.getElementById(elementID),
listElement: uploadStatus, listElement: uploadStatus,
request: { request: {
endpoint: \'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user' endpoint: \'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user\',
. '&' . getSecurityTokenName() . '=' . getSecurityTokenValue() . '\',
forceMultipart: true, forceMultipart: true,
paramsInBody: true, paramsInBody: true,
params: parameters params: parameters

View File

@ -548,17 +548,13 @@ function addSecurityTokenToSession($overwrite = true) {
/** /**
* Checks if the security token from SESSION matches POST data. * Checks if the security token from SESSION matches POST data.
*
* @param $post use POST, set to false for GET (default: true)
*/ */
function validateSecurityToken($post = true) { function validateSecurityToken() {
$vars = $post ? $_POST : $_GET; if (empty($_POST)) {
if (empty($vars)) {
return; return;
} }
if (empty($vars[getSecurityTokenName()]) || ($vars[getSecurityTokenName()] != $_SESSION[getSecurityTokenName()])) { if (empty($_POST[getSecurityTokenName()]) || ($_POST[getSecurityTokenName()] != $_SESSION[getSecurityTokenName()])) {
$method = $post ? 'POST' : 'GET'; logNewMessage(LOG_ERR, 'Security token does not match POST data.');
logNewMessage(LOG_ERR, 'Security token does not match ' . $method . ' data.');
die(); die();
} }
} }

View File

@ -1,9 +1,7 @@
/** /**
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2017 Roland Gruber Copyright (C) 2003 - 2018 Roland Gruber
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -236,11 +234,13 @@ function showSimpleDialog(title, okText, cancelText, formID, dialogDivID) {
* @param cancelText text for Cancel button * @param cancelText text for Cancel button
* @param randomText text for random password * @param randomText text for random password
* @param ajaxURL URL used for AJAX request * @param ajaxURL URL used for AJAX request
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
*/ */
function passwordShowChangeDialog(title, okText, cancelText, randomText, ajaxURL) { function passwordShowChangeDialog(title, okText, cancelText, randomText, ajaxURL, tokenName, tokenValue) {
var buttonList = {}; var buttonList = {};
buttonList[okText] = function() { passwordHandleInput("false", ajaxURL); }; buttonList[okText] = function() { passwordHandleInput("false", ajaxURL, tokenName, tokenValue); };
buttonList[randomText] = function() { passwordHandleInput("true", ajaxURL); }; buttonList[randomText] = function() { passwordHandleInput("true", ajaxURL, tokenName, tokenValue); };
buttonList[cancelText] = function() { buttonList[cancelText] = function() {
jQuery('#passwordDialogMessageArea').html(""); jQuery('#passwordDialogMessageArea').html("");
jQuery(this).dialog("close"); jQuery(this).dialog("close");
@ -262,8 +262,10 @@ function passwordShowChangeDialog(title, okText, cancelText, randomText, ajaxURL
* *
* @param random "true" if random password should be generated * @param random "true" if random password should be generated
* @param ajaxURL URL used for AJAX request * @param ajaxURL URL used for AJAX request
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
*/ */
function passwordHandleInput(random, ajaxURL) { function passwordHandleInput(random, ajaxURL, tokenName, tokenValue) {
// get input values // get input values
var modules = new Array(); var modules = new Array();
jQuery('#passwordDialog').find(':checked').each(function() { jQuery('#passwordDialog').find(':checked').each(function() {
@ -286,8 +288,10 @@ function passwordHandleInput(random, ajaxURL) {
"sendMail": sendMail, "sendMail": sendMail,
"sendMailAlternateAddress": sendMailAlternateAddress "sendMailAlternateAddress": sendMailAlternateAddress
}; };
var data = {jsonInput: pwdJSON};
data[tokenName] = tokenValue;
// make AJAX call // make AJAX call
jQuery.post(ajaxURL, {jsonInput: pwdJSON}, function(data) {passwordHandleReply(data);}, 'json'); jQuery.post(ajaxURL, data, function(data) {passwordHandleReply(data);}, 'json');
} }
/** /**
@ -551,8 +555,10 @@ function checkFieldsHaveSameValues(fieldID, fieldIDReference) {
* Field is marked red if fail and green if ok. * Field is marked red if fail and green if ok.
* *
* @param fieldID ID of field to check * @param fieldID ID of field to check
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
*/ */
function checkPasswordStrength(fieldID, ajaxURL) { function checkPasswordStrength(fieldID, ajaxURL, tokenName, tokenValue) {
var field = jQuery('#' + fieldID); var field = jQuery('#' + fieldID);
var check = var check =
function() { function() {
@ -560,8 +566,10 @@ function checkPasswordStrength(fieldID, ajaxURL) {
var pwdJSON = { var pwdJSON = {
"password": value "password": value
}; };
var data = {jsonInput: pwdJSON};
data[tokenName] = tokenValue;
// make AJAX call // make AJAX call
jQuery.post(ajaxURL + "&function=passwordStrengthCheck", {jsonInput: pwdJSON}, function(data) {checkPasswordStrengthHandleReply(data, fieldID);}, 'json'); jQuery.post(ajaxURL + "&function=passwordStrengthCheck", data, function(data) {checkPasswordStrengthHandleReply(data, fieldID);}, 'json');
}; };
jQuery(field).keyup(check); jQuery(field).keyup(check);
} }
@ -654,12 +662,18 @@ window.lam.upload = window.lam.upload || {};
* Continues a CSV file upload. * Continues a CSV file upload.
* *
* @param url URL where to get status JSON * @param url URL where to get status JSON
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
*/ */
window.lam.upload.continueUpload = function(url) { window.lam.upload.continueUpload = function(url, tokenName, tokenValue) {
var data = {
jsonInput: ''
};
data[tokenName] = tokenValue;
jQuery.ajax({ jQuery.ajax({
url: url, url: url,
method: 'POST', method: 'POST',
data: 'jsonInput=' data: data
}) })
.done(function(jsonData){ .done(function(jsonData){
if (!jsonData.accountsFinished) { if (!jsonData.accountsFinished) {
@ -673,7 +687,7 @@ window.lam.upload.continueUpload = function(url) {
} }
// next call if not finished // next call if not finished
if (!jsonData.allDone) { if (!jsonData.allDone) {
window.lam.upload.continueUpload(url); window.lam.upload.continueUpload(url, tokenName, tokenValue);
} }
else { else {
window.lam.upload.uploadDone(jsonData); window.lam.upload.uploadDone(jsonData);

View File

@ -61,7 +61,7 @@ class Ajax {
public function handleRequest() { public function handleRequest() {
$this->setHeader(); $this->setHeader();
// check token // check token
validateSecurityToken(false); validateSecurityToken();
if (isset($_GET['module']) && isset($_GET['scope']) && in_array($_GET['module'], getAvailableModules($_GET['scope']))) { if (isset($_GET['module']) && isset($_GET['scope']) && in_array($_GET['module'], getAvailableModules($_GET['scope']))) {
enforceUserIsLoggedIn(); enforceUserIsLoggedIn();

View File

@ -1,10 +1,9 @@
<?php <?php
namespace LAM\UPLOAD; namespace LAM\UPLOAD;
/* /*
$Id$
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2004 - 2017 Roland Gruber Copyright (C) 2004 - 2018 Roland Gruber
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -82,7 +81,7 @@ $tokenPrefix = '?' . getSecurityTokenName() . '=' . getSecurityTokenValue();
?> ?>
<script type="text/javascript"> <script type="text/javascript">
jQuery(document).ready(function(){ jQuery(document).ready(function(){
window.lam.upload.continueUpload('../misc/ajax.php' + '<?php echo $tokenPrefix; ?>' + '&function=upload&typeId=' + '<?php echo $type->getId() ?>'); window.lam.upload.continueUpload('../misc/ajax.php?function=upload&typeId=' + '<?php echo $type->getId() ?>', '<?php echo getSecurityTokenName(); ?>', '<?php echo getSecurityTokenValue(); ?>');
}); });
</script> </script>