Description: CVE-2018-8764
 CSRF token in URL CVE-2018-8764
Author: Roland Gruber <post@rolandgruber.de>
Applied-Upstream: 6.3
Last-Update: 2018-03-28

--- ldap-account-manager-5.5.orig/lib/html.inc
+++ ldap-account-manager-5.5/lib/html.inc
@@ -597,19 +597,20 @@ class htmlInputField extends htmlElement
 			';
 		}
 		if ($this->checkPasswordStrength) {
-			$tokenSuffix = '?' . getSecurityTokenName() . '=' . getSecurityTokenValue();
+			$query = '?noselfservice=1';
 			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")) {
-				$ajaxPath = "../../templates/misc/ajax.php" . $tokenSuffix;
+				$ajaxPath = "../../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">
-					checkPasswordStrength("' . $this->fieldName . '", "' . $ajaxPath . '");
+					checkPasswordStrength("' . $this->fieldName . '", "' . $ajaxPath . '", "' . getSecurityTokenName() . '", "' . getSecurityTokenValue() . '");
 				</script>
 			';
 		}
--- ldap-account-manager-5.5.orig/lib/modules.inc
+++ ldap-account-manager-5.5/lib/modules.inc
@@ -1251,8 +1251,8 @@ class accountContainer {
 			$passwordButton = new htmlButton('accountContainerPassword', _('Set password'));
 			$passwordButton->setIconClass('passwordButton');
 			$passwordButton->setOnClick('passwordShowChangeDialog(\'' . _('Set password') . '\', \'' . _('Ok') . '\', \''
-				 . _('Cancel') . '\', \'' . _('Set random password') . '\', \'../misc/ajax.php?function=passwordChange&'
-				 . getSecurityTokenName() . '=' . getSecurityTokenValue() . '\');');
+				 . _('Cancel') . '\', \'' . _('Set random password') . '\', \'../misc/ajax.php?function=passwordChange\',\''
+				 . getSecurityTokenName() . '\',\'' . getSecurityTokenValue() . '\');');
 			$leftButtonGroup->addElement($passwordButton);
 		}
 		$table->addElement($leftButtonGroup);
--- ldap-account-manager-5.5.orig/lib/modules/inetOrgPerson.inc
+++ ldap-account-manager-5.5/lib/modules/inetOrgPerson.inc
@@ -2926,9 +2926,10 @@ class inetOrgPerson extends baseModule i
 					"action": "delete",
 					"id": id
 				};
-				jQuery.post(\'../misc/ajax.php?selfservice=1&module=inetOrgPerson&scope=user'
-				 . '&' . getSecurityTokenName() . '=' . getSecurityTokenValue()
-				 . '\', {jsonInput: actionJSON}, function(data) {inetOrgPersonDeleteCertificateHandleReply(data);}, \'json\');
+				var data = {jsonInput: actionJSON};
+				data["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
+				jQuery.post(\'../misc/ajax.php?selfservice=1&module=inetOrgPerson&scope=user\',
+						data, function(data) {inetOrgPersonDeleteCertificateHandleReply(data);}, \'json\');
 			}
 
 			function inetOrgPersonDeleteCertificateHandleReply(data) {
@@ -2942,6 +2943,8 @@ class inetOrgPerson extends baseModule i
 
 			function inetOrgPersonUploadCert(elementID) {
 				var uploadStatus = document.getElementById(\'inetOrgPerson_upload_status_cert\');
+				var params = { action: \'ajaxCertUpload\' };
+				params["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
 				var uploader = new qq.FineUploader({
 					element: document.getElementById(elementID),
 					listElement: uploadStatus,
@@ -2949,9 +2952,7 @@ class inetOrgPerson extends baseModule i
 						endpoint: \'../misc/ajax.php?selfservice=1&module=inetOrgPerson&scope=user'
 						 . '&' . getSecurityTokenName() . '=' . getSecurityTokenValue() . '\',
 						forceMultipart: true,
-						params: {
-							action: \'ajaxCertUpload\'
-						}
+						params: params
 					},
 					multiple: false,
 					callbacks: {
--- ldap-account-manager-5.5.orig/lib/modules/ldapPublicKey.inc
+++ ldap-account-manager-5.5/lib/modules/ldapPublicKey.inc
@@ -396,9 +396,10 @@ class ldapPublicKey extends baseModule {
 				for (c = 0; c < count; c++) {
 					actionJSON["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val();
 				}
-				jQuery.post(\'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user'
-					. '&' . getSecurityTokenName() . '=' . getSecurityTokenValue()
-					. '\', {jsonInput: actionJSON}, function(data) {ldapPublicKeyDeleteKeyHandleReply(data);}, \'json\');
+				var data = {jsonInput: actionJSON};
+				data["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
+				jQuery.post(\'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user\',
+						data, function(data) {ldapPublicKeyDeleteKeyHandleReply(data);}, \'json\');
 			}
 
 			function ldapPublicKeyDeleteKeyHandleReply(data) {
@@ -417,9 +418,11 @@ class ldapPublicKey extends baseModule {
 				for (c = 0; c < count; c++) {
 					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'
 					. '&' . getSecurityTokenName() . '=' . getSecurityTokenValue()
-					. '\', {jsonInput: actionJSON}, function(data) {ldapPublicKeyAddKeyHandleReply(data);}, \'json\');
+					. '\', data, function(data) {ldapPublicKeyAddKeyHandleReply(data);}, \'json\');
 			}
 
 			function ldapPublicKeyAddKeyHandleReply(data) {
@@ -439,12 +442,12 @@ class ldapPublicKey extends baseModule {
 				for (c = 0; c < count; c++) {
 					parameters["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val();
 				}
+				parameters["' . getSecurityTokenName() . '"] = "' . getSecurityTokenValue() . '";
 				var uploader = new qq.FineUploader({
 					element: document.getElementById(elementID),
 					listElement: uploadStatus,
 					request: {
-						endpoint: \'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user'
-						. '&' . getSecurityTokenName() . '=' . getSecurityTokenValue() . '\',
+						endpoint: \'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user\',
 						forceMultipart: true,
 						paramsInBody: true,
 						params: parameters
--- ldap-account-manager-5.5.orig/lib/security.inc
+++ ldap-account-manager-5.5/lib/security.inc
@@ -516,15 +516,12 @@ function addSecurityTokenToSession() {
 
 /**
  * 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) {
-	$vars = $post ? $_POST : $_GET;
-	if (empty($vars)) {
+function validateSecurityToken() {
+	if (empty($_POST)) {
 		return;
 	}
-	if (empty($vars[getSecurityTokenName()]) || ($vars[getSecurityTokenName()] != $_SESSION[getSecurityTokenName()])) {
+	if (empty($_POST[getSecurityTokenName()]) || ($_POST[getSecurityTokenName()] != $_SESSION[getSecurityTokenName()])) {
 		logNewMessage(LOG_ERR, 'Security token does not match POST data.');
 		die();
 	}
@@ -624,4 +621,4 @@ function lamDecrypt($data, $prefix='') {
 	}
 }
 
-?>
\ No newline at end of file
+?>
--- ldap-account-manager-5.5.orig/templates/lib/500_lam.js
+++ ldap-account-manager-5.5/templates/lib/500_lam.js
@@ -236,11 +236,13 @@ function showSimpleDialog(title, okText,
  * @param cancelText text for Cancel button
  * @param randomText text for random password
  * @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 = {};
-	buttonList[okText] = function() { passwordHandleInput("false", ajaxURL); };
-	buttonList[randomText] = function() { passwordHandleInput("true", ajaxURL); };
+	buttonList[okText] = function() { passwordHandleInput("false", ajaxURL, tokenName, tokenValue); };
+	buttonList[randomText] = function() { passwordHandleInput("true", ajaxURL, tokenName, tokenValue); };
 	buttonList[cancelText] = function() {
 		jQuery('#passwordDialogMessageArea').html("");
 		jQuery(this).dialog("close");
@@ -262,8 +264,10 @@ function passwordShowChangeDialog(title,
  * 
  * @param random "true" if random password should be generated
  * @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
 	var modules = new Array();
 	jQuery('#passwordDialog').find(':checked').each(function() {
@@ -286,8 +290,10 @@ function passwordHandleInput(random, aja
 		"sendMail": sendMail,
 		"sendMailAlternateAddress": sendMailAlternateAddress
 	};
+	var data = {jsonInput: pwdJSON};
+	data[tokenName] = tokenValue;
 	// make AJAX call
-	jQuery.post(ajaxURL, {jsonInput: pwdJSON}, function(data) {passwordHandleReply(data);}, 'json');
+	jQuery.post(ajaxURL, data, function(data) {passwordHandleReply(data);}, 'json');
 }
 
 /**
@@ -563,8 +569,10 @@ function checkFieldsHaveSameValues(field
  * Field is marked red if fail and green if ok.
  * 
  * @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 check = 
 		function() {
@@ -572,8 +580,10 @@ function checkPasswordStrength(fieldID,
 			var pwdJSON = {
 					"password": value
 			};
+			var data = {jsonInput: pwdJSON};
+			data[tokenName] = tokenValue;
 			// 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);
 }
--- ldap-account-manager-5.5.orig/templates/misc/ajax.php
+++ ldap-account-manager-5.5/templates/misc/ajax.php
@@ -60,7 +60,7 @@ class lamAjax {
 	public static function handleRequest() {
 		lamAjax::setHeader();
 		// check token
-		validateSecurityToken(false);
+		validateSecurityToken();
 
 		if (isset($_GET['module']) && isset($_GET['scope']) && in_array($_GET['module'], getAvailableModules($_GET['scope']))) {
 			if (isset($_GET['useContainer']) && ($_GET['useContainer'] == '1')) {
