This ought to do it:
function wpse15750_comment_check( $id ){
if( get_post_type( $id ) == 'attachment' )
exit;
}
add_action( 'pre_comment_on_post', 'wpse15750_comment_check' );
EDIT
Ignore the above. That will stop new comments, but to do what you want, this is much better:
function wpse15750_comments_closed( $open, $id ){
if( get_post_type( $id ) == 'attachment' )
return false;
return $open;
}
add_action( 'pre_comment_on_post', 'wpse15750_comments_closed', 10, 2 );
That will tell WordPress that attachments always have closed comments, but their database values will still say ‘open’. If you want to change that, run the following code:
global $wpdb;
$wpdb->update( $wpdb->posts, array( 'comment_status' => 'closed' ), array( 'post_type' => 'attachments', 'comment_status' => 'open' ) );
To prevent any future attachments from having open comments, use the following filter:
function wpse15750_no_attachment_comments( $data ){
if( $data['post_type'] == 'attachment' )
$data['comment_status'] = 'closed';
return $data;
}
add_filter( 'wp_insert_post_data', 'wpse15750_no_attachment_comments' );