Sigurnost, jedna od stvari s kojoj svi prilikom razvoja aplikacije govore, ali ju malo njih smatra ozbiljnom ili odgađa za kasnije.
S druge strane, HTTP headeri su nešto što korisnici Express.js aplikacije ne vide i onda je developerima lako zapostaviti ih i gledati na njih kao na nešto nebitno. S obzirom da headeri daju razne informacije koje osobe s lošim namjerama mogu iskoristiti jasno je zašto ipak treba voditi brigu o njima tj. informacijama koje pružaju.
Jedna od tih informacije je X-Powered-By: Express što web pregledniku govori što pokreće aplikaciju tj. na čemu se temelji. Helmet.js će, između ostalog, sakriti ovu informaciju.
Zato je cilj ovog blog posta pokazati kako na brz i jednostavan način zaštititi Express.js aplikaciju koristeći Helmet.js koji neće riješiti sve sigurnosne probleme, ali je ipak odličan početak.
Što je Helmet.js?
Helmet.js je kolekcija od 14 modula koje se brinu za sigurnost HTTP zaglavlja (headers) točnije response headera.
7 od 14 modula aktiviraju se jednom linijom koda
1 |
app.use(helmet()) |
Osim toga, svaki od tih zadanih modula moguće je individualno aktivirati
1 2 |
app.use(helmet.noCache()) app.use(helmet.frameguard()) |
ili deaktivirati
1 2 3 |
app.use(helmet({ frameguard: false })) |
Helmet.js moduli
Trenutno postoji 14 modula (defaultni označeni sa (✓)), a to su sljedeći:
Sets the Content-Security-Policy header which can help protect against malicious injection of JavaScript, CSS, plugins, and more.
2.) crossdomain
Prevents Adobe Flash and Adobe Acrobat from loading content on your site.
3.) dnsPrefetchControl (✓)
This middleware lets you disable browsers’ DNS prefetching by setting the X-DNS-Prefetch-Control header.
4.) expectCt
Tells browsers to expect Certificate Transparency. For more about Certificate Transparency and this header, see this blog post and the in-progress spec.
5.) featurePolicy
Lets you restrict which browser features can be used. For example, you can disable fullscreen or vibration APIs.
6.) frameguard (✓)
Frameguard mitigates clickjacking attacks by setting the X-Frame-Options header.
7.) hidePoweredBy (✓)
Removes the X-Powered-By header to make it slightly harder for attackers to see what potentially-vulnerable technology powers your site.
8.) hpkp
Helps you set the Public-Key-Pins header to prevent person-in-the-middle attacks. Usage of this header (and therefore this middleware) is not recommended. Be very careful when deploying this—you can easily misuse this header and cause problems. Chrome dropped support for HPKP citing risks of misuse.
9.) hsts (✓)
This module sets the Strict-Transport-Security header to keep your users on HTTPS.
10.) ieNoOpen (✓)
This middleware sets the X-Download-Options to prevent Internet Explorer from executing downloads in your site’s context.
11.) noCache
Aims to disable browser caching by setting several headers.
12.) noSniff (✓)
Helps prevent browsers from trying to guess (“sniff”) the MIME type, which can have security implications. It does this by setting the X-Content-Type-Options header to nosniff.
13.) referrerPolicy
Can control the behavior of the Referer header by setting the Referrer-Policy header.
14.) xssFilter (✓)
Sets the X-XSS-Protection header to prevent reflected XSS attacks.
Kreiranje projekta
Kreiram mapu projekta ExpressHelmet i unutar nje datoteku server.js
sa sljedećim sadržajem:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var express = require('express'); var app = express(); var port = process.env.PORT || 8080; var apiRoutes = express.Router(); apiRoutes.get('/', function(req, res) { res.json({ message: 'API radi!' }); }); // ostale GET, POST, PUT, DELETE definiraju se u nstavku // sve rute sadržavaju '/api' app.use('/api', apiRoutes); app.listen(port); console.log('API je pokrenut i koristi port:' + ' ' + port); |
Detalje o tome kako kreirati osnovni Express.js API moguće je pronaći u blog postu pod naslovom Izrada RESTful API-ja koristeći Node.js i Express.js
Ako sada pokrenem API na adresi http://localhost:8080/api unutar Google Chrome Developer alata pod tabom Network dobit ću sljedeće:
Postavljanje Helmet.js-a
Sljedećom naredbom untuar mape projekta instaliram Hellmet.js
1 |
$ npm install helmet --save |
Također, unutar server.js datoteke dodajem sljedeće:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var express = require('express'); var app = express(); var helmet = require('helmet'); var port = process.env.PORT || 8080; var apiRoutes = express.Router(); app.use(helmet()); apiRoutes.get('/', function(req, res) { res.json({ message: 'API radi!' }); }); // sve rute sadržavati će '/api' app.use('/api', apiRoutes); app.listen(port); console.log('API je pokrenut i koristi port:' + ' ' + port); |
Ako sada pokrenem API na adresi http://localhost:8080/api unutar Google Chrome Developer alata pod tabom Network dobit ću sljedeće:
Na slici iznad mogu se vidjeti headeri kojih ranije nije bilo, a to su:
1 2 3 4 5 6 |
Strict-Transport-Security: max-age=15552000; includeSubDomains X-Content-Type-Options: nosniff X-DNS-Prefetch-Control: off X-Download-Options: noopen X-Frame-Options: SAMEORIGIN X-XSS-Protection: 1; mode=block |
Također, headere mogu vidjeti i pokretanjem sljedeće naredbe:
1 |
curl -i http://localhost:8080/api |
Zaključak
Helmet.js nije “all in one” rješenje niti se njegovim postavljenjem unutar projekta može reći da je sigurnosna zaštita aplikacije gotova, ali je svakako dobar početak procesa razmišljanja o sigurnosti.