Encje HTML i ochrona przed XSS — jak bezpiecznie wyświetlać tekst na stronie
Dlaczego znak „<” w komentarzu może przejąć konto użytkownika, czym jest atak XSS, jak działa kodowanie encji w PHP i JavaScript i dlaczego kontekst (treść, atrybut, URL, skrypt) zmienia zasady.
XSS (cross-site scripting) to atak, w którym do strony trafia kod JavaScript pochodzący od atakującego — np. wpisany w komentarzu, nazwie użytkownika czy parametrze adresu. Wykonuje się on w przeglądarkach innych osób, z ich uprawnieniami: może odczytać dane, wykonać akcje w ich imieniu albo podmienić treść strony.
Skąd bierze się podatność
Gdy aplikacja wstawia tekst od użytkownika do HTML bez zmian, przeglądarka nie odróżnia go od kodu strony. Komentarz zawierający znacznik z atrybutem zdarzenia (np. obrazek z onerror) zostanie potraktowany jak element strony i uruchomi skrypt.
Kodowanie encji — podstawowa ochrona
Przed wstawieniem tekstu do treści HTML zamienia się znaki specjalne na encje: < → <, > → >, & → &, " → ", ' → '. Przeglądarka wyświetli wtedy znaki dosłownie, zamiast interpretować je jako znaczniki.
PHP: echo htmlspecialchars($tekst, ENT_QUOTES, 'UTF-8'); JavaScript: element.textContent = tekst; // zamiast innerHTML
Jak wygląda zakodowany tekst, sprawdzisz w koderze encji HTML.
Kontekst ma znaczenie
| Gdzie trafia tekst | Co zrobić |
|---|---|
| treść elementu HTML | encje HTML |
| wartość atrybutu | encje HTML, atrybut zawsze w cudzysłowie |
| adres w href/src | sprawdź schemat (tylko http/https), parametry koduj jak URL (zob. kodowanie URL) |
| wnętrze <script> | nie wstawiaj surowego tekstu; przekaż dane jako JSON (np. json_encode z flagami JSON_HEX_TAG) |
| CSS (style) | unikaj wstawiania danych użytkownika |
Kodowanie encji nie chroni adresu href przed schematem javascript: — dlatego linki od użytkowników trzeba dodatkowo weryfikować.
Dodatkowe warstwy ochrony
- Silniki szablonów (np. Twig, Blade, React) domyślnie kodują wyjście — nie wyłączaj tego bez powodu.
- Content-Security-Policy — nagłówek ograniczający, skąd mogą pochodzić skrypty; utrudnia wykorzystanie błędu.
- Ciasteczka HttpOnly — skrypt na stronie nie odczyta identyfikatora sesji (zob. też bezpieczne przechowywanie tokenów).
- Walidacja danych wejściowych — np. numer telefonu tylko z cyfr; wzorce przetestujesz w testerze wyrażeń regularnych (zob. wyrażenia regularne od podstaw). Walidacja nie zastępuje kodowania przy wyświetlaniu.
- Edytory treści (HTML od użytkownika) — gdy użytkownik może formatować tekst, użyj sprawdzonej biblioteki czyszczącej HTML z listą dozwolonych znaczników, zamiast pisać własne filtry.
Zasada do zapamiętania
Koduj dane przy wyświetlaniu, w kontekście, w którym są wyświetlane — a nie przy zapisie do bazy. Ten sam tekst może trafić do HTML, e-maila, pliku CSV czy API i w każdym miejscu wymaga innego traktowania.
Narzędzia do tego poradnika
XSSbezpieczeństwoHTMLencjePHPJavaScript