CVE-2012-1121: Permissions, Privileges, and Access Controls (CWE-264)
value: MantisBT before 1.2.9 does not properly check permissions, which allows remote authenticated users with manager privileges to (1) modify or (2) delete global categories.
CWE description: Weaknesses in this category are related to the management of permissions, privileges, and other security features that are used to perform access control.
Published: 2012-06-29T19:55Z
Repository: https://github.com/mantisbt/mantisbt
Language: PHP
Files changed: manage_proj_cat_delete.php, manage_proj_cat_edit_page.php, manage_proj_page.php
Commit date: 2012-01-02 01:54:50 +0100
Commit message: User must have global access to update global categories

The user's global access level must be >= $g_manage_site_threshold to
be allowed to add, edit or delete global categories.

Prior to this, once a user had been defined as Manager on at least one
project, they could freely update global categories.

Also prevents such updates through URL manipulation.

Fixes #13561

Diff: diff --git a/manage_proj_cat_delete.php b/manage_proj_cat_delete.php
index 59ea3374b..d3f6f7f27 100644
--- a/manage_proj_cat_delete.php
+++ b/manage_proj_cat_delete.php
@@ -58,16 +58,16 @@ form_security_validate( 'manage_proj_cat_delete' );
 auth_reauthenticate();
 
 $f_category_id = gpc_get_int( 'id' );
 $f_project_id = gpc_get_int( 'project_id' );
 
-access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id );
-
 $t_row = category_get_row( $f_category_id );
 $t_name = category_full_name( $f_category_id );
 $t_project_id = $t_row['project_id'];
 
+access_ensure_project_level( config_get( 'manage_project_threshold' ), $t_project_id );
+
 # Get a bug count
 $t_bug_table = db_get_table( 'bug' );
 $t_query = "SELECT COUNT(id) FROM $t_bug_table WHERE category_id=" . db_param();
 $t_bug_count = db_result( db_query_bound( $t_query, array( $f_category_id ) ) );
 
diff --git a/manage_proj_cat_edit_page.php b/manage_proj_cat_edit_page.php
index 89f69327f..a6e2d4c6d 100644
--- a/manage_proj_cat_edit_page.php
+++ b/manage_proj_cat_edit_page.php
@@ -53,17 +53,17 @@ require_api( 'string_api.php' );
 auth_reauthenticate();
 
 $f_category_id		= gpc_get_int( 'id' );
 $f_project_id		= gpc_get_int( 'project_id' );
 
-access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id );
-
 $t_row = category_get_row( $f_category_id );
 $t_assigned_to = $t_row['user_id'];
 $t_project_id = $t_row['project_id'];
 $t_name = $t_row['name'];
 
+access_ensure_project_level( config_get( 'manage_project_threshold' ), $t_project_id );
+
 html_page_top();
 
 print_manage_menu( 'manage_proj_cat_edit_page.php' ); ?>
 
 <div id="manage-proj-category-update-div" class="form-container">
diff --git a/manage_proj_page.php b/manage_proj_page.php
index 681e49024..4cbbca414 100644
--- a/manage_proj_page.php
+++ b/manage_proj_page.php
@@ -162,45 +162,53 @@ print_manage_menu( 'manage_proj_page.php' );
 
 <div id="categories" class="form-container">
 	<h2><?php echo lang_get( 'global_categories' ) ?></h2>
 	<table cellspacing="1" cellpadding="5" border="1"><?php
 		$t_categories = category_get_all_rows( ALL_PROJECTS );
+		$t_can_update_global_cat = access_has_global_level( config_get( 'manage_site_threshold' ) );
+
 		if ( count( $t_categories ) > 0 ) { ?>
 		<tr class="row-category">
 			<td><?php echo lang_get( 'category' ) ?></td>
 			<td><?php echo lang_get( 'assign_to' ) ?></td>
+			<?php if( $t_can_update_global_cat ) { ?>
 			<td class="center"><?php echo lang_get( 'actions' ) ?></td>
+			<?php } ?>
 		</tr><?php
 		}
 
-	foreach ( $t_categories as $t_category ) {
+	foreach( $t_categories as $t_category ) {
 		$t_id = $t_category['id'];
 	?>
 		<tr <?php echo helper_alternate_class() ?>>
 			<td><?php echo string_display( category_full_name( $t_id, false ) )  ?></td>
 			<td><?php echo prepare_user_name( $t_category['user_id'] ) ?></td>
+			<?php if( $t_can_update_global_cat ) { ?>
 			<td class="center">
 				<?php
 					$t_id = urlencode( $t_id );
 					$t_project_id = urlencode( ALL_PROJECTS );
 
 					print_button( "manage_proj_cat_edit_page.php?id=$t_id&project_id=$t_project_id", lang_get( 'edit_link' ) );
 					echo '&#160;';
 					print_button( "manage_proj_cat_delete.php?id=$t_id&project_id=$t_project_id", lang_get( 'delete_link' ) );
 				?>
 			</td>
+			<?php } ?>
 		</tr><?php
 	} # end for loop ?>
 	</table>
 
+<?php if( $t_can_update_global_cat ) { ?>
 	<form method="post" action="manage_proj_cat_add.php">
 		<fieldset>
 			<?php echo form_security_field( 'manage_proj_cat_add' ) ?>
 			<input type="hidden" name="project_id" value="<?php echo ALL_PROJECTS ?>" />
 			<input type="text" name="name" size="32" maxlength="128" />
 			<input type="submit" class="button" value="<?php echo lang_get( 'add_category_button' ) ?>" />
 		</fieldset>
 	</form>
+<?php } ?>
 </div>
 
 <?php
 html_page_bottom();

Vulnerable code: access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id );

access_ensure_project_level( config_get( 'manage_project_threshold' ), $f_project_id );

	foreach ( $t_categories as $t_category ) {
Fixed code: access_ensure_project_level( config_get( 'manage_project_threshold' ), $t_project_id );

access_ensure_project_level( config_get( 'manage_project_threshold' ), $t_project_id );

		$t_can_update_global_cat = access_has_global_level( config_get( 'manage_site_threshold' ) );

			<?php if( $t_can_update_global_cat ) { ?>
			<?php } ?>
	foreach( $t_categories as $t_category ) {
			<?php if( $t_can_update_global_cat ) { ?>
			<?php } ?>
<?php if( $t_can_update_global_cat ) { ?>
<?php } ?>