diff --git a/lib/internal/debugger/inspect_client.js b/lib/internal/debugger/inspect_client.js index cd277a4cf5a946..419b984cc9f473 100644 --- a/lib/internal/debugger/inspect_client.js +++ b/lib/internal/debugger/inspect_client.js @@ -11,6 +11,7 @@ const { } = primordials; const Buffer = require('buffer').Buffer; +const crypto = require('crypto'); const { ERR_DEBUGGER_ERROR } = require('internal/errors').codes; const { EventEmitter } = require('events'); const http = require('http'); @@ -35,6 +36,10 @@ const kTwoBytePayloadLengthField = 126; const kEightBytePayloadLengthField = 127; const kMaskingKeyWidthInBytes = 4; +// This guid is defined in the Websocket Protocol RFC +// https://tools.ietf.org/html/rfc6455#section-1.3 +const WEBSOCKET_HANDSHAKE_GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; + function unpackError({ code, message, data }) { const err = new ERR_DEBUGGER_ERROR(`${message} - ${data}`); err.code = code; @@ -42,6 +47,19 @@ function unpackError({ code, message, data }) { return err; } +function validateHandshake(requestKey, responseKey) { + const expectedResponseKeyBase = requestKey + WEBSOCKET_HANDSHAKE_GUID; + const shasum = crypto.createHash('sha1'); + shasum.update(expectedResponseKeyBase); + const shabuf = shasum.digest(); + + if (shabuf.toString('base64') !== responseKey) { + throw new ERR_DEBUGGER_ERROR( + `WebSocket secret mismatch: ${requestKey} did not match ${responseKey}` + ); + } +} + function encodeFrameHybi17(payload) { var i; @@ -287,8 +305,8 @@ class Client extends EventEmitter { _connectWebsocket(urlPath) { this.reset(); - const key1 = require('crypto').randomBytes(16).toString('base64'); - debuglog('request websocket', key1); + const requestKey = crypto.randomBytes(16).toString('base64'); + debuglog('request WebSocket', requestKey); const httpReq = this._http = http.request({ host: this._host, @@ -297,7 +315,7 @@ class Client extends EventEmitter { headers: { 'Connection': 'Upgrade', 'Upgrade': 'websocket', - 'Sec-WebSocket-Key': key1, + 'Sec-WebSocket-Key': requestKey, 'Sec-WebSocket-Version': '13', }, }); @@ -314,7 +332,7 @@ class Client extends EventEmitter { }); const handshakeListener = (res, socket) => { - // TODO: we *could* validate res.headers[sec-websocket-accept] + validateHandshake(requestKey, res.headers['sec-websocket-accept']); debuglog('websocket upgrade'); this._socket = socket;