Autor | Zpráva | ||
---|---|---|---|
Andreas Profil * |
#1 · Zasláno: 10. 3. 2013, 11:32:53
Dobrý den, je takovýto SQL dotaz bezpečný?
$mysqli->query("SELECT * FROM tabulka WHERE xxx='".htmlspecialchars($_POST["xxx"])."' AND yyy=".intval($_POST["yyy"]); |
||
Jan Tvrdík Profil |
#2 · Zasláno: 10. 3. 2013, 11:50:51
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 |
#3 · Zasláno: 10. 3. 2013, 11:51:39
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 |
#4 · Zasláno: 10. 3. 2013, 11:56:28
„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 * |
#5 · Zasláno: 10. 3. 2013, 12:24:08
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 |
#6 · Zasláno: 10. 3. 2013, 12:25:29
Andreas:
Ano, ale většinou je lepší volat htmlspecialchars až při výpisu.
|
||
pcmanik Profil |
#7 · Zasláno: 10. 3. 2013, 12:35:46
Andreas:
Keď už používaš mysqli prečo neprejsť rovno na vysší level a použiť prepare statement? |
||
Andreas Profil * |
#8 · Zasláno: 10. 3. 2013, 13:01:26
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 |
#9 · Zasláno: 10. 3. 2013, 13:19:14
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 * |
#10 · Zasláno: 10. 3. 2013, 23:42:54
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 |
#11 · Zasláno: 10. 3. 2013, 23:54:54
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 |
#12 · Zasláno: 11. 3. 2013, 10:50:03
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 |
#14 · Zasláno: 11. 3. 2013, 11:29:39
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 |
#16 · Zasláno: 11. 3. 2013, 14:35:46
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 |
#18 · Zasláno: 11. 3. 2013, 15:51:11
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 |
#21 · Zasláno: 11. 3. 2013, 16:52:33
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 |
#22 · Zasláno: 11. 3. 2013, 18:02:46
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 |
#23 · Zasláno: 11. 3. 2013, 19:27:54
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 |
#24 · Zasláno: 11. 3. 2013, 21:39:04
„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 |
#25 · Zasláno: 11. 3. 2013, 21:56:54
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 <adam> . 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 |
#26 · Zasláno: 11. 3. 2013, 22:48:26
Str4wberry:
„Negativně narušíš stávající obsah.“ OK, tak HTML Purifier nebo něco takového. |
||
Camo Profil |
#27 · Zasláno: 12. 3. 2013, 09:17:17
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 |
#28 · Zasláno: 12. 3. 2013, 09:37:31
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 |
#29 · Zasláno: 12. 3. 2013, 09:57:45
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 |
#30 · Zasláno: 12. 3. 2013, 14:21:21
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? |
||
Téma pokračuje na další straně.
|
0