Mnoho čitateľov mi posiela emaily, v ktorým ma žiadajú o radu akými metódami sa chrániť proti jednotlivým zraniteľnostiam. Keďže ako odpoveď odoslať odkaz na strýka googla nepomáha, rozhodol som sa napísať článoček, v ktorom by som zhrnul aspoň základne možnosti ochrany v php.
Dnes existuje relatívne dosť veľké množstvo zraniteľností, ktoré môžu postihnúť váš web. Určite by ste ich nezrátali na prsty svojej ruky. Na všetky z nich môžete nájsť množstvá dobrých článkov, ktoré radia, ako predchádzať týmto zraniteľnostiam a ako ošetrovať vstupy aj výstupy webu. Ja som sa rozhodol venovať sa piatim, ktoré podľa mňa znamenajú najväčšie a najčastejšie bezpečnostné riziko.
SQL Injection
Veľmi dobre známa zraniteľnosť, ktorá umožňuje útočníkovi prístup do databázy za pomoci hotového skriptu. V ňom sa snaží útočník pozmeniť príkazy databáze tak, aby na výstupe dostal informácie, ktoré mu majiteľ/tvorca webu určite nechcel prezradiť. SQL Injection ste už pravdepodobne videli, resp. videli ste, ako sa vyvoláva chybová hláška SQL servera, ktorá prítomnosť tejto zraniteľnosti potvrdí.
http://web.com/show.php?id=’
DB: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''\\''' at line 1 (SELECT id FROM web WHERE name RLIKE '\\'') Ak používate dnes veľmi štandardný databázový systém MySQL, tak máte priamo v PHP niekoľko vstavaných možností, väčšina už však archaických ako napríklad mysql_escape_string, alebo mysql_real_escape_string. Mne tam už chýba len mysql_really_real_true_dont_use_anything_else_escape_everything_on_the_world. Ani jedna z týchto “fantastických” funkcií vás nechráni dostatočne a to hlavne pred podľa mňa zákernejšou formou SQL Injection, tzv. Blind SQL Injection.
Aby ste sa mohli komplexne chrániť pred oboma formami, museli by ste každú premennú dopredu ošetriť na typ a veľkosť. Ruku na srdce, koľkí z vás to skutočne aj robia? Preto vo verzii PHP 5 pribudla trieda The MySQLi_STMT class, ktorá vám pomôže vysporiadať sa s touto zákernou zraniteľnosťou. Použitie je podľa modelového príkladu skutočne jednoduché, pričom vás núti pri každej komunikácii s databázovým serverom určiť typy vstupných premenných, čím odstráni potrebu určovať typ predtým v skripte.
$mysqli = new mysqli("localhost", "my_user", "my_password", "world"); /* check connection */ if (mysqli_connect_errno()) { printf("Connect failed: %s\n", mysqli_connect_error()); exit(); } $city = "Amersfoort"; /* create a prepared statement */ $stmt = $mysqli->stmt_init(); if ($stmt->prepare("SELECT District FROM City WHERE Name=?")) { /* bind parameters for markers */ $stmt->bind_param("s", $city); /* execute query */ $stmt->execute(); /* bind result variables */ $stmt->bind_result($district); /* fetch value */ $stmt->fetch(); printf("%s is in district %s\n", $city, $district); /* close statement */ $stmt->close(); } /* close connection */ $mysqli->close();
Takto by sa mala miera rizika minimalizovať na minimum, ale u PHP jeden nikdy nevie.
Cross-site Scripting (XSS)
O XSS som na tomto blogu popísal toho skutočne veľa. Nájdete tu mnoho príkladov, ako môže byť táto dnes ešte stále veľmi podceňovaná zraniteľnosť zneužitá a čo všetko dokáže.
Štandardne odporúčanou ochranou proti XSS je využívať funkciu htmlspecialchars(), ktorá je relatívne dobrou ochranou proti XSS. Samotná funkcia však nedokáže chrániť proti všetkým existujúcim typom XSS a preto je ju potrebné trošku rozšíriť. Tu by som sa rád inšpiroval hotovou ochranou spoločnosti Mozilla na svojom open-source projekte AMO (addons.mozilla.org) (vedeli ste že je to open-source, postavený na cakephp?). Páni z mozilly sa postavili k ochrane proti XSS nanajvýš zodpovedne a aplikovali ochranu proti všetkým možným spôsobom infikovania, vrátane ochrany proti využitiu iného kódovania, ako aj C0 ASCII control code.
Ako prvú ochranu zvolili kontrolu (bootstrap.php) nepovolených znakov v URL. Ak sa v URL objaví takýto nepovolený znak, aplikácia pošle HTTP chybovú hlášku č. 400.
if (array_key_exists('url',$_GET) && !preg_match('/\/api\//', $_GET['url']) && preg_match('/[^\w\d\/\.\-_!: ]/u',$_GET['url'])) { header("HTTP/1.1 400 Bad Request"); exit; }
Tento kód vás samozrejme neochráni pred samotným XSS, len zabezpečí, že sa časť prípadných útokov nepodarí vykonať. Kód si samozrejme upravte do podoby, ktorá vám vyhovuje. Táto je určená priamo pre potreby AMO. Dôležitejšiu ochranu proti XSS, ktorá odfiltruje všetky nepovolené pokusy nájdete v súbore app_controller.php.
Najdôležitejšie sú tieto časti kódu.
$sanitize_patterns = array( 'patterns' => array("/%/u", "/\(/u", "/\)/u", "/\+/u", "/-/u"), 'replacements' => array("%", "(", ")", "+", "-") ); ........ $data = iconv('UTF-8', 'UTF-8//IGNORE', $data); $data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8'); $data = preg_replace($sanitize_patterns['patterns'], $sanitize_patterns['replacements'], $data);
V tomto kratučkom kóde môžete nájsť univerzálnu ochranu proti XSS. Prvá funkcia iconv() zabezpečí, že sa dáta zkonvertujú z UTF-8 do UTF-8, pričom //IGNORE zabezpečí, že sa zahodia všetky znaky, ktoré nie je možne zobraziť korektne.
Druhá funkcia htmlspecialchars(), je už pomerne dobre známa. Tá vďaka zadanému druhému parametru ENT_QUOTES zabezpečí, že budú prevedené nielen všetky nepovolené znaky na entity, ale rovnako aj jednoduché úvodzovky. Tretí parameter určuje kódovanie pri konverzii nebezpečných znakov na entity.
Posledná funkcia preg_replace() nahradí niekoľko vybraných znakov (% ( ) + -”) na entity.
Veľmi vhodné by bolo využiť aj parameter pre cookies httpOnly cookie, ktorý bol pridaný vo verzii PHP 5.2.
ini_set("session.cookie_httponly", 1); // alebo session_set_cookie_params(0, NULL, NULL, NULL, TRUE); // v starších, alebo nepodporovaných verziách header("Set-Cookie: hidden=value; httpOnly");
Tento parameter v niektorých nových verziách prehliadačov neumožňuje pristupovať JavaScriptu k takto vytvoreným cookies. To vám môže ušetriť mnoho problémov s útočníkmi, ktorí sa snažia odchytiť cookies užívateľa aby sa mohli prihlásiť.
Clickjacking
Clickjacking je relatívne nová forma útoku, pri ktorej sa snaží útočník donútiť obeť kliknúť na objekt, ktorý vykoná nielen požadovanú ale aj útočníkom navrhnutú interakciu.
Príklad: užívateľ príde na stránku s SMS bránou, vypíše text SMS a klikne na tlačítko. Toto tlačítko samozrejme odošle SMS správu a zároveň vďaka iFrameu odošle správu na Facebook.
Ako sa hovorí, je lepšie raz vidieť ako čokoľvek ďalšie, tak tu sú dve videá, ktoré dokonale demonštrujú celý postup útoku.
Pre tento útok je možné využiť nielen iFrame, ale aj flash.
Ako sa voči nemu chrániť? Dnes moc možností neexistuje. Tou najlepšou možnosťou by bolo doslova náhodne rozloženie aktívnych prvkov na stránke. Asi vám však hneď došlo, že keby sa pri každom načítaní stránky zmenila poloha odosielacieho tlačítka, tak by ste asi radosť nemali. Preto ostáva možnosť, zakázať načítavanie vlastného webu vo v cudzom frame. Nie pre každého prijateľná možnosť, no drvivá väčšina skutočne nepotrebuje, aby ich web bol načítavaný v cudzích framoch. Na zablokovanie načítavania webu vo framoch sa využíva tzv. FrameKiller, čo je kus JavaScriptového kódu, ktorý načítanie webu vo frame neumožní. Bohužiaľ, má isté obmedzenia. Ak užívateľ nemá zapnutý JavaScript, kód je nefunkčný. No i tak ním dokážete ochrániť približne 95% užívateľov, ktorí JavaScript zapnutý majú.
<script type="text/javascript">if (top!=self) top.location.href=self.location.href;</script>
Ďalšou možnosťou bude už čoskoro možnosť využiť dodatočný meta tag pre prehliadač IE8, ktorý automaticky zabráni zobrazeniu vášho webu vo frame niekoho cudzieho. Táto možnosť síce nie je tzv. silver bullet, ale určite pomôže mierne eliminovať túto hrozbu.
Na strane užívateľa je samozrejme možné využiť veľmi populárne rozšírenie pre prehliadač Firefox NoScript, pričom existuje aj inšpirovaná verzia pre prehliadač Opera. Nemusíte sa obávať, pri NoScripte nie je potrebné zablokovať JavaScript globálne, aby ochrana fungovala.
O Clickjackingu ako aj o rozšírení NoScript plánujem už čoskoro publikovať články, ktoré by vám mali prezradiť viac. Aby som však nezostal nič dlžný ochrane proti XSS, môžete vo svojom projekte využiť IDS pre php od môjho priateľa maria, ktorý dokáže zastaviť až 99% útokov.
Cross-site Request Forgery (CSRF)
Aj o CSRF som popísal na blogu už dosť veľa, preto sa jeho podstate venovať v tomto článku nebudem.
Najväčším nebezpečenstvom u CSRF je jeho veľmi zložitá odhaliteľnosť, pričom na prekonanie ochrany proti nemu stačí jediný XSS na vytipovanom webe. Proti CSRF je dnes možné bojovať buď za pomoci WAF (Web Application Firewall) a spoľahnúť sa na jeho dobré schopnosti identifikovať prichádzajúci útok, alebo nasadiť tokeny na všetky formuláre.
WAF je možné nasadiť celkovo proti ktorejkoľvek z popisovaných zraniteľností. Jeho implementácia je relatívne jednoduchá a odporúčam ju každému, kto je pod aktívnym útokom. Je len malá pravdepodobnosť, že bude majiteľ webu schopný odstrániť všetky nedostatky do niekoľkých hodín a práve WAF je schopný zastaviť väčšinu prichádzajúcich útokov.
Ale späť k tokenom. Tokeny sú náhodne generované reťazce, ktoré sa používajú k overeniu interakcie konkrétneho užívateľa. Pri nasadení token zaručí, že formulár odoslal len ten užívateľ, ktorému sa vygeneroval a ktorý o to požiadal (otvorenie webovej stránky). Pri tokenoch je samozrejme veľmi dôležité časové obmedzenie, aby nemohlo dôjsť k opätovnému využitiu tokenu, resp. aby nemohol byť token zistený po nejakom čase a následne použitý.
Pre PHP nájdete doslova tisíce hotových riešení, ktoré vám pomôžu veľmi jednoducho nasadiť túto ochranu. Ja som narazil na dva, ktoré nemám ani otestované a ani som ich moc neskúmal. Nepovažujem to za dôležité keďže verím, že si sami nájdete ten, ktorý vám bude vyhovovať a fungovať podľa vašich predstáv.
Prvým z nich je CsrfProtect, celkom jednoduchá trieda, ktorá by sa mala po zapnutí “prilepiť” na všetky formuláre a tým ich aktívne chrániť bez nutného zásahu do kódu webu.
Oveľa lepší a kvalitnejší mi však pripadá csrf-magic, ktorý by mal tiež fungovať automaticky po zapnutí pre všetky formuláre bez obmedzení.
Výber nechám na vás, zaručene sa však dopredu presvedčte o kvalite, obmedzeniach a funkcionalite daného skriptu, aby ste po jeho nasadení neľutovali.
Záver
Pevne verím, že som na nič nezabudol a že vám tento článok pomôže zvýšiť bezpečnosť svojho webu. Mimo to vás prosím, aby ste mi už ďalej nepísali maily s požiadavkami o návody, ako chrániť vlastné weby pred rôznymi zraniteľnosťami. Na internete je skutočne dosť materiálu a ja v prípade, že si nájdem trošku času, vždy pridám ďalší článok, ktorý by vás mohol naviesť tým správnym smerom.
Ako vždy, ak máte akékoľvek návrhy, otázky, alebo pripomienky, píšte ich do komentárov po článkom.
Zaujal vás článok? Sledujte ma na Twitteri.




Já u Abakowiki používám filtr vycházející z tohoto. Jedná se o soubor pravidel pro apache mod rewrite. Takže je lehce implementovatelný i pro ty, kdo nechtějí zasahovat do php kódu.
RewriteEngine On
Options +FollowSymLinks
ServerSignature Off
RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC,OR]
RewriteCond %{THE_REQUEST} ^.*(\\r|\\n|%0A|%0D).* [NC,OR]
RewriteCond %{HTTP_REFERER} ^(.*)(|’|%0A|%0D|%27|%3C|%3E|%00).* [NC,OR]
RewriteCond %{HTTP_COOKIE} ^.*(|’|%0A|%0D|%27|%3C|%3E|%00).* [NC,OR]
RewriteCond %{REQUEST_URI} ^/(,|;|:||”>|”<|/|\\\.\.\\).{0,9999}.* [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^$ [OR]
RewriteCond %{HTTP_USER_AGENT} ^(java|curl|wget).* [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^.*(winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner).* [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^.*(libwww-perl|curl|wget|python|nikto|scan).* [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^.*(|’|%0A|%0D|%27|%3C|%3E|%00).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(;||’|”|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|cast|set|declare|drop|update|md5|benchmark).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(localhost|loopback|127\.0\.0\.1).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*\.[A-Za-z0-9].* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(|’|%0A|%0D|%27|%3C|%3E|%00).* [NC]
RewriteRule ^(.*)$ access_log.php
Velmi dobrý článok. Diki moc.
HTMLPurifier odporucam, je to dobre riesenie a ma extenzivne pokrytie na rozne rizika.
Teraz ešte zostáva prinútiť web developerov sa nad bezpečnosťou aspoň zamýšlať. Čo ja každodenne zažívam, to je hrůza…
Hi Rasto, vdaka za dorby clanok, uzitocne kody (BTW v Opere je rozbite zobrazovanie).
Kcem sa spytat odvaznu otazku >> nenapises clanok ako testovat webove aplikacie na hore uvedene utoky? Viem, ze takato tema bude velmi “horuca”, ale nie kazdy ma $$$ na zaplatenie bezpecnostneho auditu (teba :D ).
#3 dusoft: nemam rad ten projekt, pretoze ignoruje rozne rizika, ktore uz napr php-ids davno poriesil. napriklad nema garetha heyesa, ktory z dlhej chvile testuje rozne XSS metody, vid http://tinyurl.com/am5vo6.
#4 Ja.: ak prides na to ako to urobit, daj mi vediet ;)
#5 Srigi: na to mna uz predsa nepotrebujes, na to je tu owasp
Z doporučených automatických obran před CSRF bych nepoužil ani jednu. Obě totiž odesílají token i na externí adresy a obě ztratí vyplněné hodnoty, když dojde k chybě (např. expirace tokenu).
U csrf_protect navíc chybí zmínka o tom, že je nutné ho zavolat až po session_start (v návodu je “somewhere near the top”).
csrf-magic zase nechrání HTML formuláře s method=POST (což je v HTML legální a csrf-magic deklaruje kompatibilitu s HTML i XHTML) a negeneruje validní výstup (input přímo ve form). Navíc má závažnou chybu ve funkci csrf_hash, kvůli které jsou některé způsoby ochrany nefunkční (autora jsem už upozornil).
Osobně bych doporučil http://php.vrana.cz/automaticka-obrana-proti-csrf.php
U SQL injection by bylo vhodné zmínit, že pokud databázi chceme předávat data od uživatele, je potřeba mít vypnuté magic_quotes_gpc. A když už to je článek o ochraně webu, tak ten příklad převzatý z manuálu je náchylný ke XSS (v manuálu je ale příklad v kontextu textového výstupu).
Jaký smysl má ošetřovat při výstupu do HTML znaky %()+- ?
#8 Jakub Vrána: “This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 6.0.0. Relying on this feature is highly discouraged.” ja uz s tym nejak nepocitam, ale mas pravdu, zmienit som sa mohol. z pohladu bezpencosti to vsak moc podstatne nie je
to ze je priklad neosetreny na XSS je samozrejme jasne kazdemu, kto ten clanok cital a pochopil, ze su to len priklady pre jednotlive zranitelnosti a nie postup ako osetrit konkretny skript. hladas tam nieco, co tam skutocne nie je.
co sa tyka znakov ktore si uviedol, precitaj si uz skutocne velmi notoricky znamy a dnes hodne stary http://ha.ckers.org/xss.html a tam si ich daj hladat. je tam dost prikladov, kedy sa vyuzivaju tieto znaky.
#7 oooo: odosielanie tokenov na externe adresy je sice neprijemne, ale z pohladu bezpecnosti nijak relevantne, ale ano, uz som poslal navrh na rozsirenie funkcionality.
ja som k nim navody nepisal, takze nezodpovedam za ich kvalitu. kazdopadne ich pouzitie si moze nastudovat kazdy kto chce a pri pouzivani snad na takuto vec pride.
to ze by csrf-magic nefungoval na metode POST je hlupost, vsak cely test pozostava z formularov vyuzivajucich metodu post
Popsaný způsob ochrany proti Cross-site Scripting mi připadá naprosto špatný. Především se tam míchají vstupní (iconv) a výstupní (htmlspecialchars) filtry. Co je výsledkem takové funkce? Hodnota, kterou mohu leda poslat na výstup, ale už ji nemohu zpracovat uvnitř aplikace. Znamená to tedy, že uvnitř je aplikace nezabezpečená?
Smysl také nevidím v nahrazování znaků % ( ) + -” za entity.
(Úroveň kódování hodnotit nechci, jen snad to, že zvolené funkce jsou těmi nejpomalejšími)
#11 David Grudl: proti XSS sa vzdy branis na vystupe, preco by si to robil na vstupe do aplikacie? Tam si fultrujes SQL Injection, vsetko ostatne uz nechavas predsa tak. Teda ja cake nepoznam skoro vobec, neviem ci app_controller pracuje so vstupom alebo vystupom, alebo rovno oboma a na co to aplikovali oni, ale samozrejme logicky sa bavime len o vystupe. Toto predsa nie je clanok pre cloveka, co nikdy php nevidel a netusi co je to XSS ale pre niekoho, kto hlada extended pomoc. O XSS som tu toho napisal tolko, ze ked si to ktokolvek prejde, musi mu to dojst automaticky.
Nahradzanie vybranych znakov za entity som uz popisal jakubovi, mozes sa nechat inspirovat.
Zaujimaju ma rychlejsie funkcie, ktorymi by si to dosiahol, urcite aj dalsich citatelov. Pre mna je uz samotne PHP extremne pomale a preto s nim nepracujem. Len sa ho pouziva najviac ludi a 99% mailov sa tykalo PHP tak je to clanok o PHP. Python niekedy nabuduce, ked si najdem opat cas
#12 oooo: No, měli jsme o tom docela dlouho diskusi přes Jabber a závěř je ten, že se v celé řadě věcí neshodneme :-) Jen jsem holt stále přesvědčen o své pravdě, zkusím o tom něco víc brzy blognout.
#13 David Grudl: ja si pockam na blognutie a potom ti to vyvratim aj tam :)
#1 Jan Kodera: Tenhle “filtr” je úplně k ničemu! Spoustu situací neřeší, tudíž je nutné je stejně řešit v kódu, čímž se pořeší i to, co ten filtr řeší. Naopak může občas odfiltrovat chtěné uživatele…
No, nebudu se opakovat: http://webtrh.cz/7277-ochrana-webovych-aplikaci-pomoci-htaccess
#10 oooo: Odeslání tokenu na cizí server je naopak naprostá tragédie. Tím se token dostane mimo server a útočník se ho tedy může dozvědět a následně využít. Nenapsal jsem, že csrf-magic, nefunguje s metodou POST, ale že nefunguje se zápisem method=POST (tedy zápis bez uvozovek, který je v HTML validní).
Co se znaků %()+- týče, můžeš být konkrétnější? Neexistuje jediný případ, kdy by např. % nebo + vypsané do HTML textu způsobilo sebemenší problém.
#16 Jakub Vrána: aha tak to s tymi uvodzovkami som si nevsimol. To ze prejde token na iny server nie je ziadna tragedia, pretoze za prve token strati platnost (dobry token je platny len na jedinu operaciu), za druhe je minimalna sanca ze server na ktory prejde token ma pod spravou utocnik a aj keby nevie opatovne s tokenom nic urobit, lebo je davno mrtvy. ak mas modelovy priklad, tak sem s nim.
co sa tyka tych znakov, dufal som, ze si pozries xss sheet, kde su sposoby pouzitia. ak by si nezabranil zobrazovaniu tychto znakov a umoznis na webe ovplyvnenie akehokolvek parametra tagu tak to je ta situacia.
#17 oooo: Nemluvil jsem o nějakém teoretickém řešení, mluvil jsem o těch dvou konkrétních nástrojích, které jsi odkázal. Oba generují permanentně platný token a oba ho dovolí odeslat na cizí server. Je to tudíž jejich chyba. Ty argumentuješ tím, že kdyby token generovaly jinak a kdyby omezovaly dobu jejich platnosti, tak to chyba nebude. Ale to “kdyby” neplatí!
XSS Sheet znám, ale není v něm jediný případ, kdy by tebou zmíněné znaky způsobily jakýkoliv problém, pokud se použijí v HTML textu (tedy mezi značkami) nebo uvnitř hodnoty atributu uzavřené do uvozovek. Pokud myslíš použití uvnitř značky (tedy mezi znaky menší-než a větší-než), tak tam jsou zase nebezpečné všechny znaky. Přestaň prosím mlžit a uveď konkrétní příklad, kdy ti tebou uvedené ošetření pomůže.
Mohol by si mi prosim vysvetlit, aky je suvis medzi escapovanim stringu a Blind SQL injection ?
Teda ja to chapem nasledovne: SQL injection moze v PHPcku vzniknut napriklad neescapovanim stringu alebo neoverenim, ze cislo je skutocne cislo. Klasickym SQL injection vies zneuzit obe moznosti aj za pomoci Blind SQL injection vies zneuzit obe monosti. Alebo to chapem zle ?
autor:
“Pevne verím, že som na nič nezabudol a že vám tento článok pomôže zvýšiť bezpečnosť svojho webu.”
Chyba mi tam jedna podstatna skupina bezpecnostnych medzier:
-local include
-remote include
dotykajuca sa funkcii require() include() poprip. require_once() include_once()
ale aj taka malickost ako:
-remote file read
napriklad nejaky ten fileread() alebo x dalsich
a samozrejme brutality typu:
-remote command execution
ako od exec(), shell_exec(), system(), passthru(), popen()
alebo aj podcenovane eval(), assert() a dokonca za istych okolnosti aj preg_replace()
@Jan Kodera,
zaujimavy sposob riesenia obrany cez httpd.conf…
…kazdopadne toto riesenie povazujem za povrchne, a spoliehat sa IBA nan by bola chyba
allow_ur_open – webmaster ma casto tento php parameter vypnuty (od 5.2 myslym vypnute ako default) a mysli si ze je super bezpecny na remote file include… …omyl. nikto sice nedokaze includnut remote adresu, ale stale je mozne pouzit local include alebo este efektivnejsie triky ako napr php://input a php://data (od php 5.2)
#18 Jakub Vrána: uff, tak to som nevedel. ako som napisal “Výber nechám na vás, zaručene sa však dopredu presvedčte o kvalite, obmedzeniach a funkcionalite daného skriptu, aby ste po jeho nasadení neľutovali.” ja som tie skripty skutocne nekontroloval, len som sa to snazil objasnit prave na teoretickej urovni. potom mas pravdu, nie je vhodny ani jeden. napisal som autorovi druheho pripomienky, snad ich premietne uz coskoro.
co sa tyka mojho zahmlievania. ano, myslim ovplyvnenie priamo tagu. jednoduchy priklad
"+onmouseover=alert(1)+nemyslim si, ze by tam boli nebezpecne vsetky znaky, alebo mas pocit ze ano? .;- ako tieto znaky obplyvnia bezpecnost vo vnutry tagu? tu mas ten moj priklad aj v praxi t-com.sk/default.aspx?CatID=98§ion=home&NewsID=”+onmouseover=alert(1)+Mozno bude pre teba zaujimavy Browser Security Handbook kde je spracovana studia o bezpecnostnych pravidlach dnesnych prehliadacov, ktore priamo ovplyvnuju bezpecnost webu, resp. uzivatela, ktory ho navstivi.
#19 paapi: sql injection je typ zranitelnosti, ten je vzdy, aj pri blind sql injection. rozdiel je pri samotnom utoku, resp. spravani webu na sql prikazy utocnika. ak utocnik nevidi vysledok svojho utoku, ale vidi zmenu spravania webu, napriklad ze web zobrazi obsah, alebo nie. casto sa to overuje pridanim niecoho takehoto AND 0=0. Toto by mal web spracovat spravne a ak sa tam objavi chyba AND 1=0 tak sa web sprava inak, napriklad nezobrazi obsah. Potom vies, ze je tam sql injection a utok musi byt blind sql injection. ja som to oddelil v clanku len aby bolo jasne, ze je treba byt chraneny proti obom typom utokov.
#20 kid_on_the_net: tak to mas pekelnu pravdu, tie som tam mohol veru pridat. asi urobim druhy diel, nech nevynecham nic. ako som uz pisal v clanku, php sa nevenujem a chcel som sa len zbavit niekolkych citatelov. nakoniec je to vsak trosku vacsi boj, ale na druhu stranu sa aj ja nieco priucim, takze som viac ako spokojny
#21 oooo: v té ukázce stačí opět ošetřit pouze znak uvozovek, tedy jeden z těch klasických ” &
#22 David Grudl: v tejto ukazke samozrejme ano. tu je dalsia ukazka vyuzivajuca entity
Ako som uz napisal, staci, aby sa dalo pracovat priamo s tagom a moznosti je uz potom vela. Castokrat dost nestandardnych, vzdy to vsak zalezi od konkretneho pripadu. Staci si prejst http://sla.ckers.org forum, kde je roznych prikladov obrovske mnozstvo.
#23 oooo: Ukázka se nejspíš poněkud rozpadla.
Trvám na tom, že vypisovat uživatelský vstup dovnitř značky je bláhové a převod pár znaků na tom nic nemění. Náhradou např. závorky za entitu se navíc nic nevyřeší, protože entita se v prohlížečích stejně interpretuje jako závorka, takže alert(text se vyhodnotí stejně jako alert#40;text (ampersand jsem z obavy před rozpadnutím komentáře vynechal).
Když už by se měl uživatelský vstup vypsat dovnitř značky, tak jedině po aplikaci whitelistu. Převod pár potenciálně nebezpečných znaků nás neochrání třeba před roztažením elementu přes celou stránku, ke kterému žádný z tebou vyjmenovaných speciálních znaků není potřeba. Ty znaky se navíc neodstraňují, ale převádí na jejich ekvivalenty.
Důsledkem je, že převod uvedených znaků je k ničemu. Pokud si stále myslíš opak, tak pořád čekám na konkrétní příklad.
#24 Jakub Vrána: mas pravdu, bola rozpadnuta, uz je v poriadku. pozri si aj tu predtym, tam vidis jasny priklad, kedy by prave zmena na entity zabranila vyvolaniu XSS, pretoze by boli zmenene znaky ( ) + na entity.
“Náhradou např. závorky za entitu se navíc nic nevyřeší, protože entita se v prohlížečích stejně interpretuje jako závorka, takže alert(text se vyhodnotí stejně jako alert#40;text (ampersand jsem z obavy před rozpadnutím komentáře vynechal).”
to ze sa zobrazi je sice v poriadku, ale nevykona sa, co je ta dolezita cast. prave tym, ze je to entita tak to nezbehne. to je vlastne cely zmysel ochrany, pretoze parser prehliadaca vie, ze ak ide o entitu, tak ju ma zobrazit ako text a nie vykonat nie nejaky ukon. Rovnako nesuhlasim ze prevod par znakov ta neochrani pred napr. roztiahnutim elementu, pretoze sa ti to nepodari zadefinovat. Stale budes mat prevedene podstatne znaky na entity, ktore sa sice v prehliadaci zobrazia ale nevykonaju.
ukazku dam vecer, teraz mam toho dost vela.
#25 oooo: Jak už psal David, tak v ukázce 20 stačí zaměnit uvozovku.
#23 oooo: Když uživateli dovolíš vložit text přímo do HTML značky, tak tě v článku zmíněné escapování před ničím neochrání. K čemu je, když se např. onmouseover=alert(‘XSS’) změní na onmouseover=alert#40;#039;XSS#039;#41; (ampersandy opět vynechány)? K ničemu, výsledek je pořád stejné XSS.
Ukázka je zcela zmatená. Co by podle tebe měla udělat bez ošetření znaků (+-%) a co s ním?
Synopsi, asi tuším, v čem je problém. Ty máš načteno spoustu threadů, kde se řeší množství *důsledků* bezpečnostních chyb. Bohužel ti chybí znalost *příčin*, respektive se příčiny snažíš odvodit z těch důsleků, což není šťastná cesta. Přitom nastudovat si a pochopit příčiny je mnohdy snažší a dá to člověku do problematiky nesrovnatelně lepší vhled.
Nenapadají mě z hlavy nějaké kvalitní informatiční zdroje, ale snad by se hodilo http://www.whatwg.org/specs/web-apps/current-work/#parsing pro HTML, http://www.w3.org/TR/REC-xml/#charsets pro XML.
Teprve když člověk zná perfektě background, může pochopit, jak se třeba liší mysql_real_escape_string a addslashes. Bez toho je to jen víra v urban legends.
(nechci se tě nijak dotknout, komentář klidně smaž)
#26 Jakub Vrána: ano v priklade 20 staci zmenit len uvodzovky, lebo je to taky priklad. behat po internete a hladat pre vas dvoch priklady na rozne situacie nie je ziadna sranda, nie kazdy web je nachylny na konkretne to, o com sa tu rozpravame.
ale k tym entitam, je to hlupost. rozhodol som sa, ze pre teba urobim ukazku, velmi jednoduchu, ktora skutocne vysvetluje snad vsetko za mna
http://synopsi.com/poc.html
ako mozes vidiet, jedna sa o dva rovnake odkazy (pouzil som tie z prikladu 20) kde prvy odkaz je normalny a druhy odkaz je upraveny cez filter, teda entitami. snad ti spravanie prehliadaca odpovie aj za mna.
#27 David Grudl: davide, nemam najmensi dovod mazat tvoje komentare. je to predsa tvoj nazor a ja som rad, ze si najdes cas a vyjadris ho tu. ja tiez nie som neomylny a rad sa nieco priucim. kazdopadne, nemyslim si, ze by si mal pravdu.
za prve, tie linky co si dal hovoria o tom, ako by malo byt spracovane html parserom prehliadaca, no nehovoria o tom, ako to skutocne prehliadac robi. na to tu mas Browser Security Handbook, kde najdes vsetky potrebne informacie.
To o com sme sa rozpravali online som ti chcel dolozit hotovym prikladom, ale nezastihol som ta, takze tu mas linku http://pentesterconfessions.blogspot.com/2008/12/weblogic-and-non-english-character-sets.html
nie je to sice aplikovane na php, ale je to ten isty princip
#28 oooo: Tím příkladem pro Jakuba jsi demonstroval, že je potřeba na entity převést uvozovky. Bez převedení uvozovek vznikl nevalidní HTML kód, pokud bychom se pohybovali na rovině XHTML, tak by na něm prohlížeč zhavaroval (parse error). Pokud se uvozovky převedou (opakuji: je to nutné, jinak XML parser zhavaruje), tak není nutno převádět závorky.
ad odkaz: jestli jsem to dobře pochopil, článek je o tom, že nějaká metoda ResponseUtils.filter obsahuje chybu? To je samozřejmě možné, ale stále nevidím souvislost se “škodlivostí” znaku \x01 v HTML výstupu PHP.
(ano, tento znak se nesmí objevit v XML kódu, ale to je taky jiné téma)
#29 David Grudl: davide, to je len tento priklad. co ak bude priamo umozneny zapis do tagu, nielen do url, kde ju budes musiet uzavriet, teda vyuzit uvozovky. tymto prikladom som chcel jakubovi ukazat, ze prevadzanie na entity dalsich vybranych znakov funguje. stale sa obaja pozerate len na tento priklad, pricom neuvazujete vobec plosne. to obaja riesite security na konkretny pripad a v konkretnej dobe, pricom vam je jedno, ze ina uprava, ci za dlhsi cas moze byt dopad iny?
ad odkaz: opatovne si sa zameral na konkretnu vec. clanok je o vyuzivani C0 ASCII control code ako formy utoku pri rozdielnom kodovani. Gary bol natolko mily, ze mi poslal aj priklad na prevod takehoto utoku do ineho kodovania, najst ho mozes tu http://tinyurl.com/dfjufm
#30 oooo: jak mi teda převod závorek na entity z bezpečnostního hlediska pomohl? Výsledkem je řetězec, na kterém XML parser zhavaruje (tedy útok vyšel!) a HTML parser to nějak zpracuje. Jestli dojde k XSS útoku nebo ne je otázkou. Nevyskočilo okénko ve tvém browseru? Fajn, ale kde je záruka, že nevyskočí v jiném.
Takhle se bezpečnost skutečně nedělá. Pokud potřebuji vkládat uživatelský vstup přímo do názvu tagu nebo mezi atributy (což je věc, se kterou jsem se nikdy nesetkal), tak na to použiji k tomu určené techniky. Mezi nimi ale nebude převod závork na entity.
ad odkaz: omlouvám se, ale vůbec nerozumím, co má odkazovaná stránka říci. Ani já ani Jakub po tobě nechceme hledat na internetu odkazy s příklady. Proč prostě nepopíšeš útok C0 ASCII control code svými slovy?
#31 David Grudl: davide vies co je podstatou utoku? to ze ti zhavaraju XML parser ziadny utok predsa nie je, ale chyba aplikacie. U HTML to parser proste nevykona, pretoze to nie je spravne zapisane. ako vidim, ani ty si asi XSS nepochopil, inak by si nenapisal “Nevyskočilo okénko ve tvém browseru?”. Ako viem ze to nevyskoci v inom? Pretoze kazdy z tychto browserov (hovorime o tych co maju cez 1% podiel na trhu) to nevykona. Uz som ti dnes daval linku na Browser security handbook, tak si to tam mozes nastudovat.
Ten uzivatelsky vstup do tagu som dal ako priklad, mozno hlupy, stretol som sa uz so vselicim. Podstatou je, ze ak su tieto znaky prevedene na entity, potom je utok neucinny. Pre mna je ale zaujimave, ze tento postup vyuzivaju viacere velke weby vratane mozilla.org.
Ja som sa ti uz snazil vysvetlit cely utok za pomoci vyuzivania ASCII kontrolneho znaku pri inom kodovani cez IM. Dal som ti rozne priklady, jedinou tvojou odpovedou bol unicode znak, ktorym si potvrdzoval, ze utf-8 ho zobrazi korektne. Na blogu http://pentesterconfessions.blogspot.com/ su popisane rozne metody vyuzivania inych kodovani na napr. TOMCAT serveri. Ja viem ze tam autor ukazuje vsetko v Jave, ale taky rozdiel to zas nie je. Keby som ti to vedel lepsie podat, tak uz by sme neviedli tuto debatu, preto sa ti snazim dat vsetky odkazy, ktore k tomu mam.
#32 oooo:
> davide vies co je podstatou utoku? to ze ti zhavaraju XML parser ziadny utok predsa nie je, ale chyba aplikacie.
Proč tedy nabádáš k zavádění chyb do aplikace?
Hele, už tu diskusi utneme, ne? :-)
#33 David Grudl: pretoze radsej chyba v aplikacii ako uspesne vykonany utok. pevne verim, ze sa to cele da osetrit na tolko, aby pri chybe v XML jednoducho aplikacia nespadla, ale vratila chybovu hlasku. Castokrat sa to tak robi aj za cenu obmedzenia uzivatela, ze ak posle nebezpecne (alebo povedzme nestandardne) znaky, tak mu jednoducho vratim chybu.
#34 David Grudl: je fakt, ze sa motame dokola. skoda je len, ze sme nikam nedosli. snad nabuduce :)
#27 oooo: Ten POC je zle, zatvorky neprevadzas na ekvivalentne html entity.
Vieš Synopsi, že v tvojom príklade http://synopsi.com/poc.html v druhom odkaze (v tom tebou ošetrenom proti XSS)
si zamenil znak ( za entitu lt; a znak ) za entitu gt; (???). Podľa mojej skromnosti je to hlúposť,
keď stačilo zameniť začiatočnú úvodzovku za entitu, ktorú si z nepochopiteľných príčin ty
nezamenil. Potom zátvorky nemusíš vôbec zamieňať. Presnejšie stačí zamieňať iba znaky (&’”) a používať UTF-8.
Len poznamenám, že v skutočnom riešení by sa v tom odkaze aj tak parameter NewsID (ak je to číslo) ošetril
funkciou intval() alebo by sa premenná jednoducho pretypovala, cez (int). Na tento
odstavec však nemusíš reagovať.
Prečo sa stále nezmyselne hádaš? Ja viem, už to zašlo ďaleko, ale stále je šanca
priznať si chybu :) . Vydaj ten článok napr. odznova prepracovaný. Z komentárov je evidentné,
že Jakub a David majú pravdivostnú prevahu, resp. nedzá sa ti čudné, že nikto s tebou
nesúhlasí?
Táto diskusia sa začína podobať na diskusiu s Radovanom K (v úlohe Synopsiho).
#37 rudot: nie? a co s nimi robim. keby si cital clanok, tak by si vedel, ze zatvorky prevadzam na entity poslednou funkciou. takze netusim comu nerozumies.
#38 Palo: Palo, podla tvojej skusenosti na com. Ako som povedal, s vami je tazka rec, pretoze ak vam nenajdem konkretny priklad, tak nie ste asi schopni porozumiet fiktivnemu prikladu. Ja som zobral tie dva linky z toho prikladu len aby som to mal na com postavit, vobec tam neslo predsa o uvodzovky. Jakub povedal #26 Jakub Vrána: ze ak zmenim tie zatvorky na entity (teda vynechame prevod uvodzoviek), tak to vyvola XSS. Ja som mu ukazoval presny opak. To su tie nepochopitelne priciny, kedze si zarucene necital komentare, alebo aspon nie je poriadne.
Ano ja suhlasim ze v tomto pripade by pomohlo overovat, ci sa jedna o integer a ak nie tak to poslat do …, ale predsa bezpecnost nie je jednotvarna, nemozes si upravovat pravidla podla toho, ako ti to v konkretnom pripade vyhovuje. Musi to byt plosne, preto su aj navrhnute opatrenia plosne pre uplne kazdy z pripadov ktory by mohol nastat.
No a k nezmyselnemu hadaniu, to ma celkom zaujima, v com je to nezmyselne. Ja si nepotrebujem priznavat chybu, nie som jediny, kto tento nazor zastava. Ako je uz v clanku napisane, skript je odkopirovany z AMO, takze skus vysvetlit niekomu s milionovou navstevnstou, ktory si presiel stovkami tisic utokov, ze vies vlastne lepsie ako on co robi. Celkom ma zaujima, co ti na taky email napisu, tak to prosim pre moje potesenie urob. Neviem cim si prisiel na tu pravdivostnu prevahu, ale to ze so mnou nik nesuhlasi si uplne trafil. Tych momentalne 11,538 unikatnych citatelov, alebo z toho ze vy traja ste s tym nesuhlasili. Ono to tak uz byva, ze vacsinou ludia ktori suhlasia sa v komentaroch nevyjadruju, preto uz Arthur Dent pisal o Like buttone.
Kazdopadne si vazim nazor kazdeho a preto ziadne neblokujem, pokial nejde o skutocne infantilnosti. Nie vzdy mam pravdu, a necham uz na citateloch, aby si to rozhodli. Kazdy komentar moze prispiet k niecomu dobremu. Napriklad samotny jakub, ktory mi jasne ukazal, ze mnou odporucane CSRF ochrany pre PHP nedosahuju potrebnych kvalit. Takze ak niekto bude hladat poriadnu ochranu, uz si bude vediet poradit. O to predsa ide.
#28 oooo: Já přece nechci, abys někde běhal, stačí ryze teoretický příklad, Proof of Concept. Tvůj poc.html je zcela špatně – neošetřuje uvozovky a kulaté závorky převádí na entity pro špičaté závorky. Proto způsobí syntaktickou chybu. Jak už jsem dokázal v komentáři 25, tak tebou doporučená ochrana je k ničemu, pokud povolíš uživatelská data uvnitř značky.
#32 oooo: To, že se vinou nevalidního XML nezobrazí stránka, je přeci útok DoS. Je to podobné jako roztažení elementu přes celou stránku zmiňované v komentáři 23 – style=position:absolute;left:0;top:0;width:1000px;height:1000px; neobsahuje žádné tebou “ošetřované” znaky a v prohlížeči se interpretuje.
#39 oooo: Co se AMO týče, tak ošetření znaků (+-%) ničemu nevadí v tom smyslu, že nezpůsobí žádnou chybu. Jen je to zbytečná práce. Ošetření těchto znaků commitnul John z CakePHP, kterému jsem 5.3.2009 psal dotaz, k čemu to je. Zatím se neozval. Odhaduji, že si to někde přečetl bez pochopení souvislostí a od té doby se to táhne přes AMO až sem. https://trac.cakephp.org/changeset/395
Já se taky přidám, i když jsem původně ani snad nechtěl. Rastislave, pokud dobře počítám tak 4 lidé napsali, že druhý příklad v poc.html je špatný, já jsem další. Ten příklad je špatný, použil jsi nesprávné entity při nahrazování (lt namísto #40) a další tvoje argumentace okolo tohoto příkladu je pak nesmyslná.
#40 Jakub Vrána: #41 Martin Straka: uff, ja som si to vazne neuvedomil, ze som zadal zle entity. mate obaja pravdu, nejak som si to nespojil do suvislosti (myslim komentare)
#40 Jakub Vrána: to ze ti spadne XML interpreter nie je ziadny DOS, kedze spadne len konkretnemu uzivatelovi, ktory zada zle znaky. Tam to je Application Error. Ale ano, prijemne by to urcite nebolo. S tym style mas samozrejme pravdu.
Ako som uz pisal u teba, IE stale este umoznuje spustit javascript aj za predpokladu, ze je enkodovany ako url HREF=”http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D”. snazil som sa najst aj realny priklad, ktory este pred par dnami fungoval, ale uz som to reportoval a opravili to. dalsie sa mi hladat nechcelo. samozrejme tento priklad funguje aj v roznych obmednach, nie len tak, ako som ho sem postol.
zmena na entitu znaku – by pomohla pri -moz-binding
viac okolo double encoding
http://www.owasp.org/index.php/Double_Encoding
http://xforce.iss.net/xforce/xfdb/18052
#42 oooo: DoS to je v případě, kdy jeden uživatel způsobí pád XML parseru druhému uživateli.
Jak už jsem vysvětloval u sebe, tak “ošetření” http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D nevyřeší vůbec nic.
Já už asi chápu, proč se točíš v kruhu. Ty nejspíš předpokládáš, že aplikace používá nějaký blacklist na kontrolu uživatelských vstupů a domníváš se, že převedením některých znaků na entity ošetříš vstupy, které tento blacklist nepokrývá. Jak už jsem ale např. v komentáři 25 dokázal, je tento přístup odsouzen k nezdaru. Když už se má uživatelský vstup vypisovat jinde než v HTML textu nebo uvnitř hodnoty atributu uzavřené do uvozovek (kde ho stačí ošetřit funkcí htmlspecialchars), tak je nutno ho ověřovat na základě whitelistu.
Co se -moz-binding týče – napadá tě, co se stane, až se vlastnost standardizuje a název se změní na binding? Nevidíš, že je jenom náhoda, že tato vlastnost obsahuje pomlčku stejně jako desítky dalších CSS vlastností a že záměna pomlčky za entitu není obranou proti této vlastnosti a znepřístupní ji vlastně jen nedopatřením?
#43 Jakub Vrána: ano, keby slo o moznost ulozit taketo data v DB. Potom by vsak utocnik asi siahol po CDATA, aby utok opatovne vyvolal, ako po niecom, co by zhodilo XML parser, co by mu bolo viacmenej k nicomu.
Nad ziadnym blacklistom som nikdy neuvazoval, hladam racionalne vysvetlenie prevedenia tychto znakov na entity. Zakladne znaky <> ” ‘ su jasne, ten zvysok az tak nie, preto hladam dovod, preco tomu tak je. Rovnako ako ty som im poslal mail, pretoze ma to zacalo po tychto komentaroch celkom zaujimat. Je fakt, ze zmena na entity tomu nijak nepomohla, teda ze sa prevadza par znakov naviac.
-moz-binding sa asi nikdy standardizovat nebude, tak aspon jedna vec, kde by to zafungovalo. Ale ako si uz povedal, je to iba nahoda.
aleluja
Ja som nasiel zaujimavu fciu, ktora dokaze parsovat html tagy na zaklade pravidiel, ktore si dotycny developer vytvori.
http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed
Sice trosku dlhsie trva kym ju clovek nastavi, ale potom moze kludne nasadit full featured wysiwyg editor na stranku bez toho aby sa obaval, ze mu pusti nejaky ten kod, ktory by tam nemal byt. Okrem ineho dokaze opravovat nevalidne tagy a ine zaujimave ficury.
P.S ak si nechcete ogrcat monitor, nech vas ani nenapadne pozerat ten kod ;)
Ja som pocul o takej dost zvlastnej a nestandardnej ochrane: web prijme prijme data (retazce) kazdy z nich si rozlozi na ASCII cisla znakov a do sql ich nasledne zapise. Napr..
INSERT INTO test (string) VALUES (CHR(cislo1,cislo2,…));
Nesuhlasim s tebou ze mysql_real_escape_string(); neni dostatocne ucinna. Ajked v istom zmysle mas pravdu, ale len taku ze pokial ten vstup neni v apostrofof. Cize:
select * from xxx where id = 1
bude sql injection fungovat priam dokonale ale kazdy skusenejsi dava vsetko do uvodzoviek cize ako by si obisiel toto ak by INPUT_STRING bol prehanany cez mysql_real_escape_string???????!
SELECT * FROM my_table WHERE `name` = ‘INPUT_STRING’