Penetration Test Report (Cure53): pentest report openpgpjs

Pentest-Report OpenPGP.js 02.2014
Cure53, Dr.-Ing. Mario Heiderich / Krzysztof Kotowicz / Jonas Magazinius / Franz Antesberger
Index
Intro
Scope
Identified Vulnerabilities
OP -01-005 Side - channe l leak in RSA decryption ( High )
OP -01-007 Algorithm Preferences ignored upon Encryption ( Low )
OP -01-008 Algorithm Preferences ignored upon Decryption ( Medium )
OP -01-009 Cleartex t Messages Spoofing by Lax Armor Headers parsing ( Critica l)
OP -01-011 Error suppression in UTF -8 decoding function ( Medium )
OP -01-014 RSA Key Generation : Seeds are no t destroyed ( Low )
OP -01-015 EME - PKCS 1- v 1_5 padding uses Math . random () ( Critica l)
OP -01-019 Cleartex t Message Spoofing in Armor Headers ( Critica l)
OP -01-020 Missing check in DSA signature generation ( Medium )
OP -01-024 Random Range Bias in DSA / Elgama l ( Low )
OP -01-025 EME - PKCS 1- v 1_5 Error Handling in RSA Decryption ( High )
OP -01-026 Errors in EMSA - PKCS 1- v 1_5 decoding routine ( High )
Miscellaneous Issues
OP -01-001 Type confusion in crypto . random . RandomBuffer ( Low )
OP -01-002 Math . random () usage in dead code branch ( Low )
OP -01-003 Suggested Code Enforcemen t o f RandomBuffer ( Low )
OP -01-004 Inconsisten t Bi t Length o f RSA Keys ( Low )
OP -01-006 Generated keys have no stored algorithm preference ( Medium )
OP -01-010 Invalid Armor Checksum Validation ( Low )
OP -01-012 RNG Bias in RSA Key Generation ( Low )
OP -01-013 RSA Key Gen .: Miller - Rabin - Tes t no t conform with FIPS 186-4 ( Low )
OP -01-016 Comments on Javascrip t Code Quality ( Low )
OP -01-017 Consider to substitute the SHA module ( Low )
OP -01-018 Suggested improvemen t in RSA signature verification ( Low )
OP -01-021 Silen t error handling in various places ( Low )
OP -01-022 Possible Optimization in RSA Supplementa l Parameters ( Low )
OP -01-023 Recommendation to avoid logging o f Private Keys ( Low )
OP -01-027 N o check o f armor type when de - armoring signed messages ( Low )
OP -01-028 Inconsisten t documentation o f PublicKey . read ( Low )
OP -01-029 Insufficien t inpu t validation in parsing packets ( Low )
OP -01-030 Insufficien t validation in parsing public keys ( Low )
OP -01-031 Insufficien t Validation in parsing PK - encrypted Session Keys ( Low )
OP -01-032 Inconsisten t documentation o f SymEncryptedSessionKey . read ( Low )
OP -01-033 Insufficien t Validation for symmetrically Encrypted Session Keys ( Low )
OP -01-034 Insufficien t Validation in Parsing One Pass Signatures ( Low )
OP -01-035 Insufficien t Inpu t Validation in Parsing Literals ( Low )
OP -01-036 Specia l “ for your eyes only ” Directive Ignored ( Low )
Conclusion
Intro
“This project aims to provide an Open Source OpenPGP library in JavaScript so it can
be used on virtually every device. Instead of other implementations that are aimed at
using native code, OpenPGP.js is meant to bypass this requirement (i.e. people will not
have to install gpg on their machines in order to use the library).
The idea is to implement all the needed OpenPGP functionality in a JavaScript library
that can be reused in other projects that provide browser extensions or server
applications. It should allow you to sign, encrypt, decrypt, and verify any kind of text - in
particular e-mails - as well as managing keys.”
From: http :/ / openpgpjs . org /
This penetration test was carried out and coordinated by four testers and yielded an
overall of 26 issues. Among these findings, Cure53 has classified 12 as vulnerabilities,
with 2 issues rated ‘critical’ in regards to their severity. This penetration test was
conducted under a paid contract agreement sponsored by Radio Free Asia’s Open
Technology Fund. The Cure53 team has spent 15 days on testing the library,
documenting the identified issues and communicating the results to the OpenPGP.js
Development Team.
Scope
● OpenPGP JavaScript Implementation.
○ http :/ / openpgpjs . org /
○ https :/ / github . com / openpgpjs /openpgpjs
Identified Vulnerabilities
The following sections list both vulnerabilities and implementation issues spotted during
the testing period. Note that findings are listed in a chronological order rather than by
their degree of severity and impact. The latter is simply given in brackets following the
title heading for each vulnerability, which is also marked with a unique identifier for the
purpose of facilitating future follow-up correspondence and referencing.
OP-01-005 Side-channel leak in RSA decryption (High)
The RSA decryption routine implemented in the library (see src/crypto/public_key/rsa.js)
introduces timing information leak that can be used to factor RSA private key, as it has
been described by Paul C Kocher in “Timing Attacks on Implementations of Diffie-
Hellman, RSA, DSS, and Other Systems”1.
The library uses Chinese Remainder Theorem for optimization. Timing attack for that
algorithm was demonstrated for OpenSSL in “Brumley, Boneh. Remote Timing Attacks
are Practical”2.
To protect from side-channel leaks in RSA decryption, RSA blinding should be used:
“RSA blinding involves computing the blinding operation E(x) = xre mod N, where
r is a random integer between 1 and N and relatively prime to N (i.e. gcd(r, N) =
1), x is the ciphertext, e is the public RSA exponent and N is the RSA modulus.
As usual, the decryption function f(z) = zd mod N is applied thus giving f(E(x)) =
xdred mod N = xdr mod N. Finally it is unblinded using the function D(z) = zr−1 mod
N. Since D(f(E(x))) = xd mod N, this is indeed an RSA decryption.”
From:
http :/ / en . wikipedia . org / wik i / Blinding _( cryptography )
It is worth noting that RSA blinding in RSA decryption is also recommended to mitigate
other side-channel attacks, such as acoustic attack on GnuPG (2013-4576)3.
We recognize that protecting JavaScript-based code from side-channel leaks and, for
example, introducing constant-time operations in JavaScript is very problematic. Further,
it becomes even more complex as the library might be used by different implementers,
run in different JS engines, including also those environments that offer varying code
isolation levels (website, node.js module, Chrome Packaged App provide just a few
examples). Currently no guarantee can be given that even the JS code carefully
designed so as to avoid side-channel leaks cannot be forced to run in conditions that
allow for e.g. timing attacks.
1 Timing Attacks http :/ / www . cryptography . com / public / pd f / TimingAttacks .pdf
2 SSL Timing Attacks http :/ / crypto . stanford . edu /~ dabo / papers / ss l - timing .pdf
3 CVE-2013-4576 http :/ / cve . mitre . org / cg i - bin / cvename . cg i ? name = CVE -2013-4576
Nevertheless, when dealing with such a crucial cryptographic library we recommend to
take the best-effort approach and implement countermeasures for all known side-
channel attacks, just as other non JS-based OpenPGP libraries do.
OP-01-007 Algorithm Preferences ignored upon Encryption (Low)
Upon message encryption performed by OpenPGP.js, the library appears to ignore the
given symmetric algorithm preference that is stored together with the provided key.
Instead, a static configuration value is used, currently defaulting to AES256 algorithm.
This can be observed in the source code below:
// src/config/config.js
var enums = require('../enums.js');
module.exports = {
prefer_hash_algorithm: enums.hash.sha256,
encryption_cipher: enums.symmetric.aes256,
compression: enums.compression.zip,
show_version: true,
show_comment: true,
integrity_protect: true,
keyserver: "keyserver.linux.it", // "pgp.mit.edu:11371"
versionstring: "OpenPGP.js VERSION",
commentstring: "http://openpgpjs.org",
node_store: './openpgp.store',
debug: false
};
// message.js
Message.prototype.encrypt = function(keys) {
var packetlist = new packet.List();
//TODO get preferred algo from signature
var sessionKey = crypto.generateSessionKey(enums.read(enums.symmetric,
config.encryption_cipher));
keys.forEach(function(key) {
var encryptionKeyPacket = key