Pred nedávnom sme zriaďovali vlastné cloudové riešenie Nextcloud Hub, ktoré je z pohľadu bezpečnosti celkom dobre zabezpečené o čom sme sa mohli presvedčiť skenovaním na scan.nextcloud.com. Keď sme vytvárali LAMP Stack, tak sme si povedali, že okrem Nextcloud Hub tam môžeme hostovať rôzné webové projekty založené na PHP prip. mySQL. Napr. jany.ml beží tiež z LAMP Stacku ako Nextclod Hub. Pozrime sa na to ako zabezpečíme web z pohľadu HTTP hlavičiek, niečo si povieme aj o HTTP/2 a nastavíme si TLSv1.3.
Obsah
HTTP hlavičky
HTTP (hypertext transfer protocol) je určený na prenos html dokumentov medzi webovým serverom (Apache, Nginx, ISS …) a webovým klientom (Mozilla, Chromium, Opera, resp. dnes už aj medzi mobilnými web prehliadačmi). Obyčajne ak chce klient zobraziť nejaký web, vyšle HTTP požiadavku ktorej obsahom sú HTTP hlavičky a webový server mu tak isto odpovedá HTTP hlavičkami, ktorých súčasťou je aj html kód. Čiže z tohto pohľadu môžeme HTTP hlavičky rozdeliť na
- Request Headers (žiadosť klienta)
- Response Headers (odpoveď servera)
Hlavičky bežný užívateľ nevidí, ale ak ste sa náhodou dostali na túto stránku a korektne sa Vám zobrazila, tak vedzte, že Váš webový prehliadač poslal webovému serveru niekoľko HTTP hlavičiek a server na ne korektne odpovedal. Ak by sme sa chceli pozrieť na HTTP hlavičky bližšie, tak veľmi dobrú konzolu pre vývojárov ma Mozilla Firefox, kde nám stačí použiť funkčnú kláves F12. Keď F12 stlačíme pred načítaním stránky, tak krásne vidíme ako sa web načitáva. Potom klikneme na Network
a na pravej časti v sekcii Headers
vidíme Response Headers
a Request Headers
Pozri obrázok nižšie (viď spodnú časť na obrázku). Vybral som vlastnú webovú stránku https://www.jany.win
.

Ak klikneme na Response Headers
alebo Request Headers
, tak sa rozbalí zoznám hlavičiek. Ak klikneme na Raw
, čo je kvázi surový stav, tak môžeme vidieť niečo podobné tomu. Toto je požiadavka webového klienta na webový server a môže vyzerať nejak takto:
GET /blog/ HTTP/2
Host: www.jany.ml
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: https://www.jany.win/
Cookie: PHPSESSID=8hsqgm73ngqdi9th1s8jjr5eke
Upgrade-Insecure-Requests: 1
TE: Trailers
a toto je odpoveď servera:
HTTP/2 200 OK
server: nginx/1.14.2
date: Fri, 18 Jun 2021 10:08:30 GMT
content-type: text/html; charset=UTF-8
content-length: 11572
expires: Thu, 19 Nov 1981 08:52:00 GMT
cache-control: no-store, no-cache, must-revalidate
pragma: no-cache
link: <https://www.jany.win/wp-json/>; rel="https://api.w.org/"
vary: Accept-Encoding
content-encoding: gzip
X-Firefox-Spdy: h2
Teraz už vieme, že existujú nejaké HTTP hlavičky. Aby sme ochránili web klientov pred nechcenými útokmi mali by sme webový server nakonfigurovať aby obsahoval hlavičky zabezpečenia. Konfiguráciu si ukážeme na reverznom proxy servery nginx. Či sme web nakonfigurovali z pohľadu bezpečnostných hlavičiek správne si môžeme preveriť napr. na securityheaders. Web si skontrolujeme pred zabezpečením.

Z pohľadu bezpečnostných HTTP hlavičiek nie je server vôbec nakonfigurovaný. Bezpečnostné hlavičky budeme implementovať pomocou smernice add_header
. Prevažná časť textov je prebraná (a voľne preložená) z securityheaders.cz.
HTTP Strict Transport Security (HSTS)
Táto hlavička informuje webový prehliadač, že túto stránku by nemal nikdy načítať cez nezabezpečený http protokol, ale stále by mal použiť https. Čas je nastavený na 1 rok platnosti a zahrnuté budú aj subdomény.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Referrer-Policy
Táto hlavička by mala byť vložená do komunikácie medzi web server a web prehliadač. Hlavička informuje webový prehliadač o tom, ako zaobchádzať s informáciami o sprostredkovaní, ktoré sa odosielajú na webové stránky, keď používateľ klikne na odkaz, ktorý vedie na inú stránku alebo webový server.
add_header Referrer-Policy "no-referrer" always;
X-Content-Type-Options
Hlavička oznamuje prehliadaču, aby overoval či zdroj má v hlavičke správne nastavený MIME typ. Webové prehliadače sa snažia prechádzať odkazované súbory a ak nájdu nejaký skript, pokúsia sa ho vykonať. Ide o tzv. Content-sniffing, kedy prehliadač spustí napríklad .js skript v textovom súbore, ktorý umiestnil útočník do webového priestoru. Skripty je možné spúšťať aj z obrazov atď. Hlavička je funkčná vo všetkých moderných prehliadačoch, nemusí sa však správať vo všetkých rovnako.
add_header X-Content-Type-Options "nosniff" always;
X-Download-Options
Táto hlavička rieši bezpečne sťahovanie súborov z internetu a bola predstavená v roku 2008 pre IE8. Zabezpečuje aby webový prehliadač neotváral súbory priamo z webu, ale aby klient mal možnosť súbor uložiť a až potom ho môže ručne otvoriť.
add_header X-Download-Options "noopen" always;
X-Frame-Options
Hlavička X-Frame-Options hovorí, či možno webovú stránku, alebo jej časť zobraziť v ráme pri použití HTML značiek ,<frame> , <iframe>, alebo <object>. Nastavenie hlavičky umožňuje kompletné zakázanie vkladanie alebo obmedzenia na konkrétnej doméne. Hlavička ochraňuje užívateľa od zneužitia pomocou tzv. „Clickjackingu„, kedy útočník na podvodnéj stránke vloží cudziu stránku a nad ňou umiestni priehľadnú vrstvu s vlastnými udalosťami a odkazy o ktorých návštevník netuší.
add_header X-Frame-Options "SAMEORIGIN" always;
X-Permitted-Cross-Domain-Policies
Hlavička X-Permitted-Cross-Domain-Policies bola vytvorená pre Adobe Flash Player alebo Adobe Acrobat, ale je určená aj pre iné programy pracujúce so súbormi flash a pdf. Ak webový klient požiada o súbor hostovaný na konkrétnej zdrojovej doméne a tento obsah je smerovaný na inú doménu, ako je jeho vlastný, musí vzdialená doména hostiť súbor zásad medzi rôznymi doménami (domenaxyz.cz/crossdomain.xml), ktorý udeľuje prístup k zdrojovej doméne , aby klient mohol pokračovať v požiadavke. Ide o dokument XML, ktorý udeľuje webovému klientovi oprávnenie na prácu s dátami v rámci domén. Zvyčajne sa definuje politika v master policy súbore, ale v prípade nemožnosti zápisu do koreňového adresára možno vykonať nastavenie pomocou hlavičky X-Permitted-Cross-Domain-Policies.
add_header X-Permitted-Cross-Domain-Policies "none" always;
X-Robots-Tag
Metaznačka robots vám umožňuje využiť podrobný prístup špecifický pre stránku k riadeniu toho, ako by sa mala jednotlivá stránka indexovať a zobrazovať používateľom vo výsledkoch Vyhľadávania Google. Značku X-Robots možno použiť ako prvok odpovede hlavičky HTTP pre danú adresu URL. Akákoľvek smernica, ktorá sa dá použiť v metaznačke robots, môže byť tiež špecifikovaná ako X-Robots-Tag
add_header X-Robots-Tag "none" always;
X-XSS-Protection
Hlavička X-XSS-Protection povoľuje využitie zabudovaného filtra proti XSS (cross-site scripting attacks). Hlavička je podporovaná už iba prehliadači Internet Explorer a Safari. Update 2021
: Moderné prehliadače túto hlavičku ignorujú. Chrome od verzie 78 a Edge od verzie 17 XSS Audítora odstránili. Prehliadač Firefox túto XSS ochranu ani neimplementovala. Je vhodné bezpečnosť aplikácie riešiť pomocou Content-Security-Policy (CSP).
add_header X-XSS-Protection "1; mode=block" always;
Content-Security-Policy
Content Security Policy je hlavička, ktorá prehliadači hovorí čo všetko za súbory môže do stránok nahrať a ako. Použitím CSP možno zabrániť, aby boli do stránok vkladané škodlivé funkcie. Nastavenie možno atomizovat až na jednotlivé typy súborov (obrázky, skripty, štýly, fonty, médiá), môže sa nariadiť len načítanie cez https protokol, alebo iba z vlastnej domény. CSP hlavička môže byť pomerne obsiahla a ak načítaný obsah nevyhovuje jej pravidlám, nie je načítaný a prehliadač do svojej konzoly vypíše chybové hlásenie. Pri zložitejších webov nasadenie hlavičku Content-Security-Policy nie je úplne triviálne a vyžaduje presnú analýzu, načitaného obsahu a nastavenie správnych pravidiel.
add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';" always;
Feature-Policy
Feature-Policy hlavička umožňuje vývojárom webu povoľovať, zakazovať a upravovať vlastnosti a správanie niektorých rozhrania API a webových funkcií v prehliadači. Táto hlavička je pomerne nová a jej použitie nie je v prehliadačoch zatiaľ široko podporované.
Hlavičku Feature-Policy využijú vývojári k zvýšeniu bezpečnosti aplikácií napríklad zakázaním funkcií, ktoré by mohli byť zneužité škodlivým kódom tretích strán. Súčasne ale môžu povoliť prístup k niektorým funkciám prehliadača, ktoré chcú využívať, ale tie sú v predvolenom nastavení zakázané.
add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()";
Toto sú HTTP bezpečnostné hlavičky, ktoré som ja implementoval na reverznom proxy servery pre konkrétny server block na ktorom beží WordPress. V konfiguračnom súbore je potrebné tieto hlavičky umiestniť do sekcie server
.
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';" always;
add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()";
Teraz si môžeme web preskénovať na securityheaders Výsledok by mal byť A+, ale dobrý výsledok je aj A

Ak si pozrieme konzolu pre vývojárov po implementácii hlavičiek, tak odpoveď servera sa už bude líšiť a uvidíme tam už aj hlavičky
HTTP/2 200 OK
server: nginx/1.14.2
date: Fri, 18 Jun 2021 10:16:09 GMT
content-type: text/html; charset=UTF-8
content-length: 11572
expires: Thu, 19 Nov 1981 08:52:00 GMT
cache-control: no-store, no-cache, must-revalidate
pragma: no-cache
link: <https://www.jany.win/wp-json/>; rel="https://api.w.org/"
vary: Accept-Encoding
content-encoding: gzip
strict-transport-security: max-age=31536000; includeSubDomains
referrer-policy: no-referrer
x-content-type-options: nosniff
x-download-options: noopen
x-frame-options: SAMEORIGIN
x-permitted-cross-domain-policies: none
x-robots-tag: none
x-xss-protection: 1; mode=block
content-security-policy: default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';
permissions-policy: geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()
X-Firefox-Spdy: h2
HTTP/2
Teraz sa ešte pozrieme na HTTP/2. Keď som niekedy v apríly 2021 spúšťal do prevádzky reverzný proxy server Nginx, tak som pri konfigurácií neuvažoval o HTTP bezpečnostných hlavičkách a ani o HTTP/2.
Protokol HTTP/1.1 bol predstavený v roku 1997 a od vtedy sa nič zaujímave neudialo (HTTP/1.1 sa hojne používa aj dnes). Až v roku 2015 vyšiel protokol HTTP/2, ktorý vznikol s experimentálneho protokolu SPDY, ktorý vyvinul Google. Medzi HTTP/1.1 a HTTP/2 je značný rozdiel z hľadiska sieťového prenosu. Veľmi kvalitne čítanie o HTTP/2 je na root.cz. V našom prípade protokol HTTP/2 použijeme len medzi webovým prehliadačom klienta a reverzným proxy serverom Nginx. Komunikácia medzi reverzným proxy serverom a webovým serverom (Apache) bude stála prebiehať na HTTP/1.1. Takéto spojenie môžeme nazvať hybridným spojením.

Niektoré základné vlastnosti HTTP/2
- Na rozdiel od HTTP/1.1 stačí jedno TCP spojenie
- Binárny protokol
- Kompresia hlavičiek
- Kompatibilný s HTTP/1.1
- podporuje ho väčšina súčasných web prehliadačov
- Omnoho rýchlejší ako HTTP/1.1
Aby fungoval protokol HTTP/2 musí byť server nakonfigurovaný min. z TLS 1.2 certifikátom (čiže musíme používať https). Minimálna verzia Nginx, ktorý podporuje HTTP/2 je 1.9.5, alebo vyššia. Ja v súčasnosti používam verziu 1.14.2. Teraz sa pozrieme aká jednoduchá je implementácia HTTP/2 na Nginx servery. Do konfiguračného súboru nám stačí pridať do sekcie server http2
sudo nano /etc/nginx/sites-available/www.example.com
Nájdeme smernicu listen a na koniec riadku pred bodkočiarku „;“ pridáme http2
listen 443 ssl http2;
Preveríme konfiguráciu po syntaktickej stránke a znova načítame konfiguráciu, po ktorej by mal web fungovať na protokole HTTP/2.
sudo nginx -t
sudo systemctl reload nginx
Či web skutočne funguje na protokole HTTP/2 sa môžeme znova presvedčiť cez webový prehliadač, Mozilla Firefox, Google Chrome a pod. stlačením klávesy F12. Pozorný čitateľ si už určite na prvom obrázku tohto blogu všimol, že web beží na protokole HTTP/2. Iná možnosť ako zistiť verziu protokolu (ale aj výpis HTTP hlavičiek) je použiť konzolovú aplikáciu curl
curl -I -L https://www.example.com
TLS 1.3
Veľmi dôležité je zabezpečiť aj komunikáciu medzi webovým prehliadačom a webovým serverom (v tomto prípade mám na mysli reverzný proxy server). Keď sme generovali certifikáty pre naše domény od lets’encrypt, tak agent certbot na náš pokyn automaticky upravoval konfiguračný súbor servera. Pre šifrovanie boli vybrané tieto verzie TLS.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
Ak však spravíme test na ssllabs.com, zistíme, že výsledky nie sú dostačujúce. Spoločnosť ssllabs.com, začala znižovať hodnotenie zabezpečenia ak je na servery nastavené TLSv1.1 a staršie (TLSv1.0, SSL3 a SSL2) a ak nie je nastavená TLSv1.3. Aj keď staršie webové prehliadače nepodporujú TLSv1.3, tak o to bude väčší dôvod užívateľa aby si prehliadač aktualizoval. Pre správne fungovanie TLSv1.3 potrebujeme min. Nginx 1.13.0, alebo novší a OpenSSL 1.1.1. Poďme si preveriť, či požiadavky spĺňame.
sudo nginx -v
nginx version: nginx/1.14.2
openssl version
OpenSSL 1.1.1d 10 Sep 2019
Požiadavky sú splnené, takže môžeme nastaviť TLSv1.3. Vzhľadom k tomu, že sme certifikáty generovali na lets’encrypt, tak v konfigurácii servera, certbot vygeneroval riadok, ktorý odkazuje na súbor s nastavením SSL. Čiže Nginx na základe smernice include
, bude čítať aj následujúci súbor a mi musíme upraviť práve tento súbor.
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
sudo nano /etc/letsencrypt/options-ssl-nginx.conf
V súbore vyhľadáme riadok
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
Vymažeme zastaralé TLSv1 TLSv1.1 a dopíšeme TLSv1.3, takže riadok bude vyzerať následovne
ssl_protocol TLSv1.2 TLSv1.3;
Skontrolujeme, či je konfigurácia v poriadku po syntaktickej stránke a môžeme reštartovať, alebo reloadnuť Nginx. Teraz preveríme výsledok na ssllabs.com (príp. tu je ďalší TLS Checker pre zistenie verzie TLS).
sudo nginx -t
sudo systemctl restart nginx

Teraz odporúčam spustiť ešte certbot na sucho a ak skončí generovanie gratuláciou, tak by sme mali mať všetko OK
sudo certbot renew --dry-run
Záver
Priznám sa, že v tejto oblasti nie som odborník a dosť veľa som musel googliť aby som si informácie dostatočne overil. Výsledky testovania dopadli dobre, takže z hľadiska bezpečnosti by mali byť webový klienti pred útokmi chránený. HTTP/2 by mal urýchliť načítanie webu oproti HTTP/1.1 aspoň o polovici. V júny 2020 pre Nginx experimentálne vyšiel http_v3_module (zatiaľ nie je dostupný v hlavnej vývojovej vetve). Na rozdiel od HTTP/2 bude používať protokol UDP, takže môžeme očakávať ďalšie zrýchlenie webu. Nakoniec sme odstránili staršie menej bezpečné šifrovacie protokoly a k TLSv1.2 sme pridali momentálne najbezpečnejší TLSv1.3.
Použitá literatúra
- Zoznam HTTP hlavičiek – WikiPedia
- securityheaders.com
- securityheaders.cz
- HTTP Response Headers
- HTTP headers na Mozilla
- HTTP Security Headers with Nginx
- How to Implement Security HTTP Headers to Prevent Vulnerabilities
- Seven Important Security Headers for Your Website
- FIXING CONTENT SECURITY POLICY FOR WORDPRESS
- Zabezpečení Nginx – CSP
- Jak funguje nový protokol HTTP/2
- HTTP/2 na WikiPedia
- HTTP na WikiPedia
- Protokol HTTP/2
- How To Set Up Nginx with HTTP/2 Support on Ubuntu 18.04
- HTTP/2 vs HTTP/3
- NGINX Support for QUIC and HTTP/3
- HTTP protokol na jakpsatweb
- How to Enable HTTP/2 in Apache & Nginx?
- Demo latencie HTTP 1.1 vs HTTP/2
- ssllabs.com
- TLS 1.3 Is Here to Stay
- How to remove TLSv1.0 / 1.1 and enable TLS 1.3 in Nginx
- SSL Server Rating Guide
- SSL Labs Grading 2018