W zasadzie kiedy muszę koniecznie sanitizować stringi przed przesłaniem ich klientowi, by zapobiec XSS?

2018-08-25 19:53

Rejestracja: 5 lat temu

Ostatnio: 11 godzin temu

0

Pamiętam, że mi tłuczono, że niezaufane stringi (czyli wszystkie przesyłane od userów do serwera) muszą koniecznie być walidowane i sanityzowane przed przesłaniem ich innym userom. Tyle, że jakoś tego nie widzę...

No mam sobie czata w tej grze. Kod po stronie klienta jest mniej więcej taki:

let p = document.createTextNode('p')
p.appendChild(document.createTextNode(message))
document.getElementById('chatbox').appendChild(p)

Gdzie message to wiadomość, którą jeden z userów wysyła na czata, i którą serwer rozgłasza wszystkim klientom.

No to się zacząłem bawić. Mianowicie (bez implementowania po stronie serwera żadnej walidacji) wysłałem sobie na czata wiadomość treści następującej:

<script>window.alert("injection")</script>

I... nic. Wyświetla się na czacie normalnie. Żadnego wyskakującego okienka.

No to teraz implementuję po stronie serwera zamianę < na &lt; Wysyłam tą samą wiadomość. Oto, co wyświetla się na czacie:

&lt;script>window.alert("injection")&lt;/script>

Wnoszę zatem, że document.createTextNode(whatever) po stronie klienta jest odporny na wszelkie dziwne pomysły i jego użycie już starczy za wszelkie walidacje, sanityzacje, i inne takie? Tak, że na własną rękę żadne walidacje już nawet nie powinny być robione? Czy jednak trzeba jeszcze czegoś dopatrzeć?

Jakaś zasada, kiedy należy próbować sanityzować niezaufane stringi (jak mnie uczono), a kiedy nie należy?

edytowany 3x, ostatnio: kmph, 2018-08-25 20:54

Pozostało 580 znaków

2018-08-25 20:21

Rejestracja: 8 lat temu

Ostatnio: 10 godzin temu

Lokalizacja: Grudziądz/Bydgoszcz

0

Zawsze trzeba. Nigdy nie ufaj userowi. to, że ten sposób ci przeszedł nie znaczy, że nie ma 20 innych sposób, np poprzez zabawę z kodami unicode.

No fajnie, ale jak pisałem, próba walidacji skończyła się tym, że mi się string źle wyświetlał. User musi być w stanie na czat wysłać znak <, nie mogę wymusić, by każdy znak < się wyświetlał jak &lt; W takim razie jak mam walidować, żeby robić to poprawnie? I blokować zabawy z kodami unicode? - kmph 2018-08-25 20:25
nie odpowiadam na komentarze - mr_jaro 2018-08-25 20:27

Pozostało 580 znaków

2018-08-25 20:28

Rejestracja: 5 lat temu

Ostatnio: 11 godzin temu

0

@mr_jaro:

No fajnie, ale jak pisałem, próba walidacji skończyła się tym, że mi się string źle wyświetlał. User musi być w stanie na czat wysłać znak <, nie mogę wymusić, by każdy znak < się wyświetlał jak &lt; W takim razie jak mam walidować, żeby robić to poprawnie? I blokować zabawy z kodami unicode?

EDIT:

jak pisałem, próba walidacji skończyła się tym, że mi się string źle wyświetlał

Tzn. jak wydawało mi się, że pisałem. Poprawiłem OP.

EDIT 2: Jejku, naprawdę są problemy z tymi encjami. Poprawiłem ten post.

edytowany 2x, ostatnio: kmph, 2018-08-25 20:32

Pozostało 580 znaków

2018-08-25 20:36

Rejestracja: 8 lat temu

Ostatnio: 10 godzin temu

Lokalizacja: Grudziądz/Bydgoszcz

0

dlaczego? czemu ni może zmienić m.in znaków <>? dopuszczasz by ludzie wysyłali html? podaj stronę to będę wiedział gdzie zacząć psocić.

Pozostało 580 znaków

2018-08-25 20:47

Rejestracja: 5 lat temu

Ostatnio: 11 godzin temu

0

czemu ni może zmienić m.in znaków <>?

Nie chodzi mi o HTML. Chodzi mi o to, że te znaki są również używane jako znaki większości / mniejszości. Jako że mają one liczne "grzeczne" zastosowania, nie tylko do różnych XSSów, to nie sądzę, by zakazanie tych znaków albo zamienianie wszystkich ich wystąpień na krzaczki było dobrym... user experience.

Skądinąd, przecież zamiana tych znaczków na krzaczki nie rozwiąże problemu wspomnianych przez Cb zabaw z Unicodem, toteż wnoszę, że oprócz tego jeszcze coś innego jest wymagane?

podaj stronę to będę wiedział gdzie zacząć psocić.

Może jak 2 miesiące poczekasz jeszcze, to będę miał się czym pochwalić, na razie gry jeszcze nie opublikowałem :)

Ale jak pamiętam rozmaite webowe gry zawierjające czaty, to nie zabraniały one przesyłania na czata < i >. Ot przykład z Pokemonów: ktoś napisał, że "clefable > wigglytuff" (co miało znaczyć, że clefable jest lepszy niż wigglytuff i należy w drużynie wyrzucić wigglytuffa i wstawić clefable) Nie chciałbym blokować podobnych zastosowań.

Wydaje mi się, że celem jest nie zabronienie tych znaków, tylko wymuszenie, by zawsze wyświetlały się one jedynie jako tekst, a nie miały żadnych dziwnych skutków ubocznych?

Pozostało 580 znaków

2018-08-25 20:51

Rejestracja: 16 lat temu

Ostatnio: 10 godzin temu

1
kmph napisał(a):

Jakaś zasada, kiedy należy próbować sanitizować niezaufane stringi (jak mnie uczono), a kiedy nie należy?

Jeśli już musisz użyć tej słownej osobliwości to sanityzować..

edytowany 1x, ostatnio: Azarien, 2018-08-25 20:51
Dzięki, poprawione. Podaj lepsze słowo niż sanityzować, a zmienię. - kmph 2018-08-25 20:55
Słowo mi nie przeszkadza, tylko błędna jego pisownia :) - Azarien 2018-08-25 20:57

Pozostało 580 znaków

2018-08-25 21:10

Rejestracja: 3 lata temu

Ostatnio: 4 godziny temu

0

Wiesz, skąd mamy wiedzieć jak napisany jest twój chat i dlaczego & lt; wyświetla się jako & lt;, a nie <? :P

Generalnie, to ktoś wysyła Ci np.

123 < 234, który jest zamieniany na 123 & lt; 234 i wyświetlany u usera jako 123 < 234 ale "interpretowany" jako 123 & lt; 234 aby nie ingerować w strukturę znaczników.

Dodałem spację pomiędzy & i lt bo post się trochę bugował.

https://jsfiddle.net/usofdcvw/

https://jsfiddle.net/amzLkhru/

edytowany 20x, ostatnio: WeiXiao, 2018-08-25 21:21

Pozostało 580 znaków

2018-08-25 21:14

Rejestracja: 8 lat temu

Ostatnio: 10 godzin temu

Lokalizacja: Grudziądz/Bydgoszcz

0

wstaw sobie na czysto znak < i zobacz, w podglądzie kodu jak ładnie przeglądarka ci zaznacza, niepoprawne użycia znaku. Zrób np coś takiego 1 < 10, 10 > 1 a dostaniesz informacje "niepoprawny znacznik początkowy <10, 10>" dlatego, że każdy czysty znak <> jest odbierano jako html

Pozostało 580 znaków

2018-08-25 21:38

Rejestracja: 1 rok temu

Ostatnio: 1 dzień temu

0

Najprawdopodobniej ten twój skrypt zamienia każde & na &amp;
W efekcie podwójnie zaencjowane < przyjmuje w kodzie postać &amp;lt; i przestaje się wyświetlać jako <.

Możesz to obejść np. zamieniając najpierw < na jakiś_unikalny_ciąg_znaków,
pozwolić skryptowi zaencjować &,
zamienić unikalny_unikalny_ciąg_znaków na &lt;.


edytowany 5x, ostatnio: Freja Draco, 2018-08-25 21:46
Nie jestem fanem tego pomysłu. O ile to obejście zadziała, to może lepiej byłoby zerknąć do tego skryptu niż dodawać kolejną warstwę "naprawczą", która później może być kolejnym elementem który trzeba debugować. - WeiXiao 2018-08-25 22:52
Masz rację. Najlepiej byłoby tak go pozmieniać, żeby najpierw encjował encje, a później encjował znaki specjalne. - Freja Draco 2018-08-25 23:00

Pozostało 580 znaków

2018-08-25 23:45

Rejestracja: 5 lat temu

Ostatnio: 11 godzin temu

0
WeiXiao napisał(a):

Wiesz, skąd mamy wiedzieć jak napisany jest twój chat i dlaczego & lt; wyświetla się jako & lt;, a nie <? :P

Ponieważ wstawienie stringa zawierającego &lt; za pomocą document.createTextNode() wyświetla się jako &lt;, a nie jako <. Podczas gdy wstawienie tego samego stringa za pomocą innerHTML wyświetla się jako <. Ja zaś użyłem createTextNode().

WeiXiao napisał(a):

Generalnie, to ktoś wysyła Ci np.

123 < 234, który jest zamieniany na 123 & lt; 234 i wyświetlany u usera jako 123 < 234 ale "interpretowany" jako 123 & lt; 234 aby nie ingerować w strukturę znaczników.

Jednakże zastosowanie tej metody w połączeniu z document.createTextNode() da efekty dalekie od optymalnych.

WeiXiao napisał(a):

https://jsfiddle.net/usofdcvw/

https://jsfiddle.net/amzLkhru/

mr_jaro napisał(a):

wstaw sobie na czysto znak < i zobacz, w podglądzie kodu jak ładnie przeglądarka ci zaznacza, niepoprawne użycia znaku. Zrób np coś takiego 1 < 10, 10 > 1 a dostaniesz informacje "niepoprawny znacznik początkowy <10, 10>" dlatego, że każdy czysty znak <> jest odbierano jako html

Tak jest, ale Wy piszecie o wstawianiu na czysto; nie widzę, by działo się to samo, gdy używam document.createTextNode().

Freja Draco napisał(a):

Najprawdopodobniej ten twój skrypt zamienia każde & na &
W efekcie podwójnie zaencjowane < przyjmuje w kodzie postać &lt; i przestaje się wyświetlać jako <.

Nic podobnego mój skrypt nie robi. Na potrzeby testów zamieniałem wyłącznie < na &lt;, nie zamieniałem natomiast & na &amp;

Bardzo Wam dziękuję za odpowiedzi, jednakże upieram się, że w opisywanych przez Was wypadkach document.createTextNode() wyświetla te znaki jako czysty tekst, podczas gdy innerHTML interpretuje je jako HTML i jest podatny na XSS na sposób, jaki tu opisujemy, tj. za pomocą znaków < oraz >. Gdybym mógł prosić, byście spojrzeli na to: http://jsfiddle.net/3e6pngt4/11/ Zwróćcie proszę uwagę na to, w jaki sposób document.createTextNode() obsługuje stringi 1 &lt; 10 oraz "<a href="evil.com">Free iPhone click here</a>", a w jaki sposób czyni to innerHTML. Zamiana znaków specjalnych na encje wywołuje wadliwe wyświetlanie stringa wstawionego po stronie klienta za pomocą createTextNode().

Tym samym odnoszę wrażenie, iż createTextNode jest zaprojektowane, by nie wymagało sanityzacji stringa podanego mu jako argument w opisywany przez nas sposób.

Nie wykluczone natomiast, że potrzebuję sanityzować tegoż stringa na inne sposoby, by uniknąć ataków na

mr_jaro napisał(a):

20 innych sposób, np poprzez zabawę z kodami unicode.

Wówczas celem moim jest dowiedzieć się, jak mam go sanityzować :)

Pozostało 580 znaków

2018-08-26 00:34

Rejestracja: 1 rok temu

Ostatnio: 1 dzień temu

0
kmph napisał(a):

Tym samym odnoszę wrażenie, iż createTextNode jest zaprojektowane, by nie wymagało sanityzacji stringa podanego mu jako argument w opisywany przez nas sposób.

Dobra, przyłapałeś nas na odpisywaniu bez czytania :)
Faktycznie createTextNode działa właśnie w taki sposób, co jest nawet logiczne, zgodne z jego nazwą i przeznaczeniem:
https://www.w3schools.com/jsr[...]jsref_document_createtextnode

Niemniej zanim createTextNode przetworzy sobie tego stringa do czysto tekstowej postaci, musisz mu go najpierw jakoś w przekazać, a to już stwarza ryzyko nie tylko zrobienia XSS, ale nawet ataku na sam serwer / bazę.


Pozostało 580 znaków

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0