90
Node.js Security FotoHiero / pixelio.de

Node.js Security

Embed Size (px)

Citation preview

Page 1: Node.js Security

Node.js Security

FotoHiero / pixelio.de

Page 2: Node.js Security

WHO AM I?

• Sebastian Springer

• aus München

• arbeite bei Mayflower

• https://github.com/sspringer82

• @basti_springer

• Consultant, Trainer, Autor

Page 3: Node.js Security
Page 4: Node.js Security

Allgemeines JavaScript

Page 5: Node.js Security

“use strict”

Makrodepecher / pixelio.de

Page 6: Node.js Security

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.

Page 7: Node.js Security

JavaScript und Dynamik

Anne Garti / pixelio.de

Page 8: Node.js Security

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…

Page 9: Node.js Security

JavaScript und Dynamik

var b = require('./b');console.log(b.b); console.log(a);

a.jsa = 'Wert von A'; module.exports = { b: 'Wert von B'};

b.js

Ausgabe?$ node a.js Wert von B Wert von A

Page 10: Node.js Security

JavaScript und Dynamik

var b = require('./b');console.log(b.b); console.log(a);

a.jsa = 'Wert von A'; module.exports = { b: 'Wert von B'};

b.js

Ausgabe?$ node a.js HEHE!HEHE!

console.log = function () { process.stdout.write('HEHE!');};

Page 11: Node.js Security

Namespacing

No rbert L o r e n z / pixelio.de

Page 12: Node.js Security

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.

Page 13: Node.js Security

Angriffsvektoren

Reinhard Simon / pixelio.de

Page 14: Node.js Security

Angriffsvektoren

Welche Ressourcen kann ein Angreifer in unserem System attackieren?

Welche Art von Angriff kann erfolgen? Wie kann man diesen Angriffen begegnen?

Page 15: Node.js Security

Memory

Jan von Bröckel / pixelio.de

Page 16: Node.js Security

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.

Page 17: Node.js Security

Memoryrequire('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);

Page 18: Node.js Security

Memory

Page 19: Node.js Security

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,

Page 20: Node.js Security

Memory

Erstellung und Größe von Objekten kontrollieren. Benutzereingaben immer validieren und sinnvoll limitieren.

Page 21: Node.js Security

Netzwerk

Klicker / pixelio.de

Page 22: Node.js Security

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.

Page 23: Node.js Security

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.

Page 24: Node.js Security

NetzwerkHier verlassen wir Node.js und gehen ins System.

Tools: z.B. iftop

Page 25: Node.js Security

Netzwerk

Maßnahmen gegen DOS: Systeme abschirmen. Firewall-Regeln => Admin Stuff.

Ziel ist, dass die Anfragen nicht mehr bis zum System durchkommen.

Page 26: Node.js Security

NetzwerkZugriffe 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}));

Page 27: Node.js Security

Access Log

Page 28: Node.js Security

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!');});

Page 29: Node.js Security

Netzwerk

Bei nicht verschlüsselter Kommunikation kann mitgelauscht werden.

Statt http und ws sollten https und wss verwendet werden.

Page 30: Node.js Security

Speicher

Q.pictures / pixelio.de

Page 31: Node.js Security

Speicher

Langfristiger Speicher auf der Festplatte. Zum Persistieren von Informationen in Form von Dateien und Verzeichnissen.

Synchroner und asynchroner Zugriff möglich.

Page 32: Node.js Security

Speicher

Das Problem: Die Festplatte läuft voll.

Logdateien, Temporärdateien, Datenbankeinträge, …

Page 33: Node.js Security

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)

Page 34: Node.js Security

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);});

Page 35: Node.js Security

CPU

Tim Reckmann / pixelio.de

Page 36: Node.js Security

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.

Page 37: Node.js Security

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);

Page 38: Node.js Security

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

Page 39: Node.js Security

Kindprozesse

Helene Souza / pixelio.de

Page 40: Node.js Security

Kindprozesse

child_prozess- oder cluster-Modul nutzen, um Kindprozesse zu forken, um Bearbeitung auszulagern. Der Webserver kann weitere Anfragen annehmen und blockiert nicht.

Page 41: Node.js Security

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);}

Page 42: Node.js Security

Kindprozesse2015-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

Page 43: Node.js Security

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.

Page 44: Node.js Security

Und wenn das nicht reicht?

Page 45: Node.js Security

Load Balancing

CC-BY-SA-3.0 / Amazon Web Services LLC

Page 46: Node.js Security

Berechtigung

Thorben Wengert / pixelio.de

Page 47: Node.js Security

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.

Page 48: Node.js Security

Berechtigung

$ sudo node app.js

No! Just no!

Page 49: Node.js Security

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)

Page 50: Node.js Security
Page 51: Node.js Security

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

Page 52: Node.js Security

NPMJeder darf mitmachen.

$ npm adduser Username: test Password: Email: (this IS public) [email protected]

$ 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

Page 53: Node.js Security

npm publish

Ups, jetzt hab ich doch tatsächlich meine Datenbankkonfiguration und sämtliche Passwörter

publiziert…

McRommy / pixelio.de

Page 54: Node.js Security

NPMpackage.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.

Page 55: Node.js Security

NPM

Keine Qualitätssicherung für das NPM-Repository.

Keine Tests erforderlich.

Keine QA erforderlich.

Keine Sicherheit.

Page 56: Node.js Security

OK, und warum ist das jetzt so gefährlich?

Jörg Blanke / pixelio.de

Page 57: Node.js Security

NPM

Admin-Berechtigung für globale Installation erforderlich, weil die Software in ein Systemverzeichnis installiert wird.

$ sudo npm install -g karma-cli

Page 58: Node.js Security

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.

Page 59: Node.js Security

NPM - Scripts

Page 60: Node.js Security

NPM

NPM kann mit einer Reihe von Skripten als Build-Tool verwendet werden. Diese Skripte können allerdings auch für

Angriffe missbraucht werden.

Page 61: Node.js Security

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"}

Page 62: Node.js Security

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.jsmodule.exports = function () { console.log('Noooo!'); };

Page 63: Node.js Security

Node in Webapplikationen

Andreas Hermsdorf / pixelio.de

Page 64: Node.js Security

Express

Frederick Kühne / pixelio.de

Page 65: Node.js Security

Express

Aktuell das populärste Web-Application Framework für Node.js. Stellt Request/Response-Handling, Routing und

Middleware zur Verfügung.

Page 66: Node.js Security

Middleware?

Funktionen, die sich zwischen Request und Response hängen können.

z.B. Logger

Page 67: Node.js Security

Express

Page 68: Node.js Security

Express

app.set('x-powered-by', false);

Page 69: Node.js Security

Helmethttps://github.com/helmetjs/helmet

blitzmaerker / pixelio.de

Page 70: Node.js Security

Helmet

Sammlung von Middleware-Komponenten, um Express sicherer zu machen.

Setzt einige hilfreiche HTTP-Header.

Page 71: Node.js Security

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.

Page 72: Node.js Security

Helmet

Die Features können auch getrennt voneinander eingesetzt werden.

app.use(helmet.hidePoweredBy());

Page 73: Node.js Security

Helmet

$ npm install --save helmet

var express = require('express');var helmet = require('helmet'); var app = express();app.use(helmet());

Page 74: Node.js Security

SQL Injection

Jörg Brinckheger / pixelio.de

Page 75: Node.js Security

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;

Page 76: Node.js Security

SQL Injectionapp.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;

Page 77: Node.js Security

SQL Injectionapp.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

Page 78: Node.js Security

XSS

Michael Loeper / pixelio.de

Page 79: Node.js Security

XSS

Cross-Site Scripting. Benutzer speichert JavaScript-Code, der auf anderen Systemen ausgeführt wird.

Kann z.B. für Identitätsdiebstahl verwendet werden.

Page 80: Node.js Security

XSSapp.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>

Page 81: Node.js Security

XSShttp://localhost:8080/list?id=%3Cscript%3Ealert(%27foo

%27)%3C/script%3E

Page 82: Node.js Security

XSS

Sanitizer, um Werte korrekt zu escapen.

npm install sanitizer

var id = require('sanitizer').escape(req.query.id);

Page 83: Node.js Security

XSS

Page 84: Node.js Security

CSRF

FW-Fotografie / pixelio.de

Page 85: Node.js Security

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.

Page 86: Node.js Security

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();});

Page 87: Node.js Security

node-inspectorProfiling und Debugging für Node-Applikationen.

Page 88: Node.js Security

Node Security Project

https://nodesecurity.io/

NPM Audits. Advisories und Fixes für die Projekte. Public API für die Audit Datenbank.

Page 89: Node.js Security

Fragen?

Rainer Sturm / pixelio.de

Page 90: Node.js Security

KONTAKT

Sebastian Springer [email protected]

Mayflower GmbH Mannhardtstr. 6 80538 München Deutschland

@basti_springer

https://github.com/sspringer82