Skip to content

Commit

Permalink
crypto: escape DNS altname
Browse files Browse the repository at this point in the history
Vulnerability credit goes to:

    Calvin Liang [email protected]

Reviewed-By: Ben Noordhuis <[email protected]>
PR-URL: ...private
  • Loading branch information
indutny committed Nov 7, 2014
1 parent b9cecc3 commit 1bb0aeb
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 2 deletions.
48 changes: 46 additions & 2 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,48 @@ void SSLWrap<Base>::OnClientHello(void* arg,
}


static bool SafeX509ExtPrint(BIO* out, X509_EXTENSION* ext) {
// Only alt_name is escaped at the moment
if (OBJ_obj2nid(ext->object) != NID_subject_alt_name)
return false;

const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
if (method == NULL || method->it == NULL)
return false;

if (method->i2v != reinterpret_cast<X509V3_EXT_I2V>(i2v_GENERAL_NAMES))
return false;

const unsigned char* p = ext->value->data;
GENERAL_NAMES* names = reinterpret_cast<GENERAL_NAMES*>(ASN1_item_d2i(
NULL,
&p,
ext->value->length,
ASN1_ITEM_ptr(method->it)));
if (names == NULL)
return false;

for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);

if (gen->type == GEN_DNS) {
ASN1_IA5STRING* name = gen->d.dNSName;

BIO_write(out, "DNS:", 4);
BIO_write(out, name->data, name->length);
} else {
STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
const_cast<X509V3_EXT_METHOD*>(method), gen, NULL);
if (nval == NULL)
return false;
X509V3_EXT_val_prn(out, nval, 0, 0);
}
}

return true;
}


static Local<Object> X509ToObject(Environment* env, X509* cert) {
EscapableHandleScope scope(env->isolate());

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

rv = X509V3_EXT_print(bio, ext, 0, 0);
CHECK_EQ(rv, 1);
if (!SafeX509ExtPrint(bio, ext)) {
rv = X509V3_EXT_print(bio, ext, 0, 0);
CHECK_EQ(rv, 1);
}

BIO_get_mem_ptr(bio, &mem);
info->Set(keys[i],
Expand Down
18 changes: 18 additions & 0 deletions test/fixtures/keys/0-dns-cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE-----
MIIC2jCCAcSgAwIBAgICJxEwCwYJKoZIhvcNAQEFMBUxEzARBgNVBAMWCm9oLm15
Lmdvc2gwHxcNMTQxMTA1MDMyMDUyWhcOMzQwMTAzMTAzMjA1MlowEzERMA8GA1UE
AxYIZXZpbC5jb20wggEfMAsGCSqGSIb3DQEBAQOCAQ4AMIIBCQKCAQCsFwwf1dsr
PdxyTHBreymbFGACLQtaOihGsSkYtIzUEF1aT90YDMzNdoLr4wkwWig5FPRMnjmX
7pXY9RVbWmwG/M2eku9S62LekUFkeY1W/QftV9LYgAg7wVDA+v3+zk/EMEqADYm6
W735tzDIKtvx+/3Dd9puQ0TLFNHBxAmTz7YNaJdIUqzs3DWT4zeZQj0RCOyWCjQL
NfqQ80I7NYFYb4IJqiUY8iOTL5kPi7b5szem5EakQbhufDWun4xGTZk/URZHgYgp
REbOLTYs2hqbK76biW/Yvwd1l7RsptIvJvkuQ1R/dO1WPv6PLKLTuS1EOHM3YqNH
o7wDSplOJe5rAgMBAAGhCQMHADEyMzQ1NqIJAwcANzg5YWJjoyYwJDAiBgNVHREB
AQAEGDAWghRnb29nbGUuY29tAC5ldmlsLmNvbTALBgkqhkiG9w0BAQEDggEBAHuf
1kxr49w51fC4nou96xj3IjcrJjOy5Aywn755enmaQ5Wh6AuVMHKqheITSbtoDT42
jlIFJ3x+XmfenzV5ac8tawGNzJ+vy4+EYwL4QC11nZJ0FSLZ6KZgPI3lpShMy6Gs
bWFHDKrz6oivsitpUpeCK7aH1a7MVmr/G004vpVFe3OHggfyn9mHK3pCp0WIQuRl
PLiRgZSvryvOaf9cbVLvaUqcL480gcDVd4RGicBU52CeStocYeIHmPat1T+IOLFc
uv0VYQ4dzUfZ5c5YwwMPpHCVprxVR+grpZtd0su0bHDL5wETKBXEz8u2bmSORHgB
x2H+/2UOb6jab+IuQ08=
-----END CERTIFICATE-----
27 changes: 27 additions & 0 deletions test/fixtures/keys/0-dns-key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEArBcMH9XbKz3cckxwa3spmxRgAi0LWjooRrEpGLSM1BBdWk/d
GAzMzXaC6+MJMFooORT0TJ45l+6V2PUVW1psBvzNnpLvUuti3pFBZHmNVv0H7VfS
2IAIO8FQwPr9/s5PxDBKgA2Julu9+bcwyCrb8fv9w3fabkNEyxTRwcQJk8+2DWiX
SFKs7Nw1k+M3mUI9EQjslgo0CzX6kPNCOzWBWG+CCaolGPIjky+ZD4u2+bM3puRG
pEG4bnw1rp+MRk2ZP1EWR4GIKURGzi02LNoamyu+m4lv2L8HdZe0bKbSLyb5LkNU
f3TtVj7+jyyi07ktRDhzN2KjR6O8A0qZTiXuawIDAQABAoIBABUlW9sJlz3QAyeU
VvgOEUW6EjYSPOPgY5SULl2XyfpA7IetapiK8huJJXtA0Z88ZNbmyUIk6yTNL2KS
cwZfrQiKxeVnXrsMq4B3ztY+zWxT+UZj1Ue/K8PT9E1SSiWmSkzsNitX/oWEwmpN
5VOjWJV6hmsfbhrAb1KZA1FQ+nBMEQrkEFpmFD1nJE8dH5rWNo4YbM/boR/kC93G
CHOwd2TKNrBa8ZeMOjcyUK9fg15CMkj7uTzfIGkjCM/mXOxvsvTuZ0np7PL7aF+o
GfSHP/l+B5rxT1GTYjZtpSEgAoqYEFJnnZELklo7KRWB7p2rgyHPElSjQN3xIn5Z
apNPrBECgYEA26gZGBP+j1Hqrh3nAhOq/t6PMj+V8yz/i2TrraJ1z7GKRGoBUOX9
ruJGJExfACzgrKl1hL4XRfLdHuooScUqrIxLX7eKHE2nBSd0M40zEKbgIMRhaMsf
lAFOkxJRHMT7edaVu3MkSfDgFXRbhr+jcdxspzhunHMJVUnC5LgAKHMCgYEAyJAw
6GF80Uud5oDHo2tGY9uYgMIUN9rmrrFjqstkVB6QMFlyyeI3MHUhiU7qH53yaRCi
FxuHU6usQFmduwZAKInoPMRhYTYbexe4CYB+C96trwoV7ltDE+a7ZTsEj5kSYvCO
KLcVTn4mcU0TSpE0MU1XQKP0Ev/mdZ5aYEopvCkCgYEAlkVa3YkYNq5g8btNRbN0
4SYbKtIrYJChRpjFTyV8mZkpMYKf4dtmANWWDNEekP0iu5y25BgzzcvHkJW6+DTl
6+OS0Sm8V36cS79hFL99dt/jJyeSSGHl+ZgnTCBU02zDaefuya2M3vTmKGdREk9a
ntOglYnayjc85Fcw+M4UdZcCgYAFw/9j7smDysSzR6h1jjPr0vhDW1Dxeh1/kCHp
Wwd7U5WZjji6jQJBJlzccaRRXF0HoC7Is0Xkpd7BytG5+qgFglFmzc5u2PtZQolL
3KHC/ZfInGWdAIqhG9TvSA8Ngb0BkyDDEuBN7Vp1j12qmxoBANQtS4lMsoaRgwfe
FMO2YQKBgGv6Ndv+eHWSkqGFOSXU6dXAjOuAji3K1yRlxUg/RS/DCMK+8XQbuh47
+p998LwvI70JIr4v2PAkO3/HaRILOTRLLvq8O/yqHwrVf+P7AQ8kPm7uUf7kTXat
DYcKIAp5ddZweyFCgwVm+JMd1E+cpL97RbHCbu7Ct6OD9uLGXCUh
-----END RSA PRIVATE KEY-----
57 changes: 57 additions & 0 deletions test/simple/test-tls-0-dns-altname.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

if (!process.versions.openssl) {
console.error('Skipping because node compiled without OpenSSL.');
process.exit(0);
}

var assert = require('assert');
var fs = require('fs');
var net = require('net');
var tls = require('tls');

var common = require('../common');

var requests = 0;

var server = tls.createServer({
key: fs.readFileSync(common.fixturesDir + '/keys/0-dns-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/0-dns-cert.pem')
}, function(c) {
c.once('data', function() {
c.destroy();
server.close();
});
}).listen(common.PORT, function() {
var c = tls.connect(common.PORT, {
rejectUnauthorized: false
}, function() {
requests++;
var cert = c.getPeerCertificate();
assert.equal(cert.subjectaltname, 'DNS:google.com\0.evil.com');
c.write('ok');
});
});

process.on('exit', function() {
assert.equal(requests, 1);
});

0 comments on commit 1bb0aeb

Please sign in to comment.