CVE-2017-12061: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: An XSS issue was discovered in admin/install.php in MantisBT before 1.3.12 and 2.x before 2.5.2. Some variables under user control in the MantisBT installation script are not properly sanitized before being output, allowing remote attackers to inject arbitrary JavaScript code, as demonstrated by the $f_database, $f_db_username, and $f_admin_username variables. This is mitigated by the fact that the admin/ folder should be deleted after installation, and also prevented by CSP.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2017-08-01T15:29Z
Repository: https://github.com/mantisbt/mantisbt
Language: PHP
Files changed: admin/install.php
Commit date: 2017-08-01 13:00:30 +0200
Commit message: Fix XSS in install.php (CVE-2017-12061)

aLLy from ONSEC (https://twitter.com/IamSecurity) reported this
vulnerability, allowing an attacker to inject arbitrary code through
crafted forms variables.

Sanitizing the database error message prior to output prevents the
attack.

Fixes #23146

Diff: diff --git a/admin/install.php b/admin/install.php
index 45a46a41b9..cd07bb50a1 100644
--- a/admin/install.php
+++ b/admin/install.php
@@ -419,11 +419,15 @@ if( 2 == $t_install_state ) {
 			$f_db_exists = true;
 		}
 
 		print_test_result( GOOD );
 	} else {
-		print_test_result( BAD, true, 'Does administrative user have access to the database? ( ' . db_error_msg() . ' )' );
+		print_test_result(
+			BAD,
+			true,
+			'Does administrative user have access to the database? ( ' . string_attribute( db_error_msg() ) . ' )'
+		);
 		$t_version_info = null;
 	}
 	?>
 </tr>
 <?php
@@ -439,11 +443,15 @@ if( 2 == $t_install_state ) {
 
 		if( $t_result == true ) {
 			$t_db_open = true;
 			print_test_result( GOOD );
 		} else {
-			print_test_result( BAD, false, 'Database user doesn\'t have access to the database ( ' . db_error_msg() . ' )' );
+			print_test_result(
+				BAD,
+				false,
+				'Database user doesn\'t have access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
+			);
 		}
 		?>
 </tr>
 
 <?php
@@ -791,13 +799,21 @@ if( 3 == $t_install_state ) {
 				} else {
 					$t_db_exists = strstr( $t_error, 'atabase exists' );
 				}
 
 				if( $t_db_exists ) {
-					print_test_result( BAD, false, 'Database already exists? ( ' . db_error_msg() . ' )' );
+					print_test_result(
+						BAD,
+						false,
+						'Database already exists? ( ' . string_attribute( db_error_msg() ) . ' )'
+					);
 				} else {
-					print_test_result( BAD, true, 'Does administrative user have access to create the database? ( ' . db_error_msg() . ' )' );
+					print_test_result(
+						BAD,
+						true,
+						'Does administrative user have access to create the database? ( ' . string_attribute( db_error_msg() ) . ' )'
+					);
 					$t_install_state--; # db creation failed, allow user to re-enter user/password info
 				}
 			}
 		}
 		?>
@@ -815,11 +831,15 @@ if( 3 == $t_install_state ) {
 		$g_db = ADONewConnection( $f_db_type );
 		$t_result = @$g_db->Connect( $f_hostname, $f_db_username, $f_db_password, $f_database_name );
 		if( $t_result == true ) {
 			print_test_result( GOOD );
 		} else {
-			print_test_result( BAD, false, 'Database user doesn\'t have access to the database ( ' . db_error_msg() . ' )' );
+			print_test_result(
+				BAD,
+				false,
+				'Database user doesn\'t have access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
+			);
 		}
 		$g_db->Close();
 	?>
 </tr>
 <?php
@@ -1215,11 +1235,15 @@ if( 6 == $t_install_state ) {
 	$t_result = @$g_db->Connect( $f_hostname, $f_db_username, $f_db_password, $f_database_name );
 
 	if( $t_result == true ) {
 		print_test_result( GOOD );
 	} else {
-		print_test_result( BAD, false, 'Database user does not have access to the database ( ' . db_error_msg() . ' )' );
+		print_test_result(
+			BAD,
+			false,
+			'Database user does not have access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
+		);
 	}
 	?>
 </tr>
 <tr>
 	<td>
@@ -1230,11 +1254,15 @@ if( 6 == $t_install_state ) {
 	$t_result = @$g_db->Execute( $t_query );
 
 	if( $t_result != false ) {
 		print_test_result( GOOD );
 	} else {
-		print_test_result( BAD, true, 'Database user does not have SELECT access to the database ( ' . db_error_msg() . ' )' );
+		print_test_result(
+			BAD,
+			true,
+			'Database user does not have SELECT access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
+		);
 	}
 	?>
 </tr>
 <tr>
 	<td>
@@ -1245,11 +1273,15 @@ if( 6 == $t_install_state ) {
 	$t_result = @$g_db->Execute( $t_query );
 
 	if( $t_result != false ) {
 		print_test_result( GOOD );
 	} else {
-		print_test_result( BAD, true, 'Database user does not have INSERT access to the database ( ' . db_error_msg() . ' )' );
+		print_test_result(
+			BAD,
+			true,
+			'Database user does not have INSERT access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
+		);
 	}
 	?>
 </tr>
 <tr>
 	<td>
@@ -1260,11 +1292,15 @@ if( 6 == $t_install_state ) {
 	$t_result = @$g_db->Execute( $t_query );
 
 	if( $t_result != false ) {
 		print_test_result( GOOD );
 	} else {
-		print_test_result( BAD, true, 'Database user does not have UPDATE access to the database ( ' . db_error_msg() . ' )' );
+		print_test_result(
+			BAD,
+			true,
+			'Database user does not have UPDATE access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
+		);
 	}
 	?>
 </tr>
 <tr>
 	<td>
@@ -1275,11 +1311,15 @@ if( 6 == $t_install_state ) {
 	$t_result = @$g_db->Execute( $t_query );
 
 	if( $t_result != false ) {
 		print_test_result( GOOD );
 	} else {
-		print_test_result( BAD, true, 'Database user does not have DELETE access to the database ( ' . db_error_msg() . ' )' );
+		print_test_result(
+			BAD,
+			true,
+			'Database user does not have DELETE access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
+		);
 	}
 	?>
 </tr>
 </table>
 </div>

Vulnerable code: 		print_test_result( BAD, true, 'Does administrative user have access to the database? ( ' . db_error_msg() . ' )' );
			print_test_result( BAD, false, 'Database user doesn\'t have access to the database ( ' . db_error_msg() . ' )' );
					print_test_result( BAD, false, 'Database already exists? ( ' . db_error_msg() . ' )' );
					print_test_result( BAD, true, 'Does administrative user have access to create the database? ( ' . db_error_msg() . ' )' );
			print_test_result( BAD, false, 'Database user doesn\'t have access to the database ( ' . db_error_msg() . ' )' );
		print_test_result( BAD, false, 'Database user does not have access to the database ( ' . db_error_msg() . ' )' );
		print_test_result( BAD, true, 'Database user does not have SELECT access to the database ( ' . db_error_msg() . ' )' );
		print_test_result( BAD, true, 'Database user does not have INSERT access to the database ( ' . db_error_msg() . ' )' );
		print_test_result( BAD, true, 'Database user does not have UPDATE access to the database ( ' . db_error_msg() . ' )' );
		print_test_result( BAD, true, 'Database user does not have DELETE access to the database ( ' . db_error_msg() . ' )' );
Fixed code: 		print_test_result(
			BAD,
			true,
			'Does administrative user have access to the database? ( ' . string_attribute( db_error_msg() ) . ' )'
		);
			print_test_result(
				BAD,
				false,
				'Database user doesn\'t have access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
			);
					print_test_result(
						BAD,
						false,
						'Database already exists? ( ' . string_attribute( db_error_msg() ) . ' )'
					);
					print_test_result(
						BAD,
						true,
						'Does administrative user have access to create the database? ( ' . string_attribute( db_error_msg() ) . ' )'
					);
			print_test_result(
				BAD,
				false,
				'Database user doesn\'t have access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
			);
		print_test_result(
			BAD,
			false,
			'Database user does not have access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
		);
		print_test_result(
			BAD,
			true,
			'Database user does not have SELECT access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
		);
		print_test_result(
			BAD,
			true,
			'Database user does not have INSERT access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
		);
		print_test_result(
			BAD,
			true,
			'Database user does not have UPDATE access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
		);
		print_test_result(
			BAD,
			true,
			'Database user does not have DELETE access to the database ( ' . string_attribute( db_error_msg() ) . ' )'
		);