CVE-2014-8553: Exposure of Sensitive Information to an Unauthorized Actor (CWE-200)
value: The mci_account_get_array_by_id function in api/soap/mc_account_api.php in MantisBT before 1.2.18 allows remote attackers to obtain sensitive information via a (1) mc_project_get_users, (2) mc_issue_get, (3) mc_filter_get_issues, or (4) mc_project_get_issues SOAP request.
CWE description: The product exposes sensitive information to an actor that is not explicitly authorized to have access to that information.
Published: 2014-12-17T19:59Z
Repository: https://github.com/mantisbt/mantisbt
Language: PHP
Files changed: api/soap/mc_account_api.php
Commit date: 2014-11-15 15:46:58 +0100
Commit message: SOAP API: apply access control to mci_account_get_array_by_id

The access controls are the same as the ones applied by
view_user_page.php, with the single addition of making the info
available if the user requests their own information.

This preserves the behaviour of the mc_login method call.

Fixes #17243 (leak of user personal information)

Signed-off-by: Damien Regad <dregad@mantisbt.org>

Diff: diff --git a/api/soap/mc_account_api.php b/api/soap/mc_account_api.php
index 8d388fc4ff..66d43d114a 100644
--- a/api/soap/mc_account_api.php
+++ b/api/soap/mc_account_api.php
@@ -31,21 +31,38 @@
 function mci_account_get_array_by_id( $p_user_id ) {
 	$t_result = array();
 	$t_result['id'] = $p_user_id;
 
 	if( user_exists( $p_user_id ) ) {
+
+		$t_current_user_id = auth_get_current_user_id();
+		$t_access_level = user_get_field ( $t_current_user_id, 'access_level' );
+		$t_can_manage = access_has_global_level( config_get( 'manage_user_threshold' ) ) &&
+			access_has_global_level( $t_access_level );
+
+		# this deviates from the behaviour of view_user_page.php, but it is more intuitive
+		$t_is_same_user = $t_current_user_id === $p_user_id;
+
+		$t_can_see_realname = access_has_project_level( config_get( 'show_user_realname_threshold' ) );
+		$t_can_see_email = access_has_project_level( config_get( 'show_user_email_threshold' ) );
+
 		$t_result['name'] = user_get_field( $p_user_id, 'username' );
-		$t_dummy = user_get_field( $p_user_id, 'realname' );
 
-		if( !empty( $t_dummy ) ) {
-			$t_result['real_name'] = $t_dummy;
+		if ( $t_is_same_user || $t_can_manage || $t_can_see_realname ) {
+			$t_realname = user_get_realname( $p_user_id );
+
+			if( !empty( $t_realname ) ) {
+				$t_result['real_name'] = $t_realname;
+			}
 		}
 
-		$t_dummy = user_get_field( $p_user_id, 'email' );
+		if ( $t_is_same_user || $t_can_manage || $t_can_see_email ) {
+			$t_email = user_get_email( $p_user_id );
 
-		if( !empty( $t_dummy ) ) {
-			$t_result['email'] = $t_dummy;
+			if( !empty( $t_email ) ) {
+				$t_result['email'] = $t_email;
+			}
 		}
 	}
 	return $t_result;
 }
 

Vulnerable code: 		$t_dummy = user_get_field( $p_user_id, 'realname' );
		if( !empty( $t_dummy ) ) {
			$t_result['real_name'] = $t_dummy;
		$t_dummy = user_get_field( $p_user_id, 'email' );
		if( !empty( $t_dummy ) ) {
			$t_result['email'] = $t_dummy;
Fixed code: 
		$t_current_user_id = auth_get_current_user_id();
		$t_access_level = user_get_field ( $t_current_user_id, 'access_level' );
		$t_can_manage = access_has_global_level( config_get( 'manage_user_threshold' ) ) &&
			access_has_global_level( $t_access_level );

		# this deviates from the behaviour of view_user_page.php, but it is more intuitive
		$t_is_same_user = $t_current_user_id === $p_user_id;

		$t_can_see_realname = access_has_project_level( config_get( 'show_user_realname_threshold' ) );
		$t_can_see_email = access_has_project_level( config_get( 'show_user_email_threshold' ) );

		if ( $t_is_same_user || $t_can_manage || $t_can_see_realname ) {
			$t_realname = user_get_realname( $p_user_id );

			if( !empty( $t_realname ) ) {
				$t_result['real_name'] = $t_realname;
			}
		if ( $t_is_same_user || $t_can_manage || $t_can_see_email ) {
			$t_email = user_get_email( $p_user_id );
			if( !empty( $t_email ) ) {
				$t_result['email'] = $t_email;
			}