W budowie
Materiał edukacyjny · Informatyka

CZĘŚĆ 16

Bezpieczeństwo: ochrona przed XSS

PPrezentacja dla nauczyciela

Dane wprowadzone przez użytkownika w formularzu, odczytane z bazy czy pobrane z ciasteczek mogą zawierać złośliwy kod HTML i JavaScript. Brak odpowiedniego zabezpieczenia przy wyświetlaniu pozwala na przejęcie konta lub kradzież sesji. W arkuszach INF.03 zabezpieczenie przed XSS jest oceniane jako osobne, kluczowe kryterium.

Na czym polega XSS

XSS (Cross-Site Scripting) to wstrzyknięcie kodu JavaScript do strony przez dane od użytkownika. Jeśli komentarz zawiera znacznik script i zostanie wypisany bez zabezpieczenia, przeglądarka wykona ten kod.

Skutki bywają poważne: kradzież ciasteczek sesji, podmiana treści strony, przekierowanie na obcy adres. Wystarczy jedno niezabezpieczone miejsce, żeby cała aplikacja była zagrożona.

Źródłem danych może być formularz, parametr adresu, a nawet zawartość bazy wpisana wcześniej przez innego użytkownika. Dlatego zabezpieczamy dane przy wypisywaniu, a nie tylko przy zapisie.

$komentarz = $_GET['komentarz'] ?? '';

// zle: przegladarka wykona ewentualny skrypt
echo '<div>' . $komentarz . '</div>';

// dobrze: dane staja sie tekstem
echo '<div>' . htmlspecialchars($komentarz, ENT_QUOTES, 'UTF-8') . '</div>';
1. Co oznacza skrót XSS?
2. Skąd pochodzą dane zagrożone XSS?
3. Co może ukraść atak XSS?

htmlspecialchars i kontekst wypisania

htmlspecialchars() zamienia znaki <, >, cudzysłowy i ampersand na encje. Przeglądarka pokazuje wtedy tekst, a nie wykonuje znaczników.

Używamy flag ENT_QUOTES i kodowania UTF-8. Wartość musi być zabezpieczona także w atrybutach HTML, np. w value="...", bo cudzysłów może zamknąć atrybut.

W kontekście JavaScriptu lub adresu URL potrzebne są inne funkcje, np. json_encode() czy urlencode(). Zasada jest jedna: zabezpieczenie zależy od miejsca wypisania.

$imie = $_GET['imie'] ?? '';

echo '<p>Witaj, ' . htmlspecialchars($imie, ENT_QUOTES, 'UTF-8') . '</p>';
echo '<input type="text" value="' . htmlspecialchars($imie, ENT_QUOTES, 'UTF-8') . '">';
echo '<a href="szukaj.php?q=' . urlencode($imie) . '">Szukaj</a>';
4. Co robi htmlspecialchars()?
5. Dlaczego ENT_QUOTES jest ważne?
6. Czym zabezpieczyć parametr URL?

Zasady bezpiecznego wypisywania

Najprostsza zasada: każdą wartość spoza skryptu wypisujemy przez funkcję zabezpieczającą. Dotyczy to również danych z bazy, bo mogły zostać zapisane wcześniej przez innego użytkownika.

Nie warto polegać na „oczyszczaniu” danych przy zapisie i wypisywaniu surowych wartości. To, co jest bezpieczne w bazie, może być niebezpieczne w innym kontekście HTML.

Dobra praktyka to jedna funkcja pomocnicza, np. e($tekst), używana w całym projekcie. Wtedy nie ma miejsca na zapomnienie i łatwo sprawdzić kod przeglądem.

function e($tekst) {
    return htmlspecialchars((string) $tekst, ENT_QUOTES, 'UTF-8');
}

$komentarz = $_GET['komentarz'] ?? '';
echo '<p>' . e($komentarz) . '</p>';
echo '<p>' . e('Wiadomosc zapisana') . '</p>';
7. Czy dane z bazy są bezpieczne?
8. Po co funkcja pomocnicza e()?
9. Gdzie zabezpieczamy dane?

Ćwiczenia