Autor Zpráva
Ghosting
Profil
Zdravím,
chtěl bych se zeptat jak se dá odzkoušet jestli je napsaný script náchylný na SQL injection. Dejme tomu že mám formulář pro vkládání textu do mysql a poté ho vypisuju. Jediné co používám je převedení speciálních znaků na entity při vkládání, nic víc nic míň.
V PHP nejsem zběhlý, mám v plánu si pořídit nějakou knihu pro paka, másla, amatéry jako jsem já, neznáte nějakou?
Stačí základy, (zápis do mysql, výpis, filtrace a pod...), nechci dělat něco velkého, prostě jen se chci naučit základy a nemusel někde obšlehávat kódy.
Díky .
Mastodont
Profil
Bezpečnost v PHP je tématem tří extra knih, ale ty AFAIK česky nevyšly:
PHP Architect Guide to PHP Security - http://www.amazon.com/php-architects-Guide-PHP-Security/dp/0973862106
Pro PHP Security - http://www.amazon.com/Pro-PHP-Security-Chris-Snyder/dp/1590595084
Essential PHP Security - http://www.amazon.com/Essential-PHP-Security-Chris-Shiflett/dp/059600656X

Pro "normálního" programátora je nejlepší asi ta první, ve druhé jsou probírány i věci typu SSL, SSH, což mne osobně moc nezajímalo, a ta třetí je dost stručná.
imploder
Profil
Pokud data vkládáš do SQL-kódu, je potřeba ještě použít funkci addslashes(), která escapuje řídící znaky (uvozovky a tak) v SQL.

V PHP se dá i zapnout direktiva magic_quotes_gpc, ale je to pak děsný opruz, protože se pak jakýkoliv vstup z formuláře escapuje i když se vůbec do SQL nevkládá. Takže doporučuju vypnout (.htaccess: php_flag magic_quotes_gpc off). Když je to zapnuté a navíc skript i ošetřuje potřebné vstupy sám, tak se ty znaky escapují dvakrát.
Mastodont
Profil
http://php.vrana.cz/obrana-proti-sql-injection.php
Joker
Profil
Ghosting
Podle mě to zabezpečení proti SQL injection není zas taková věda.

Obecné pravidlo bezpečnosti aplikací je: Vstupní data dělíme na důvěryhodná a nedůvěryhodná, přičemž data pocházející od uživatele jsou vždycky nedůvěryhodná.
Krátce "Nikdy nevěř tomu, co přijde zvenku od uživatele" :-)

Ve světě PHP jsou data od uživatele všechno, co přišlo s požadavkem na stránku: GET, POST, cookies, případně uploadované soubory.
Prakticky všechny zranitelnosti na SQL injection vznikají tak, že programátor tohle pravidlo porušil a spolehl se na to, že v nějakém poli dostane jen očekávaný vstup- třeba proto, že je to skryté formulářové pole, nebo se spolehl na Javascriptovou validaci na straně klienta.
srigi
Profil
Joker
Nedoverihodne udaje su aj tie v DB! Db moze byt totiz napadnuta utocnikom rovnako ako vstupny formular (napr. cez dieru v PHP kode). To znamena, ze aj udaje v DB su nedoveryhodne. V Zend manuali je jednoducha poucka - vstupne udaje filtrovat, vystupne escapovat.
armin
Profil
Joker: Podle mě to zabezpečení proti SQL injection není zas taková věda.
Jak se to veme a jak pro koho. Někdo pokládá za normální rvát do sloupce datového typu integer texty, resp. nepřímo to umožňuje (modifikací post/get). Základem injection (jakékoliv) je využití nechráněného vstupu, kdy je možné docílit "svého". Takže pokud někdo pracuje v php s getem jakoby se ani nechumelilo, tak pak nemá cenu ani moc oponovat takovýmto lidem jak je to zranitelné, nakolik oni tvrdí, že k napadení webu nedojde, protože na jejich webu se na škodnou url nikde neodkazuje, a že kdo by to modifikoval přece? Takže asi tolik z mé strany, záverěm jen shrnu tuto problematiku dvěma slovy: hlídat vstupy.
Ghosting
Profil
Pokud data vkládáš do SQL-kódu, je potřeba ještě použít funkci addslashes(), která escapuje řídící znaky (uvozovky a tak) v SQL.

Mám klasické pole (input, textarea) a jediné co provádím je převedení spešl znaků na entity. (Do mysql jako "text").
Pokud vím tak samotné uvozovky problémem nejsou ne?

Mastodont
Díky za linky, já bych spíše potřeboval něco v češtině. Knížku psanou stylem: Tohle a tohle dělá tuto a tuto a tamto zase tamto a nyní zkusem jednoduchý příklad... prostě něco pro lamy.
Mastodont
Profil
Ghosting
Těžko ti někdo u nás vydá knihu jen o zabezpečení PHP, moc by se toho neprodalo ... a minimální náklad se teď pohybuje kolem 1500 kusů (mohu se zeptat šéfredaktory Grady, jestli se něco nezměnilo, ale myslím, že ne).
Joker
Profil
srigi
Zas někde ta paranoia musí skončit, to můžu dojít i k tomu, že nejsou důvěryhodná ani data v session, protože při nabourání serveru může někdo modifikovat i session.
Nelze zas escapovat data všude, nemůžu escapovat něco, co už jsem předtím escapoval.

Navíc SQL injection je vpodstatě záležitost vstupních dat, narušení bezpečnosti u výstupních dat může k SQL injection vést jen dost těžko. Na výstupu se zase řeší věci jako zasahování do kódu stránky a podobně- což se zase obvykle neřeší na vstupu.

armin
...nakolik oni tvrdí, že k napadení webu nedojde, protože na jejich webu se na škodnou url nikde neodkazuje, a že kdo by to modifikoval přece?
Naprostý souhlas, ale to je právě ukázkové porušení pravidla, které jsem psal výše.
Správně: Jakýkoliv vstup od uživatele je nutné považovat za nedůvěryhodný.
Špatně: Tadyto políčko nemusím kontrolovat, vždyť to jde ze skrytého pole formuláře... a kdo by to modifikoval... to nikomu nebude stát za to zkoušet.

Pak to dopadne jak libimseti.cz - průběh bych popsal asi takhle:
1. fáze: Jéžiš, jaký zabezpečení, dyť si jen zkouším skripty u mě v počítači. Sám si to přece hackovat nebudu.
2. fáze: No je to na webu, ale je to jen takový malý pokus-projekt, to nikomu nebude stát za to hackovat.
3. fáze: Už to bůhvíjak dlouho běží v téhle podobě a nikdy nebyl žádný problém. A teď mám důležitější věci na práci.
4. fáze: Tyjo, on nám to někdo naboural! Jak je to možný?!
Timy
Profil
Ghosting
Díky za linky, já bych spíše potřeboval něco v češtině. Knížku psanou stylem: Tohle a tohle dělá tuto a tuto a tamto zase tamto a nyní zkusem jednoduchý příklad... prostě něco pro lamy.
Zkus knihu Zranitelný kód. Nezaměřuje se na SQL injection ani na PHP, ale na zranitelnost obecně. Ale je dobrá.
Ghosting
Profil
Timy
Dobře díky vyzkouším.
imploder
Profil
Ghosting
Mám klasické pole (input, textarea) a jediné co provádím je převedení spešl znaků na entity. (Do mysql jako "text").
Pokud vím tak samotné uvozovky problémem nejsou ne?

Pokud tím myslíš htmlspecialchars(), tak to nepomůže, to je určené na "bezpečný" (tj. že případné speciální znaky se na stránce zobrazí, nebudou prohlížečem interpretovány) výstup do HTML. Speciální znaky v SQL ošetřuje addslashes(). Uvozovky a apostrofy právě problém jsou. Dejme tomu, že se provádí příkaz:
mysql_query("select * from `index` where `keyword`='" . htmlspecialchars($keyword) . "'")

Pro $keyword="houba" pak bude příkaz vypadat takto:
select * from `index` where `keyword`='houba';

a všechno bude v pořádku. Pokud ale někdo zadá do $keyword třeba:
houba'; delete from `index` where 'a'='a

tak vznikne SQL-kód:
select * from `index` where `keyword`='houba'; delete from `index` where 'a'='a'

a celý obsah tabulky se tak smaže.
Řešení je jednoduché:
mysql_query("select * from `index` where `keyword`='" . addslashes($keyword) . "'")

takže se z uvozovek a apostrofů stanou neškodné znaky řetězce - to se v SQL značí zpětným lomítkem, což addslashes právě udělá - takže výsledný SQL-kód je:
select * from `index` where `keyword`='houba\'; delete from \`index\` where \'a\'=\'a'

Možná to escapuje i ten středník, nejsem si jistý. V každém případě to prostě zamezí uživateli ovlivňovat v SQL něco jiného než ten atribut (keyword), podle kterého se vybírá.

-- EDIT: doplnil jsem tam apostrofy, bez nich to opravdu nějak nechce fungovat. je to takhle v pořádku, Mastodonte?

HTMLSpecialChars (tj. převod speciálních znaků HTML na entity) s tím vůbec nesouvisí a ničemu takovému zabránit nedokáže. Tu je potřeba používat, když se vypisuje do stránky něco, co by mohlo obsahovat HTML-kód.
Mastodont
Profil
imploder
vznikne SQL-kód:
select * from index where keyword='houba'; delete from index where 'a'='a'

a celý obsah tabulky se tak smaže.
Zkusil jsi někdy takový kód spustit? Udělej to a napiš jestli došlo ke smazání nějakých záznamů ...
Ghosting
Profil
imploder
Ale já speciální znaky převádím už při zadávání do databáze (htmlspecialchars() ), ne při vypisování, čili si myslím že by to mělo být neškodné.
To co uvádíš ty je podle mne jen výpis, (select from), mě se nevypíše dejme tomu <?php echo $blablabla ;?> ale už jen &lt;?php echo $blablabla ;?&gt; .

Ještě abych to upřesnil, v dokumentaci systému který používám je něco podobného.

Mastodont
Teď nevím komu veřit, platí tedy to co napsal imploder?
Mastodont
Profil
imploder
doplnil jsem tam apostrofy, bez nich to opravdu nějak nechce fungovat
Ehm, a ZKUSIL sis to, jestli to něco maže s těmi zpětnými apostrofy? Mně to totiž nemaže nic a vzhledem k tomu že manuál praví jasně mysql_query() sends a unique query (multiple queries are not supported), tak to asi nikomu nic mazat nebude.
imploder
Profil
Mastodont
Ehm, a ZKUSIL sis to, jestli to něco maže s těmi zpětnými apostrofy? Mně to totiž nemaže nic a vzhledem k tomu že manuál praví jasně mysql_query() sends a unique query (multiple queries are not supported), tak to asi nikomu nic mazat nebude.
Zkusil jsem to v SQL a funguje to, o téhle vlastnosti mysql_query jsem nevěděl. Aspoň tak mysql_query() samotná má nějakou ochranu proti SQL-injectionu. Ale i v jednom příkazu jdou udělat injectiony, třeba když se má zobrazit něco patřící určitému uživateli:
select * from `veci` where `uziv`='Standa'

zobrazí věci Standy a někdo může zadat místo Standa něco jako Standa' or 'a'='a
select * from `veci` where `uziv`='Standa' or 'a'='a'

a tím získá věci všech uživatelů. Prostě to nebezpečné je a vstupy se musí ošetřit. I kdyby nešlo o záměrný útok, tak pokud se třeba zadává do formuláře text obsahující uvozovky, který se pak ukládá do databáze, tak by se to bez ošetření addslashes() neuložilo správně. Chtěl jsem ukázat, v čem SQL injection spočívá a že neošetřené uvozovky rozhodně nebezpečné jsou. Asi teda ne tolik, jak jsem si myslel, ale stejně to prostě SQL injection umožňuje a musí se tomu zabránit.

Ghosting
To, co jsem psal, je pravda. Jenom v tomhle případě by byl útok neúspěšný, protože mysql_query() umožňuje zadat jenom jeden příkaz. Nic to nemění na tom, že speciální znaky SQL je potřeba escapovat a že to funkce addslashes() dělá.

Prostě všechny údaje, které v PHP vkládáš do SQL příkazů, ošetři funkcí addslashes() a budeš v pohodě, pokud se nemýlím. Všechny, to znamená i takové, do kterých uživatel žádný text zadat ve formuláři nemůže. HTTP metodami GET a POST se dá do jakékoliv proměnné v poli $_GET[] a $_POST[] uložit cokoliv, tak se s tím musí počítat.

htmlspecialchars() je v tomhle úplně k ničemu. Dělá sice v podstatě totéž, co addslashes() - tj. převádí speciální znaky jazyka na neškodný text - ale pro jiný jazyk. HTML je jeden jazyk, SQL je úplně jiný jazyk. Některé znaky, které jsou speciální v jednom, v druhém nic nedělají. Proto je potřeba použít na ošetření speciálních znaků pro každý z těch jazyků jinou funkci:
- addslashes() pro SQL
- htmlspecialchars() pro HTML
Ghosting - škola
Profil *
imploder
Dobře díky, už jsem to snad pochopil.
Teď tedy prakticky.

Když tedy pošlu toto
select * from `index` where `keyword`='houba'; delete from `index` where 'a'='a'
přes textareu do mysql a použiju addslashes tak by mělo vypsat toto
select * from `index` where `keyword`='houba\'; delete from \`index\` where \'a\'=\'a'
ne?
Nebo jak jinak by se dala vyzkoušet fce addslashes ?
Kurnik, to jsem si myslel že to bude jednodužší :D
imploder
Profil
Ghosting - škola
ne?
Nebo jak jinak by se dala vyzkoušet fce addslashes ?
Kurnik, to jsem si myslel že to bude jednodužší :D

Ano, tak nějak se to převede. Vyzkoušet to můžeš jednoduše - ulož si do proměnné ten příkaz, nech si ho vypsat, pak na něj aplikuj addslashes a nech ho znovu vypsat a uvidíš, v čem je rozdíl.
$prikaz = "select * from `index` where `keyword`='houba'; delete from `index` where 'a'='a'";
echo $prikaz . "<br>";
$prikaz = addslashes($prikaz);
echo $prikaz;

Je jedno, jestli pomocí addslashes() vstup ošetříš až ve volání mysql_query (jak jsem to udělal já v příspěvku #13), nebo někdy dřív. Hlavní je to udělat, a to právě jednou.

pozn.: Kdybys už ošetřený vstup ošetřil znovu nebo měl navíc zapnutou direktivu magic_quotes_gpc - ta jakoby volá addslashes() automaticky na každý vstup z formuláře, není to moc šikovné, viz můj první příspěvek - tak by se lomítka začaly množit. Nebylo by to nebezpečné, jenom by vyšly vstupy obsahující speciální znaky špatně. Já jsem na to, že existuje magic_quotes_gpc, přišel právě tak, že mi skript, který mimochodem vůbec databázi nepoužíval, nesmyslně dával lomítka před všechny uvozovky a apostrofy.
Ghosting
Profil
Dobře díky.

Vaše odpověď

Mohlo by se hodit

Příspěvky nesouvisející s webem budou odstraněny.

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

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