Brak X-Frame-Options (clickjacking)
Co to jest
Twoja strona nie wysyła nagłówka X-Frame-Options ani nie ma w CSP dyrektywy frame-ancestors. Bez nich każdy może osadzić Cię w <iframe> na obcej witrynie.
Dlaczego to problem
Atak nazywa się clickjacking. Napastnik tworzy zwyczajnie wyglądającą stronę, umieszcza na niej Twoją witrynę w iframie, czyni ją przezroczystą trikiem CSS, a na wierzchu daje przycisk „Wygraj iPhone”. Odwiedzający klika — a w rzeczywistości kliknął „Usuń konto” w Twojejwitrynie, do której jest zalogowany.
Scenariusze praktyczne:
- Zmiana hasła (
POST /change-passwordtego samego konta, z formularza chronionego przed CSRF). - Zakup jednym kliknięciem — podsunięcie przycisku „Confirm purchase”.
- Zatwierdzenie aplikacji OAuth.
Jak to naprawić
Istnieją dwa nagłówki — możesz wysłać oba:
X-Frame-Options (starszy, obsługują wszystkie przeglądarki)
X-Frame-Options: DENY
# lub
X-Frame-Options: SAMEORIGINDENY — nikt nie może Cię osadzić w iframie, nawet Ty sam.SAMEORIGIN — w iframie tylko z własnej domeny.
CSP frame-ancestors (nowocześniejszy, bardziej szczegółowy)
Content-Security-Policy: frame-ancestors 'none';
# lub:
Content-Security-Policy: frame-ancestors 'self';
# lub z allowlistą:
Content-Security-Policy: frame-ancestors 'self' https://partner.example.cz;Jeśli masz CSP, frame-ancestors ma pierwszeństwo przed X-Frame-Options.
Konkretne konfiguracje
nginx:
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none'" always;Apache:
Header always set X-Frame-Options "DENY"
Header always set Content-Security-Policy "frame-ancestors 'none'"Kiedy NIE używać DENY?
Czasami witryna musi być w iframie — we własnym sklepie (widget koszyka), w portalu partnerskim, w rozwiązaniu white-label. W takim przypadku nie używaj DENY, lecz podaj konkretną allowlistę przez frame-ancestors.