Bug 404698 - Decryption Oracle based on replying to PGP or S/MIME encrypted emails
Summary: Decryption Oracle based on replying to PGP or S/MIME encrypted emails
Status: RESOLVED FIXED
Alias: None
Product: kmail2
Classification: Applications
Component: crypto (show other bugs)
Version: unspecified
Platform: Debian stable Linux
: NOR normal (vote)
Target Milestone: ---
Assignee: kdepim bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-02-22 12:52 UTC by Jens Mueller
Modified: 2019-07-31 02:15 UTC (History)
11 users (show)

See Also:
Latest Commit:
Version Fixed In: 5.11.2


Attachments
Proof-of-concept PGP (1.95 KB, message/rfc822)
2019-02-22 12:52 UTC, Jens Mueller
Details
Proof-of-concept S/MIME (1.56 KB, message/rfc822)
2019-02-22 12:52 UTC, Jens Mueller
Details
html mail with two images embeded. (859 bytes, application/mbox)
2019-05-12 22:10 UTC, Sandro Knauß
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jens Mueller 2019-02-22 12:52:18 UTC
In the scope of academic research in cooperation with Ruhr-Uni Bochum and FH Münster, Germany we discovered a security issue in KMail: An attacker who is in possession of PGP or S/MIME encrypted messages can embed them into a multipart message and re-send them to the intended receiver. When the message is read and decrypted by the receiver, the attacker's content is shown. If the victim replies, the plaintext is leaked to an attacker's email address. The root cause for these vulnerabilities lies in the way KMail (and many other mail clients) handle partially encrypted multipart messages.

-----------------------------------------
*Leaking plaintext through reply/forward*
-----------------------------------------

/Attacker model/: Attacker is in possession of PGP or S/MIME encrypted messages, which she may have obtained as passive man-in-the-middle or by actively hacking into the victim's mail server or gateway

/Attacker's goal/: Leak the plaintext by wrapping the ciphertext part within a benign-looking MIME mail sent to and decrypted+replied to by the victim

/Attack outline:/ If KMail receives a multipart email, as depicted below, it decrypt the ciphertext part(s), together with the attacker-controlled text (which may be prepended and/or appended).

multipart/mixed
   |--- Attacker's part
   |--- [encrypted part to leak]
   +--- [Attacker's encrypted part]

A benign-looking attacker's text may lure the victim into replying. Because the decrypted part is also quoted in the reply, the user unintentionally acts as a decryption oracle. To obfuscate the existence of the encrypted part(s), the attacker may add a lot of newlines or hide it within a long conversation history. A user replying to such a ‘mixed content’ conversation thereby leaks the plaintext of encrypted messages wrapped within attacker-controlled text.

Please find attached a raw .eml file which depicts the issue.

---------------
Countermeasures
---------------

Do not decrypt emails unless the PGP or S/MIME encrypted part is the root node -- and therefore the only part -- in the MIME tree (exception: multipart/signed for encrypted-then-signed S/MIME messages). Another, potentially less secure, option would be to quote only the very first MIME part in replies.
Comment 1 Jens Mueller 2019-02-22 12:52:40 UTC
Created attachment 118288 [details]
Proof-of-concept PGP
Comment 2 Jens Mueller 2019-02-22 12:52:53 UTC
Created attachment 118289 [details]
Proof-of-concept S/MIME
Comment 3 Daniel Vrátil 2019-04-08 16:55:35 UTC
In KMail this attack requires that user would enable "Automatic decryption of encrypted messages when viewing" option in KMail settings, which is disabled by default.

Without this option enabled the user has to click on "Decrypt" on the part that the attacker wants to leak. At this point, the user will still clearly see which part of the content was encrypted and which part was not. When the user wants to reply to this decrypted message, the content would indeed get leaked to the attacker. However, I believe that at this point KMail has done enough to prevent (by not enabling auto-decryption by default) and warn (by clearly showing which part is encrypted and which not) the user so he or she could judge for themselves the potential risks when replying to the message.
Comment 4 Jens Mueller 2019-04-09 15:41:27 UTC
Things may have changed in the meantime, but for the version we tested (v5.2.3), there is no need to click on "Decrypt Message". While the plaintext is not shown to the user, if he does not explicitly click "Decrypt Message", the plaintext is still included in replies -- just re-tested for S/MIME and PGP/MIME. Note that KMail was tested in the default settings (the option "Attempt decryption of encrypted messages when viewing" was *not* set).
Comment 5 Sandro Knauß 2019-04-09 20:54:50 UTC
(In reply to Daniel Vrátil from comment #3)
> In KMail this attack requires that user would enable "Automatic decryption
> of encrypted messages when viewing" option in KMail settings, which is
> disabled by default.

As Jens already explained, this setting does not help here. This Setting only do not trigger decryption directly when you view the mail. But if you reply the mail is decrypted in anycase. And we use the same code paths for rendering the view and prepare the reply/forward.
Comment 6 Albert Astals Cid 2019-04-13 10:39:21 UTC
I am not sure I understand where the problem is, potentially means you need to explain it in simpler words (or that i need to learn how to read long sentences :D)

Is this problem?
 * A sends encrypted email to B
 * C intercepts that email
 * C resends the email modified to B (adding his own reply address and some plain text)
 * B answers to C
 * C can see the original email
Comment 7 Jens Mueller 2019-04-13 12:29:02 UTC
Exactly that's the problem. Note that not only one message, but hundreds of captured messages can be wrapped and leaked with one single reply.

Traditional message takeover attacks under a new identity (C) are considered as an acceptable risk in email e2e encryption because it is assumed that given the context of the message (e.g.,“Hi A, [...] Yours, B”) B can tell that this message is not originally from C and could easily discover the deception. However, using MIME wrapping, C can make a different content being displayed to B (if B does not carefully scroll down the whole message conversation) and therefore potentially trick B into replying to C.
Comment 8 Albert Astals Cid 2019-04-15 21:36:49 UTC
Right i can see the problem.

Question is, are those kind of messages that you are suggesting to stop supporting "common" or even is there a reason for someone to be sending messages like that?

Or if you get a message like this it's most probably someone trying to trick you?

Because if those messages are common, stopping to work on them is going to be a pain for the people that have a valid usecase.
Comment 9 Jens Mueller 2019-04-16 09:06:50 UTC
Imho, there are no legitimate use cases for `partial encryption` in S/MIME and PGP/MIME, but it's hard to measure if such emails do exist in the wild. In case of PGP/Inline, unfortunately, every part is encrypted separately. Note that a captured PGP/MIME message can be `downgraded` to be interpreted in the context of PGP/INLINE.
Comment 10 Jens Mueller 2019-04-18 13:30:36 UTC
Update: Here's a full (public) report on the issue:
https://arxiv.org/ftp/arxiv/papers/1904/1904.07550.pdf

For KMail, CVE-2019-10732 was assigned for reply-based `decryption oracles`.
Comment 11 David Faure 2019-04-21 17:14:23 UTC
Interesting problem. Here's my feedback.

- Preventing KMail from *sending* such messages would obviously be no help (one could just craft that message by hand or using another email client). 

- Preventing the user from replying to such a message would be very weird user experience (sorry, you are not allowed to reply to this message!)

- So I guess the best solution is that when replying, we don't decrypt parts that were encrypted in the original message. I.e. if we are replying with a copy of those parts, and they were encrypted, they should be copied "as is". This would prevent any newly-added recipient from reading those, but that's fair enough I would say.
I wouldn't really know how to implement this though.
Might be tricky if the tree in memory only has the decrypted version.

- Alternatively, KMail could say "for security reasons, these parts are going to be removed from your reply". But this also requires that we somehow know that these parts used to be encrypted in the original email.
Comment 12 David Faure 2019-04-22 09:31:07 UTC
About the original suggestion: "Do not decrypt emails unless the PGP or S/MIME encrypted part is the root node -- and therefore the only part -- in the MIME tree (exception: multipart/signed for encrypted-then-signed S/MIME messages)."

This would mean if you attach a non-encrypted image (say, company logo) to an encrypted email, the recipient can't reply to the email anymore? I think we always want to decrypt the main text part? (fuzzy term, I don't know what the actual logic is in kmail, but I mean the text that gets quoted).
Comment 13 Sandro Knauß 2019-04-22 21:21:16 UTC
@Jens: what version did you test? You set "Debian Stable" and "5.10.3" this does not match. Debian stable has 16.04.3 aka 5.2.3. 

I now started to look into the issue, but I can't reproduce it with the attached messages for 18.08.3 nor for master. At least for the encrypted content to be simple text. Do I need to construct a mimetree inside the encrypted message parts?
And this make totally sense, as we have already have the concept of firstTextNode inside ObjectTreeParser, that takes effect here.

I added the proof-of-concept mails to our autotests: 
  https://phabricator.kde.org/D20757
the plain.reply files are the output of the reply window.

For those you have a test environment for messagelib, those can view such mails and reply/forward:

GNUPGHOME=<buildpath of messagelib>/messagecore/autotests/gnupg_home/ kmail --view 404698-gpg.mbox

A short explanation, how a reply/forward is created (everything in messagelib):
* templateparser/src/templateparserjob constructs a new KMime::Message mMsg from a given mOrigMsg.
* TemplateParserJob uses MimeTreeParser::ObjectTreeParser to get htmlContent/plainTextContent. At least for plainTextContent it is easy to follow, that only the content from first text node is used. For htmlContent it looks, like we merge different htmlNodes via messagepart.cpp:HtmlMessagePart::fix()
Comment 14 Sandro Knauß 2019-04-22 21:44:01 UTC
(In reply to David Faure from comment #11)
> - Preventing KMail from *sending* such messages would obviously be no help
> (one could just craft that message by hand or using another email client). 

ACK.

> - Preventing the user from replying to such a message would be very weird
> user experience (sorry, you are not allowed to reply to this message!)

jepp bad UX.

> - So I guess the best solution is that when replying, we don't decrypt parts
> that were encrypted in the original message. I.e. if we are replying with a
> copy of those parts, and they were encrypted, they should be copied "as is".
> This would prevent any newly-added recipient from reading those, but that's
> fair enough I would say.
> I wouldn't really know how to implement this though.
> Might be tricky if the tree in memory only has the decrypted version.
>
> - Alternatively, KMail could say "for security reasons, these parts are
> going to be removed from your reply". But this also requires that we somehow
> know that these parts used to be encrypted in the original email.

Both things are not that hard to solve. We have MimeTreeParser::ObjecttreeParser that returns a MessagePart tree. This is a tree, where only visual interesting nodes of the Mime messages with the additional information of each node, about their encrypted status, used keys etc... To get an idea about those trees look at mimetreeparser/autotests/data/*tree files, these are the MessagePart tree for the corresponding mbox. Also TemplateParser, that is responsible for creating a reply/template, uses MimeTreeParser::ObjecttreeParser, so we are able to filter out bad nodes.
Comment 15 Jens Mueller 2019-04-26 10:09:00 UTC
@David: This would mean if you attach a non-encrypted image to an encrypted...

Absolutely, such an email could not be decrypted anymore if you follow our suggestions (or had to be manually decrypted on the command line). While this may seem a bit harsh, we have not seen any mail client that allows to send such "partially encrypted" emails (e.g., with unencrypted attachments), and I think handling such edge cases can become a security nightmare. Either the whole mail is encrypted or it's not, everything else gives a false sense of security, imho.

However, I see the developer's perspective and the and the fear of potentially breaking things, too. I guess a rule like "in case of an encrypted, multipart email, reply only with the first part" *should* be fine too.

@Sandro: We originally tested in version 5.2.3 on Debian 9.8 (stretch). This version is probably outdated by now.
Comment 16 Sandro Knauß 2019-04-26 11:00:21 UTC
(In reply to Jens Mueller from comment #15)
> @David: This would mean if you attach a non-encrypted image to an
> encrypted...
> 
> Absolutely, such an email could not be decrypted anymore if you follow our
> suggestions (or had to be manually decrypted on the command line). While
> this may seem a bit harsh, we have not seen any mail client that allows to
> send such "partially encrypted" emails (e.g., with unencrypted attachments),
> and I think handling such edge cases can become a security nightmare. Either
> the whole mail is encrypted or it's not, everything else gives a false sense
> of security, imho.

One client that supports sending encrypted mails with unencrypted attachment is kmail (but you need to do it explicitly).

One common use case, of such partial encrypted mails are mails forwarded via Mailman. Mailman adds a non encrypted footer to each email. So not supporting these mails make would break my workflow. This was the reason, why I fixed a several things, because I didn't wanted to see this footer in the reply ;D And I see a big difference between displaying such broken mails and replying. 

> However, I see the developer's perspective and the and the fear of
> potentially breaking things, too. I guess a rule like "in case of an
> encrypted, multipart email, reply only with the first part" *should* be fine
> too.

I think so, too, that reply to only one part you be fine.

> @Sandro: We originally tested in version 5.2.3 on Debian 9.8 (stretch). This
> version is probably outdated by now.

yes! Did you tested any other version?
Comment 17 Sandro Knauß 2019-05-12 21:59:21 UTC
Git commit d397aa46e809203c94e31891caac57affac746d9 by Sandro Knauß.
Committed on 12/05/2019 at 20:34.
Pushed by knauss into branch 'Applications/19.04'.

Test mails for Decryption Oracle based on replying to PGP or S/MIME.

Summary:
In order to make sure we never add a Decryption Oracle add test mails to
TemplateParser.

Reviewers: #kde_pim, aacid, dfaure

Subscribers: kde-pim

Tags: #kde_pim

Differential Revision: https://phabricator.kde.org/D20757

A  +120  -0    templateparser/autotests/data/404698-gpg.mbox
A  +51   -0    templateparser/autotests/data/404698-gpg.mbox.plain.reply
A  +88   -0    templateparser/autotests/data/404698-smime.mbox
A  +51   -0    templateparser/autotests/data/404698-smime.mbox.plain.reply

https://commits.kde.org/messagelib/d397aa46e809203c94e31891caac57affac746d9
Comment 18 Sandro Knauß 2019-05-12 22:10:25 UTC
Created attachment 120026 [details]
html mail with two images embeded.

There is one question, how we should handle forwards with embedded images.
We have a testcase with two images embedded (see attachment), that are added to the forwarded message. IMO this is not a security issue, as we do not parse those two images (aka do not encrypt them) and just copy them like they were sent over the wire. So we can't leak private information.
Comment 19 Sandro Knauß 2019-05-12 22:14:40 UTC
Git commit a58286aec8f300d78c570726924baa91d9a22771 by Sandro Knauß.
Committed on 12/05/2019 at 21:48.
Pushed by knauss into branch 'Applications/19.04'.

Merge branch 'CVE-2019-10732' into Applications/19.04

Fixes the CVE-2019-10732, with additional tests, to make sure, we fixed
the CVE completely.

FIXED-IN: 5.11.2
CCMAIL: security@kde.org


https://commits.kde.org/messagelib/a58286aec8f300d78c570726924baa91d9a22771
Comment 20 Sandro Knauß 2019-05-12 22:14:40 UTC
Git commit 8f9b85b664be0987014c5d2485e706ab5a198e1b by Sandro Knauß.
Committed on 12/05/2019 at 20:37.
Pushed by knauss into branch 'Applications/19.04'.

Make unexpected data leak harder via reply.

ObjectTreeParser.htmlContent/plainTextContent may concats different encrypted parts
without the user noticing it. That would lead to a Decryption oracle. We have already
a logic to find the topleveltextNode in MimeTreeParser, this does not take HTML nodes
into account nor that TEXT nodes may have several PGP Inline blocks.

That plaintextContent for HtmlMessagePart is not return QString(), that bubbled up by
testing the stuff.

M  +5    -0    mimetreeparser/src/messagepart.cpp
M  +1    -0    mimetreeparser/src/messagepart.h
A  +31   -0    templateparser/autotests/data/openpgp-inline-space.mbox
A  +1    -0    templateparser/autotests/data/openpgp-inline-space.mbox.html.reply
A  +1    -0    templateparser/autotests/data/openpgp-inline-space.mbox.plain.reply
M  +46   -14   templateparser/src/templateparserjob.cpp

https://commits.kde.org/messagelib/8f9b85b664be0987014c5d2485e706ab5a198e1b
Comment 21 Sandro Knauß 2019-05-12 22:14:43 UTC
Git commit ac360b3a57eacbf0542ed0800e6054db76f01398 by Sandro Knauß.
Committed on 12/05/2019 at 20:37.
Pushed by knauss into branch 'Applications/19.04'.

Decryption Oracle based on forwarding PGP or S/MIME mails (CVE-2019-10732)

Summary:
Add test coverage for mail forwarding.

Test Plan:
all tests passes
forward (text/html):
[x] PGP Mime text
[x] PGP Mime html
[x] S/MIME
[x] PGP inline

Reviewers: #kde_pim, vkrause, aacid, dfaure

Subscribers: kde-pim, security-team

Tags: #kde_pim

Differential Revision: https://phabricator.kde.org/D20847

A  +72   -0    templateparser/autotests/data/404698-gpg-attachments.mbox
A  +66   -0    templateparser/autotests/data/404698-gpg-attachments.mbox.forwarded.mbox
A  +1    -0    templateparser/autotests/data/404698-gpg-attachments.mbox.html.reply
A  +5    -0    templateparser/autotests/data/404698-gpg-attachments.mbox.plain.reply
A  +83   -0    templateparser/autotests/data/html-attachment1 [details].mbox.forwarded.mbox
A  +28   -0    templateparser/autotests/data/html-attachment2 [details].mbox.forwarded.mbox
M  +162  -0    templateparser/autotests/templateparserjobtest.cpp
M  +9    -0    templateparser/autotests/templateparserjobtest.h

https://commits.kde.org/messagelib/ac360b3a57eacbf0542ed0800e6054db76f01398
Comment 22 beuc 2019-06-12 14:59:32 UTC
Hi,

As part of the Debian LTS project, I'm trying to fix this vulnerability in Debian Jessie, which ships kdepim 4.14.1.

I'm attempting to backport
https://commits.kde.org/messagelib/8f9b85b664be0987014c5d2485e706ab5a198e1b
but the API is very different, I'm not even sure there are available functions to expose the MIME parts and extract their quotable content independently.

Do you think this is doable?
Comment 23 beuc 2019-06-12 18:57:26 UTC
I wrote something cruder but that works with the 404698-* messagelib test cases:
https://www.beuc.net/tmp/kdepim-CVE-2019-10732.patch
This should be a good compromise, let me know if I missed something.
I plan to upload an update shortly, probably next week :)
Comment 24 Sandro Knauß 2019-06-28 15:38:27 UTC
(In reply to beuc from comment #23)
> I wrote something cruder but that works with the 404698-* messagelib test
> cases:
> https://www.beuc.net/tmp/kdepim-CVE-2019-10732.patch
> This should be a good compromise, let me know if I missed something.
> I plan to upload an update shortly, probably next week :)

The code looks like it should be enough. But the surrounding code has changed a lot between 4.14.1 and had less tests etc. It may be that there are other things to fix.
Comment 25 removed by sysadmin 2019-07-31 02:15:35 UTC