Closed Bug 1666360 (CVE-2021-23993) Opened 4 years ago Closed 3 years ago

rnp trips over subkeys with invalid self signatures

Categories

(MailNews Core :: Security: OpenPGP, defect)

defect

Tracking

(thunderbird_esr78 fixed)

RESOLVED FIXED
88 Branch
Tracking Status
thunderbird_esr78 --- fixed

People

(Reporter: neal, Unassigned)

References

()

Details

(Keywords: sec-moderate, Whiteboard: [RNP][fixed-in-rnp])

Attachments

(3 files)

749 bytes, application/pgp-encrypted
Details
79.82 KB, image/png
Details
112.08 KB, image/png
Details

User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0

Steps to reproduce:

Note: I attempted to submit the following issue to rnp. I went to https://www.ribose.com/feedback/security, submitted the issue and got an error "Error sending feedback". If someone has a better way of contacting rnp about such security issues, I'd appreciate a pointer.

Consider the following OpenPGP Certificate (attached below):

Public-Key Packet, new CTB, 51 bytes
Version: 4
Creation time: 2020-09-21 12:46:13 UTC
Pk algo: EdDSA Edwards-curve Digital Signature Algorithm
Pk size: 256 bits
Fingerprint: 4BC6 DDAA 8893 94D0 9C62 6631 54E9 563F B183 FFC6
KeyID: 54E9 563F B183 FFC6

Signature Packet, new CTB, 129 bytes
Version: 4
Type: DirectKey
Pk algo: EdDSA Edwards-curve Digital Signature Algorithm
Hash algo: SHA512
Hashed area:
Signature creation time: 2020-09-21 12:46:13 UTC (critical)
Symmetric algo preferences: AES256
Hash preferences: SHA512
Key flags: CS (critical)
Features: MDC
Unhashed area:
Issuer: 54E9 563F B183 FFC6
Issuer Fingerprint: 4BC6 DDAA 8893 94D0 9C62 6631 54E9 563F B183 FFC6
Digest prefix: 5681
Level: 0 (signature over data)

User ID Packet, new CTB, 57 bytes
Value: Invalid Encryption Subkey <encryption-subkey@example.org>

Signature Packet, new CTB, 132 bytes
Version: 4
Type: PositiveCertification
Pk algo: EdDSA Edwards-curve Digital Signature Algorithm
Hash algo: SHA512
Hashed area:
Signature creation time: 2020-09-21 12:46:13 UTC (critical)
Symmetric algo preferences: AES256
Hash preferences: SHA512
Primary User ID: true (critical)
Key flags: CS (critical)
Features: MDC
Unhashed area:
Issuer: 54E9 563F B183 FFC6
Issuer Fingerprint: 4BC6 DDAA 8893 94D0 9C62 6631 54E9 563F B183 FFC6
Digest prefix: BF69
Level: 0 (signature over data)

Public-Subkey Packet, new CTB, 56 bytes
Version: 4
Creation time: 2020-09-21 12:46:13 UTC
Pk algo: ECDH public key algorithm
Pk size: 256 bits
Fingerprint: EAC7 2FA2 5266 278C 512E 8F35 B60F 4310 804F 8535
KeyID: B60F 4310 804F 8535

Signature Packet, new CTB, 129 bytes
Version: 4
Type: SubkeyBinding
Pk algo: EdDSA Edwards-curve Digital Signature Algorithm
Hash algo: SHA512
Hashed area:
Signature creation time: 2020-09-21 12:46:13 UTC (critical)
Key flags: Et (critical)
Features: MDC
Key expiration time: PT1S
Unhashed area:
Issuer: 54E9 563F B183 FFC6
Issuer Fingerprint: 4BC6 DDAA 8893 94D0 9C62 6631 54E9 563F B183 FFC6
Digest prefix: CDE2
Level: 0 (signature over data)

Public-Subkey Packet, new CTB, 56 bytes
Version: 4
Creation time: 2020-09-21 12:46:13 UTC
Pk algo: ECDH public key algorithm
Pk size: 256 bits
Fingerprint: AC5C F91D D06C 518A 0142 B1E4 BC63 472A 109D 5859
KeyID: BC63 472A 109D 5859

Signature Packet, new CTB, 123 bytes
Version: 4
Type: SubkeyBinding
Pk algo: EdDSA Edwards-curve Digital Signature Algorithm
Hash algo: SHA512
Hashed area:
Signature creation time: 2020-09-21 12:46:13 UTC (critical)
Key flags: EtEr (critical)
Features: MDC
Unhashed area:
Issuer: 54E9 563F B183 FFC6
Issuer Fingerprint: 4BC6 DDAA 8893 94D0 9C62 6631 54E9 563F B183 FFC6
Digest prefix: 79EC
Level: 0 (signature over data)

The certificate has two encryption-capable subkeys. The first one has
an invalid self-signature, and is thus invalid:

$ sq inspect encryption-subkey-bad.pgp
encryption-subkey-bad.pgp: OpenPGP Certificate.

  Fingerprint: 4BC6 DDAA 8893 94D0 9C62  6631 54E9 563F B183 FFC6

Public-key algo: EdDSA Edwards-curve Digital Signature Algorithm
Public-key size: 256 bits
Creation time: 2020-09-21 12:46:13 UTC
Key flags: certification, signing

       Subkey: AC5C F91D D06C 518A 0142  B1E4 BC63 472A 109D 5859

Public-key algo: ECDH public key algorithm
Public-key size: 256 bits
Creation time: 2020-09-21 12:46:13 UTC
Key flags: transport encryption, data-at-rest encryption

       UserID: Invalid Encryption Subkey <encryption-subkey@example.org>

           Bad Signature: V4(Signature4 { version: 4, typ: SubkeyBinding, pk_algo: EdDSA, hash_algo: SHA512, hashed_area: [Subpacket { critical: true, value: SignatureCreationTime(1600692373) }, Subpacket { critical: true, value: KeyFlags(Et) }, Subpacket { value: Features(MDC) }, Subpacket { value: KeyExpirationTime(1s) }], unhashed_area: [Subpacket { value: Issuer(KeyID("54E9 563F B183 FFC6")) }, Subpacket { value: IssuerFingerprint(Fingerprint("4BC6 DDAA 8893 94D0 9C62  6631 54E9 563F B183 FFC6")) }], digest_prefix: "CDE2", computed_digest: None, level: 0, mpis: EdDSA { r: 251 bits: 0613 F704 5023 23B0 3155 9634 DFB5 BC84 B31A 402D 9BBF E018 84CE 90CB 7C88 A6F5, s: 251 bits: 0492 E4EF D2D8 894A 83D1 D49B D2C6 322B 7666 215B 1D3C 01D2 0B1E 8D41 1074 5A0F } })

Since the OpenPGP Certificate still has a valid encryption subkey, it
should be usable. For instance, GnuPG correctly ignores the subkey
that does not have a valid binding signature, and it is possible to
encrypt a message to that key using gpg.

$ gpg --import encryption-subkey-bad.pgp
gpg: key 0x54E9563FB183FFC6: 1 bad signature
gpg: key 0x54E9563FB183FFC6: public key "Invalid Encryption Subkey <encryption-subkey@example.org>" imported
gpg: Total number processed: 1
gpg: imported: 1
$ gpg -k 0x54E9563FB183FFC6
pub ed25519/0x54E9563FB183FFC6 2020-09-21 [SC]
Key fingerprint = 4BC6 DDAA 8893 94D0 9C62 6631 54E9 563F B183 FFC6
uid [ unknown] Invalid Encryption Subkey <encryption-subkey@example.org>
sub cv25519/0xBC63472A109D5859 2020-09-21 [E]

$ echo foo | gpg -e -r 0x54E9563FB183FFC6 >/dev/null
...
$ echo $?
0

When importing the OpenPGP Certificate into rnp, rnp does not suggest
that the subkey or the certificate is invalid in anyway:

$ rm $T/*
$ src/rnpkeys/rnpkeys --homedir=$T --import encryption-subkey-bad.pgp
[init_file_src() /home/us/neal/work/pep/rnp/src/librepgp/stream-common.cpp:408] can't stat '/tmp/tmp.MhdvXtVrFA/pubring.gpg'
wrong pubring path
[signature_validate() /home/us/neal/work/pep/rnp/src/lib/crypto/signatures.cpp:217] wrong lbits

pub 255/EdDSA 54e9563fb183ffc6 2020-09-21 [SC]
4bc6ddaa889394d09c62663154e9563fb183ffc6
uid Invalid Encryption Subkey <encryption-subkey@example.org>
sub 255/ECDH b60f4310804f8535 2020-09-21 [E]
eac72fa25266278c512e8f35b60f4310804f8535
sub 255/ECDH bc63472a109d5859 2020-09-21 [E]
ac5cf91dd06c518a0142b1e4bc63472a109d5859

But, it is not possible to encrypt to the OpenPGP Certificate:

$ src/rnp/rnp --homedir=$T --encrypt -r 54e9563fb183ffc6 foo.txt
[signature_validate() /home/us/neal/work/pep/rnp/src/lib/crypto/signatures.cpp:217] wrong lbits
[encrypted_add_recipient() /home/us/neal/work/pep/rnp/src/librepgp/stream-write.cpp:518] attempt to use invalid key as recipient

The problem appears to be in src/lib/pgp-key.cpp:find_suitable_key:
this function iterates over all of the keys and returns the first key
that has the encryption-capable flag set. But, it doesn't check that
the signature is actually valid before doing so. Since
find_suitable_key encounters the bad subkey first, and that subkey has
the required flags, it returns that key. When rnp goes to encrypt to
that key, it actually checks that the key is valid, and correctly
rejects it. But, it doesn't bother to try and encrypt the message to
the other, valid subkey.

https://github.com/rnpgp/rnp/blob/6a5fb89/src/lib/pgp-key.cpp#L1875

An attacker can use this to poison OpenPGP Certificates. They
attacker could insert a subkey with an invalid binding signature, and
convince the victim to import it. This could be done in a targetted
way, or simply as a type of vandalism, e.g., by uploading corrupted
certificates to key servers that don't validate signatures, like the
SKS pool.

Unfortunately, importing a good version of the key (one without the
subkey, and its invalid signature) will not fix the problem, because
rnp merges the key in place, and the bad subkey is still first.
Instead, a user must somehow remove the key from their keyring.

We can CC Nickolay here, which I'm doing with this update.

Attached image 1.png
Attached image 2.png
Component: Untriaged → Security: OpenPGP
Product: Thunderbird → MailNews Core

Thanks for reporting, will fix this together with some other issue (most likely https://github.com/rnpgp/rnp/issues/1313).

Status: UNCONFIRMED → NEW
Ever confirmed: true
Whiteboard: [RNP]
Whiteboard: [RNP] → [RNP][fixed-in-rnp]

Hi, I reported this 78 days ago. I plan to publish a report in the next few weeks. Do you need additional time?

I can confirm the report. TB attempts to select a suitable encryption key, and in this scenario will attempt to use the first one, and ask RNP to encrypt. But RNP rejects the attempt with a failure.

I have a patch in hand that will cause TB to skip the invalid subkey, and will ask RNP to use the other subkey, which works.
Also, TB key manager, properties, structure, will not list the invalid subkey.

Kai,
Since the PR https://github.com/rnpgp/rnp/pull/1318 (which is part of version 0.14.0) RNP changes default encryption subkey selection algorithm, now it picks the latest valid one. So you may rely on this instead of doing the same in JS. Or we may add some API like rnp_key_default_subkey, so you may check whether it is picked correctly/display this in GUI.

Patch is in bug 1673240.

(In reply to Nickolay Olshevsky from comment #8)

Since the PR https://github.com/rnpgp/rnp/pull/1318 (which is part of version 0.14.0) RNP changes default encryption subkey selection algorithm, now it picks the latest valid one. So you may rely on this instead of doing the same in JS. Or we may add some API like rnp_key_default_subkey, so you may check whether it is picked correctly/display this in GUI.

I currently have a common function to find either encryption subkey or signature subkey, so if we consider to move this check to RNP, I'd need an API that works for both usages. (I use them with rnp_op_encrypt_add_recipient, rnp_op_encrypt_add_signature, rnp_op_sign_add_signature.) It seems working currently. Thanks for the offer, but it seems it isn't a high priority - unless we find that an RNP implementation can be smarter or avoid problems.
https://searchfox.org/comm-central/rev/706f5b3749753e7b01290f71bf8c6bc3536be936/mail/extensions/openpgp/content/modules/RNP.jsm#2119

(In reply to Kai Engert (:KaiE:) from comment #10)

I currently have a common function to find either encryption subkey or signature subkey, so if we consider to move this check to RNP, I'd need an API that works for both usages.

Yeah, it is planned to have some flags parameter to specify subkey's usage. Filed an issue here: https://github.com/rnpgp/rnp/issues/1457
Definitely not of high priority as you have working solution already.

See Also: → CVE-2021-23991

potential advisory text, for the TB issue:

CVE-??:
     title: Inability to send encrypted OpenPGP email after importing a crafted
OpenPGP key
     impact: moderate
     reporter: Neal Walfield
     description: |
       An attacker may perform a DoS attack to prevent a user from sending
encrypted email to a correspondent. If an attacker creates a crafted OpenPGP key
with a subkey that has an invalid self signature, and the Thunderbird user
imorts the crafted key, then Thunderbird may try to use the invalid subkey,
but the RNP library rejects it from being used, causing encryption to fail.
     bugs:
       - url: 1666360
Alias: CVE-2021-23993

Given comment 9 and that bug 1673240 is now fixed, should this bug also be resolved?

Flags: needinfo?(kaie)
Keywords: sec-moderate

c/the Thunderbird user imorts/the Thunderbird user imports/

(In reply to Daniel Veditz [:dveditz] from comment #13)

Given comment 9 and that bug 1673240 is now fixed, should this bug also be resolved?

yes, thanks, 78.9.1

Status: NEW → RESOLVED
Closed: 3 years ago
Flags: needinfo?(kaie)
Resolution: --- → FIXED
Target Milestone: --- → 88 Branch
Group: mail-core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: