Skip to content

Commit 1bb0aeb

Browse files
committed
crypto: escape DNS altname
Vulnerability credit goes to: Calvin Liang [email protected] Reviewed-By: Ben Noordhuis <[email protected]> PR-URL: ...private
1 parent b9cecc3 commit 1bb0aeb

File tree

4 files changed

+148
-2
lines changed

4 files changed

+148
-2
lines changed

src/node_crypto.cc

+46-2
Original file line numberDiff line numberDiff line change
@@ -1104,6 +1104,48 @@ void SSLWrap<Base>::OnClientHello(void* arg,
11041104
}
11051105

11061106

1107+
static bool SafeX509ExtPrint(BIO* out, X509_EXTENSION* ext) {
1108+
// Only alt_name is escaped at the moment
1109+
if (OBJ_obj2nid(ext->object) != NID_subject_alt_name)
1110+
return false;
1111+
1112+
const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
1113+
if (method == NULL || method->it == NULL)
1114+
return false;
1115+
1116+
if (method->i2v != reinterpret_cast<X509V3_EXT_I2V>(i2v_GENERAL_NAMES))
1117+
return false;
1118+
1119+
const unsigned char* p = ext->value->data;
1120+
GENERAL_NAMES* names = reinterpret_cast<GENERAL_NAMES*>(ASN1_item_d2i(
1121+
NULL,
1122+
&p,
1123+
ext->value->length,
1124+
ASN1_ITEM_ptr(method->it)));
1125+
if (names == NULL)
1126+
return false;
1127+
1128+
for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
1129+
GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
1130+
1131+
if (gen->type == GEN_DNS) {
1132+
ASN1_IA5STRING* name = gen->d.dNSName;
1133+
1134+
BIO_write(out, "DNS:", 4);
1135+
BIO_write(out, name->data, name->length);
1136+
} else {
1137+
STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
1138+
const_cast<X509V3_EXT_METHOD*>(method), gen, NULL);
1139+
if (nval == NULL)
1140+
return false;
1141+
X509V3_EXT_val_prn(out, nval, 0, 0);
1142+
}
1143+
}
1144+
1145+
return true;
1146+
}
1147+
1148+
11071149
static Local<Object> X509ToObject(Environment* env, X509* cert) {
11081150
EscapableHandleScope scope(env->isolate());
11091151

@@ -1146,8 +1188,10 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
11461188
ext = X509_get_ext(cert, index);
11471189
CHECK_NE(ext, nullptr);
11481190

1149-
rv = X509V3_EXT_print(bio, ext, 0, 0);
1150-
CHECK_EQ(rv, 1);
1191+
if (!SafeX509ExtPrint(bio, ext)) {
1192+
rv = X509V3_EXT_print(bio, ext, 0, 0);
1193+
CHECK_EQ(rv, 1);
1194+
}
11511195

11521196
BIO_get_mem_ptr(bio, &mem);
11531197
info->Set(keys[i],

test/fixtures/keys/0-dns-cert.pem

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIC2jCCAcSgAwIBAgICJxEwCwYJKoZIhvcNAQEFMBUxEzARBgNVBAMWCm9oLm15
3+
Lmdvc2gwHxcNMTQxMTA1MDMyMDUyWhcOMzQwMTAzMTAzMjA1MlowEzERMA8GA1UE
4+
AxYIZXZpbC5jb20wggEfMAsGCSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQCsFwwf1dsr
5+
PdxyTHBreymbFGACLQtaOihGsSkYtIzUEF1aT90YDMzNdoLr4wkwWig5FPRMnjmX
6+
7pXY9RVbWmwG/M2eku9S62LekUFkeY1W/QftV9LYgAg7wVDA+v3+zk/EMEqADYm6
7+
W735tzDIKtvx+/3Dd9puQ0TLFNHBxAmTz7YNaJdIUqzs3DWT4zeZQj0RCOyWCjQL
8+
NfqQ80I7NYFYb4IJqiUY8iOTL5kPi7b5szem5EakQbhufDWun4xGTZk/URZHgYgp
9+
REbOLTYs2hqbK76biW/Yvwd1l7RsptIvJvkuQ1R/dO1WPv6PLKLTuS1EOHM3YqNH
10+
o7wDSplOJe5rAgMBAAGhCQMHADEyMzQ1NqIJAwcANzg5YWJjoyYwJDAiBgNVHREB
11+
AQAEGDAWghRnb29nbGUuY29tAC5ldmlsLmNvbTALBgkqhkiG9w0BAQEDggEBAHuf
12+
1kxr49w51fC4nou96xj3IjcrJjOy5Aywn755enmaQ5Wh6AuVMHKqheITSbtoDT42
13+
jlIFJ3x+XmfenzV5ac8tawGNzJ+vy4+EYwL4QC11nZJ0FSLZ6KZgPI3lpShMy6Gs
14+
bWFHDKrz6oivsitpUpeCK7aH1a7MVmr/G004vpVFe3OHggfyn9mHK3pCp0WIQuRl
15+
PLiRgZSvryvOaf9cbVLvaUqcL480gcDVd4RGicBU52CeStocYeIHmPat1T+IOLFc
16+
uv0VYQ4dzUfZ5c5YwwMPpHCVprxVR+grpZtd0su0bHDL5wETKBXEz8u2bmSORHgB
17+
x2H+/2UOb6jab+IuQ08=
18+
-----END CERTIFICATE-----

test/fixtures/keys/0-dns-key.pem

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEowIBAAKCAQEArBcMH9XbKz3cckxwa3spmxRgAi0LWjooRrEpGLSM1BBdWk/d
3+
GAzMzXaC6+MJMFooORT0TJ45l+6V2PUVW1psBvzNnpLvUuti3pFBZHmNVv0H7VfS
4+
2IAIO8FQwPr9/s5PxDBKgA2Julu9+bcwyCrb8fv9w3fabkNEyxTRwcQJk8+2DWiX
5+
SFKs7Nw1k+M3mUI9EQjslgo0CzX6kPNCOzWBWG+CCaolGPIjky+ZD4u2+bM3puRG
6+
pEG4bnw1rp+MRk2ZP1EWR4GIKURGzi02LNoamyu+m4lv2L8HdZe0bKbSLyb5LkNU
7+
f3TtVj7+jyyi07ktRDhzN2KjR6O8A0qZTiXuawIDAQABAoIBABUlW9sJlz3QAyeU
8+
VvgOEUW6EjYSPOPgY5SULl2XyfpA7IetapiK8huJJXtA0Z88ZNbmyUIk6yTNL2KS
9+
cwZfrQiKxeVnXrsMq4B3ztY+zWxT+UZj1Ue/K8PT9E1SSiWmSkzsNitX/oWEwmpN
10+
5VOjWJV6hmsfbhrAb1KZA1FQ+nBMEQrkEFpmFD1nJE8dH5rWNo4YbM/boR/kC93G
11+
CHOwd2TKNrBa8ZeMOjcyUK9fg15CMkj7uTzfIGkjCM/mXOxvsvTuZ0np7PL7aF+o
12+
GfSHP/l+B5rxT1GTYjZtpSEgAoqYEFJnnZELklo7KRWB7p2rgyHPElSjQN3xIn5Z
13+
apNPrBECgYEA26gZGBP+j1Hqrh3nAhOq/t6PMj+V8yz/i2TrraJ1z7GKRGoBUOX9
14+
ruJGJExfACzgrKl1hL4XRfLdHuooScUqrIxLX7eKHE2nBSd0M40zEKbgIMRhaMsf
15+
lAFOkxJRHMT7edaVu3MkSfDgFXRbhr+jcdxspzhunHMJVUnC5LgAKHMCgYEAyJAw
16+
6GF80Uud5oDHo2tGY9uYgMIUN9rmrrFjqstkVB6QMFlyyeI3MHUhiU7qH53yaRCi
17+
FxuHU6usQFmduwZAKInoPMRhYTYbexe4CYB+C96trwoV7ltDE+a7ZTsEj5kSYvCO
18+
KLcVTn4mcU0TSpE0MU1XQKP0Ev/mdZ5aYEopvCkCgYEAlkVa3YkYNq5g8btNRbN0
19+
4SYbKtIrYJChRpjFTyV8mZkpMYKf4dtmANWWDNEekP0iu5y25BgzzcvHkJW6+DTl
20+
6+OS0Sm8V36cS79hFL99dt/jJyeSSGHl+ZgnTCBU02zDaefuya2M3vTmKGdREk9a
21+
ntOglYnayjc85Fcw+M4UdZcCgYAFw/9j7smDysSzR6h1jjPr0vhDW1Dxeh1/kCHp
22+
Wwd7U5WZjji6jQJBJlzccaRRXF0HoC7Is0Xkpd7BytG5+qgFglFmzc5u2PtZQolL
23+
3KHC/ZfInGWdAIqhG9TvSA8Ngb0BkyDDEuBN7Vp1j12qmxoBANQtS4lMsoaRgwfe
24+
FMO2YQKBgGv6Ndv+eHWSkqGFOSXU6dXAjOuAji3K1yRlxUg/RS/DCMK+8XQbuh47
25+
+p998LwvI70JIr4v2PAkO3/HaRILOTRLLvq8O/yqHwrVf+P7AQ8kPm7uUf7kTXat
26+
DYcKIAp5ddZweyFCgwVm+JMd1E+cpL97RbHCbu7Ct6OD9uLGXCUh
27+
-----END RSA PRIVATE KEY-----

test/simple/test-tls-0-dns-altname.js

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
if (!process.versions.openssl) {
23+
console.error('Skipping because node compiled without OpenSSL.');
24+
process.exit(0);
25+
}
26+
27+
var assert = require('assert');
28+
var fs = require('fs');
29+
var net = require('net');
30+
var tls = require('tls');
31+
32+
var common = require('../common');
33+
34+
var requests = 0;
35+
36+
var server = tls.createServer({
37+
key: fs.readFileSync(common.fixturesDir + '/keys/0-dns-key.pem'),
38+
cert: fs.readFileSync(common.fixturesDir + '/keys/0-dns-cert.pem')
39+
}, function(c) {
40+
c.once('data', function() {
41+
c.destroy();
42+
server.close();
43+
});
44+
}).listen(common.PORT, function() {
45+
var c = tls.connect(common.PORT, {
46+
rejectUnauthorized: false
47+
}, function() {
48+
requests++;
49+
var cert = c.getPeerCertificate();
50+
assert.equal(cert.subjectaltname, 'DNS:google.com\0.evil.com');
51+
c.write('ok');
52+
});
53+
});
54+
55+
process.on('exit', function() {
56+
assert.equal(requests, 1);
57+
});

0 commit comments

Comments
 (0)