Ghid de securitate · România

Ce headere de securitate HTTP configurez în nginx?

Headerele de securitate sunt instrucțiuni pe care serverul le dă browserului: ce scripturi are voie să ruleze, dacă pagina poate fi pusă într-un iframe, ce informații trimite mai departe. Câteva linii în nginx închid clase întregi de atacuri asupra utilizatorilor tăi.

Actualizat la

Răspuns scurt

  1. Configurezi în nginx headerele X-Content-Type-Options: nosniff, Referrer-Policy, Permissions-Policy și frame-ancestors, plus server_tokens off, pe toate răspunsurile, cu add_header ... always.
  2. Content-Security-Policy o introduci întâi ca Content-Security-Policy-Report-Only și o treci pe blocare doar după ce rapoartele nu mai arată resurse legitime blocate.
  3. frame-ancestors din CSP înlocuiește X-Frame-Options, pe care îl păstrezi pentru browserele vechi.
  4. Testezi rezultatul cu curl -I și cu un scaner public de headere, după fiecare deploy.
Header obligatoriu pe orice site
X-Content-Type-Options: nosniff
Împotriva clickjacking
frame-ancestors 'self' în CSP (+ X-Frame-Options)
Cum introduci CSP
Content-Security-Policy-Report-Only, apoi blocare
Capcana nginx
add_header într-un location anulează cele din server

Ce face fiecare header și împotriva a ce

Content-Security-Policy e cel mai puternic: listează originile de unde browserul acceptă scripturi, stiluri, imagini și conexiuni, ceea ce reduce drastic efectul unui XSS, pentru că scriptul injectat nu are voie să ruleze. X-Content-Type-Options: nosniff oprește browserul să „ghicească” tipul unui fișier și să execute ca script ceva servit ca text. frame-ancestors, și predecesorul X-Frame-Options, împiedică încadrarea site-ului într-un iframe străin, baza clickjacking-ului. Referrer-Policy controlează cât din URL pleacă spre alte site-uri. Permissions-Policy dezactivează camera, microfonul sau geolocația.

Cum le pui în nginx fără să rupi site-ul

Regula de aur în nginx: directivele add_header dintr-un bloc location înlocuiesc complet lista moștenită din server. Dacă adaugi un add_header pentru cache într-un location pentru imagini, headerele de securitate dispar de pe acele răspunsuri. Soluția e un fișier inclus în fiecare bloc care are propriile add_header. Adaugi always ca headerele să apară și pe răspunsurile 4xx și 5xx. CSP o scrii în report-only și o urmărești câteva săptămâni: scripturile inline, fonturile externe, widgeturile de chat apar toate în rapoarte. Abia apoi o treci pe blocare, cu nonce pentru scripturile inline.

  • server_tokens off ascunde versiunea nginx din antet și din paginile de eroare
  • HSTS are pagina lui în acest ghid; se adaugă doar pe răspunsurile HTTPS
  • object-src 'none' și base-uri 'self' închid două vectori des uitați
Headerele de securitate HTTP recomandate pentru un site de producție
HeaderValoare recomandatăCe previne
Content-Security-Policydefault-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'XSS, injectare de resurse, clickjacking
X-Content-Type-OptionsnosniffExecutarea fișierelor cu tip greșit
X-Frame-OptionsSAMEORIGIN (pentru browsere vechi)Clickjacking
Referrer-Policystrict-origin-when-cross-originScurgerea URL-urilor cu token-uri
Permissions-Policycamera=(), microphone=(), geolocation=()Acces la senzori din pagini compromise
Strict-Transport-Securitymax-age=31536000; includeSubDomains (doar pe HTTPS)Downgrade la HTTP
Serverserver_tokens offIdentificarea versiunii pentru exploatare

Comenzi și configurări

/etc/nginx/snippets/security-headers.conf, inclus în fiecare bloc cu add_header
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; report-uri /csp-report" always;
Blocul server care le folosește
server_tokens off;

server {
  listen 443 ssl;
  http2 on;
  server_name exemplu.ro;
  include snippets/security-headers.conf;

  location ~* \.(png|jpg|webp|css|js)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    include snippets/security-headers.conf;  # altfel headerele dispar aici
  }

  location = /csp-report {
    access_log /var/log/nginx/csp.log;
    return 204;
  }
}
Verifici după deploy
curl -sI https://exemplu.ro/ | grep -iE "content-security|x-frame|x-content-type|referrer|permissions|strict-transport|^server"
curl -sI https://exemplu.ro/pagina-inexistenta | grep -i x-content-type

Exemple practice

Magazin online din Cluj cu XSS într-un câmp de recenzii

Un script injectat într-o recenzie citea cookie-urile utilizatorilor autentificați. Cu CSP în modul de blocare și script-src limitat la propriul domeniu, scriptul nu s-a mai executat, iar rapoartele CSP au indicat exact pagina afectată înainte ca cineva să reclame.

Platformă de programări din Timișoara încadrată într-un iframe

Un site terț încadra pagina de login într-un iframe invizibil, suprapus peste un buton de „descarcă”. frame-ancestors 'self' a oprit încadrarea. Verificarea a arătat că headerul lipsea pe /login din cauza unui add_header pentru cache din acel location.

Greșeli frecvente

  • Pui headerele în blocul server și le pierzi pe rutele care au propriul add_header, fără să observi.
  • Publici CSP direct în modul de blocare și rupi widgetul de plată sau chat-ul de suport.
  • Folosești 'unsafe-inline' în script-src „temporar” și CSP nu mai oprește niciun XSS.
  • Omiți always și headerele lipsesc de pe paginile de eroare.

Cum te ajută 4hosting

  • Serviciul Hardening & Compliance configurează headerele și trece CSP din report-only în blocare pe baza rapoartelor, în orele incluse: 1–8 lunar la VPS, 10 la dedicate și GPU, cerute din panoul de client, secțiunea „Servicii DevOps”; orele se consumă în luna calendaristică și nu se reportează.
  • Serviciul React / Next.js adaptează aplicația la o CSP strictă, cu nonce pe scripturile inline, fără 'unsafe-inline'.
  • Serviciul Pentesting & Security Audit include verificarea headerelor și a politicii CSP în raportul de audit web.

Întrebări conexe

  • CSP rupe Google Analytics, Stripe sau chat-ul de suport?

    Doar dacă nu le declari. Fiecare serviciu terț publică originile de care are nevoie în script-src, connect-src și frame-src. Perioada de report-only e exact pentru asta: rapoartele îți arată ce origini lipsesc din politică. Le adaugi explicit, nu deschizi politica cu wildcard.

  • Mai am nevoie de X-Frame-Options dacă am frame-ancestors?

    frame-ancestors are prioritate în toate browserele moderne și e mai flexibil, permițând mai multe origini. X-Frame-Options îl păstrezi pentru compatibilitate cu browsere vechi; când amândouă există, browserul modern ignoră X-Frame-Options. Nu strică nimic să le ai pe ambele.

  • Aceste headere se pun în nginx sau în aplicație?

    Cele statice, nosniff, Referrer-Policy, Permissions-Policy, frame-ancestors, în nginx, ca să acopere și fișierele statice și paginile de eroare. CSP cu nonce per cerere trebuie generată de aplicație, pentru că nonce-ul se schimbă la fiecare răspuns. Le verifici pe ambele straturi ca să nu le dublezi.

Cere o verificare de securitate

Un server de producție e atacat automat din primele minute după ce primește IP public, indiferent cât de mic e proiectul. Ghidul ordonează controalele după impact, de la accesul SSH până la răspunsul la incident, cu legislația din România care se aplică. Fiecare temă are o pagină dedicată, cu răspuns scurt, exemple și configurări.