Jak uchronić stronę przed atakiem XSS?

0

Jak byscie uchronili swoja strone przed takim atakiem XSS

https://www.mydomain.com/company/user?email=gkjftk`};alert(document.domain);test=%20{test:`123

?

2

Nijak, taki atak nic nie da bo w parametrze w get jak coś ci przychodzi to zazwyczaj jest to porównywane z innymi wartościami a nie gdzieś zapisywane/wyświetlane.

0

Jeśli już w tym parametrze musiałby być konkretnie email - to bym walidował ten parametr czy jest to faktycznie email. Z tego co mi wiadomo emaile nie mogą zawierać znaków takich jakie podałeś w tym ciągu. Tu ogólnie chyba nie ma większej filozofii.

0

To jest atak XSS. email to tylko poczatek. Chodzi o alert(). Na stronie zostanie wyswietlony windows pop up. A pozniej moze zostac zmieniony path URL w HTML, bo w przypadku aplikacji na ktorej pracuje ten URL jest uzyty np w formularzu, czy HTML header og tags. I teraz wiadomo, ze taki url mozna nadpisac i np wyslac dane z formularza do zewnetrznego serwera. To jest tylko maly przyklad. Nie balbym sie o sam email. Tylko co jest dalej.

Ja myslalem, zeby rozbic query string i dac urlendoce().

0

to nie jest żaden atak, to po prostu brednie wrzucone w parametr, który ogarnie każdy dostepny dziś normalny framework. Jesli nie wrzucisz tego w htmla a parametrów takich się nie wrzuca to żaden alert ci się nie pojawi.

0

PHP framework powienien to ogarnoc. Z tego co widze ta apka siedzi na yii 2 i tego wlasnie nie ogarnia. Dlatego musze cos sam napisac. htmlspecialchars($content, ENT_QUOTES | ENT_SUBSTITUTE) troche nie daje z tym rade. Bo w sumie ten framework tylko to robi z URLem.

3

Użyj nagłówka Content-Security-Policy i nawet jak korzystasz z najbardziej dziurawego frameworka to żaden atak XSS się nie uda.
Np możesz użyć nonce - serwer zwraca nagłówek z jakimś magicznym stringiem (dynamicznie generowanym którego atakujący nie zgadnie), np

Content-Security-Policy: script-src 'nonce-foobar

i dokładasz ten string do każdego tagu script któremu ufasz

<script nonce="foobar">...</script>

Żaden inny skrypt się nie odpali i strona jest względnie zabezpieczona przed XSS (o ile nie używasz eval na wartościach od usera w kodzie). Możesz też w tym nagłówku użyć listę źródeł skryptów którym ufasz, ale uważaj żeby nie dodawać inline, pamiętaj że kod wstrzyknięty przez XSS jest traktowany jak lokalny.

https://web.dev/strict-csp/

Teraz możesz na spokojnie dodać walidację i sanityzację danych

0
obscurity napisał(a):

Użyj nagłówka Content-Security-Policy i nawet jak korzystasz z najbardziej dziurawego frameworka to żaden atak XSS się nie uda.
Np możesz użyć nonce - serwer zwraca nagłówek z jakimś magicznym stringiem (dynamicznie generowanym którego atakujący nie zgadnie), np

Ma to sense. Ale mam duzo kodu inline. Nie dam rady powrzucac tego do plikow JS. Musze znalezc tymczasowe rozwiazanie.

Z tego co rozumiem to PHP wbudowane funcje tj htmlspecialchars() czy htmlentities() to konwertuja wylacznie elementy HTML, ale nie nic nie robia z kodem JavaScript tj chociazby alert(). W sumie widze, ze ten header() jest tez uzyty header("Content-Security-Policy: frame-ancestors 'self' *.example.com").

W URL podawany jest ?email= w ktorym jest ten alert(). Jezeli email zostanie podany w URL to zawartosc $_GET['email'] zostanie wyswietlony na stronie przy logowaniu do uzytkownika oraz alert() czy inny kod JS bedzie wykonany.

Przed wyswietleniem tego adresu email, musze go jakos przefiltrowac. I zastanawiam sie nad najlepsza opcja.

1

Patrzyłeś do dokumentacji YII?
https://www.yiiframework.com/doc/guide/2.0/en/security-best-practices#avoiding-xss
Poza tym najprostsza metoda na XSS to robić coś ze znakami otwarcia i zamknięcia skryptu: <>
Jak ich nie ma to przeglądarka nie wypluje sama z siebie okienka po samym alert. Jeśli u Ciebie na sam alert jest wywoływany JS to coś jest mocno skopane i omija wszystkie wbudowane zabezpieczenia.
Przeanalizuj co się dzieje w widokach.
Może ktoś inteligentnie wsadza w widoku dane w tagi skryptu.

0

Generalnie, ten kod:

gkjftk`};alert(document.domain);test= {test:`123

Jest wklejony tez do JS. Widze jakas var email = 'jak wyzej'. Inline JS. I normalnie JavaScript wywoluje ten kod.

Wiec nie ma tam tagow tj < i >.

Musze w PHP pobrac $_GET['email'] i przefiltrowac jakos, zeby to byl tylko email to moge sprawdzic czy to email czy nie np z filter_var(). Tylko problem jest taki, ze to moze byc email, name, date itd itd.

Wiec potrzebuje generalnego rozwiazania.

Sprawdzielm XSS w Yii i one nie dzialaja. Te Yii methody uzywaja poprstoy tych dwoch wbudowanych funkcji w PHP co podalem wyzej.

0

Tylko problem jest taki, ze to moze byc email, name, date

No ale jaki problem? Przecież i tak musisz walidować. email ma być formatu email - wytniesz wtedy nawiasy np. Imię - no chyba też nie powinno zawierać nawiasów. Data - powinna być w konkretnym formacie inaczej też powinienieś zwracać jakiś błąd
No i jak ktoś wcinął dane w var = no to ten var jest gdzieś w skrypcie? Przecież inaczej wyrenderowałby się taki HTML. Wypychaj to może w jakimś Jsonie, chyba przy parsowaniu Jsona JS powinien sam wyeskejpować takie alerty, ale to trzeba sprawdzić, koledzy od JSa może coś więcej powiedzą.

0

Wklej to w ten js.

filter_var($_GET['email'], FILTER_VALIDATE_EMAIL) ? $_GET['email'] : '';
0
Oto Twój dziwaczny e-mail:
<?= \yii\helpers\Html::encode($_GET['email']) ?>
0
dzek69 napisał(a):
Oto Twój dziwaczny e-mail:
<?= \yii\helpers\Html::encode($_GET['email']) ?>

Yii uzywa htmlspecialchars() w tej statycznej metodzie.

Widzisz roznice? https://3v4l.org/rts1W#v7.4.33 Nie ma roznicy. String jest ten sam.

1

To nie wklejaj tego bezpośrednio w JS (doczytałem dopiero). To proszenie się o problemy, bo sposób na obskoczenie problemów jest dynamiczny i łatwo o pomyłkę.

Zrób sobie osobne tagi HTML na surowe dane, a potem w JS wyciągaj sobie zawartość:

  // przeglądarka nie będzie wykonywać typu `text/plain`
  <script type="text/plain" id="email"><?= \yii\helpers\Html::encode($_GET['email']) ?></script>
 


a gdy potrzebujesz tego użyć:


  <script>
    // najpierw wyciąg sobie dane
    const email = document.querySelector("#email").innerHTML;

    // A potem użyj ich tam jak trzeba
    alert("Twój szalony adres to: " + email);
  </script>


  
0

To chyba tez lipa. Kod JS jest inline. Jak zauwazysz, ktos dosc dobrze to skonstruowal.

0

No ale ten kod pobrany z query niech będzie stringiem a nie wykonywalnym kodem, czemu używasz go tak aby się wykonywał? A najlepiej pobierz go z query samym jsem a nie przez php.

0

Generalnie ten projekt to taki CMS. User moze stworzyc sobie swoja strone uzywajac naszej appki. Dodatkowo user moze utworzyc swoj JS snippet code i dadac go do swojej strony. I tak wlasnie stalo sie w tym przypadku.

I ten alert jest normalnie wykonywany. Laduje sie strona i wyskakuje pop-up window. To jest maly atak wiem, ale moze byc znacznie wiekszy. Istnieje mozliwosc wklejenia kodu jakiego sie chce w kod zrodlowy JS.

0

@poniatowski: no ale przecież to nadal jest prostu ogarnać i miałes już wiele przykładów jak np

var user = {
    email: '`gkjftk`};alert(document.domain);test=%20{test:`123`';
}
1

Błędy masz omówione.
Jeśli dajcie możliwość wpisania wszystkiego w pole typy email bez walidacji i do tego dajcie możliwość wpisania tego w kod JS bezpośrednio to jest to błąd u podstaw, który ciężko będzie potem wyprostować i zabezpieczyć dalej przed atakami.
Po co ktoś ma mieć możliwość wpisywania sobie w pole typu email czy data czegoś innego niż de facto powinno tam być.

0
jurek1980 napisał(a):

Błędy masz omówione.
Jeśli dajcie możliwość wpisania wszystkiego w pole typy email bez walidacji i do tego dajcie możliwość wpisania tego w kod JS bezpośrednio to jest to błąd u podstaw, który ciężko będzie potem wyprostować i zabezpieczyć dalej przed atakami.
Po co ktoś ma mieć możliwość wpisywania sobie w piel typu email czy data czegoś innego niż de facto powinno tam być.

Zgadza sie, ale ja tego nie napisalem. Staram sie to jakos polatac, bo inaczej nie da tego nazwac. I dalej bedziemy pracowac nad nowym podulem, ten zostanie bo dosc duzy klinetow go uzywa, a my napisemy lepszy nowy juz.

Na razie porostu jakos zrobie escape dla tych backtick w stringu i tyle. Nie rozumiem, dlaczego htmlspecialchars() nie zalatwia sprawy, ale widac czegos nie rozumiem.

1

Z dokumtacji

' (single quote) ' (for ENT_HTML401) or ' (for ENT_XML1, ENT_XHTML or ENT_HTML5), but only when ENT_QUOTES is set

Ustawiasz w parametrze ENT_QUOTES?

0

Wlasnie tez to widzialem w dokumentacji i nie dziala https://3v4l.org/iMGAF#v8.1.18

0

No i według przykładu Ci działa. Na sigle quote ' na ` ta funcja nie działa. Sorry chyba zgubiłem się w tym jakie znaki chcesz zamieniać

0

To chyba tez lipa.

To chyba czy na pewno? Nie znajdziesz bezpieczniejszego rozwiązania niż to, co Ci podałem. Generalnie straszna Januszeria się odwala w tym temacie, także ostrożnie z doborem rozwiązań.

Kod JS jest inline.

Pokaż konkret. To Ci dam konkretne rozwiązanie, skoro nie potrafisz sobie sam zaadaptować

1
poniatowski napisał(a):

Jak byscie uchronili swoja strone przed takim atakiem XSS

https://www.mydomain.com/company/user?email=gkjftk`};alert(document.domain);test=%20{test:`123

?

Strony internetowe nie są podatne na XSS domyślnie.

Kiedy tworzysz stronę, to ona z automatu jest bezpieczna i żaden XSS nie może jej nic zrobić, chyba że sam dodasz lukę w bezpieczeństwie, i tą luką, w przypadku XSS w 99% jest niepoprawne renderowanie HTML'a, dokładnie mówiąc niepoprawne łączenie HTML'a i plaintekstu. Podobnie jak query SQL'owe nie są z defaulta podatne na SQLInjection, chyba że sam dodasz lukę przez nieodpowiednie łączenie plaintekstu (parametrów) z SQL'em.

Znajdź wszystkie miejsca gdzie łączysz HTML z plaintekstem, i odpowiednio je połącz (np poprzez .innerText zamiast .innerHTML), a jeśli to SSR to używając odopwiedniego escape'owania HTML (w miejscu gdzie ono występuje, a nie wszędzie!), i żaden XSS nie ma prawa się wkraść. Możesz też użyć silnika template'ów, który automatycznie traktuje każdą zmienną jak plaintekst, jak np JSX.

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