Skip to content
This repository was archived by the owner on Apr 5, 2024. It is now read-only.

Commit d10d72c

Browse files
authoredMay 3, 2022
Merge pull request #286 from lotas/regex-exploit-fix
Parse URLs using stdlib
2 parents aa5e09e + ade1341 commit d10d72c

File tree

3 files changed

+29
-13
lines changed

3 files changed

+29
-13
lines changed
 

‎lib/utils.js

+12-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
const Boom = require('@hapi/boom');
4+
const Url = require('url');
45

56

67
const internals = {};
@@ -17,12 +18,6 @@ exports.limits = {
1718
};
1819

1920

20-
// Extract host and port from request
21-
22-
// $1 $2
23-
internals.hostHeaderRegex = /^(?:(?:\r\n)?\s)*((?:[^:]+)|(?:\[[^\]]+\]))(?::(\d+))?(?:(?:\r\n)?\s)*$/; // (IPv4, hostname)|(IPv6)
24-
25-
2621
exports.parseHost = function (req, hostHeaderName) {
2722

2823
hostHeaderName = (hostHeaderName ? hostHeaderName.toLowerCase() : 'host');
@@ -35,14 +30,21 @@ exports.parseHost = function (req, hostHeaderName) {
3530
return null;
3631
}
3732

38-
const hostParts = hostHeader.match(internals.hostHeaderRegex);
39-
if (!hostParts) {
33+
if (hostHeader.indexOf('/') !== -1) {
34+
return null;
35+
}
36+
37+
let uri;
38+
try {
39+
uri = new Url.URL('http://' + hostHeader);
40+
}
41+
catch (err) {
4042
return null;
4143
}
4244

4345
return {
44-
name: hostParts[1],
45-
port: (hostParts[2] ? hostParts[2] : (req.connection && req.connection.encrypted ? 443 : 80))
46+
name: uri.hostname,
47+
port: (uri.port ? uri.port : (req.connection && req.connection.encrypted ? 443 : 80))
4648
};
4749
};
4850

‎test/server.js

+14
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,20 @@ describe('Server', () => {
433433
await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid Host header');
434434
});
435435

436+
it('errors on an bad host header (includes path and query)', async () => {
437+
438+
const req = {
439+
method: 'GET',
440+
url: '/resource/4?filter=a',
441+
headers: {
442+
host: 'example.com:8080/path?x=z',
443+
authorization: 'Hawk'
444+
}
445+
};
446+
447+
await expect(Hawk.server.authenticate(req, credentialsFunc, { localtimeOffsetMsec: 1353788437000 - Hawk.utils.now() })).to.reject('Invalid Host header');
448+
});
449+
436450
it('errors on an bad host header (pad port)', async () => {
437451

438452
const req = {

‎test/utils.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ describe('Utils', () => {
5555
method: 'POST',
5656
url: '/resource/4?filter=a',
5757
headers: {
58-
host: '[123:123:123]',
58+
host: '[123:123::123]',
5959
'content-type': 'text/plain;x=y'
6060
},
6161
connection: {
@@ -72,7 +72,7 @@ describe('Utils', () => {
7272
method: 'POST',
7373
url: '/resource/4?filter=a',
7474
headers: {
75-
host: '[123:123:123]:8000',
75+
host: '[123:123::123]:8000',
7676
'content-type': 'text/plain;x=y'
7777
},
7878
connection: {
@@ -82,7 +82,7 @@ describe('Utils', () => {
8282

8383
const host = Hawk.utils.parseHost(req, 'Host');
8484
expect(host.port).to.equal('8000');
85-
expect(host.name).to.equal('[123:123:123]');
85+
expect(host.name).to.equal('[123:123::123]');
8686
});
8787

8888
it('errors on header too long', () => {

0 commit comments

Comments
 (0)
This repository has been archived.