1'use strict'; 2 3// Response splitting is no longer an issue with HTTP/2. The underlying 4// nghttp2 implementation automatically strips out the header values that 5// contain invalid characters. 6 7const common = require('../common'); 8if (!common.hasCrypto) 9 common.skip('missing crypto'); 10const assert = require('assert'); 11const http2 = require('http2'); 12 13// Response splitting example, credit: Amit Klein, Safebreach 14const str = '/welcome?lang=bar%c4%8d%c4%8aContentLength:%200%c4%8d%c4%8a%c' + 15 '4%8d%c4%8aHTTP/1.1%20200%20OK%c4%8d%c4%8aContentLength:%202' + 16 '0%c4%8d%c4%8aLastModified:%20Mon,%2027%20Oct%202003%2014:50:18' + 17 '%20GMT%c4%8d%c4%8aContentType:%20text/html%c4%8d%c4%8a%c4%8' + 18 'd%c4%8a%3chtml%3eGotcha!%3c/html%3e'; 19 20// Response splitting example, credit: Сковорода Никита Андреевич (@ChALkeR) 21const x = 'fooഊSet-Cookie: foo=barഊഊ<script>alert("Hi!")</script>'; 22const y = 'foo⠊Set-Cookie: foo=bar'; 23 24let remaining = 3; 25 26function makeUrl(headers) { 27 return `${headers[':scheme']}://${headers[':authority']}${headers[':path']}`; 28} 29 30const server = http2.createServer(); 31server.on('stream', common.mustCall((stream, headers) => { 32 33 const obj = Object.create(null); 34 switch (remaining--) { 35 case 3: 36 const url = new URL(makeUrl(headers)); 37 obj[':status'] = 302; 38 obj.Location = `/foo?lang=${url.searchParams.get('lang')}`; 39 break; 40 case 2: 41 obj.foo = x; 42 break; 43 case 1: 44 obj.foo = y; 45 break; 46 } 47 stream.respond(obj); 48 stream.end(); 49}, 3)); 50 51server.listen(0, common.mustCall(() => { 52 const client = http2.connect(`http://localhost:${server.address().port}`); 53 54 function maybeClose() { 55 if (remaining === 0) { 56 server.close(); 57 client.close(); 58 } 59 } 60 61 function doTest(path, key, expected) { 62 const req = client.request({ ':path': path }); 63 req.on('response', common.mustCall((headers) => { 64 assert.strictEqual(headers.foo, undefined); 65 assert.strictEqual(headers.location, undefined); 66 })); 67 req.resume(); 68 req.on('end', common.mustCall()); 69 req.on('close', common.mustCall(maybeClose)); 70 } 71 72 doTest(str, 'location', str); 73 doTest('/', 'foo', x); 74 doTest('/', 'foo', y); 75 76})); 77