Sigurnosna analiza NodeJS platforme za izradu skalabilnih aplikacija

Izvor: SIS Wiki
Skoči na: orijentacija, traži

Članovi: Danijel Vincijanović

--Danijel Vincijanović 15:32, 6. studenog 2015. (CET)

Sadržaj

Uvod

Javascript se godinama koristi na klijentskoj strani kako bi pružio bogatije i kvalitetnije korisničko iskustvo. Zadnjih nekoliko godina pojavili su se interesi za korištenjem javascripta ne samo na klijentskoj strani već i na server strani. Stoga danas postoje SSJS (Server-side Javascript) mogućnosti korištene kod servera baza podataka poput CouchCB, servera datoteka kao Opera Unite i web servera (Node.js)

Node JS je platforma za razvoj skalabilnih web aplikacija. Izrađen je na Google V8 Javascript sustavu uz implementaciju web poslužiteljskog dijela. Kao takav sadrži web poslužiteljsku podršku pa nije potrebno drugo web poslužiteljsko programsko rješenje. Ideja na kojoj se zasniva Node je non-blocking i event-driven I/O model koji ga čine jednostavnim i brzim. Kreator Node-a - Ryan Dahl, težio je kreiranju real-time web aplikacija sa push tehnologijom, a nit vodilja su mi bile aplikacije poput Gmail-a. Real-time web aplikacije sa mogućnosti push tehnologije preko web socketa čine srž Node js-a. Ono što je važno napomenuti je kako Node.js nije nova platforma koja će zavladati web svijetom već je ona tu da upotpuni određene potrebe. Slabost Node.js-a je u obavljanju procesorski intezivnih zadataka gdje će sve njegove prednosti biti zagušene. Rad na samo jednoj dretvi je razlog zbog kojega procesorski intezivni zadaci nisu poželjni jer bi stvarali probleme za sve klijente koji šalju zahtjev koji će biti blokirani sve dok zadatak nije završen. Stoga je Node.js najbolje iskoristiti kada razvijamo aplikaciju koja će biti zadužena za upravljanje velikim brojem povezivanja gdje se ne obavljaju procesorski teške operacije.

Node donosi određene sigurnosne prednosti u odnosu na ostale paradigme tradicionalnog razvoja server strane. Npr. sljedeći kod prikazuje kostur jednostavnog web servera kojemu je zadatak da radi upravo ono za što je konfiguriran i ništa više od toga za razliku od drugih web servera poput Tomcat, Apache ili IIS. Naime, ovakav način razvoja web servera predstavlja prednost jer povećanjem broja mogućnosti web servera, povećava se i mogućnost napada. [1]

Each new developer hire is a potential set of vulnerabilities, patch them with education. — Lift Security Team

GitHub repozitorij - NodeJS Security projekt

Hello World

Za početak ćemo se držati programerske tradicije i izraditi aplikaciju koja će ispisati 'Hello World'. Server sluša port 8080.

http = require('http');

http.createServer(function(request, response) {
	response.writeHead(200, {'Content-Type': 'text/html'});
	response.write('<p>Hello World</p>');
	response.end();
}).listen(8080);

console.log('Server running at http://127.0.0.1:8080/');

PHP verzija 'Hello World' aplikacije:

<?php echo "<p>Hello World</p>"; ?>

Zatim ćemo usporediti brzinu kojom će Node.js i Apache server + PHP obraditi 100 000 zahtjeva na 'Hello World' aplikaciju. Testiranje radimo pomoću Apache Bench alata. Apache Bench ćemo instalirati i pokrenuti sljedećim naredbama u terminalu:

$sudo aptitude install apache2-utils
$ab -r -n 100000 -c 100 <url>

Umjesto <url> stavljamo url kojega testiramo. Prethodna naredba će izvršiti 100 000 zahtjeva sa ukupno 1000 zahtjeva koji će se desiti u isto vrijeme. Rezultati dobiveni testiranjem Node.js-a:

Concurrency Level:      1000
Time taken for tests:   10.352 seconds
Complete requests:      100000
Failed requests:        0
Total transferred:      11800000 bytes
HTML transferred:       1800000 bytes
Requests per second:    9659.89 [#/sec] (mean)
Time per request:       103.521 [ms] (mean)
Time per request:       0.104 [ms] (mean, across all concurrent requests)
Transfer rate:          1113.15 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   73 450.4      0    7016
Processing:     3   22  22.5     21     433
Waiting:        3   22  22.5     21     433
Total:          7   95 459.1     21    7441

Percentage of the requests served within a certain time (ms)
  50%     21
  66%     24
  75%     28
  80%     29
  90%     33
  95%     68
  98%   1030
  99%   1220
 100%   7441 (longest request)

Sada ćemo ponoviti isto sa Apache serverom i PHP-om nakon čega dobivamo sljedeće rezultate:

Concurrency Level:      1000
Time taken for tests:   25.685 seconds
Complete requests:      100000
Failed requests:        0
Total transferred:      20600000 bytes
HTML transferred:       1800000 bytes
Requests per second:    3893.35 [#/sec] (mean)
Time per request:       256.848 [ms] (mean)
Time per request:       0.257 [ms] (mean, across all concurrent requests)
Transfer rate:          783.23 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   13 158.2      0    3004
Processing:     2   75 947.7      6   25659
Waiting:        1   75 947.7      6   25659
Total:          5   87 1004.3      6   25677

Percentage of the requests served within a certain time (ms)
  50%      6
  66%      6
  75%      7
  80%      7
  90%      7
  95%      8
  98%     11
  99%   1006
 100%  25677 (longest request)

Zaključujemo kako Node može obraditi više zahtjeva u jedinici vremena što predstavlja njegovu snagu. Kada bi u aplikaciju dodali određeni procesorski zahtjevniji zadatak Node bi izgubio svoju prednost i trebalo bi mu znatno više vremena da obradi sve zahtjeve jer bi obradom jednog drugi bili blokirani. Node zahvaljujući svojoj arhitekturi koristi malo sistemskog resursa za obradu zahtjeva. Stoga, utvrđivanjem zahtjeva aplikacije možemo saznati pruža li nam Node željene prednosti te da li ga ima smisla koristiti u razvoju iste.

Kostur web servera

Slijedi primjer prilično jednostavnog kostura web servera koji dohvaća i prikazuje datoteke ovisno o putanji. Ukoliko takve ne postoje vraća 404 - Not Found. Server sluša port 8080.

var http = require("http");
var fs = require('fs');
var url = require('url');

http.createServer(function (request, response) {
	var path = url.parse(request.url).pathname.substr(1);

	fs.readFile(path, function(error, data){
		if (error){
			rSesponse.writeHead(404, {'Content-Type':'text/html'});
			response.end();
		}

		else {
			response.writeHead(200, {'Content-Type':'text/html'});
			response.write(data.toString());
			response.end();
		}
	});

}).listen(8080);

console.log('Server running at http://127.0.0.1:8080/');

Cross Site Scripting

Cross Site Scripting (XSS) je napad koji se dogodi kada stranica pokazuje podatke koji nisu prethodno provjereni. Na taj način napadač može u stranicu unijeti zlonamjerni Javascript kod koji će se izvršiti prilikom korisnikovog posjeta stranici. XSS ranjivost napadaču omogućuje pristup povjerljivim informacijama, kolačićima, slanje lažnih zahtjeva itd.. Postoje dvije glavne vrste XSS napada: [2]

Reflected XSS

Kod Reflected XSS-a zlonamjerna skripta se šalje korisniku tako što korisnik sam pošalje zahtjev prema web aplikaciji. Napadač na taj način prevari korisnika da sam izvrši napad putem email-a, društvenih mreža ili bilo koje druge web stranice. Rezultat toga je da korisnik pristupi zlonamjernoj poveznici i potvrdi formu ili napravi zahtjev prema malicioznoj stranici. [2]

Sljedeći dijagram prikazuje na koji način se izvršava reflected XSS:

Xss1.png

Na dijagramu možemo vidjeti kako je implementiran pretraživač na endpointu /search?=unos Napadač na ovaj način može saznati da se unos ne provjerava čime se otvaraju mogućnosti za napad. Napad se može izvršiti na način da napadač na svojoj stranici postavi poveznicu sa zlonamjernim kodom prema ranjivoj stranici. Napadač je vlasnik /index.html stranice koja izgleda ovako:

<html>
  <a href="https://site.com/search?q=<script>alert('hacked')</script>">
    Click Here
  </a>
</html>

Ukoliko korisnik dođe na tu stranicu i klikne na poveznicu preglednik će napraviti zahtjev prema toj stranici zajedno sa malicioznim Javascript kodom. U ovome slučaju 'maliciozni' kod je samo alert funkcija, ali napadač može napraviti bilo koju drugu radnju pomoću Javascripta. Također je moguće napad izvršiti bez poveznice već automatskim preusmjeravanjem korisnika na ranjivu stranicu.

Stored XSS

Kod Stored XSS napada maliciozna skripta se unosi u bazu ranjive web aplikacije. Uneseni maliciozni kod će se izvršiti kada korisnik dođe na određenu rutu stranice koja dohvaća maliciozni kod iz baze i ubacuje ga u HTML.

Xss2.png

Na dijagramu je vidljivo da je omogućen POST zahtjev na endpoint /comment. Stranica koja je XSS ranjiva ne provjerava korisnikov unos pa je tako omogućeno napadaču da unese maliciozni kod. Nakon toga korisnik dođe na stranicu i šalje zahtjev kojim se dohvaća maliciozni kod iz baze. [2]

XSS - zaštita

exports.escape = function escape(html){
  var result = String(html)
    .replace(/&/g, '&')
    .replace(/</g, '<')
    .replace(/>/g, '>')
    .replace(/"/g, '"');
  if (result === '' + html) return html;
  else return result;
};
Kontekst Primjer koda Enkodiranje
HTML Entity <span>NEPOVJERLJIVI SADRŽAJ</span> Promijeniti & u &amp
Promijeniti < u &lt
Promijeniti > u &gt
Promijeniti " u &quot
Promijeniti ' u &#x27
Promijeniti / u &#x2F
HTML enkodiranje atributa <input type='text' name='name' value='NEPOVJERLJIVI SADRŽAJ' escape-ati sve znakove (osim alfanumeričkih) sa HTML entitetom formata &#xHV; gdje HV predstavlja hex. vrijednost.
URl enkodiranje <a href='/site/search?value= 'NEPOVJERLJIVI SADRŽAJ'> klikni me </a> escape-ati sve znakove (osim alfanumeričkih) sa ASCII vrijednošću manjom od 256 sa HTML entitetom formata &#xHV gdje HV predstavlja hex. vrijednost
Javascript enkodiranje <script>var currentValue='NEPOVJERLJIVI SADRŽAJ';</script> <script>someFunction('NEPOVJERLJIVI SADRŽAJ');</script> Osigurati da su varijable pod navodnicima. escape-ati sve znakove (osim alfanumeričkih) sa ASCII vrijednošću manjom od 256 sa \uXXXX unicode formatom gdje je X integer ili xHV format gdje je HV hex. vrijednost
CSS enkodiranje <div style="width: NEPOVJERLJIVI SADRŽAJ;">Selection</div> escape-ati sve znakove (osim alfanumeričkih) sa ASCII vrijednošću manjom od 256 sa \HV formatom gdje je HV hex. vrijednost


Detaljnije o zaštiti od XSS napada - https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet

Server-Side JavaScript Injection

Node je naslijedio kontroverznu javascript funkciju eval. Sintaksa funkcije eval je: eval(string) Funkcija eval izvršava proslijeđeni argument

 //nakon što se izvrši naredbeni redak varijabla 'x' će sadržavati broj 4. 
var x = eval("2 + 2"); 

Eval() funkcija predstavlja ranjivost na strani klijenta tako što je moguće napraviti Cross-site Scripting (XSS) napad, a sada je pomoću iste moguće napraviti server side injection. Prema OWASP-u, XSS se trenutno nalazi na drugom mjestu opasnih prijetnji web aplikacija.

Kako bi provjerili je li web aplikacija ranjiva na server side injection kao request ćemo poslati:

response.end('Ranjiv sam')

Nakon toga će server izvršiti naredbu i ispisati 'Ranjiv sam' kao tijelo HTTP odgovora. Ukoliko uspijemo na ovaj način dobiti odgovor od servera znači da je on ranjiv. [5]

SSJI DoS

Kako se Node izvodi na jednoj dretvi jednostavna greška može prouzročiti Denial of Service (DOS). Zbog toga je moguće srušiti server na način da kao request proslijedimo npr. while(1) gdje će eval funkcija izvršiti takvu naredbu i server će koristiti 100% svoga procesorskog vremena na beskonačnu petlju i time će biti u nemogućnosti procesuirati bilo kakav zahtjev sve dok administrator ručno ne resetira proces. U ovome slučaju napadač ne mora izvršiti milijune zahtjeva kako bi onesposobio server već je potreban samo jedan HTTP zahtjev i server je srušen. Alternativa prethodne verzije bi bilo ubijanje ili izlazak iz procesa: process.exit() ili process.kill(process.pid) [4]

SSJI Pristup lokalnim datotekama

Sljedeća opasnost eval() funkcije je mogućnost pristupa lokalnim datotekama. Pristup datotekama sustava je moguć uključivanjem 'fs' modula. Moduli se mogu uključivati bilo kada što otvara mogućnosti napadaču da ju uključi i iskoristi za pristup datotekama. Na ovaj način je moguće dobiti popis svih datoteka u sustavu te ih čitati ili pisati u njih.

Kako bi dobili popis svih datoteka unutar trenutnog direktorija poslati ćemo sljedeće:

response.end(require('fs').readdirSync('.').toString())

Nakon toga je jednostavno otvoriti ili mijenjati postojeće datoteke pomoću naredbi 'fs' modula. Valja napomenuti kako funkcije poput setTimeout() i setInterval() također mogu primiti kod u stringu kao argument te time prouzročiti iste probleme kao i eval() funkcija. [4]

Video primjer Server Side Injection-a: https://www.youtube.com/watch?v=krOx9QWwcYw

SSJI - zaštita

ReDoS

ReDos – Regular expression Denial of Service je vrsta Denial of Service napada koji leži na činjenici da se izvršavanje regex može znatno usporiti gdje je brzina izvršavanja eksponencijalno povezana sa korisnikovim unosom. Na ovaj način se napadaču otvara mogućnost da onemogući server na neko vrijeme. Algoritam regexa provjerava sve moguće kombinacije dok ne pronađe poklapanje pa tu završava ili drugi slučaj kada prolazi kroz sve kombinacije i ne pronađe poklapanje. Što je korisnikov unos veći to je i veći broj mogućnosti koje se moraju provjeriti. Npr. Za regex ^(a+)+$ i unos 'aaaa' postoji ukupno 16 mogućnosti dok za unos 'aaaaaaaaaaaaaaaa' i isti regex postoji ukupno 65536 mogućnosti te se taj broj duplo povećava sa svakim dodatnim slovom 'a'. [10]

Za regex:

/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/

provjeriti ćemo vrijeme koje je potrebno da se ispitaju sljedeći unosi:

'dvincija@foi.hr' => validan e-mail pa je potrebno kratko vrijeme za testiranje

'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@bbbbbbbbbbbbbbbbbbbbbbbbbb.5555555555555555555555555555555555555555555555555555{' => nije validan e-mail pa je potrebno puno više vremena dok se ispitaju sve mogućnosti

Dobiveni rezultat testiranja:

true 
[ 0, 4435278 ] 
false 
[ 3, 351614980 ] 

ReDoS - zaštita

Korištenje safe-regex paketa je vrlo jednostavno. Prvo je potrebno instalirati paket naredbom: [19]

$ npm install safe-regex 

Zatim u kodu pozivom jedne funkcije doznajemo da li je regex potencijalno katastrofalan:

var safe  = require('safe-regex');
var regex = /^[a-z0-9_-]{3,16}$/;

console.log(safe(regex));

Node Package Manager

NPM je package manager za Javascript te kao takav čini neizostavni dio Node aplikacije. Komponente poput biblioteka, frameworka i ostalih softverskih modula u većini slučajeva za pokretanje zahtjevaju puna prava pa valja biti oprezan. Važno je znati kako neke komponente koje instaliramo putem npm-a mogu biti ranjive odnosno sadržavati nesiguran kod i kao takve predstavljati napadaču priliku za napad. Oko 14% npm paketa sadrži određene ranjivosti, a ova brojka je proizašla iz testiranja velikog broja najpopularnijih paketa. Napadač na taj način može kreirati i pokrenuti skripte u raznim stadijima instalacije i korištenja paketa, također može čitati, brisati, ažurirati i brisati datoteke sa sustava kao i prikupljati osjetljive podatke.

Kako bi spriječili da se ovo dogodi aplikacije ne treba pokretati sa root privilegijama. Potrebno je koristiti module koji sadrže statičku analizu koda, provedene unit testove i recenzije. Preporučljivo je pregledati kod da li pristupa nekim datotekama ili bazi podataka te prije korištenja istražiti koliko je popularan paket i koja je trenutna verzija. Osim toga, poželjno je pratiti github repozitorije na kojima možemo saznati ukoliko se otkriju određene ranjivosti.

Korisni alati za analizu node web aplikacije i npm paketa:

http://retirejs.github.io/retire.js/

https://snyk.io/

Insecure Direct Object References

Nesiguran direktan pristup prema objektima poput datoteka, direktorija ili ključevima baze podataka. Bez kontrole pristupa napadač može manipulirati navedenim referencama i tako ostvariti neautorizirani pristup podacima. Ukoliko web aplikacija koristi ime ili određeni ključ objekta prilikom generiranja stranice te ne provjerava autorizaciju korisnika prema ciljanom objektu tada napadač može doći do nesigurnih referenci. Napadač tada može iskoristiti ranjivost i mijenjajući parametre doći do podataka za koje nema ovlašten pristup.

Kao primjer možemo navesti web aplikaciju koja prilikom generiranja web stranice dohvaća 'id' korisnika koji je proslijeđen kao url parametar te zatim dohvaća podatke toga korisnika. Na ovaj način napadač može promijeniti url i doći do podataka drugih korisnika. [8]

app.get('/:id', function (request, response) { 
	var id = request.params.id;
	// ...dohvati korisnika
	response.render('index.jade', {user: user});
} 

Ovu ranjivost možemo otklonuti kontrolom pristupa korisnika određenom objektu. Sigurniji način od ovoga je dohvaćanje potrebnih ključeva iz sesije.

Brute Force

Brute force napad predstavlja sustavno pronalaženje svih mogućih kandidata za rješenje i uzastopnim pokušavanjem svakog od njih. Ovakav napad je jednostavan za implementaciju i često se koristi za probijanje zaporki ili raznih enkripcija. Ograničenje brute force napada su vrijeme i resursi koji su potrebni za rješavanje problema jer oni rastu povećanjem broja mogućih kandidata za rješenje.

Kod web aplikacija login endpointovi su prilika za napadača za brute force napad. Kako bi spriječili brute force moramo na neki način omogućiti veliki broj requestova na način da ih ograničimo na određeni broj ili da eksponencijalno povećavamo vrijeme potrebno za svaki dodatni zahtjev. U ovom slučaju ćemo koristiti express-brute paket (https://www.npmjs.com/package/express-brute). Ukoliko se dogodi veći broj zahtjeva prema ruti '/login' server će vratiti 429 grešku, a vrijeme između dva zahtjeva će se povećavati u fibonaccijevom nizu čime se onemogućuje brute force napad. [8]

Instalacija express-brute paketa:

$ npm install express-brute

Jednostavan primjer implementacije express-brute paketa:

var ExpressBrute = require('express-brute'),
var express      = require('express');
var store        = new ExpressBrute.MemoryStore(); // MemoryStore za pohranu podataka lokalno, koristiti samo za razvoj! 
var bruteforce   = new ExpressBrute(store);
var app          = express();

//ukoliko se dogodi veći broj zahtjeva prema /login ruti server će vratiti 429 grešku
app.post('/login', bruteforce.prevent,  
	function (req, res, next) {
		res.send('Success!');
	}
);

Cross-site Request Forgery

CSRF predstavlja vrstu napada koji se izvodi posredstvom klijentskog programa. Direktno sa zloćudne stranice moguće je pokrenuti zahtjev prema drugoj ranjivoj stranici u ime korisnika koji se koristi web preglednikom. Takva zloćudna stranica sadrži kod za pokretanje određenog zahtjeva koji će se automatski učitati i pokrenuti prilikom učitavanja stranice. Stranica može postati ranjivom na CSRF napad ukoliko se ne izvode provjere sigurnosti i identiteta korisnika gdje će se zahtjev poslan sa zloćudne stranice obraditi kao da ga je poslao klijent.

Da bi napad imao učinka koriste se GET i POST zahtjevi. GET zahtjev je predviđen za dohvat podataka te kao takav se ne provjerava dovoljno što otvara mogućnost podmetanja GET zahtjeva koji će izazvati štetne izmjene podataka na stranici. CSRF napadi se najčešće izvode putem internetskih foruma koje koristi veliki broj korisnika. [13]

CSRF napad se može izvoditi pomoću: [14]

CSRF - zaštita

CSRF - zaštita pomoću tokena

Korištenjem jedinstvenog, tajnog i nasumičnog tokena koji se nalazi skriven u HTML-u web aplikacije moguće je otklonuti prijetnje od CSRF napada. Takav token se nakon poslanog zahtjeva provjerava na serverskoj strani.

Način rada CSRF tokena:

  1. Server šalje token klijentu
  2. Klijent šalje zahtjev server zajedno sa tokenom
  3. Server prihvaća zahtjev ukoliko je token validan

CSRF tokene ne smije se moći dohvatiti AJAX-om, odnosno nije preporučljivo kreirati rutu /csrf samo kako bi dohvatili token. Ukoliko stranica ne podržava CORS onda ne postoji mogućnost da napadač dođe do CSRF tokena.

Instalacija csurf paketa:

$ npm install csurf

Zatim u aplikaciji dodamo sljedeći kod pomoću kojega ćemo generirati token za formu na klijentskoj strani: [18]

var express      = require('express');
var cookieParser = require('cookie-parser')
var bodyParser   = require('body-parser')
var csrf         = require('csurf')
var app          = express();

// postavljanje middleware-a
var csrfProtection = csrf({ cookie: true });
var parseForm      = bodyParser.urlencoded({ extended: false });

// kako bi csurf funkcionirao potrebno je prvo inicijalizirati session middleware ili cookie-parser
// ova linija je potrebna jer je "cookie" true u csrfProtection-u. 
app.use(cookieParser());

// postavljanje /form rute
// GET zahtjev će prikazati traženu stranicu (pogled) i proslijediti joj csrf token koji ćemo kasnije koristiti u formi
app.get('/form', csrfProtection, function(req, res) { 
     res.render('form', { csrfToken: req.csrfToken() });
});

// Potvrdom forme izvršava se POST zahtjev prema /process ruti zajedno sa tokenom i ostalim podacima forme
app.post('/process', parseForm, csrfProtection, function(req, res) {
     res.send('data is being processed');
});

Ovime smo dovršili serversku stranu. Sada je potrebno u pogledu definirati formu koja će imati skriveno polje sa dobivenim tokenom: (napomena: način prosljeđivanje vrijednosti tokena u skriveno polje ovisi o korištenom template engine-u, u našem slučaju to je JADE)

form(action="/process", method="POST")
   input(type="hidden", name="_csrf", value="#{csrfToken}")
   input(type="text", name="text">
   | Insert data
   button(type="submit) Submit

Konfiguriranje HTTP zaglavlja

Konfiguriranje HTTP zaglavlje na web serverima Apache ili nginx se može podesiti u samoj konfiguraciji web servera. Konfiguriranje HTTP zaglavlja u Node-u se izvršava u kodu aplikacije. HTTP zaglavlja koja je potrebno podesiti: [11]

Prethodno navedena konfiguriranja se jednostavno mogu podesiti korištenjem Helmet paketa. https://www.npmjs.com/package/helmet

Instalacija helmet npm paketa:

$ npm install helmet --save

Zatim u aplikaciji dodamo sljedeći kod kojim ćemo konfigurirati HTTP zaglavlje: [17]

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

U zadanim postavkama helmet paket ne uključuje konfiguriranje Content-Security-Policy, HTTP Public Key Pinning i No-Cache zaglavlja. Budući da Content-Security-Policy zaglavlje može uvelike spriječiti XSS i ostale unose malicioznog koda u stranicu konfigurirati ćemo ga u nastavku. Konfiguriranjem CSP zaglavlja omogućen nam je whitelisting izvora stranice. Npr. možemo znati da je skripta sa stranice https://apis.google.com/js/plusone.js povjerljiva te da ne sadrži maliciozni kod, ali to preglednik ne može znati već će on učitati i izvršiti sve skripte koje mu damo. [20] Zbog toga postoji CSP zaglavlje kojim ćemo definirati kojim izvorima vjerujemo te ćemo samo od njih dopuštati učitavanje datoteka: [17]

app.use(helmet.csp({ 
  directives: {
    defaultSrc: ["'self'", 'default.com'],
    scriptSrc: ["'self'", "'unsafe-inline'"],
    styleSrc: ['style.com'],
    imgSrc: ['img.com', 'data:'],
    sandbox: ['allow-forms', 'allow-scripts'],
    reportUri: '/report-violation',
    objectSrc: []
  }
}));

Literatura

  1. Node.js službena stranica - https://nodejs.org/en/
  2. Secure node apps against owast top 10 - http://scottksmith.com/blog/2015/06/22/secure-node-apps-against-owasp-top-10-cross-site-scripting/
  3. XSS Prevention Cheat Sheet - https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
  4. Server side javascript injection - https://media.blackhat.com/bh-us-11/Sullivan/BH_US_11_Sullivan_Server_Side_WP.pdf
  5. Node.js Security - the good, bad and ugly - http://bishankochher.blogspot.hr/2011/12/nodejs-security-good-bad-and-ugly.html
  6. Javascript injection detection - https://blog.gdssecurity.com/labs/2015/4/15/nodejs-server-side-javascript-injection-detection-exploitati.html
  7. OWASP Node.js Goat Project - https://www.owasp.org/index.php/Projects/OWASP_Node_js_Goat_Project
  8. OWASP Top 10 Node Goat Tutorial - http://nodegoat.herokuapp.com/tutorial
  9. Udemy Node JS Security -https://www.udemy.com/nodejs-security-pentesting-and-exploitation
  10. Regular expression dos and Node.js - https://blog.liftsecurity.io/2014/11/03/regular-expression-dos-and-node.js
  11. Node.js Security Checklist - https://blog.risingstack.com/node-js-security-checklist
  12. Simple steps to secure your express Node application - http://scottksmith.com/blog/2014/09/04/simple-steps-to-secure-your-express-node-application/
  13. Understanding CSRF - https://github.com/pillarjs/understanding-csrf
  14. CSRF - http://www.cert.hr/sites/default/files/NCERT-PUBDOC-2010-04-297.pdf
  15. Lift Security Blog - https://blog.liftsecurity.io/
  16. Jade - Template Engine - http://jade-lang.com/
  17. NPM Helmet paket - https://www.npmjs.com/package/helmet
  18. NPM csurf paket - https://www.npmjs.com/package/csurf
  19. NPM safe-regex paket - https://www.npmjs.com/package/safe-regex
  20. Content-Security-Policy - http://www.html5rocks.com/en/tutorials/security/content-security-policy/

tl;dr

Osobni alati
Imenski prostori
Inačice
Radnje
Orijentacija
Traka s alatima