Articles

CORS, XSS și CSRF cu exemple în 10 minute

Acest articol ar trebui să fie punctul dumneavoastră de intrare pentru standardele de securitate web existente, cele mai frecvente atacuri web și metodele de prevenire a acestora. La final, veți afla, de asemenea, cum și de ce Samy a fost eroul tuturor (cu excepția lui Rupert Murdoch, cred)

Cross-origin resource sharing, sau CORS, este caracteristica de securitate a IE10+, Chrome 4+, Firefox 3.5+ sau aproape fiecare versiune de browser lansată după 2012, cu excepția Opera Mini.

Când CORS este configurat pe un server care este disponibil pe domeniul website.com, atunci resursele din acel domeniu care sunt solicitate prin AJAX trebuie să fie inițiate din resurse care sunt servite din același domeniu.
CORS

Cu alte cuvinte, dacă activăm CORS pe domain-b.com și îl configurăm pentru a permite doar cererile GET din domeniul domain-b.com, atunci dacă doriți să utilizați imaginea disponibilă sub https://domain-b.com/images/example.png în canvas pe site-ul dvs. web care este găzduit pe domain-a.com, atunci acea imagine nu va fi încărcată pentru majoritatea vizitatorilor dvs.
Resursele dvs. protejate de CORS vor fi în continuare disponibile atunci când vor fi solicitate de orice instrument sau browser care nu respectă CORS policy.

Configurarea CORS

CORS sunt dezactivate în mod implicit, ceea ce înseamnă că nu există un manager de server adecvat care să configureze CORS, ceea ce înseamnă că nu puteți accesa resurse de origine diferită în XHR-ul dvs. Practic, dacă nu faceți nimic sau dacă activați în mod specific CORS doar pentru anumite domenii, atunci orice cerere AJAX care încearcă să acceseze resursele dvs. va fi respinsă deoarece browserele web sunt respectuoase față de CORS policy.
Acesta este motivul pentru care întâmpinați problema CORS atunci când începeți să dezvoltați SPA folosind VueJS și NodeJS. Aplicația dvs. VueJS este găzduită pe http://localhost:8080 și atunci când încercați să accesați aplicația server NodeJS pe http://localhost:8000 veți obține „No Access-Control-Allow-Origin header is present” deoarece acestea sunt două ORIGINS diferite (combinație de PROTOCOL, HOST și PORT).

Corectul cool pentru problema CORS în modul de dezvoltare VueJS este de a seta proxy-ul devServer în fișierul vue.config.js după cum urmează:

module.exports = { ... devServer: { proxy: 'http://localhost:8000', }, ...}
Intră în modul fullscreen Ieși din modul fullscreen

Pentru a configura CORS în producție, trebuie să adăugați un ascultător corespunzător pentru cererea OPTIONS. Acest ascultător ar trebui să trimită răspunsul 200 cu no body, dar cu Headers care va defini politica CORS dorită:

Access-Control-Allow-Origin: https://domain-b.comAccess-Control-Allow-Methods: GET
Intrați în modul fullscreen Ieșiți din modul fullscreen

Pentru mai multe informații despre cum să configurați CORS verificați https://enable-cors.org/index.html, iar pentru a intra mai adânc în CORS policyverificați https://livebook.manning.com/book/cors-in-action/part-1/

XSS

XSS înseamnă Cross Site Scripting și este un tip de atac prin injecție. Acesta se află pe locul 7 din primele 10 vulnerabilități identificate de OWASP în 2017. Cross site scripting este metoda prin care atacatorul injectează un script malițios într-un site web de încredere. (secțiune actualizată, mulțumiri Sandor) Există 3 tipuri de astfel de atacuri.

  1. Stored XSS – Vulnerabilitate care provine din intrările neprotejate și neprotejate ale utilizatorilor, care sunt stocate direct în baza de date și afișate altor utilizatori
  2. Reflected XSS – Vulnerabilitate care provine din valorile neprotejate și neprotejate din URL-uri care sunt folosite direct în paginile web
  3. DOM based XSS – Similar cu XSS reflectat, valori neprotejate și neprotejate de la URL-uri folosite direct în paginile web, cu diferența că DOM based XSS nici măcar nu merge pe partea serverului

Atac

1. Stored XSS

Iată un exemplu de atac. Atacatorul vine pe site-ul dvs. web și găsește un câmp de intrare neprotejat, cum ar fi câmpul de comentarii sau câmpul de nume de utilizator și introduce un script malițios în locul valorii așteptate. După aceea, ori de câte ori acea valoare ar trebui să fie afișată altor utilizatori, acesta va executa un cod malițios. Scriptul malițios poate încerca să vă acceseze contul pe alte site-uri web, poate fi implicat într-un atac DDoS sau similar. Reprezentare vizuală(sursa geeksforgeeks.org):

XSS example

2. XSS reflectat

XSS reflectat este un atac care are loc atunci când atacatorul descoperă pagina cu o astfel de vulnerabilitate, de exemplu:

URL așteptat: https://mywebpage.com/search?q=javascript
URL malițios: https://mywebpage.com/search?q=<script>alert('fortunately, this will not work!')</script>

<body>...<div> showing results for keyword <script> document.write(window.location.href.substr(window.location.href.indexOf('q=') + 2))</script></div>......JavaScript results......</body>
Intră în modul fullscreen Iese din modul fullscreen

După descoperire, atacatorul momește utilizatorul să dea click pe un astfel de URL malițios și voila. Datele sensibile ale utilizatorului sunt exploatate.

Ciclul de viață al atacului ilustrat în exemplul furnizat de geekforgeeks.com:

Reflected XSS example

3. DOM based XSS

Acest tip de atac este același cu cel reflectat, dar cu diferența că partea malițioasă URL nu va fi trimisă deloc către server. Pentru exemplul de mai sus:

URL așteptat: https://mywebpage.com/search?q=javascript
URL malițios (XSS reflectat): https://mywebpage.com/search?q=<script>alert('fortunately, this will not work!')</script>
URL malițios(DOM based XSS): https://mywebpage.com/search#q=<script>alert('fortunately, this will not work!')</script>

Diferența constă în faptul că se folosește caracterul # în loc de ?. Browserele nu trimit partea din URL după # la server, așa că o transmit direct codului client.

Protecție

Care valoare care poate fi introdusă de utilizator și este utilizată în aplicația dvs.(fie pe partea serverului, fie pe partea clientului) trebuie tratată ca date nesigure și, prin urmare, trebuie procesată înainte de a fi utilizată! Ar trebui să faceți verificări de siguranță atât în aplicația server, cât și în aplicația client!
Așa cum se arată în documentație, VueJS de unul singur evadează șirul de caractere înainte de a obține valoarea din variabilă. Versiunile mai noi ale Angular evadează, de asemenea, implicit șirurile de caractere, astfel încât, dacă utilizați Vanilla JS, JQuery sau altele similare, ar trebui să implementați manual scăparea șirurilor de caractere.

Există trei abordări cele mai comune privind procesarea datelor nesigure sunt enumerate mai jos, iar metoda ideală depinde de tipul real al câmpului pe care trebuie să îl procesați.

1. Validarea șirurilor de caractere

Validarea este metoda prin care utilizatorul definește un set de reguli și cere ca datele nesigure să satisfacă aceste reguli înainte de a merge mai departe. Această metodă este bună pentru valori numerice, nume de utilizator, e-mail, parolă și câmpuri similare cu un set concret de reguli de sintaxă.

Verificați dacă există biblioteci existente pentru cadrul dvs. înainte de a vă gândi să scrieți validatori pe cont propriu.

2. Validare de șiruri de caractere. String escape

Metoda escape este utilă pentru cazurile în care trebuie să permiteți utilizatorului să utilizeze semne de punctuație. Această metodă parcurge șirul și caută caractere speciale, cum ar fi < > și le înlocuiește cu numele entității de caractere HTML corespunzătoare. Iată funcția de bază pe care ați putea să o folosiți:

function escapeText(text) { return text.replace(/&/g, '&amp;') .replace(/</g, '&lt;') .replace(/>/g, '&gt;') .replace(/"/g, '&quot;')}
Intră în modul fullscreen Iese din modul fullscreen

Încă o dată, verificați bibliotecile existente înainte de a vă scrie propria bibliotecă.

3. Sanitizarea șirurilor de caractere

Sanitizarea șirurilor de caractere este utilizată atunci când utilizatorului i se permite să introducă unele etichete HTML în comentariile, articolele sau altele asemenea. Metoda de salubrizare trece prin text și caută tag-urile HTML pe care le specificați și le elimină. Una dintre cele mai populare biblioteci care utilizează această abordare este Google Closure.
Această metodă este costisitoare din punct de vedere al resurselor și este considerată dăunătoare, așa că faceți mai multe cercetări înainte de a o alege.

Browser-ele web (nu există surse disponibile de la ce versiune, IE a rezolvat această problemă în 2014.) scapă automat de URL-uri înainte de a le trimite pe partea serverului și le face disponibile și în obiectul window.location, așa că al 2-lea și al 3-lea tip de atac sunt aici doar pentru a fi conștienți de ele și pentru a clarifica faptul că parametrii URL ar trebui, de asemenea, să fie tratați ca date nesigure.

Pentru informații mai detaliate despre XSS și despre cum să vă protejați în mod corespunzător aplicația în cazul în care rotiți o mulțime de date nesigure, vă rugăm să consultați OWASP cheatsheet on XSS prevention.

CSRF

Cross site request forgery sau CSRF este un tip de atac care are loc atunci când un site web, un e-mail, un blog, un mesaj instantaneu sau un program malițios determină browserul web al unui utilizator să efectueze o acțiune nedorită pe un alt site de încredere unde utilizatorul este autentificat. Această vulnerabilitate este posibilă atunci când browserul trimite automat resurse de autorizare, cum ar fi cookie-ul de sesiune, adresa IP sau altele similare la fiecare solicitare.

ATAC

Să presupunem că utilizatorul este conectat la aplicația dvs. web neprotejată pentru bursa de valori și că folosiți fie cookie-ul de sesiune, fie cookie-ul JWT pentru autentificare. Atacatorul utilizează, de asemenea, serviciul dumneavoastră și este capabil să verifice modul în care funcționează API-ul dumneavoastră. Atacatorul păcălește utilizatorul să execute un script (făcând clic pe un link SPAM din e-mail sau similar) care va trimite o cerere către API-ul dvs. https://www.stockexchange.com/users/withdraw?how_much=all&address=MY_ADDRESS (design API teribil, nu întrebați). Deoarece cererea este executată din browserul care trimite payload-ul de autentificare la fiecare cerere, serverul dvs. web stockexchange va autentifica utilizatorul cu succes și va executa tranzacția, iar utilizatorul păcălit își va pierde tot soldul fără ca acesta să fie conștient, deoarece totul s-a întâmplat în fundal. Reprezentare vizuală(sursa miro.medium.com)
CSRF attack

PROTECȚIE

Din fericire, există modele ușor de implementat care previn aceste atacuri web. Unul dintre cele mai comune modele este utilizarea CSRF token. Practic, procedura este următoarea:

  1. Generați un token unic pentru fiecare cerere a utilizatorului, așa-numitul CSRF token.
  2. Stocați-l în siguranță pe server și trimiteți-l înapoi la utilizator ca sarcină utilă a răspunsului.
  3. Stocați CSRF token pe partea clientului.
  4. Când utilizatorul încearcă să execute orice cerere de schimbare a stării* trimite acel CSRF token împreună cu cererea ca sarcină utilă.
  5. Înainte de a executa acea cerere pe partea serverului, verificați dacă CSRF token este prezent și dacă este valid.

Aceasta este cea mai simplă modalitate de a preveni atacul CSRF pentru toți utilizatorii.

Dacă aveți de-a face doar cu vizitatori care folosesc browsere moderne, atunci vă puteți baza pe atributul SameSite al cookie-ului de sesiune (mulțumesc Gergely)

Din moment ce răspunsurile serverului pot fi procesate în răspunsul XHR, atunci nu există protecție împotriva atacului CSRF dacă aplicația dvs. web este vulnerabilă la XSS!

Pentru a pătrunde mai adânc, consultați OWASP cheatsheet on CSRF.

BONUS

Un scurt documentar despre Samy, autorul viermelui care a doborât MySpace în 2005 abuzând de vulnerabilitatea XSS, trecând de apărarea CSRF a MySpace.
https://youtu.be/DtnuaHl378M

Mai multe informații despre viermele lui Samy
https://samy.pl/myspace/tech.html

.