Version in base suite: 0.19.2-5sarge4.1 Version in overlay suite: 0.19.2-5sarge5 Base version: mantis_0.19.2-5sarge4.1 Target version: mantis_0.19.2-5sarge5 Base file: /org/ftp.debian.org/ftp/pool/main/m/mantis/mantis_0.19.2-5sarge4.1.dsc Target file: /org/ftp.debian.org/ftp/pool/main/m/mantis/mantis_0.19.2-5sarge5.dsc diff -u mantis-0.19.2/manage_user_page.php mantis-0.19.2/manage_user_page.php --- mantis-0.19.2/manage_user_page.php +++ mantis-0.19.2/manage_user_page.php @@ -98,7 +98,7 @@ echo ' : '; } - echo '', $row['username'], ''; + echo '', string_display( $row['username'] ), ''; } ?> @@ -132,7 +132,7 @@ echo ' : '; } - echo '', $row['username'], ''; + echo '', string_display( $row['username'] ), ''; } ?> @@ -256,9 +256,9 @@ ?> > - + - + diff -u mantis-0.19.2/core/prepare_api.php mantis-0.19.2/core/prepare_api.php --- mantis-0.19.2/core/prepare_api.php +++ mantis-0.19.2/core/prepare_api.php @@ -47,11 +47,11 @@ if ( !is_blank( $t_email ) ) { return prepare_email_link( $t_email, $t_username ); } else { - return $t_username; + return string_display( $t_username ); } } else { $t_result = ''; - $t_result .= $t_username; + $t_result .= string_display( $t_username ); $t_result .= ''; return $t_result; } diff -u mantis-0.19.2/core/custom_field_api.php mantis-0.19.2/core/custom_field_api.php --- mantis-0.19.2/core/custom_field_api.php +++ mantis-0.19.2/core/custom_field_api.php @@ -12,6 +12,7 @@ $t_core_dir = dirname( __FILE__ ).DIRECTORY_SEPARATOR; require_once( $t_core_dir . 'bug_api.php' ); + require_once( $t_core_dir . 'string_api.php' ); ### Custom Fields API ### @@ -232,6 +233,10 @@ # the definition are the default values and can be changes later # return the ID of the new definition function custom_field_create( $p_name ) { + if ( string_contains_scripting_chars( $p_name ) ) { + trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR ); + } + $c_name = db_prepare_string( trim( $p_name ) ); if ( is_blank( $p_name ) ) { @@ -255,6 +260,10 @@ # Update the field definition # return true on success, false on failure function custom_field_update( $p_field_id, $p_def_array ) { + if ( string_contains_scripting_chars( $p_def_array['name'] ) ) { + trigger_error( ERROR_CUSTOM_FIELD_INVALID_DEFINITION, ERROR ); + } + $c_field_id = db_prepare_int( $p_field_id ); $c_name = db_prepare_string( trim( $p_def_array['name'] ) ); $c_type = db_prepare_int( $p_def_array['type'] ); @@ -570,6 +579,34 @@ # Data Access #=================================== + # -------------------- + # Get the id of the custom field with the specified name. + # false is returned if no custom field found with the specified name. + function custom_field_get_id_from_name( $p_field_name, $p_truncated_length = null ) { + $t_custom_field_table = config_get( 'mantis_custom_field_table' ); + + $c_field_name = db_prepare_string( $p_field_name ); + + if ( ( null === $p_truncated_length ) || ( strlen( $c_field_name ) != $p_truncated_length ) ) { + $query = "SELECT id FROM $t_custom_field_table WHERE name = '$c_field_name'"; + } else { + # @@@ This is to handle the case where we only have a truncated part of the name. This happens in the case where + # we are getting the custom field name from the history logs, since history is 32 and custom field name is 64. + # This fix will handle entries already in the database, future entries should be handled by making the field name max lengths match. + $query = "SELECT id FROM $t_custom_field_table WHERE name LIKE '$c_field_name%'"; + } + + $t_result = db_query( $query, 1 ); + + if ( db_num_rows( $t_result ) == 0 ) { + return false; + } + + $row = db_fetch_array( $t_result ); + + return $row['id']; + } + # -------------------- # Return an array all custom field ids function custom_field_get_ids( $p_project_id = ALL_PROJECTS ) { @@ -1189 +1226 @@ -?> \ No newline at end of file +?> diff -u mantis-0.19.2/core/email_api.php mantis-0.19.2/core/email_api.php --- mantis-0.19.2/core/email_api.php +++ mantis-0.19.2/core/email_api.php @@ -1042,7 +1042,7 @@ # put history data if ( ON == config_get( 'history_default_visible' ) && $t_user_access_level >= config_get( 'view_history_threshold' ) ) { - $t_bug_data['history'] = history_get_raw_events_array( $p_bug_id ); + $t_bug_data['history'] = history_get_raw_events_array( $p_bug_id, $p_user_id ); } # Sponsorship Information diff -u mantis-0.19.2/core/file_api.php mantis-0.19.2/core/file_api.php --- mantis-0.19.2/core/file_api.php +++ mantis-0.19.2/core/file_api.php @@ -159,7 +159,7 @@ $row = db_fetch_array( $result ); extract( $row, EXTR_PREFIX_ALL, 'v' ); - $t_file_display_name = file_get_display_name( $v_filename ); + $t_file_display_name = string_html_specialchars( file_get_display_name( $v_filename ) ); $t_filesize = number_format( $v_filesize ); $t_date_added = date( config_get( 'normal_date_format' ), db_unixtimestamp( $v_date_added ) ); diff -u mantis-0.19.2/core/history_api.php mantis-0.19.2/core/history_api.php --- mantis-0.19.2/core/history_api.php +++ mantis-0.19.2/core/history_api.php @@ -108,6 +108,8 @@ $t_history_order = config_get( 'history_order' ); $c_bug_id = db_prepare_int( $p_bug_id ); + $t_user_id = ( ( null === $p_user_id ) ? auth_get_current_user_id() : $p_user_id ); + # grab history and display by date_modified then field_name # @@@ by MASC I guess it's better by id then by field_name. When we have more history lines with the same # date, it's better to respect the storing order otherwise we should risk to mix different information @@ -122,20 +124,52 @@ $raw_history_count = db_num_rows( $result ); $raw_history = array(); - for ( $i=0; $i < $raw_history_count; ++$i ) { + $t_private_bugnote_threshold = config_get( 'private_bugnote_threshold' ); + $t_private_bugnote_visible = access_has_bug_level( + config_get( 'private_bugnote_threshold' ), $p_bug_id, $t_user_id ); + for ( $i=0, $j=0; $i < $raw_history_count; ++$i ) { $row = db_fetch_array( $result ); extract( $row, EXTR_PREFIX_ALL, 'v' ); - $raw_history[$i]['date'] = db_unixtimestamp( $v_date_modified ); - $raw_history[$i]['userid'] = $v_user_id; + // check that the item should be visible to the user + // custom fields - we are passing 32 here to notify the API that the custom field name is truncated by the history column from 64 to 32 characters. + $t_field_id = custom_field_get_id_from_name( $v_field_name, 32 ); + if ( false !== $t_field_id && + !custom_field_has_read_access( $t_field_id, $p_bug_id, $t_user_id ) ) { + continue; + } + + // bugnotes + if ( $t_user_id != $v_user_id ) { // bypass if user originated note + if ( ( $v_type == BUGNOTE_ADDED ) || + ( $v_type == BUGNOTE_UPDATED ) || + ( $v_type == BUGNOTE_DELETED ) ) { + if ( !$t_private_bugnote_visible && + ( bugnote_get_field( $v_old_value, 'view_state' ) == VS_PRIVATE ) ) { + continue; + } + } + + if ( $v_type == BUGNOTE_STATE_CHANGED ) { + if ( !$t_private_bugnote_visible && + ( bugnote_get_field( $v_new_value, 'view_state' ) == VS_PRIVATE ) ) { + continue; + } + } + } + + $raw_history[$j]['date'] = db_unixtimestamp( $v_date_modified ); + $raw_history[$j]['userid'] = $v_user_id; # user_get_name handles deleted users, and username vs realname - $raw_history[$i]['username'] = user_get_name( $v_user_id ); + $raw_history[$j]['username'] = user_get_name( $v_user_id ); + + $raw_history[$j]['field'] = $v_field_name; + $raw_history[$j]['type'] = $v_type; + $raw_history[$j]['old_value'] = $v_old_value; + $raw_history[$j]['new_value'] = $v_new_value; - $raw_history[$i]['field'] = $v_field_name; - $raw_history[$i]['type'] = $v_type; - $raw_history[$i]['old_value'] = $v_old_value; - $raw_history[$i]['new_value'] = $v_new_value; + $j++; } # end for loop return $raw_history; diff -u mantis-0.19.2/core/html_api.php mantis-0.19.2/core/html_api.php --- mantis-0.19.2/core/html_api.php +++ mantis-0.19.2/core/html_api.php @@ -294,8 +294,8 @@ PRINT ' | ' . lang_get( 'signup_link' ) . ''; } } else { - echo lang_get( 'logged_in_as' ), ": $t_username "; - echo is_blank( $t_realname ) ? "($t_access_level)" : "($t_realname - $t_access_level)"; + echo lang_get( 'logged_in_as' ), ": ", string_display( $t_username ), " "; + echo is_blank( $t_realname ) ? "($t_access_level)" : "(", string_display( $t_realname ), " - $t_access_level)"; echo ""; } PRINT ''; diff -u mantis-0.19.2/core/string_api.php mantis-0.19.2/core/string_api.php --- mantis-0.19.2/core/string_api.php +++ mantis-0.19.2/core/string_api.php @@ -597,2 +597,11 @@ + # -------------------- + # Checks the supplied string for scripting characters, if it contains any, then return true, otherwise return false. + function string_contains_scripting_chars( $p_string ) { + if ( ( strstr( $p_string, '<' ) !== false ) || ( strstr( $p_string, '>' ) !== false ) ) { + return true; + } + return false; + } + ?> diff -u mantis-0.19.2/core/user_api.php mantis-0.19.2/core/user_api.php --- mantis-0.19.2/core/user_api.php +++ mantis-0.19.2/core/user_api.php @@ -13,6 +13,7 @@ require_once( $t_core_dir . 'email_api.php' ); require_once( $t_core_dir . 'ldap_api.php' ); + require_once( $t_core_dir . 'string_api.php' ); ### User API ### @@ -199,6 +200,21 @@ # We have a valid username return true; } + # -------------------- + # Check if the realname is a valid (does not account for uniqueness) + # true: valid, false: not valid + function user_is_realname_valid( $p_realname ) { + return ( !string_contains_scripting_chars( $p_realname ) ); + } + + # -------------------- + # Check if the realname is a valid (does not account for uniqueness), if not, trigger an error + function user_ensure_realname_valid( $p_realname ) { + if ( !user_is_realname_valid( $p_realname ) ) { + trigger_error( ERROR_USER_REAL_NAME_INVALID, ERROR ); + } + } + # -------------------- # Check if the username is a valid username (does not account for uniqueness) @@ -294,6 +310,7 @@ user_ensure_name_valid( $p_username ); user_ensure_name_unique( $p_username ); + user_ensure_realname_valid( $p_realname ); user_ensure_realname_unique( $p_username, $p_realname ); email_ensure_valid( $p_email ); diff -u mantis-0.19.2/lang/strings_english.txt mantis-0.19.2/lang/strings_english.txt --- mantis-0.19.2/lang/strings_english.txt +++ mantis-0.19.2/lang/strings_english.txt @@ -220,6 +220,7 @@ $MANTIS_ERROR[ERROR_VERSION_DUPLICATE] = 'A version with that name already exists.'; $MANTIS_ERROR[ERROR_VERSION_NOT_FOUND] = 'Version not found.'; $MANTIS_ERROR[ERROR_USER_NAME_INVALID] = 'The username is invalid. Usernames may only contain letters, numbers, spaces, hyphens, and underscores.'; +$MANTIS_ERROR[ERROR_USER_REAL_NAME_INVALID] = 'The user real name is invalid.'; $MANTIS_ERROR[ERROR_USER_DOES_NOT_HAVE_REQ_ACCESS] = 'User does not have required access level'; $MANTIS_ERROR[ERROR_USER_REAL_MATCH_USER] = 'The "Real Name" chosen matches another user\'s login name. Please choose another.'; $MANTIS_ERROR[ERROR_SPONSORSHIP_NOT_ENABLED] = 'Sponsorship support not enabled.'; diff -u mantis-0.19.2/debian/changelog mantis-0.19.2/debian/changelog --- mantis-0.19.2/debian/changelog +++ mantis-0.19.2/debian/changelog @@ -1,3 +1,18 @@ +mantis (0.19.2-5sarge5) oldstable-security; urgency=high + + * Maintainer upload for the security team + * Fixed security issue CVE-2007-6611: "Upload File" Script + insertion vulnerability by applying the patch from sid. + (Closes: #458377) + * Fixed security issue CVE-2006-6574: Custom Field Information Disclosure by + backporting changes in history_api.php from sid + (Closes: #402802) + * Fixed security issue: Email notifications bypass security on custom fields + * Fixed multiple XSS vulnerabilites by backporting changes from upstream + version 1.0.7 + + -- Patrick Schoenfeld Wed, 09 Jan 2008 10:24:53 +0100 + mantis (0.19.2-5sarge4.1) stable-security; urgency=high * Non-maintainer upload for security issues. only in patch2: unchanged: --- mantis-0.19.2.orig/account_page.php +++ mantis-0.19.2/account_page.php @@ -165,7 +165,7 @@ - + only in patch2: unchanged: --- mantis-0.19.2.orig/bug_report_advanced_page.php +++ mantis-0.19.2/bug_report_advanced_page.php @@ -365,7 +365,7 @@ ?> > - * + * only in patch2: unchanged: --- mantis-0.19.2.orig/bug_report_page.php +++ mantis-0.19.2/bug_report_page.php @@ -251,7 +251,7 @@ * - + only in patch2: unchanged: --- mantis-0.19.2.orig/bug_update_advanced_page.php +++ mantis-0.19.2/bug_update_advanced_page.php @@ -439,7 +439,7 @@ ?> > - * + * > - * + * > - + only in patch2: unchanged: --- mantis-0.19.2.orig/bug_view_page.php +++ mantis-0.19.2/bug_view_page.php @@ -319,7 +319,7 @@ ?> > - + only in patch2: unchanged: --- mantis-0.19.2.orig/manage_user_update.php +++ mantis-0.19.2/manage_user_update.php @@ -38,6 +38,10 @@ trigger_error( ERROR_USER_NAME_NOT_UNIQUE, ERROR ); } + user_ensure_name_valid( $f_username ); + user_ensure_realname_valid( $f_realname ); + user_ensure_realname_unique( $f_username, $f_realname ); + $f_email = email_append_domain( $f_email ); email_ensure_valid( $f_email ); only in patch2: unchanged: --- mantis-0.19.2.orig/manage_proj_edit_page.php +++ mantis-0.19.2/manage_proj_edit_page.php @@ -352,7 +352,7 @@ ?> > - +
only in patch2: unchanged: --- mantis-0.19.2.orig/manage_user_create.php +++ mantis-0.19.2/manage_user_create.php @@ -36,6 +36,7 @@ # blank password (don't want to prompt the user if the process will fail # anyway) user_ensure_name_valid( $f_username ); + user_ensure_realname_valid( $f_realname ); if ( $f_password != $f_password_verify ) { trigger_error( ERROR_USER_CREATE_PASSWORD_MISMATCH, ERROR ); only in patch2: unchanged: --- mantis-0.19.2.orig/manage_user_edit_page.php +++ mantis-0.19.2/manage_user_edit_page.php @@ -54,7 +54,7 @@ : - + only in patch2: unchanged: --- mantis-0.19.2.orig/print_all_bug_page.php +++ mantis-0.19.2/print_all_bug_page.php @@ -75,7 +75,7 @@
- +
only in patch2: unchanged: --- mantis-0.19.2.orig/print_bug_page.php +++ mantis-0.19.2/print_bug_page.php @@ -242,7 +242,7 @@ ?> - : + :