-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 6efeb12
Showing
6 changed files
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
# Node TLS crash demo | ||
|
||
## Repro: | ||
|
||
* Checkout | ||
* `npm install` | ||
* `npm start` | ||
* Start chrome using this as a proxy | ||
* Node will segfault with a minute or two | ||
|
||
This module is a minimal POC implementation of an HTTPS intercepting proxy. It's using no native modules at all, but it still reliably | ||
crashes with SIGSEGV/SIGABRT in recent Node versions. | ||
|
||
## Details | ||
|
||
Running `npm start` starts an intercepting HTTPS proxy server on port 8000. You'll need to disable cert validation or trust `test-ca.pem` as a CA to use it. | ||
|
||
E.g. with curl: | ||
|
||
```bash | ||
curl -k --proxy-insecure -x https://localhost:8000 https://example.com | ||
``` | ||
|
||
You can start a fresh Chrome session using this proxy & trusting the cert with: | ||
|
||
``` | ||
google-chrome --user-data-dir=/tmp/chrome --proxy-server="https://localhost:80" --ignore-certificate-errors-spki-list=AvVrqB/anBbJ+KRCMH/anWgZbeE0Y28JtqYB0+2MDmE= | ||
``` | ||
|
||
After a minute of heavy use the proxy will crash with SIGSEGV/SIGABRT, I think always in CRYPTO_free, and typically inside DestroySSL. | ||
|
||
The easiest repro for me is just to open `https://cnn.com` in a few tabs. This fails in at least Node 8.9.1 and 6.12.0 (though v6 seems to take longer). | ||
|
||
Note that this code doesn't use any native modules - it's pure JS all the way down (according to `find node_modules/ -name \*.node`), so this | ||
is a crash coming directly from Node itself. | ||
|
||
Failures typically look something like: | ||
|
||
``` | ||
*** Error in `node': free(): invalid next size (fast): 0x0000000003ea2660 *** | ||
======= Backtrace: ========= | ||
/lib/x86_64-linux-gnu/libc.so.6(+0x7908b)[0x7f3ba3ff908b] | ||
/lib/x86_64-linux-gnu/libc.so.6(+0x82c3a)[0x7f3ba4002c3a] | ||
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f3ba4006d2c] | ||
node(CRYPTO_free+0x25)[0x997995] | ||
node(ASN1_primitive_free+0x6f)[0x90ed0f] | ||
node(asn1_item_combine_free+0x93)[0x90eea3] | ||
node(ASN1_item_free+0x2b2)[0x90f502] | ||
node(sk_pop_free+0x37)[0x9d2767] | ||
node[0x913a3d] | ||
node(asn1_item_combine_free+0x5e)[0x90ee6e] | ||
node(asn1_item_combine_free+0x2e2)[0x90f0f2] | ||
node(ASN1_item_free+0x2b2)[0x90f502] | ||
node(sk_pop_free+0x37)[0x9d2767] | ||
node(ssl_sess_cert_free+0x53)[0x8d3793] | ||
node(SSL_SESSION_free+0x8f)[0x8e0fcf] | ||
node(SSL_free+0xf5)[0x8db195] | ||
node(_ZN4node6crypto7SSLWrapINS_7TLSWrapEE10DestroySSLEv+0x1a)[0x12dd7ea] | ||
node(_ZN4node7TLSWrap10DestroySSLERKN2v820FunctionCallbackInfoINS1_5ValueEEE+0xb8)[0x12e33b8] | ||
node(_ZN2v88internal25FunctionCallbackArguments4CallEPFvRKNS_20FunctionCallbackInfoINS_5ValueEEEE+0x193)[0xb1a073] | ||
node[0xb8fe3c] | ||
node(_ZN2v88internal21Builtin_HandleApiCallEiPPNS0_6ObjectEPNS0_7IsolateE+0xaf)[0xb90a8f] | ||
[0x15bab148463d] | ||
``` | ||
|
||
``` | ||
*** Error in `node': free(): invalid pointer: 0x0000000002ff6580 *** | ||
======= Backtrace: ========= | ||
/lib/x86_64-linux-gnu/libc.so.6(+0x7908b)[0x7f78f945b08b] | ||
/lib/x86_64-linux-gnu/libc.so.6(+0x82c3a)[0x7f78f9464c3a] | ||
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f78f9468d2c] | ||
node(CRYPTO_free+0x25)[0x997995] | ||
node(sk_free+0x1f)[0x9d27df] | ||
node(asn1_item_combine_free+0x1f4)[0x90f004] | ||
node(ASN1_item_free+0x2b2)[0x90f502] | ||
node(_ZN4node6crypto13SecureContextD0Ev+0x3f)[0x12d76ef] | ||
node(_ZN2v88internal13GlobalHandles31DispatchPendingPhantomCallbacksEb+0xee)[0xe7b01e] | ||
node(_ZN2v88internal13GlobalHandles31PostGarbageCollectionProcessingENS0_16GarbageCollectorENS_15GCCallbackFlagsE+0x2a)[0xe7b28a] | ||
node(_ZN2v88internal4Heap24PerformGarbageCollectionENS0_16GarbageCollectorENS_15GCCallbackFlagsE+0x2be)[0xea660e] | ||
node[0xea7933] | ||
node(_ZN2v88internal4Heap36FinalizeIncrementalMarkingIfCompleteENS0_23GarbageCollectionReasonE+0x4a)[0xea86ca] | ||
node(_ZN2v88internal21IncrementalMarkingJob4Task11RunInternalEv+0x119)[0xeaa0d9] | ||
node(_ZN2v88internal14CancelableTask3RunEv+0x36)[0xbc83e6] | ||
node(_ZN4node12NodePlatform28FlushForegroundTasksInternalEv+0x1f4)[0x1272174] | ||
node[0x145796b] | ||
node[0x14694c8] | ||
node(uv_run+0x156)[0x14582f6] | ||
node(_ZN4node5StartEP9uv_loop_siPKPKciS5_+0xc75)[0x122af15] | ||
node(_ZN4node5StartEiPPc+0x163)[0x1223b73] | ||
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7f78f94023f1] | ||
node[0x8ae7c1] | ||
``` | ||
|
||
``` | ||
*** Error in `node': corrupted size vs. prev_size: 0x0000000003fd6060 *** | ||
======= Backtrace: ========= | ||
/lib/x86_64-linux-gnu/libc.so.6(+0x7908b)[0x7f66633b608b] | ||
/lib/x86_64-linux-gnu/libc.so.6(+0x814a7)[0x7f66633be4a7] | ||
/lib/x86_64-linux-gnu/libc.so.6(+0x82f20)[0x7f66633bff20] | ||
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f66633c3d2c] | ||
node(CRYPTO_free+0x25)[0x997995] | ||
node(SSL_CTX_free+0x1e3)[0x8da9b3] | ||
node(_ZN4node6crypto13SecureContextD0Ev+0x31)[0x12d76e1] | ||
node(_ZN2v88internal13GlobalHandles31DispatchPendingPhantomCallbacksEb+0xee)[0xe7b01e] | ||
node(_ZN2v88internal13GlobalHandles31PostGarbageCollectionProcessingENS0_16GarbageCollectorENS_15GCCallbackFlagsE+0x2a)[0xe7b28a] | ||
node(_ZN2v88internal4Heap24PerformGarbageCollectionENS0_16GarbageCollectorENS_15GCCallbackFlagsE+0x2be)[0xea660e] | ||
node[0xea7933] | ||
node(_ZN2v88internal4Heap36FinalizeIncrementalMarkingIfCompleteENS0_23GarbageCollectionReasonE+0x4a)[0xea86ca] | ||
node(_ZN2v88internal21IncrementalMarkingJob4Task11RunInternalEv+0x119)[0xeaa0d9] | ||
node(_ZN2v88internal14CancelableTask3RunEv+0x36)[0xbc83e6] | ||
node(_ZN4node12NodePlatform28FlushForegroundTasksInternalEv+0x1f4)[0x1272174] | ||
node[0x145796b] | ||
node[0x14694c8] | ||
node(uv_run+0x156)[0x14582f6] | ||
node(_ZN4node5StartEP9uv_loop_siPKPKciS5_+0xc75)[0x122af15] | ||
node(_ZN4node5StartEiPPc+0x163)[0x1223b73] | ||
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7f666335d3f1] | ||
node[0x8ae7c1] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "tls-crash-demo", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "proxy.js", | ||
"scripts": { | ||
"start": "node proxy.js" | ||
}, | ||
"author": "", | ||
"license": "MIT", | ||
"dependencies": { | ||
"mockttp": "^0.4.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
const https = require('https'); | ||
const tls = require('tls'); | ||
const fs = require('fs'); | ||
|
||
const { CA } = require('mockttp/dist/util/tls'); | ||
|
||
const port = 8000; | ||
|
||
const caKey = fs.readFileSync('./test-ca.key'); | ||
const caCert = fs.readFileSync('./test-ca.pem'); | ||
|
||
const ca = new CA(caKey, caCert); | ||
|
||
const serverCert = ca.generateCertificate('localhost'); | ||
const server = https.createServer({ | ||
key: caKey, | ||
cert: caCert, | ||
ca: [caCert], | ||
SNICallback: (domain, cb) => { | ||
const generatedCert = ca.generateCertificate(domain); | ||
cb(null, tls.createSecureContext(generatedCert)); | ||
} | ||
}); | ||
|
||
server.addListener('connect', (req, socket, head) => { | ||
console.log(`Proxying request to ${req.url}`); | ||
let [ targetHost, port ] = req.url.split(':'); | ||
port = parseInt(port, 10); | ||
|
||
// Note that the CA caches generated certificates by domain, so this is typically fairly cheap. | ||
// This is pure JS with node-forge, source at https://unpkg.com/[email protected]/dist/util/tls.js | ||
const { key, cert } = ca.generateCertificate(targetHost); | ||
|
||
socket.write('HTTP/' + req.httpVersion + ' 200 OK\r\n\r\n', 'UTF-8', () => { | ||
let tlsSocket = new tls.TLSSocket(socket, { | ||
isServer: true, | ||
secureContext: tls.createSecureContext({ | ||
key, | ||
cert, | ||
ca: caCert | ||
}) | ||
}); | ||
|
||
let upstream = tls.connect(port, targetHost, {}, () => { | ||
upstream.write(head); | ||
|
||
tlsSocket.pipe(upstream); | ||
upstream.pipe(tlsSocket); | ||
}); | ||
|
||
upstream.on('error', (e) => { | ||
console.log(`Upstream error for ${targetHost}`, e); | ||
socket.destroy(e); | ||
}); | ||
}); | ||
}); | ||
|
||
server.listen(port, (err) => console.log(err || `Listening on ${port}`)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
-----BEGIN PRIVATE KEY----- | ||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDNfC2Wrf1+skkr | ||
eS53j4BNHjL6579cu/mK/VX1oENG/FTqEw7QC4bO6y56h1dLaCtgaUutmtfAlM9T | ||
AQBBAzRMriNmXqzu/lHp3AoH57/1WbQ5skRzwn2zUU9ktPm63dWsFnJI/k9thL1a | ||
D+vnakJAzjj7J4agFs91Ll3FLDzX44g4ptVERAP9aQ9HlooU991e1EDchNuRynTM | ||
E+oHV+s7oV0jWq5m3m0KeJrVtug9NdtcUTTQCzlC9OXBBiGlspAr8lrLg8MnIAUY | ||
A33nmbaINdqu1u8LxLVjTfmQJI4e19FGfiyMJLX9iFhT+ATnpt6itAoXkIR/nKYi | ||
CIxcTqLlAgMBAAECggEBALYMRB9wulsa/PRFAkPuoM6x6Jyd4M35w5W96AAbIj+r | ||
oldW1xK+g4qilaT8bvxhp7xczS1bN7ZooF17T4xJmHYu+THiwvdh3ZSA22oxicGG | ||
3cMYCsk8ED1j1iD0rSM/EeTKZioBFMGEjnVSEcAORfBAQ/9O/1ipnNbGY1EiZi0k | ||
0lIKcCwLmyXWTK07o40W2l2cxpJddcM1ZSWr5jiw6SNfuhIDMelM+ctvFcdBp2HJ | ||
6RP40e4nCliz+bBsjJ9rI9JnxJ4Zx11CI0a7Fi4B3va1Pips58wvZhm1V6PzRVyx | ||
WPm1Sjj0hLmzjpwGX5XdTfGAaw71ekJpr1ZXnbVItSkCgYEA+dXGKsKvgI+WamM1 | ||
EpDwvBUGwWyA7MSUDX10iT/vawUP7jmvwASvcSbsOy8n5kvm2zyCA/5ZPGJvEvNK | ||
mHASenbBXlPmSbUg31Ju1ndTf4KLkmPHldzR0Wg7lzYypP1mKh1ZeZzr3jLLc35g | ||
CRyHorAudlxipDOKFiLdQl3Jgp8CgYEA0o498Y+O0gcX/OP9yG2Osap9Ixj64EHs | ||
sOPUfYPElvHzPyngPwF6zDLNVOiZrv4dnW6S1vLveYFWjm9HuzVlqLVg2wC+nYrS | ||
baURB7phwjJUBzLyRh9e4qKwmjwygbhhmvpqLXPw3tq00KkFui9u+AR7l6q0W0aU | ||
PBC9TwjDz/sCgYEAvZqAh2kzGkVeqSTbXVjEamkmtFqtSYMyvT4t2A++mqC/41LC | ||
T97+ashYVd5G0J9f95hnL7KzdIFbvK0JOsErNOe1fun7horBBNshpP/wTX/8fr/c | ||
854fWmZZezu1mcN56pJVmlb+Jqa0AtWw+pk9UrmUuV0Ju4Yl0QDqnHhi+w8CgYBe | ||
SDdQjXnkbiy9ntGrB/PXdoImTy83cA2uf7ZMpc5H0PudEwFI9T6pZS4wkR8QDtXw | ||
Au1Zttqoy9OYYBf8qkJlMyK1rjWskdb8JefkT/8qWCLsPlHiOHXigfsWdVIgaBG8 | ||
tdkJlVsMT16b+LOJ1WeZQ1icZ2HvZUFHTC+YzlHwNQKBgQCUp1NT93fXNs9mYU5l | ||
Az0gsAdjECz6N7kNQWGrl883Y3YZ/wqrfir3UCKGxJ6270IkA+VPdSmplCPf1zwQ | ||
TmppzR3WuKqlj29W0qavT+4f/67aKTZGormo+QfXjL6kkXRGJ0xLsentcuoM7zCC | ||
gIBTGAb9wqjI1WPO6ImlPYVxjA== | ||
-----END PRIVATE KEY----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIIDKzCCAhOgAwIBAgIJAP4Z15C7V0rSMA0GCSqGSIb3DQEBCwUAMCwxKjAoBgNV | ||
BAMMIU1vY2t0dHAgVGVzdGluZyBDQSAtIERPIE5PVCBUUlVTVDAeFw0xNzExMTQy | ||
MTU2MDlaFw0xNzEyMTQyMTU2MDlaMCwxKjAoBgNVBAMMIU1vY2t0dHAgVGVzdGlu | ||
ZyBDQSAtIERPIE5PVCBUUlVTVDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC | ||
ggEBAM18LZat/X6ySSt5LnePgE0eMvrnv1y7+Yr9VfWgQ0b8VOoTDtALhs7rLnqH | ||
V0toK2BpS62a18CUz1MBAEEDNEyuI2ZerO7+UencCgfnv/VZtDmyRHPCfbNRT2S0 | ||
+brd1awWckj+T22EvVoP6+dqQkDOOPsnhqAWz3UuXcUsPNfjiDim1UREA/1pD0eW | ||
ihT33V7UQNyE25HKdMwT6gdX6zuhXSNarmbebQp4mtW26D0121xRNNALOUL05cEG | ||
IaWykCvyWsuDwycgBRgDfeeZtog12q7W7wvEtWNN+ZAkjh7X0UZ+LIwktf2IWFP4 | ||
BOem3qK0CheQhH+cpiIIjFxOouUCAwEAAaNQME4wHQYDVR0OBBYEFGZVh4J+GvDD | ||
iFJlD0ubhr4iD188MB8GA1UdIwQYMBaAFGZVh4J+GvDDiFJlD0ubhr4iD188MAwG | ||
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAL1PwkVVCuJoSn4PLdw3MmUP | ||
YBtrTnC4n6v1p2uHNktWA5Mq0AyLggdp4URlBunsfPCEwx3/dbNimOmav/rHIsiC | ||
uQgT6G3KT0Npr95EpO8GXka1vkYP1sI81j4ANR3h3smGXilFLSBQQfFkzRMg427z | ||
ABP9PDiuwlYModoE5aXr0mhgW+gi8HffIWrzickbOdyZgrljB1ehHh1oiGTNs3gi | ||
JAKhQc7bEejuyLI8pYovZVSKzdajGsr4+CZqqkz4OOxo3z+C55hCDyJILHJUlWS7 | ||
mSfkXJTIhnyW3gyMp6o3F0c2XvAqLAawnHo1lUXHcu7JChJAWDXRxdu4H1+jwQc= | ||
-----END CERTIFICATE----- |