rjbs / Email-MIME

perl library for parsing MIME messages
20 stars 30 forks source link

DoS on excessive or deeply nested parts #66

Closed carnil closed 6 months ago

carnil commented 4 years ago

Hi,

We have the following bug reported to the Debian package of Email-MIME, c.f. https://bugs.debian.org/960062

------8<-----------8<-----------8<-----------8<-----------8<-----

Package: libemail-mime-perl
Version: 1.946-1
Severity: important
Tags: upstream

Messages with too many tiny MIME parts can OOM on split().

Messages with many nested MIME parts can also fail on deep
recursion (Email::MIME->new calls ->subparts, ->subparts calls
->new, ad infinitum).

Smallish messages can generate these, since the a boundary
only needs to be 4 bytes "--a\n" and the header+body of
each part can just be 4 bytes "x:y\n\n", too.

Perl takes 42 bytes to represent a 4 byte string on 64-bit:

    use Devel::Size; say Devel::Size::total_size("--\n\n")

This affects many other MIME parsers, too.

------8<-----------8<-----------8<-----------8<-----------8<-----

Thanks for considering, Salvatore Bonaccorso, Debian Perl Group

rjbs commented 4 years ago

Thanks, I had received a similar notice a few weeks ago and today set aside a little time to do something. I don't care for the fix that's now in master, but it puts a limit on things. I will make a release of this in the future and, if possible, make more systemic fixes.

carnil commented 4 years ago

@rjbs any news on this issue?

slyon commented 1 year ago

@rjbs Can you confirm that this got fixed/mitigated in this version?

        1.947 2020-05-09 14:30:06-04:00 America/New_York (TRIAL RELEASE)
        - add $Email::MIME::MAX_DEPTH and refuse to parse deeper than that many
          parts; current default: 10

As an Ubuntu "main" inclusion reviewer, I'm considering this package to enter Ubuntu's "main" component of the archive (5-10 years of support by the Ubuntu team). But this DoS issue could be a blocker for main inclusion.

eslerm commented 7 months ago

@slyon this issue appears to be fixed: https://github.com/rjbs/Email-MIME/commit/3a12edd119e493156a5a05e45dd50f4e36b702e8 https://github.com/rjbs/Email-MIME/commit/7e96ecfa1da44914a407f82ae98ba817bba08f2d https://github.com/rjbs/Email-MIME/commit/02bf3e26812c8f38a86a33c168571f9783365df2

eslerm@mino:~/code/Email-MIME$ git tag --contains 3a12edd
1.947
1.948
1.949
1.950
1.951
1.952
1.953
3a12edd119e493156a5a05e45dd50f4e36b702e8
mpurg commented 7 months ago

Hi @rjbs

I believe only part of this issue was resolved, namely, the deeply nested parts. Below is a proof of concept script which creates a ~40MB message with 10M tiny mime parts. On my test system (Ubuntu 23.10), it consumes the entire RAM (4GB) and SWAP (4GB) and is killed by OOM.

use Email::MIME;

$asd = <<EOT;
MIME-Version: 1.0
Content-Type: multipart/alternative;
    boundary=a

EOT
$asd .= "--a\n" x 10000000;
$asd .= "a--\n";

my $email = Email::MIME->new($asd);

The MIME parser uses around 1GB of RAM per 2MB of email message size.

rjbs commented 6 months ago

The patch in #80 doesn't make me very happy, but solves this problem by dying early. Any thoughts before I ship it? (I'm going to look for a max number that seems safe. 100 was picked arbitrarily.)

eslerm commented 6 months ago

The multipart MIME issue described in https://github.com/rjbs/Email-MIME/issues/66 and https://github.com/rjbs/Email-MIME/pull/80) has been assigned CVE-2024-4140

The full patch-set will be released in 1.954.

A big thank you to @rjbs and to everyone who helped resolve this :tada: