Autor Zpráva
RPG
Profil
Ahoj všem,

Při programování dalšího z mých projektů mě napadl způsob, jakým by se dalo přihlášení uživatele chránit proti útoku přes SQL injection.

Při registraci uživatele by se uložilo následující:

1. login, plaintext,
2. login, hash (dejme tomu sha1),
3. heslo, hash.

A při přihlašování bychom vložená data nejprve hashovali (to by svým způsobem "zničilo" jakýkoliv škodlivý/nežádoucí kód) a získané hashe porovnávali s hashi uloženými v databázi.

Jako jedinou nevýhodu bych tedy viděl "zbytečný" záznam v databázi navíc, což by u velkých projektů mohlo představovat další nadbytečnou zátěž.

Samozřejmě, i přes smělý titulek jsem si vědom toho, že v tom bude háček, na který už v jedenáct večer nejsem schopen přijít, proto bych rád Vaše názory.

Děkuji
Alphard
Profil
slashování považuji za neprůstřelné, snad mi to nikdo nevyvrátí :-)
nevidím důvod hashovat login, nikde jsem to neviděl
joe
Profil
Hashovat login? Nezdá se ti to zbytečný? Stačí na něj použít třeba nějakej regulérní výraz ne, aby ti tam nechal jen a-zA-Z0-9 třeba. Stačí hashovat jen heslo a nemusí to být sha1, md5 si myslim že stačí :-)
RPG
Profil
Alphard
Já právě taky ne, proto mě to zajímalo… Je fakt že slashování bude asi jednodušší.

joe
Regulární výrazy v tomhle případě IMO nic neřeší a i tak by se musel ten konkrétní výraz napsat tak složitým způsobem, že by to za to prostě nestálo… a hashovat jen heslo nestačí, napadnutelný je právě prostor skrze který se vkládá plaintext, jako třeba zrovna login.
A nemůžu posoudit o kolik je použití sha1 bezpečnější než použití md5, každopádně po chvíli studování této problematiky se mi zdálo jako lepší volba.
DoubleThink
Profil *
Nezdá se ti, že vymýšlíš znovu kolo? 100% ochrana proti SQL injection už existuje - ošetřením vstupních dat - nejčastěji escapovací funkcí mysql_escape_string respektive mysql_real_escape_string.
joe
Profil
RPG
Jak nic neřeší, proč by neřešily, stačí udělat jednoduchý RE, kterým odstraníš znaky, které ve vstupních datech prostě nechceš. A před každým dotazem do db na proměnnou co v dotazu jako string použiješ mysql_escape_string nebo ...real....

a hashovat jen heslo nestačí, napadnutelný je právě prostor skrze který se vkládá plaintext, jako třeba zrovna login.
To mi teda vysvětli, proč podle tebe nestačí jen hashovat heslo? Osobně k hashi hesla přidávám ještě nějaký salt. A co bys chtěl hashovat, celej řádek v tabulce? =o)
Joker
Profil
RPG
Jak už bylo řečeno, ošetření vstupních dat postačí.
Zranitelnost na SQL injection obvykle vzniká spíš tak, že se na nějakou proměnnou "zapomene" a nekontroluje se vůbec. Případně se autor mylně domnívá, že "tady žádné nebezpečí nehrozí" (například že hodnotu z input type="hidden" není třeba kontrolovat).

Hashovat i jméno by samozřejmě fungovalo, ale poněkud to pak zesložiťuje zpracování...
RPG
Profil
DoubleThink
Nic "nevymýšlím". Jsem si samozřejmě vědom jiných, používaných metod.
Tohle mě napadlo, chtěl jsem znát názor jiných. To je vše.

joe
Takové ošetřování by mírně (mírně, ale přece) omezovalo i uživatele, nebo ne? Samozřejmě, připouštím že by nejspíš fungovalo odstranit vše, kromě alfanumerických znaků…

To mi teda vysvětli, proč podle tebe nestačí jen hashovat heslo?
Protože login, který se kontroluje jako čistý text, je prostě zranitelný. Už jsem to napsal jednou, nevím, jak jinak to mám vysvětlit.

Joker
Co, prosím, myslíš tím složitějším zpracováním?
bukaj
Profil
RPG
Protože login, který se kontroluje jako čistý text, je prostě zranitelný. Už jsem to napsal jednou, nevím, jak jinak to mám vysvětlit.
Porovnávání řetězců aplikaci nijak ohrozit nemůže. Zkus mě přesvědčit důvody, proč si myslíš, že ano. Ale jako důvod nepovažuji to, že prostě říkáš ;o)

Pokud samozřejmě vstup neošetříš (neescapuješ) před použitím v dotazu, je to něco jiného. Ale je podle mě nesmysl login hashovat a ukládat do databáze hash navíc jenom kvůli tomu, že si neumím ošetřit vstupy.
RPG
Profil
bukaj
Pokud samozřejmě vstup neošetříš (neescapuješ) před použitím v dotazu, je to něco jiného.
To jsem měl celou dobu na mysli, nahrazení excapování hashováním.
peta
Profil
RPG
znam 2 takove bezpecne zpusoby
- https
- odesilani hash javascriptem
U vseho ostatniho se odesila pri prihlaseni heslo nekryptovane a je mozne jej precist.
Co se tyce nalogovani na nekoho jineho, tak v obou pripadech se da komunikace zkopirovat a nalogovat se tam pred nim nebo na nej.

Co se tyce SQL injection, tak to resi osetreni vstupu. To je jediny bezpecny zpusob. Kryptovani udaju by v tomto pripade byla zdrzovacka. Kryptovani do SHA1 by zrusilo moznost udaj precist. Takova tabulka je v podstate nepouzitelna a neopravitelna, kdyz program obsahuje vhyby a je treba primo zmenit neco v databazi. Nebo takhle jsem mazal 40MB spamu z phpRS nebo minibb. Proste jsem se s tim neparal a mazal to primo pres phpadmina. u minibb je pak treba opravit jeste cisla poctu prispevku a na to jsem se tehda vykaslal.
bukaj
Profil
RPG
To jsem měl celou dobu na mysli, nahrazení excapování hashováním.
Což je v praxi k ničemu. Sice se zbavíš „nebezpečných“ znaků, ale už nikdy nedostaneš zpátky původní data. U hesla je to tak nejlepší – ten, kdo se případně vloupe do databáze, nebude moci zjistit hesla uživatelů a tak je to správně –, ale u toho loginu to tak záhodno není. Nevím, jak tobě, ale mně osobně by se nelíbilo, kdyby mě nějaká aplikace neoslovovala jako „uživatele bukaj“, ale jako „uživatele s hashem loginu ed0f249e5551e3ee38ab9dc3f31921a8105d7811“ :o) A pokud by jsi chtěl ukládat login i, jak píšeš, v „plaintextu“, musel bys stejně „plaintextový“ login oescapovat při ukládání.

A teď k výkonostní stránce. Kdyby porovnávání loginů probíhalo pomocí hashů, nic by se nezměnilo oproti porovnávání skrz jejich nezahashovanou podobu. Pořád musíš porovnat dva řetězce. Navíc, hash loginu ve většině případů bude mnohem delší než nezahashovaný login, takže nakonec by porovnávání hashů mohlo být ještě pomalejší :o) (při použití indexu bych řekl, že se ale ty rozdíly mažou).

Ukládat tedy k položkám ještě jejich hash je ve výsledku práce a zabrané místo navíc.
Joker
Profil
edit: Nic, nic, to co jsem tu předtím napsal byla blbost

Ale bude to samozřejmě složitější a pomalejší (je tam jedna funkce navíc a databáze u každého jména musí nejdřív udělat hash a potom porovnat).

Navíc to nevyřeší jeden problém: Když mám přihlášení, obvykle potřebuju i registraci nového uživatele. A když mám registraci, potřebuju INSERT. A do INSERTu nemůžu dát hash...
Navíc tohle půjde použít jen při hledání přesné shody. Existuje ale spousta případů, kdy hledám od/do nějaké hodnoty, případně obsahující nějaký řetězec a podobně.

Takže tahle metoda funguje jen někdy, zatímco escapování řetězce je univerzální a bezpečné.
RPG
Profil
peta, bukaj
Kryptovani do SHA1 by zrusilo moznost udaj precist.
Sice se zbavíš „nebezpečných“ znaků, ale už nikdy nedostaneš zpátky původní data.

Samozřejmě že jsem nechtěl login ukládat jako "uživatele 4031e41303ff290b1ff824563da58234a805acec". V mém úvodním příspěvku je to napsáno.

bukaj
A pokud by jsi chtěl ukládat login i, jak píšeš, v „plaintextu“, musel bys stejně „plaintextový“ login oescapovat při ukládání.
Ale to už je něco jiného, viz. opět můj úvodní příspěvek:
způsob, jakým by se dalo přihlášení uživatele chránit“.
Mluvil jsem o zabezpečení přihlášení. Jen a jen přihlášení.

Pořád musíš porovnat dva řetězce.
To ano, ale s tím jsem taky žádný problém neměl. Celý nápad byl "zničit" hashováním škodlivý kód vložený přes plaintextový input, toť celý problém.

Samozřejmě, vím že je slashování jednodušší, používanější a tak vůbec. Tohle mi jen přišlo jako zajímavá metoda, protože by měla teoreticky být schopna zničit jakýkoliv pokus o vložení škodlivého kódu za jakékoliv situace.
joe
Profil
Mluvil jsem o zabezpečení přihlášení. Jen a jen přihlášení.
Celý nápad byl "zničit" hashováním škodlivý kód vložený přes plaintextový input, toť celý problém.
Pokud budeš všechno escapovat, tak nemusíš myslet, na takové "ptákoviny" jako je třeba hashovat login do sha1 :-) A jak bys to pak asi chtěl udělat? Teď nevím jestli by to fungovalo, ale nějak takhle bys to napsal?

SELECT * FROM members WHERE SHA1(login) = 'hash' AND SHA1(password) = 'hash'

Myslim, že by to trvalo docela dlouho, když by každý login musel hashovat a porovnávat... Nebo nevím jak jsi to myslel...

Prostě použij mysql_escape_string nebo mysql_real_escape_string (s připojením) a nemysli na blbosti :-)
RPG
Profil
Jo, asi jo… díky všem za názory a za jejich čas.

Edit.
Děkuji moderátorovi (Mistře?) za odstranění posledního bezpředmětného příspěvku.
Téma nechávám odemčeno, kdyby někdo chtěl k tématu později vyjádřit svůj názor. Věc však pokládám za uzavřenou.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

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