Commit ecbdf95e authored by Thomas Sibley's avatar Thomas Sibley
Browse files

Headers in the parsed MIME entities of Templates are modifiable

This allows reformatting of inserted headers by canonicalizing tag case
and, crucially, folding (or refolding) lines.

When the header object is not explicitly marked modifiable — such as
when generated via parsing a raw MIME message — Mail::Header assumes
that header values you set should be inserted as-is.  This means
newlines are not stripped or validated as you're expected to construct
proper continuations yourself.

RT incorrectly assumed newlines in header values would be stripped,
leaving open the possibility of header injection via various
user-controlled inputs.  This commit resolves CVE-2012-4730.

Fixes failing tests by removing the assumptions that:

    1) Case of header names is preserved
    2) Header values are always on a single line
parent b501977f
......@@ -390,6 +390,7 @@ sub _Parse {
# Unfold all headers
$self->{'MIMEObj'}->head->unfold;
$self->{'MIMEObj'}->head->modify(1);
return ( 1, $self->loc("Template parsed") );
......
......@@ -8,6 +8,7 @@ use RT::Test::GnuPG
'trust-model' => 'always',
};
use Test::Warn;
use MIME::Head;
use RT::Action::SendEmail;
......@@ -70,8 +71,7 @@ $user->SetEmailAddress('general@example.com');
for my $mail (@mail) {
unlike $mail, qr/Some content/, "outgoing mail was encrypted";
my ($content_type) = $mail =~ /^(Content-Type: .*)/m;
my ($mime_version) = $mail =~ /^(MIME-Version: .*)/m;
my ($content_type, $mime_version) = get_headers($mail, "Content-Type", "MIME-Version");
my $body = strip_headers($mail);
$mail = << "MAIL";
......@@ -139,8 +139,7 @@ for my $mail (@mail) {
like $mail, qr/Some other content/, "outgoing mail was not encrypted";
like $mail, qr/-----BEGIN PGP SIGNATURE-----[\s\S]+-----END PGP SIGNATURE-----/, "data has some kind of signature";
my ($content_type) = $mail =~ /^(Content-Type: .*)/m;
my ($mime_version) = $mail =~ /^(MIME-Version: .*)/m;
my ($content_type, $mime_version) = get_headers($mail, "Content-Type", "MIME-Version");
my $body = strip_headers($mail);
$mail = << "MAIL";
......@@ -212,8 +211,7 @@ ok(@mail, "got some mail");
for my $mail (@mail) {
unlike $mail, qr/Some other content/, "outgoing mail was encrypted";
my ($content_type) = $mail =~ /^(Content-Type: .*)/m;
my ($mime_version) = $mail =~ /^(MIME-Version: .*)/m;
my ($content_type, $mime_version) = get_headers($mail, "Content-Type", "MIME-Version");
my $body = strip_headers($mail);
$mail = << "MAIL";
......@@ -279,8 +277,7 @@ ok(@mail, "got some mail");
for my $mail (@mail) {
like $mail, qr/Thought you had me figured out didya/, "outgoing mail was unencrypted";
my ($content_type) = $mail =~ /^(Content-Type: .*)/m;
my ($mime_version) = $mail =~ /^(MIME-Version: .*)/m;
my ($content_type, $mime_version) = get_headers($mail, "Content-Type", "MIME-Version");
my $body = strip_headers($mail);
$mail = << "MAIL";
......@@ -326,6 +323,20 @@ MAIL
like($attachments[0]->Content, qr/$RT::rtname/, "RT's mail includes this instance's name");
}
sub get_headers {
my $mail = shift;
open my $fh, "<", \$mail or die $!;
my $head = MIME::Head->read($fh);
return @{[
map {
my $hdr = "$_: " . $head->get($_);
chomp $hdr;
$hdr;
}
@_
]};
}
sub strip_headers
{
my $mail = shift;
......
......@@ -49,7 +49,7 @@ diag "Forward Ticket" if $ENV{TEST_VERBOSE};
my ($mail) = RT::Test->fetch_caught_mails;
like( $mail, qr!Subject: test forward!, 'Subject field' );
like( $mail, qr!To: rt-test, rt-to\@example.com!, 'To field' );
like( $mail, qr!Cc: rt-cc\@example.com!, 'Cc field' );
like( $mail, qr!Cc: rt-cc\@example.com!i, 'Cc field' );
like( $mail, qr!This is a forward of ticket!, 'content' );
like( $mail, qr!this is an attachment!, 'att content' );
like( $mail, qr!$att_name!, 'att file name' );
......@@ -75,8 +75,8 @@ qr/Forwarded Transaction #\d+ to rt-test, rt-to\@example.com, rt-cc\@example.com
my ($mail) = RT::Test->fetch_caught_mails;
like( $mail, qr!Subject: test forward!, 'Subject field' );
like( $mail, qr!To: rt-test, rt-to\@example.com!, 'To field' );
like( $mail, qr!Cc: rt-cc\@example.com!, 'Cc field' );
like( $mail, qr!Bcc: rt-bcc\@example.com!, 'Bcc field' );
like( $mail, qr!Cc: rt-cc\@example.com!i, 'Cc field' );
like( $mail, qr!Bcc: rt-bcc\@example.com!i, 'Bcc field' );
like( $mail, qr!This is a forward of transaction!, 'content' );
like( $mail, qr!$att_name!, 'att file name' );
like( $mail, qr!this is an attachment!, 'att content' );
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment