« 1 2 »
Autor Zpráva
Andreas
Profil *
Dobrý den, je takovýto SQL dotaz bezpečný?
$mysqli->query("SELECT * FROM tabulka WHERE xxx='".htmlspecialchars($_POST["xxx"])."' AND yyy=".intval($_POST["yyy"]);
Děkuji.
Jan Tvrdík
Profil
Andreas:
Ne, funkce htmlspecialchars neslouží jako ochrana proti SQL injection. K tomu se používá např. mysqli_real_escape_string. Viz také phpfashion.com/escapovani-definitivni-prirucka.
juriad
Profil
NE, v žádném případě; vždy escapuj podle situace:
při výpisu stránky: htmlspecialchars
při sestavování SQL: mysql_real_escape_string

ukázka SQL injection v tvém případě:
$_POST['xxx'] = "' OR 1=1 --"
Str4wberry
Profil
je takovýto SQL dotaz bezpečný?

To nelze takto určit. Zkuste si schválně do $_POST["xxx"] dát třeba jednoduchou uvozovku. Pokud tam přežije v původní podobě, ochrana je nedostatečná.

Jinak funkce htmlspecialchars neslouží primárně k ochraně proti SQL injection. Jak už název vypovídá, slouží pro ošetřování HTML.
Andreas
Profil *
Toho jsem se bál... A když chci mít ošetřená data už v DB, tak prostě použiju mysql_real_escape_string(htmlspecialchars($_POST["text"]))?
Jan Tvrdík
Profil
Andreas:
Ano, ale většinou je lepší volat htmlspecialchars až při výpisu.
pcmanik
Profil
Andreas:
Keď už používaš mysqli prečo neprejsť rovno na vysší level a použiť prepare statement?
Andreas
Profil *
A přináší mi to nějakou výhodu krom toho, že nemusím ručně escapovat?
Pro číselný hodnoty ten intval stačí?
Jan Tvrdík
Profil
Andreas:
A přináší mi to nějakou výhodu krom toho, že nemusím ručně escapovat?
Předpokládám, že reaguješ na prepared statements. Jejich výhoda je jednak v tom, že způsob myšlení, který při jejich použití máš, snižuje šanci SQL injection. U ručního escapování je poměrně velká šance, že v jednom ze stovek dotazů na něj zapomeneš. Ze stejného důvodu mám rád dibi. A jednak také v tom, že by měly být o něco rychlejší na zpracování.

Pro číselný hodnoty ten intval stačí?
Stačí jako ochrana před SQL injection. Nicméně může být vhodné validovat vstup striktněji. Teď když ti někdo do $_POST["yyy"] vloží 123BLBOST nebo i jenom BLBOST, tak to bez problémů přijme a převede na 123 resp. na 0.
Andreas
Profil *
Děkuji. Ještě se zeptám, když použiju funkci array_map("mysqli_real_escape_string", $_POST), tak tím vlastně ošetřím všechna data v POSTu a nemusím pak psát 20x $mysqli->real_escape_string($_POST[...]) v SQL dotazu, že?
Alphard
Profil
A fakt chcete vždy všechno ošetřovat touto funkcí? On už zde tento nápad jednou byl...

Navíc bývá zvykem neměnit globální proměnné, je to moc magické, nelze to doporučit.
peta
Profil
Jan Tvrdík:
"Ano, ale většinou je lepší volat htmlspecialchars až při výpisu. "
Zalezi na tom. Pokud muzes, je lepsi co nejvic operaci udelat uz pri ukladani, protoze vypis se dela mnohonasobne vic a kazda milisekunda je draha.
Na druhou stranu, pokud ma omezene policko na velikost znaku, pak htmlspecialchars navysi pocet znaku.
juriad
Profil
peta:
A krásně si tím zazdíš cestu buď k případným pozdějším analýzám dat, nebo (hůře) k možnosti publikace dat do jiného formátu než je html (například pdf reporty).
Str4wberry
Profil
Nemyslím si, že text se zaentitovanými znaky <>&"' je nějak zvlášť nevhodný pro další zpracovávání. V zásadě je to problematické akorát pro určování délky. A případný zpětný převod je triviální.
Joker
Profil
peta [#12]:
Nesmysl.

Jednak nelze bez znalosti situace paušálně tvrdit, že číst se bude mnohonásobně častěji než zapisovat.
A jednak je hloupost na oltář mantry „každá milisekunda dobrá“ obětovat flexibilitu při práci s daty.

U většiny stránek je úplně jedno, jestli skript běží 80 nebo 90 milisekund a ani třeba 350 by nebyl problém. A pokud by na tom záleželo, nejspíš stejně bude výhodnější udělat cache pro celý sestavený výstup, než přesouvat htmlspecialchars.
Zato fakt, že můžu udělat jiný formát výstupu nebo jednoduše změnit třeba konverzi z ENT_COMPAT na ENT_QUOTES když je potřeba, může být dost podstatný.

Str4wberry:
Nemyslím si, že text se zaentitovanými znaky <>&"' je nějak zvlášť nevhodný pro další zpracovávání.
Pokud ten výstup bude v něčem jiném než v HTML, nebo skript který to zpracovává sám dělá htmlspecialchars (v nejhorším případě s jiným nastavením než ten ukládací skript do databáze), tak ano.

A případný zpětný převod je triviální.
No, jak kdy. S některými nastaveními html_specialchars nemusí zpětný převod být vůbec možný.
Str4wberry
Profil
Reakce na Jokera:
První reakce ovšem platí jen v případě, že reversní převod nebude možný. Což při běžném použití htmlspecialchars možné je. Tedy v tomto případě mají oba přístupy své výhody i nevýhody.
Camo
Profil
Joker:
Čo je na tom nesmysl?
Ja tam vidím napísané "Zalezi na tom" a nemyslím, si, že je hlúposť urobiť jeden preklad na entity pri ukladaní do DB než ho robiť pri každej požiadavke. Skôr je hlúposť to robiť naopak. Ale samozrejme "Zalezi na tom". Peta nikde paušálne netvrdí, že čítať sa bude mnohonásobne viac krát ako zapisovať, ale myslím, že vo väčšine prípadov, čo sa týka webu je to proste tak.
Joker
Profil
Str4wberry:
První reakce ovšem Andreas [#10] platí jen v případě, že reversní převod nebude možný.


Camo:
Čo je na tom nesmysl?
Vždyť jsem to tam popsal.
1. Nesouhlasím s „Pokud muzes, je lepsi co nejvic operaci udelat uz pri ukladani
V případě escapování se obvykle doporučuje escapovat až ve chvíli, kdy je to potřeba. Svým způsobem to je trochu podobné myšlence „preventivně“ prohnat celé $_POST přes myqli_real_escape_string().
Ostatně úplně stejná myšlenka („preventivně“ escapovat úplně všechno) stála za magic_quotes, což je podle mě snad vůbec nejhorší vlastnost v historii PHP.

2. Nesouhlasím s „vypis se dela mnohonasobne vic“, protože to na základě informací z tohoto vlákna nelze tvrdit. Úplně klidně se může dělat o něco víc, zhruba stejně, o něco méně nebo mnohonásobně méně ve srovnání s ukládáním.

3. Nesouhlasím s radou obětovat čitelnost dat ve prospěch zrychlení skriptu.

Peta nikde paušálne netvrdí, že čítať sa bude mnohonásobne viac krát ako zapisovať
Vždyť to tam přímo píše.

nemyslím, si, že je hlúposť urobiť jeden preklad na entity pri ukladaní do DB než ho robiť pri každej požiadavke. Skôr je hlúposť to robiť naopak.
Kdysi jsem si tohle taky myslel, že je lepší escapovat HTML hned na začátku.
Postupem času jsem přešel k tomu, že je lepší escapovat HTML ve chvíli, kdy chci HTML výstup.
Možná krom výše zmíněných problémů stojí zato zmínit ještě potíže s editací záznamů, kdy načtu záznam, nějak s ním pracuju, uložím… a buch, ta původní část je escapovaná dvakrát.
A pak je nápad, který tomu nasadí korunu: Chtěl bych do toho obsahu vložit i nějaký svůj kód, který se bude zobrazovat jako HTML. No a protože ten obsah mám escapovaný a zobrazuji ho přímo, „není nic snazšího“, než si k němu po escapování připojit neescapované HTML a voilá.

To všechno známe :-)
Camo
Profil
Joker:
Zoberme si napríklad toto fórum. Určite má implementovanú nejakú ochranu ako je htmlenntities, alebo niečo podobné. Ako sa do DB ukladajú dáta tejto diskusie? Neverím, že by sa ošetrovali pri výpise. Alebo hej?

Žiadne voilá ani to všechno známe neplatí...
Joker
Profil
Camo:
Zoberme si napríklad toto fórum.
Já z něj „zevnitř“ viděl jen malou část, kdyžtak mě opraví někdo s většími znalostmi.

Nakolik vím, toto fórum funguje přibližně tak, jak jsem popisoval já s tou optimalizací na výkon.
To znamená, že jako zdrojový obsah se ukládá BBCode zadaný autorem příspěvku. Ale HTML se negeneruje při každém zobrazení příspěvku, používá se cache.

Jinak s těmi všemi vylomeninami co zdejší BBCode umožňuje a zároveň možností editovat příspěvky (v BBCode) mě překvapuje, že někoho překvapuje, že jako zdrojová data se ukládá ten BBCode.
Str4wberry
Profil
Reakce na Jokera:
• Nevím, co přesně myslíš tím escapováním HTML. Pokud chci editovat HTML pomocí HTML stránky, musím samozřejmě taková data do editačního formuláře stejně tak upravit funkcí htmlspecialchars. Tedy v tom problém v tomto případě není.
• A pokud budu najednou chtít HTML značky interpretovat, budu v čistém řešení nucen upravovat zpětně všechna data, aby se mi náhodou neinterpretovalo něco, co nemá, tedy to také nevypadá jako výhoda čistého řešení.


mě překvapuje, že někoho překvapuje, že jako zdrojová data se ukládá ten BBCode
Ehm, on se právě neukládá. :–) Data všech příspěvků jsou ve finálním HTML. Pro editaci se používá reversní funkce HTML → BB. Což je celkem otravné, protože pro všechny nové BB kódy se musí vytvářet zpětný převod do HTML. Nicméně i to má nějakou tu výhodu — nevzniká redundance, tabulka příspěvků tak nemusí mít takřka dvojnásobnou velikost.
Jan Tvrdík
Profil
Andreas:
použiju funkci array_map("mysqli_real_escape_string", $_POST)
Tohle je špatný přístup, jak už bylo naznačeno. Navíc nebude vůbec fungovat, pokud $_POST bude obsahovat nějaká pole.
Joker
Profil
Str4wberry:
Ehm, on se právě neukládá. :–)
Aha :) Tak to se omlouvám za mystifikaci.

Tak se opravím: Tak jak jsem popsal, mínus cache, funguje současná „alfaverze“ učebnice PHP, kde ten kód vznikl analýzou odpovídající funkčnosti z DJPW tak, aby to bylo kompatibilní.
Že v tom kódu existuje i reverzní funkce pro převod HTML na BBCode jsem si sice všiml, ale víceméně jsem ji ignoroval s tím, k čemu to proboha může být dobré :)

pokud budu najednou chtít HTML značky interpretovat
Já to myslel trochu jinak, třeba „administrátorská“ vsuvka uvnitř textu, která může používat HTML. Původní obsah by se pořád neinterpretoval.

Nicméně kdybych se v nějaký moment rozhodl uložený obsah začít interpretovat jako HTML:
- Pokud mám uložený původní formát obsahu, na výpisu změním htmlspecialchars na strip_tags s povolenými tagy.
- Pokud mám uložený obsah projetý htmlspecialchars, je asi nejschůdnější řešení projet všechny záznamy nějakým unhtmlspecialchars a pokračovat podle prvního bodu.
Str4wberry
Profil
Pokud mám uložený původní formát obsahu, na výpisu změním htmlspecialchars na strip_tags s povolenými tagy.

Nevyhovující. Negativně narušíš stávající obsah. Přestane fungovat v textu „a<b“, „interval <0;1>“ atd. Navíc strip_tags neřeší potenciálně nebezpečný obsah v atributech povolených HTML značek.
Jan Tvrdík
Profil
Těch problémů z ukládáním escapovného textu je víc než již zmíněný problém s délkou. Ten základní (bezpečností) problém je IMHO v tom, že aby to dobře fungovalo, musí být vždy naprosto jasné, v jakém formátu jsou data v kterém sloupci databáze. Ukládat všechny data ošetřené htmlspecialchars se v praxi moc nehodí. Představte si, že má někdo nick <adam>. V databázi tedy &lt;adam&gt;. Když chcete najít uživatele podle jména, musíte nick nejprve ošetřit htmlspecialchars a pak až poslat do databáze. A takových míst bude spousta a někde se na to snadno zapomene. Budeme-li ukládat jen některé sloupce escapované, tak vzniká problém nejistoty, zda ten daný sloupec je či není escapovaný. Nejistota vede k bezpečnostním chybám ještě snáz. Ukládání všech data v jejich surové podobě je mnohem snáze uchopitelné a programátoři netrpí nejistotou.
Joker
Profil
Str4wberry:
Negativně narušíš stávající obsah.
OK, tak HTML Purifier nebo něco takového.
Camo
Profil
Takže ako vidím, je to presne tak ako som predpokladal a to som zdroják diskusie ani nevidel.
Proste je to logické. Sme na internete a rýchlosť nieje mantra, ale fakt. Takže ak stojím pred otázkou či prekladať iba raz(resp. pri editácii len jeden príspevok), alebo ukladať surové data a prekladať pri každom zobrazení(napriek kešovaniu) všetko, tak mi je jasné, že si zvolím prvé riešenie.

PS: By ma zaujímalo, ako sa správne kešujú požiadavky. Nemá niekto nejaký link? Ď.
Joker
Profil
Camo:
Proste je to logické
Mně to přijde logické přesně naopak.
Jinak poznámka, tato diskuse historicky vychází z prastaré verze miniBB s hromadou bezpečnostních chyb, které se zdejší vývojáři postupně snaží odbourávat.
Tzn. že něco používá tato diskuse ještě neznamená, že to tak je správně. Viz třeba toto.

Můj názor tedy zůstává stejný: Je lepší mít uložený nezpracovaný zdrojový text a escapovat ho pro výstup, jaký chci v tu chvíli udělat.

Přičemž platí, že jakékoliv obecné pravidlo v programování je možné porušit, jestliže k tomu existují pádné důvody a zároveň jsem si naprosto jistý, co dělám.
Str4wberry
Profil
Reakce na Jokera:
Pořád je problém, že neodlišíš staré značky, které se cíleně neinterpretovaly, a nové – stejné – které se interpretovat mají.

Reakce na Jana Tvrdíka:
1) Bezpečnostní risiko představuje na druhou stranu i ukládání surových dat, když se někde zapomene na ošetření při výpise.
2) Nejistotu máme i při ukládání jen surových dat, protože něco je potřeba escapovat při výpise a něco ne. Ta nejistota je jen na jiné straně.

Reakce na Cama:
Logické je, že se formátování každého příspěvku neprovádí při každém načtení, protože bychom potom čekali na zobrazení témata dlouhou dobu. Kešování může být např. v podobě dalšího sloupce v tabulce příspěvků (sloupec s finálním HTML slouží k výpisu, sloupec se syrovými daty k editacím) nebo je možno kešovat třeba výslednou HTML stránku tématu a v tabulce příspěvků pracovat jen se surovými daty.
Joker
Profil
Str4wberry:
Pořád je problém, že neodlišíš staré značky, které se cíleně neinterpretovaly, a nové – stejné – které se interpretovat mají.
Ano, přesně tak.
Já ten problém myslel trochu jinak: Když se ukládá surový obsah, je hned jasné, že se to musí udělat jinak, nemůže vzniknout směs escapovaného a neescapovaného obsahu, protože se prostě ukládá jen neescapovaný.
Když se ukládá escapovaný obsah, tak to tak zdánlivě udělat můžu: Přidám si tam neescapované HTML a ono to nějak funguje. Do té doby než začnu dělat editaci nebo něco a dodatečně zjistím, jaká blbost to byla.

2) Nejistotu máme i při ukládání jen surových dat, protože něco je potřeba escapovat při výpise a něco ne. Ta nejistota je jen na jiné straně.
To bych neřekl.
Když mám jen surová data (neescapuji nic), mám jistotu, že vždy musím řetězce na výstupu escapovat pro daný výstupní formát.

Když chci převádět HTML, tak v první řadě u čeho vlastně? Budu přes htmlspecialchars prohánět všechny řetězce? Co třeba jméno, bydliště, telefonní číslo, e-mailovou adresu, webovou adresu (URL), cestu k souboru na disku?

Obvykle to skončí tak, že se escapují jen ty sloupce, kde se očekává HTML a na zbytek se nastaví validace. A pak to stojí na tom, že ta validace bude neprůstřelná (a krom toho to celkem zbytečně omezuje povolené hodnoty té položky).
A co hodnoty, které znaky <>&"' obsahovat mohou (validací je zakázat nelze), ale nikdy se nevypisují do HTML?
A co když je za dva roky budu chtít v HTML začít používat?
« 1 2 »

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

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

0