CVE-2016-2515 (JavaScript, published 2016-04-13T16:59Z)
Description: value: Hawk before 3.1.3 and 4.x before 4.1.1 allow remote attackers to cause a denial of service (CPU consumption or partial outage) via a long (1) header or (2) URI that is matched against an improper regular expression.
Severity: HIGH (CVSS v3 base score: 7.5)
Weakness: CWE-399 \u2014 Resource Management Errors
Weaknesses in this category are related to improper management of system resources.
Repository: https://github.com/hueniverse/hawk
Files changed:
lib/server.js
lib/utils.js
package.json
test/server.js
test/utils.js
Commit message: Fix minor DoS attack on long headers or uris. Closes #168


Vulnerable code:
    //                                 1     2             3           4
    const resource = request.url.match(/^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/);
    const headerParts = header.match(/^(\w+)(?:\s+(.*))?$/);       // Header: scheme[ something]
        // Allowed attribute value characters: !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9
        if ($2.match(/^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/) === null) {
  "version": "4.1.0",

Fixed code:

//                       1     2             3           4
internals.bewitRegex = /^(\/.*)([\?&])bewit\=([^&$]*)(?:&(.+))?$/;


    if (request.url.length > Utils.limits.maxMatchLength) {
        return callback(Boom.badRequest('Resource path exceeds max length'));
    }

    const resource = request.url.match(internals.bewitRegex);
exports.limits = {
    maxMatchLength: 4096            // Limit the length of uris and headers to avoid a DoS attack on string matching
};


    if (hostHeader.length > exports.limits.maxMatchLength) {
        return null;
    }

internals.authHeaderRegex = /^(\w+)(?:\s+(.*))?$/;                                      // Header: scheme[ something]
internals.attributeRegex = /^[ \w\!#\$%&'\(\)\*\+,\-\.\/\:;<\=>\?@\[\]\^`\{\|\}~]+$/;   // !#$%&'()*+,-./:;<=>?@[]^_`{|}~ and space, a-z, A-Z, 0-9


    if (header.length > exports.limits.maxMatchLength) {
        return Boom.badRequest('Header length too long');
    }

    const headerParts = header.match(internals.authHeaderRegex);
        // Allowed attribute value characters
        if ($2.match(internals.attributeRegex) === null) {
  "version": "4.1.1",
    describe('authenticateBewit()', () => {

        it('errors on uri too long', (done) => {

            let long = '/';
            for (let i = 0; i < 5000; ++i) {
                long += 'x';
            }

            const req = {
                method: 'GET',
                url: long,
                host: 'example.com',
                port: 8080,
                authorization: 'Hawk id="1", ts="1353788437", nonce="k3j4h2", mac="zy79QQ5/EYFmQqutVnYb73gAc/U=", ext="hello"'
            };

            Hawk.server.authenticateBewit(req, credentialsFunc, {}, (err, credentials, bewit) => {

                expect(err).to.exist();
                expect(err.output.statusCode).to.equal(400);
                expect(err.message).to.equal('Resource path exceeds max length');
                done();
            });
        });
    });


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

            let long = '';
            for (let i = 0; i < 5000; ++i) {
                long += 'x';
            }

            expect(Hawk.utils.parseHost({ headers: { host: long } })).to.be.null();
            done();
        });
    });

    describe('parseAuthorizationHeader()', () => {

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

            let long = 'Scheme a="';
            for (let i = 0; i < 5000; ++i) {
                long += 'x';
            }
            long += '"';

            const err = Hawk.utils.parseAuthorizationHeader(long, ['a']);
            expect(err).to.be.instanceof(Error);
            expect(err.message).to.equal('Header length too long');
            done();
        });