OP-01-019 Cleartext Message Spoofing in Armor Headers (Critical). Fix: throw error if unknown ASCII armor type.
This commit is contained in:
parent
329c92bc73
commit
93ca8b62fe
|
@ -27,7 +27,8 @@ var base64 = require('./base64.js'),
|
||||||
config = require('../config');
|
config = require('../config');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds out which Ascii Armoring type is used. This is an internal function
|
* Finds out which Ascii Armoring type is used. Throws error if unknown type.
|
||||||
|
* @private
|
||||||
* @param {String} text [String] ascii armored text
|
* @param {String} text [String] ascii armored text
|
||||||
* @returns {Integer} 0 = MESSAGE PART n of m
|
* @returns {Integer} 0 = MESSAGE PART n of m
|
||||||
* 1 = MESSAGE PART n
|
* 1 = MESSAGE PART n
|
||||||
|
@ -35,24 +36,27 @@ var base64 = require('./base64.js'),
|
||||||
* 3 = PGP MESSAGE
|
* 3 = PGP MESSAGE
|
||||||
* 4 = PUBLIC KEY BLOCK
|
* 4 = PUBLIC KEY BLOCK
|
||||||
* 5 = PRIVATE KEY BLOCK
|
* 5 = PRIVATE KEY BLOCK
|
||||||
* null = unknown
|
|
||||||
*/
|
*/
|
||||||
function getType(text) {
|
function getType(text) {
|
||||||
var reHeader = /^-----([^-]+)-----$\n/m;
|
var reHeader = /^-----BEGIN PGP (MESSAGE, PART \d+\/\d+|MESSAGE, PART \d+|SIGNED MESSAGE|MESSAGE|PUBLIC KEY BLOCK|PRIVATE KEY BLOCK)-----$\n/m;
|
||||||
|
|
||||||
var header = text.match(reHeader);
|
var header = text.match(reHeader);
|
||||||
|
|
||||||
|
if (!header) {
|
||||||
|
throw new Error('Unknow ASCII armor type');
|
||||||
|
}
|
||||||
|
|
||||||
// BEGIN PGP MESSAGE, PART X/Y
|
// BEGIN PGP MESSAGE, PART X/Y
|
||||||
// Used for multi-part messages, where the armor is split amongst Y
|
// Used for multi-part messages, where the armor is split amongst Y
|
||||||
// parts, and this is the Xth part out of Y.
|
// parts, and this is the Xth part out of Y.
|
||||||
if (header[1].match(/BEGIN PGP MESSAGE, PART \d+\/\d+/)) {
|
if (header[1].match(/MESSAGE, PART \d+\/\d+/)) {
|
||||||
return enums.armor.multipart_section;
|
return enums.armor.multipart_section;
|
||||||
} else
|
} else
|
||||||
// BEGIN PGP MESSAGE, PART X
|
// BEGIN PGP MESSAGE, PART X
|
||||||
// Used for multi-part messages, where this is the Xth part of an
|
// Used for multi-part messages, where this is the Xth part of an
|
||||||
// unspecified number of parts. Requires the MESSAGE-ID Armor
|
// unspecified number of parts. Requires the MESSAGE-ID Armor
|
||||||
// Header to be used.
|
// Header to be used.
|
||||||
if (header[1].match(/BEGIN PGP MESSAGE, PART \d+/)) {
|
if (header[1].match(/MESSAGE, PART \d+/)) {
|
||||||
return enums.armor.multipart_last;
|
return enums.armor.multipart_last;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
|
@ -60,25 +64,25 @@ function getType(text) {
|
||||||
// Used for detached signatures, OpenPGP/MIME signatures, and
|
// Used for detached signatures, OpenPGP/MIME signatures, and
|
||||||
// cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE
|
// cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE
|
||||||
// for detached signatures.
|
// for detached signatures.
|
||||||
if (header[1].match(/BEGIN PGP SIGNED MESSAGE/)) {
|
if (header[1].match(/SIGNED MESSAGE/)) {
|
||||||
return enums.armor.signed;
|
return enums.armor.signed;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
// BEGIN PGP MESSAGE
|
// BEGIN PGP MESSAGE
|
||||||
// Used for signed, encrypted, or compressed files.
|
// Used for signed, encrypted, or compressed files.
|
||||||
if (header[1].match(/BEGIN PGP MESSAGE/)) {
|
if (header[1].match(/MESSAGE/)) {
|
||||||
return enums.armor.message;
|
return enums.armor.message;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
// BEGIN PGP PUBLIC KEY BLOCK
|
// BEGIN PGP PUBLIC KEY BLOCK
|
||||||
// Used for armoring public keys.
|
// Used for armoring public keys.
|
||||||
if (header[1].match(/BEGIN PGP PUBLIC KEY BLOCK/)) {
|
if (header[1].match(/PUBLIC KEY BLOCK/)) {
|
||||||
return enums.armor.public_key;
|
return enums.armor.public_key;
|
||||||
|
|
||||||
} else
|
} else
|
||||||
// BEGIN PGP PRIVATE KEY BLOCK
|
// BEGIN PGP PRIVATE KEY BLOCK
|
||||||
// Used for armoring private keys.
|
// Used for armoring private keys.
|
||||||
if (header[1].match(/BEGIN PGP PRIVATE KEY BLOCK/)) {
|
if (header[1].match(/PRIVATE KEY BLOCK/)) {
|
||||||
return enums.armor.private_key;
|
return enums.armor.private_key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,9 +281,6 @@ function dearmor(text) {
|
||||||
text = text.replace(/\r/g, '');
|
text = text.replace(/\r/g, '');
|
||||||
|
|
||||||
var type = getType(text);
|
var type = getType(text);
|
||||||
if (!type) {
|
|
||||||
throw new Error('Unknow ASCII armor type');
|
|
||||||
}
|
|
||||||
|
|
||||||
var splittext = text.split(reSplit);
|
var splittext = text.split(reSplit);
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,25 @@ describe("ASCII armor", function() {
|
||||||
expect(msg).to.throw(Error, /Improperly formatted armor header/);
|
expect(msg).to.throw(Error, /Improperly formatted armor header/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Exception if wrong armor header type', function () {
|
||||||
|
var msg =
|
||||||
|
['-----BEGIN PGP SIGNED MESSAGE\u2010\u2010\u2010\u2010\u2010\nHash:SHA1\n\nIs this properly-----',
|
||||||
|
'',
|
||||||
|
'sign this',
|
||||||
|
'-----BEGIN PGP SIGNATURE-----',
|
||||||
|
'Version: GnuPG v2.0.22 (GNU/Linux)',
|
||||||
|
'',
|
||||||
|
'iJwEAQECAAYFAlMrPj0ACgkQ4IT3RGwgLJfYkQQAgHMQieazCVdfGAfzQM69Egm5',
|
||||||
|
'HhcQszODD898wpoGCHgiNdNo1+5nujQAtXnkcxM+Vf7onfbTvUqut/siyO3fzqhK',
|
||||||
|
'LQ9DiQUwJMBE8nOwVR7Mpc4kLNngMTNaHAjZaVaDpTCrklPY+TPHIZnu0B6Ur+6t',
|
||||||
|
'skTzzVXIxMYw8ihbHfk=',
|
||||||
|
'=e/eA',
|
||||||
|
'-----END PGP SIGNATURE-----'].join('\n');
|
||||||
|
|
||||||
|
msg = openpgp.cleartext.readArmored.bind(null, msg);
|
||||||
|
expect(msg).to.throw(Error, /Unknow ASCII armor type/);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user