-
Notifications
You must be signed in to change notification settings - Fork 30.5k
Commit
PR-URL: nodejs-private/node-private#26 Reviewed-By: Rod Vagg <[email protected]> Reviewed-By: Сковорода Никита Андреевич <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]>
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -231,3 +231,20 @@ function checkIsHttpToken(val) { | |
return typeof val === 'string' && token.test(val); | ||
} | ||
exports._checkIsHttpToken = checkIsHttpToken; | ||
|
||
/** | ||
* True if val contains an invalid field-vchar | ||
* field-value = *( field-content / obs-fold ) | ||
* field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] | ||
* field-vchar = VCHAR / obs-text | ||
**/ | ||
function checkInvalidHeaderChar(val) { | ||
val = '' + val; | ||
for (var i = 0; i < val.length; i++) { | ||
const ch = val.charCodeAt(i); | ||
if (ch === 9) continue; | ||
if (ch <= 31 || ch > 255 || ch === 127) return true; | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
bnoordhuis
Member
|
||
} | ||
return false; | ||
} | ||
exports._checkInvalidHeaderChar = checkInvalidHeaderChar; |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const http = require('http'); | ||
const net = require('net'); | ||
const url = require('url'); | ||
const assert = require('assert'); | ||
|
||
// Response splitting example, credit: Amit Klein, Safebreach | ||
const str = '/welcome?lang=bar%c4%8d%c4%8aContentLength:%200%c4%8d%c4%8a%c' + | ||
'4%8d%c4%8aHTTP/1.1%20200%20OK%c4%8d%c4%8aContentLength:%202' + | ||
'0%c4%8d%c4%8aLastModified:%20Mon,%2027%20Oct%202003%2014:50:18' + | ||
'%20GMT%c4%8d%c4%8aContentType:%20text/html%c4%8d%c4%8a%c4%8' + | ||
'd%c4%8a%3chtml%3eGotcha!%3c/html%3e'; | ||
|
||
// Response splitting example, credit: Сковорода Никита Андреевич (@ChALkeR) | ||
const x = 'fooഊSet-Cookie: foo=barഊഊ<script>alert("Hi!")</script>'; | ||
const y = 'foo⠊Set-Cookie: foo=bar'; | ||
|
||
var count = 0; | ||
|
||
const server = http.createServer((req, res) => { | ||
switch (count++) { | ||
case 0: | ||
const loc = url.parse(req.url, true).query.lang; | ||
assert.throws(common.mustCall(() => { | ||
res.writeHead(302, {Location: `/foo?lang=${loc}`}); | ||
})); | ||
break; | ||
case 1: | ||
assert.throws(common.mustCall(() => { | ||
res.writeHead(200, {'foo' : x}); | ||
})); | ||
break; | ||
case 2: | ||
assert.throws(common.mustCall(() => { | ||
res.writeHead(200, {'foo' : y}); | ||
})); | ||
break; | ||
default: | ||
assert.fail(null, null, 'should not get to here.'); | ||
} | ||
if (count === 3) | ||
server.close(); | ||
res.end('ok'); | ||
}); | ||
server.listen(common.PORT, () => { | ||
const end = 'HTTP/1.1\r\n\r\n'; | ||
const client = net.connect({port: common.PORT}, () => { | ||
client.write(`GET ${str} ${end}`); | ||
client.write(`GET / ${end}`); | ||
client.write(`GET / ${end}`); | ||
client.end(); | ||
}); | ||
}); |
2 comments
on commit 7bef1b7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this commit has broken a good number of implementations that have used invalid characters in headers.
Would you mind sharing some links to the spec that should be followed and, if possible, some tips on how to make the code compliant?
Found this link which appears to point to the spec: http://stackoverflow.com/questions/19028068/illegal-characters-in-http-headers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec is RFC 7230 (https://tools.ietf.org/html/rfc7230). Specifically, section 3.2 (https://tools.ietf.org/html/rfc7230#section-3.2). The key reason for being strict here is that there are a number of very real security issues related to being too lenient on header parsing. Specifically, code that uses multi-byte character encodings for values in header field names or values can end up with request splitting or response smuggling vulnerabilities because the multi-byte encodings get interpreted as single-byte encodings by http implementations.
Inconsistency detected.
comment:
obs-text is
%x80-FF
http_parser.c:
Real example (nginx + maxmind) with
GEOIP_CITY: Düsseldorf
- got an empty reply, so nginx will send the request to next upstream and then it will end with 502 bad gateway cause nobody replied.ping @jasnell
newly only. but there shuld be compatibility though.