Răspuns scurt
- Configurezi în nginx un set de headere de securitate HTTP care spun browserului ce are voie să facă pagina: Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, Permissions-Policy și frame-ancestors.
- Content-Security-Policy o pornești în modul Report-Only, culegi rapoartele câteva săptămâni și abia apoi o impui, ca să nu rupi propriile scripturi.
- X-Content-Type-Options: nosniff și frame-ancestors 'none' sau 'self' se pot activa din prima zi, fără risc.
- Dezactivezi versiunea din antetul Server cu server_tokens off și scoți antetele care dezvăluie tehnologia, precum X-Powered-By.
- Verifici rezultatul cu curl -I după fiecare deploy, fiindcă un bloc location cu propriul add_header șterge headerele moștenite.
- Fără risc din prima zi
- nosniff, frame-ancestors, Referrer-Policy, Permissions-Policy
- Cu perioadă de test
- Content-Security-Policy-Report-Only, apoi CSP impusă
- Capcana nginx
- add_header într-un location anulează add_header din server
- Verificare
- curl -sI https://exemplu.md | grep -iE 'content-security|x-content|referrer|permissions'
Ce închide fiecare header
Content-Security-Policy limitează sursele de scripturi, stiluri, imagini și conexiuni, deci un script injectat prin XSS nu se mai execută sau nu mai poate trimite datele nicăieri. frame-ancestors, directiva CSP care înlocuiește X-Frame-Options, împiedică încadrarea site-ului în iframe de pe alt domeniu, adică clickjacking-ul. X-Content-Type-Options: nosniff oprește browserul să „ghicească” tipul unui fișier și să execute ca script ceva servit ca text. Referrer-Policy controlează ce URL trimiți mai departe, iar Permissions-Policy închide camera, microfonul și geolocația unde nu sunt folosite.
CSP se construiește, nu se copiază
O politică copiată de pe un blog blochează scriptul de plăți, widgetul de chat sau fontul de la un CDN și afli de la clienți. Pornești cu Content-Security-Policy-Report-Only și rapoarte către un endpoint al tău: browserele raportează ce ar fi blocat, fără să blocheze. După două-trei săptămâni ai lista reală de surse — propriul domeniu, procesatorul de plăți, analitica, CDN-ul de fonturi. Scrii politica pe ea, evitând 'unsafe-inline' prin nonce sau hash, și abia apoi treci pe antetul impus.
- Report-Only cu report-uri către un endpoint propriu
- lista de surse din rapoarte, nu din presupuneri
- nonce sau hash în loc de 'unsafe-inline' pentru scripturi
- object-src 'none' și base-uri 'self' aproape întotdeauna
Capcana add_header și verificarea
În nginx, directivele add_header se moștenesc din server în location doar dacă blocul location nu are niciun add_header propriu. De îndată ce adaugi un Cache-Control într-un location pentru fișiere statice, toate headerele de securitate dispar de pe acele răspunsuri. Soluția e un fișier include cu toate headerele, inclus explicit în fiecare location care definește altele, sau modulul headers-more. Verifici cu curl -I pe pagina principală, pe un fișier static și pe o pagină de eroare — toate trei cu setul complet — și pui verificarea în pipeline.
Headere de securitate HTTP recomandate pentru un site de producție| Header | Valoare recomandată | Ce previne | Risc la activare |
|---|
| Content-Security-Policy | default-src 'self'; script-src 'self' 'nonce-…'; object-src 'none'; frame-ancestors 'none'; base-uri 'self' | XSS, clickjacking, injecție de resurse | mare fără Report-Only |
|---|
| X-Content-Type-Options | nosniff | execuția unui fișier cu tip greșit | niciunul |
|---|
| Referrer-Policy | strict-origin-when-cross-origin | scurgerea URL-urilor cu tokenuri | niciunul |
|---|
| Permissions-Policy | camera=(), microphone=(), geolocation=() | acces la senzori din scripturi injectate | mic, dacă nu le folosești |
|---|
| Strict-Transport-Security | max-age=300 în prima săptămână, apoi 31536000; includeSubDomains, doar pe blocul HTTPS | degradarea la HTTP | vezi pagina despre HTTPS și HSTS |
|---|
| Server / X-Powered-By | server_tokens off; antetul X-Powered-By eliminat | identificarea versiunilor de scanere | niciunul |
|---|
Comenzi și configurări
/etc/nginx/snippets/security-headers.confadd_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
# HSTS NU se pune aici: se adaugă doar în blocul HTTPS și doar după perioada de test
# (începe cu max-age=300 o săptămână) — vezi pagina despre HTTPS și HSTS.
# CSP-ul de blocare începe cu directivele fără risc — acestea NU au nevoie de perioadă de test
add_header Content-Security-Policy "frame-ancestors 'none'; base-uri 'self'; object-src 'none'" always;
add_header X-Frame-Options "DENY" always;
# etapa 2: restul politicii, deocamdată doar raportare
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self' https://plati.exemplu.md; img-src 'self' data:; style-src 'self' 'unsafe-inline'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; report-uri /csp-report" always;
Includerea în server ȘI în fiecare location cu add_header propriuserver {
server_tokens off;
include snippets/security-headers.conf;
location ~* \.(css|js|woff2|png|svg)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
include snippets/security-headers.conf; # altfel dispar aici
}
location = /csp-report {
access_log /var/log/nginx/csp.log;
return 204;
}
}
Verificare după deployfor u in / /static/app.js /pagina-inexistenta; do
echo "== $u"; curl -sI "https://exemplu.md$u" | grep -iE '^(content-security|x-content-type|referrer|permissions|strict-transport|server):'
done
Exemple din practică
Portal al unei instituții din Chișinău
Un audit extern a găsit că portalul putea fi încadrat în iframe de pe orice domeniu și că antetul Server afișa versiunea exactă de nginx. Adăugarea frame-ancestors 'none', nosniff și server_tokens off a durat o oră; retestul nu a mai avut observații.
Magazin online din Bălți cu plăți prin procesator extern
O CSP copiată dintr-un articol a blocat scriptul procesatorului de plăți, iar comenzile au căzut la zero timp de o oră. Refăcută în Report-Only, cu sursele culese din rapoarte două săptămâni, politica impusă a trecut fără incident.
Aplicație SaaS din Cahul, pentru un client german
Chestionarul de securitate al clientului cerea lista headerelor și dovada unei CSP fără 'unsafe-inline'. Echipa a trecut scripturile inline pe nonce generat la fiecare cerere și a atașat rezultatul curl -I; punctul s-a închis fără discuții.
Greșeli frecvente
- Adaugi headerele în blocul server și le pierzi în location-urile cu add_header propriu.
- Impui o CSP fără perioadă de Report-Only și blochezi scriptul de plăți sau fonturile.
- Folosești 'unsafe-inline' și 'unsafe-eval' peste tot și rămâi cu iluzia unei politici.
- Setezi X-Frame-Options și frame-ancestors cu valori contradictorii; browserele moderne ascultă doar de frame-ancestors.
- Verifici headerele doar la instalare, nu după fiecare deploy care schimbă nginx.
Cum te ajută 4hosting
- Hardening & Compliance configurează headerele și CSP în etape, cu verificare după deploy, pe VPS-urile și serverele dedicate 4hosting.
- Serviciul React / Next.js aplică nonce-uri CSP la nivel de aplicație, ca politica să nu aibă nevoie de 'unsafe-inline'.
- Orele de CyberSecurity incluse (1–8 lunar la VPS, 10 la dedicate și GPU) acoperă trecerea de la Report-Only la politica impusă; le ceri din panoul de client; orele se consumă în luna calendaristică, fără reportare.
- WAF & DDoS completează headerele cu reguli OWASP la nivel de server, pentru cererile care nu ajung niciodată în browser.
Întrebări conexe
Mai am nevoie de X-XSS-Protection și X-Frame-Options?
X-XSS-Protection e ignorat de browserele moderne și poate introduce probleme; nu îl seta. X-Frame-Options e înlocuit de frame-ancestors din CSP, dar îl poți păstra cu DENY sau SAMEORIGIN pentru browsere vechi, dacă nu contrazice directiva CSP.
Headerele de securitate afectează performanța sau SEO?
Nu. Sunt câteva sute de octeți pe răspuns și nu influențează indexarea. Singurul efect vizibil apare dacă o CSP prea strictă blochează un script necesar — de aceea trece prin Report-Only. Scanerele publice includ headerele în scor, ceea ce contează la chestionarele clienților.