Funkcja bezpiecznego czyszczenia XSS (regularnie aktualizowana)

Od kilku dni poluję wokół sieci, próbując to rozgryźć, ale otrzymuję sprzeczne odpowiedzi.

Czy istnieje Biblioteka, klasa lub funkcja PHP, która bezpiecznie dezynfekuje / koduje łańcuch znaków przeciwko XSS? Musi być regularnie aktualizowany, aby przeciwdziałać nowym atakom.

Mam kilka przypadków użycia:

Przypadek użycia 1) mam pole tekstowe, powiedzmy dla imienia lub nazwiska

  • użytkownik wprowadza tekst do pola i przesyła formularz
  • zanim to zostanie zapisane do bazy danych chcę a) przyciąć wszelkie białe spacje z przodu i koniec łańcucha i b) usuwa wszystkie znaczniki HTML z wejścia. To pole tekstowe nazwy, nie powinny mieć w nim żadnego HTML.
  • następnie zapiszę to w bazie danych z przygotowanymi deklaracjami PDO.

Myślę, że mógłbym po prostu zrobić trim() i strip_tags() następnie użyć filtru dezynfekcji lub RegEx z białą listą znaków. Czy naprawdę potrzebują postacie jak ! i ? lub < > w ich imieniu, nie bardzo.

Przypadek użycia 2) podczas wyprowadzania zawartości z wcześniej zapisanego rekordu bazy danych (lub z wcześniej przesłanego formularza) do widoku/HTML chcę dokładnie wyczyścić go dla XSS. NB: Może, ale nie musi, przejść przez etap filtrowania w przypadku użycia 1, ponieważ może to być inny typ wejścia, więc załóżmy, że nie przeprowadzono dezynfekcji.

Początkowo myślałem, że HTMLPurifier zrobi to, ale wygląda na to, że to jest nie to, czego potrzebuję, gdy zadałem pytanie ich poparciu:

Oto Test lakmusa: jeśli użytkownik zgłosi <b>foo</b> powinien pokazać się jako <b>foo</b>lub foo? Jeśli ten pierwszy, nie potrzebujesz HTML Purifier.

Więc wolałbym, aby wyświetlał się jako <b>foo</b>, ponieważ nie chcę, aby wyświetlany był żaden HTML dla prostego pola tekstowego ani żadnego JavaScript.

Więc szukałem funkcji, która zrobi to wszystko za mnie. I natknąłem się na metodę xss_clean używaną przez Kohana 3.0, która zgaduję, że działa, ale tylko jeśli chcesz zachować HTML. Jest teraz przestarzały z Kohana 3.1, ponieważ zastąpiono go HTMLPurifier. Więc zgaduję, że powinieneś zrobić HTML::chars() zamiast tego, co robi tylko ten kod :

public static function chars($value, $double_encode = TRUE)
{
    return htmlspecialchars( (string) $value, ENT_QUOTES, Kohana::$charset, $double_encode);
}

Teraz najwyraźniej powinieneś używać htmlentities zamiast jak wspomniano w całkiem kilku miejscach w Stack Overflow , ponieważ jest bezpieczniejszy niż htmlspecialchars.

  • więc jak używać htmlentities właściwie?
  • To wszystko, czego potrzebuję?
  • w jaki sposób chroni on przed wysyłaniem wartości zakodowanych hex, decimal i base64 z ataków wymienionych tutaj ?

Teraz widzę, że trzecim parametrem dla metody htmlentities jest charset używany w konwersji. Teraz moja strona / db jest w UTF-8, ale być może formularz przesłane dane nie był UTF-8 zakodowane, może przesłane ASCII lub HEX więc może trzeba najpierw przekonwertować na UTF-8? Oznaczałoby to jakiś kod w stylu:

$encoding = mb_detect_encoding($input);
$input = mb_convert_encoding($input, 'UTF-8', $encoding);
$input = htmlentities($input, ENT_QUOTES, 'UTF-8');
Tak czy nie? W takim razie nadal nie jestem pewien, jak zabezpieczyć się przed możliwymi wejściami XSS hex, decimal i base64...

Jeśli istnieje jakaś Biblioteka lub framework PHP o otwartym kodzie źródłowym, które potrafią poprawnie chronić XSS, to chciałbym zobaczyć jak to robią w kodzie.

Każda pomoc bardzo doceniana, przepraszam za długi post!

Author: Community, 2011-06-17

2 answers

Aby odpowiedzieć na śmiałe pytanie: tak, jest. Nazywa się htmlspecialchars.

Musi być regularnie aktualizowany, aby przeciwdziałać nowym atakom.

Właściwym sposobem zapobiegania atakom XSS nie jest przeciwdziałanie konkretnym atakom, filtrowanie / dezynfekcja danych, ale odpowiednie kodowanie , wszędzie.

htmlspecialchars (lub htmlentities) w połączeniu z rozsądną decyzją kodowania znaków (tj. UTF-8) i wyraźną specyfikacją kodowania znaków jest wystarczająca aby zapobiec wszystkim atakom XSS. Na szczęście wywołanie htmlspecialchars bez jawnego kodowania (zakłada wtedy ISO-8859-1) działa również dla UTF-8. Jeśli chcesz, aby było to jawne, Utwórz funkcję pomocniczą:

// Don't forget to specify UTF-8 as the document's encoding
function htmlEncode($s) {
    return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}
A żeby rozwiązać problem z formularzem: nie próbuj wykrywać kodowania, to na pewno się nie uda. Zamiast tego podaj formularz w UTF-8. Każda przeglądarka wyśle wtedy dane użytkownika w UTF-8.

Rozwiązywanie szczególnych problemów:

(...) you ' re supposed do użycia htmlcentities ponieważ htmlspecialchars jest podatny na exploit XSS UTF-7.

Exploit UTF-7 XSS może być zastosowany tylko wtedy, gdy przeglądarka uzna, że dokument jest zakodowany w UTF-7. Określenie kodowania dokumentu jako UTF-8 (w nagłówku HTTP/meta znaczniku zaraz po <head>) zapobiega temu.

Również jeśli nie wykryję kodowania, co zatrzymać pobieranie atakującego pliku html, następnie zmieniając go na UTF-7 lub jakieś inne kodowanie, wtedy składając Wyślij zapytanie z powrotem do mojego serwer ze zmodyfikowanej strony html?

Ten scenariusz ataku jest niepotrzebnie skomplikowany. Atakujący może po prostu stworzyć ciąg UTF-7, nie trzeba niczego pobierać.

Jeśli akceptujesz Post atakującego (tzn. akceptujesz anonimowe publiczne wejście użytkownika), Twój serwer zinterpretuje ciąg UTF-7 jako dziwny UTF-8. To nie jest problem, Post atakującego po prostu pokaże zniekształcony. Atakujący może osiągnąć ten sam efekt (wysyłając dziwny tekst) zgłaszając" grfnlk " sto razy.

Jeśli moja metoda działa tylko dla UTF-8 to atak XSS przejdzie, nie?

Kodowanie nie jest magiczne. Kodowanie jest tylko sposobem interpretacji ciągu binarnego. Na przykład łańcuch "ö" jest zakodowany jako (szesnastkowy) 2B 41 50 59 w UTF-7 (i C3 B6 w UTF-8). Dekodowanie 2B 41 50 59 jako UTF-8 daje "+ APY " - nieszkodliwe, pozornie losowo znaki.

Również w jaki sposób htmlentities chroni przeciwko HEX lub innym atakom XSS?

Dane szesnastkowe będą wyświetlane jako tylko to. Atakujący wysyłający "3C "opublikuje wiadomość"3C". "3C" może tylko stać się < jeśli aktywnie próbujesz zinterpretować dane szesnastkowe w inny sposób, na przykład aktywnie mapować je na punkty kodu unicode, a następnie wypisywać je. Oznacza to tylko, że jeśli akceptujesz dane w czymś innym niż zwykły UTF-8( na przykład kodowany w base32 UTF-8), będziesz musiał najpierw rozpakować kodowanie i następnie użyj htmlspecialchars Przed włączeniem go między kod HTML.

 24
Author: phihag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-17 14:11:19

Wielu inżynierów bezpieczeństwa zaleca użycie tej biblioteki do tego konkretnego problemu:

Https://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API

 0
Author: Olivier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-06 08:51:39