CVE-2012-1119: Permissions, Privileges, and Access Controls (CWE-264)
value: MantisBT before 1.2.9 does not audit when users copy or clone a bug report, which makes it easier for remote attackers to copy bug reports without detection.
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: bug_actiongroup.php, core/bug_api.php, core/history_api.php
Commit date: 2012-03-02 00:10:53 +0100
Commit message: Fix #13816: Update history when copying issues

Until now, copying bugs using the "View Issues" page creates wrong/
incomplete history (entries for notes reflect the id's of the original
issue's notes) and also does not record any trace that the new issue is
in fact clone of another, which can be a source of confusion.

This commit prevents the duplication of the original bug's history,
generating instead a single history entry similar to what happens when
cloning a bug with the Clone button in view.php page.

The display of history entries for cloned bugs has been slightly
modified, the bug id is now printed under the 'Field' column instead of
the 'Change' column, like entries for adding notes (as cloning s not a
change).

Diff: diff --git a/bug_actiongroup.php b/bug_actiongroup.php
index c68a07fb1..72c9c7b6c 100644
--- a/bug_actiongroup.php
+++ b/bug_actiongroup.php
@@ -148,11 +148,12 @@ foreach( $f_bug_arr as $t_bug_id ) {
 
 	case 'COPY':
 		$f_project_id = gpc_get_int( 'project_id' );
 
 		if ( access_has_project_level( config_get( 'report_bug_threshold' ), $f_project_id ) ) {
-			bug_copy( $t_bug_id, $f_project_id, true, true, true, true, true, true );
+			# Copy everything except history
+			bug_copy( $t_bug_id, $f_project_id, true, true, false, true, true, true );
 		} else {
 			$t_failed_ids[$t_bug_id] = lang_get( 'bug_actiongroup_access' );
 		}
 		break;
 
diff --git a/core/bug_api.php b/core/bug_api.php
index b3cca646d..149433702 100644
--- a/core/bug_api.php
+++ b/core/bug_api.php
@@ -905,10 +905,14 @@ function bug_check_workflow( $p_bug_status, $p_wanted_status ) {
  * @todo Not managed FTP file upload
  * @param array p_bug_id integer representing bug id
  * @param int p_target_project_id
  * @param bool p_copy_custom_fields
  * @param bool p_copy_relationships
+ * @param bool p_copy_history
+ * @param bool p_copy_attachments
+ * @param bool p_copy_bugnotes
+ * @param bool p_copy_monitoring_users
  * @return int representing the new bugid
  * @access public
  */
 function bug_copy( $p_bug_id, $p_target_project_id = null, $p_copy_custom_fields = false, $p_copy_relationships = false, $p_copy_history = false, $p_copy_attachments = false, $p_copy_bugnotes = false, $p_copy_monitoring_users = false ) {
 	global $g_db;
@@ -1052,10 +1056,14 @@ function bug_copy( $p_bug_id, $p_target_project_id = null, $p_copy_custom_fields
 						  		   " . db_param() . " );";
 			db_query_bound( $query, Array( $t_bug_history['user_id'], $t_new_bug_id, $t_bug_history['date_modified'], $t_bug_history['field_name'], $t_bug_history['old_value'], $t_bug_history['new_value'], $t_bug_history['type'] ) );
 		}
 	}
 
+	# Create history entries to reflect the copy operation
+	history_log_event_special( $t_new_bug_id, BUG_CREATED_FROM, '', $t_bug_id );
+	history_log_event_special( $t_bug_id, BUG_CLONED_TO, '', $t_new_bug_id );
+
 	return $t_new_bug_id;
 }
 
 /**
  * Moves an issue from a project to another.
diff --git a/core/history_api.php b/core/history_api.php
index dbfc30b87..27be7b090 100644
--- a/core/history_api.php
+++ b/core/history_api.php
@@ -554,16 +554,14 @@ function history_localize_item( $p_field_name, $p_type, $p_old_value, $p_new_val
 					} else {
 						$t_change = bug_format_id( $p_new_value );
 					}
 					break;
 				case BUG_CLONED_TO:
-					$t_note = lang_get( 'bug_cloned_to' );
-					$t_change = bug_format_id( $p_new_value );
+					$t_note = lang_get( 'bug_cloned_to' ) . ': ' . bug_format_id( $p_new_value );
 					break;
 				case BUG_CREATED_FROM:
-					$t_note = lang_get( 'bug_created_from' );
-					$t_change = bug_format_id( $p_new_value );
+					$t_note = lang_get( 'bug_created_from' ) . ': ' . bug_format_id( $p_new_value );
 					break;
 				case TAG_ATTACHED:
 					$t_note = lang_get( 'tag_history_attached' ) . ': ' . $p_old_value;
 					break;
 				case TAG_DETACHED:

Vulnerable code: 			bug_copy( $t_bug_id, $f_project_id, true, true, true, true, true, true );
					$t_note = lang_get( 'bug_cloned_to' );
					$t_change = bug_format_id( $p_new_value );
					$t_note = lang_get( 'bug_created_from' );
					$t_change = bug_format_id( $p_new_value );
Fixed code: 			# Copy everything except history
			bug_copy( $t_bug_id, $f_project_id, true, true, false, true, true, true );
 * @param bool p_copy_history
 * @param bool p_copy_attachments
 * @param bool p_copy_bugnotes
 * @param bool p_copy_monitoring_users
	# Create history entries to reflect the copy operation
	history_log_event_special( $t_new_bug_id, BUG_CREATED_FROM, '', $t_bug_id );
	history_log_event_special( $t_bug_id, BUG_CLONED_TO, '', $t_new_bug_id );

					$t_note = lang_get( 'bug_cloned_to' ) . ': ' . bug_format_id( $p_new_value );
					$t_note = lang_get( 'bug_created_from' ) . ': ' . bug_format_id( $p_new_value );