Vulnerability: Cross-site scripting (XSS) vulnerability in helper_api.php in MantisBT 1.1.0a1 through 1.2.x before 1.2.18, when Extended project browser is enabled, allows remote attackers to inject arbitrary web script or HTML via the project cookie.
Vulnerability ID: CVE-2014-9269
CWE: CWE-79
Severity score: 2.9
Project: https://github.com/mantisbt/mantisbt
Published: 2015-01-09
File: core/helper_api.php
Commit message: Fix #17890: XSS in extended project browser

Extended project browser allows projects to be passed in as A;B.
helper_get_current_project() and helper_get_current_project_trace() then
explodes the string by ';' and don't check that A is an int (a project /
sub-project id).  Finally, print_extended_project_browser() prints the
result of the split into a javascript array.

Paul Richards discovered the issue and wrote the original patch for it.
His code was modified to remove a redudant typecast as well as an
unnecessary foreach loop in helper_get_current_project(), replacing it
with a single type cast.
Commit author: Damien Regad

Vulnerable version (before fix):
 function helper_get_current_project() { 			$t_project_id = $t_pref->default_project; 		} else { 			$t_project_id = explode( ';', $t_project_id ); 			$t_project_id = $t_project_id[count( $t_project_id ) - 1]; 		}  		if( !project_exists( $t_project_id ) || ( 0 == project_get_field( $t_project_id, 'enabled' ) ) || !access_has_project_level( VIEWER, $t_project_id ) ) { 			$t_project_id = ALL_PROJECTS; 		} 		$g_cache_current_project = (int) $t_project_id; 	} 	return $g_cache_current_project; } function helper_get_current_project_trace() {  	} else { 		$t_project_id = explode( ';', $t_project_id ); 		$t_bottom = $t_project_id[count( $t_project_id ) - 1]; 	} 

Fixed version (after fix):
 function helper_get_current_project() { 			$t_project_id = $t_pref->default_project; 		} else { 			$t_project_id = explode( ';', $t_project_id ); 			$t_project_id = (int)$t_project_id[count( $t_project_id ) - 1]; 		}  		if( !project_exists( $t_project_id ) || ( 0 == project_get_field( $t_project_id, 'enabled' ) ) || !access_has_project_level( VIEWER, $t_project_id ) ) { 			$t_project_id = ALL_PROJECTS; 		} 		$g_cache_current_project = $t_project_id; 	} 	return $g_cache_current_project; } function helper_get_current_project_trace() {  	} else { 		$t_project_id = explode( ';', $t_project_id ); 		foreach( $t_project_id as $t_key => $t_id ) { 			$t_project_id[$t_key] = (int)$t_id; 		} 		$t_bottom = $t_project_id[count( $t_project_id ) - 1]; 	} 

Patch:
patch: @@ -232,13 +232,13 @@ function helper_get_current_project() {
 			$t_project_id = $t_pref->default_project;
 		} else {
 			$t_project_id = explode( ';', $t_project_id );
-			$t_project_id = $t_project_id[count( $t_project_id ) - 1];
+			$t_project_id = (int)$t_project_id[count( $t_project_id ) - 1];
 		}
 
 		if( !project_exists( $t_project_id ) || ( 0 == project_get_field( $t_project_id, 'enabled' ) ) || !access_has_project_level( VIEWER, $t_project_id ) ) {
 			$t_project_id = ALL_PROJECTS;
 		}
-		$g_cache_current_project = (int) $t_project_id;
+		$g_cache_current_project = $t_project_id;
 	}
 	return $g_cache_current_project;
 }
@@ -272,6 +272,9 @@ function helper_get_current_project_trace() {
 
 	} else {
 		$t_project_id = explode( ';', $t_project_id );
+		foreach( $t_project_id as $t_key => $t_id ) {
+			$t_project_id[$t_key] = (int)$t_id;
+		}
 		$t_bottom = $t_project_id[count( $t_project_id ) - 1];
 	}
path: core/helper_api.php