Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Jakub 10. 09. 2012, 12:15:11
-
Dobrý den,
mám takový jednoduchý formulář, kde od uživatelů dostávám citlivé údaje ....
Celý server proto "kryji" pomocí HTTPS...
Formulář pak jako bezpečnostní prvky používá mysql_real_escape_string proti injekci SQL a proti spamu funkci rand(),
pomocí které vytváří 3 náhodné otázky a do proměnných SESSION registruje odpovědi z důvodu, aby nebyli přímo uživateli dostupné.
Pokud je registrace dokončena a je adminem validována uživatel dostane přistup na web admin, kde má možnosti přístupu podle toho
jaké má proměnné v SESSION.
Co se týče samotných formulářů a jednotlivých sekcí kde je nutná autorizace, tak tam testuji zdal - li je SESSION přihlášená a všechny formuláře jsou ve složce s oprávněním 644.
Považujete tohle za dostatečné řešení ? Měl bych to udělat jinak ? Nebo něco doplnit pro navýšení bezpečnosti ?
-
Co se jinak ještě těch formulářů týče, tak obsahují skryté prvky jako "username" atd... které když jsou vyplněny tak se stane formulář neplatným.
Předávání dat mezi registrační stránkou a stránkou, která provádí kontrolu dat a odeslání dat je provedeno pomocí "post"
-
Formulář pak jako bezpečnostní prvky používá mysql_real_escape_string proti injekci SQL a proti spamu funkci rand(),
pomocí které vytváří 3 náhodné otázky a do proměnných SESSION registruje odpovědi z důvodu, aby nebyli přímo uživateli dostupné.
mysql_real_escape_string() nevyriesi vsetko (to len ci si na to davate pozor) - napr.
$hodnota = mysql_real_escape_string($_POST['hodnota']);
$q = mysql_query("SELECT * FROM tabulka WHERE stlpec=$hodnota");
Pokud je registrace dokončena a je adminem validována uživatel dostane přistup na web admin,
Validacia dufam obsahuje nieco ako htmlspecialchars() alebo to mate osetrene niekde pri vstupe...
kde má možnosti přístupu podle toho jaké má proměnné v SESSION.
Co se týče samotných formulářů a jednotlivých sekcí kde je nutná autorizace, tak tam testuji zdal - li je SESSION přihlášená
Pozor na zdielane hostingy, tam je casto treba nastavit vlastnu cestu pomocou PHP funkcie session_save_path() alebo nastavenia session.save_path - inak je casto mozne, aby druhy uzivatel hostingu nastavil lubovolne session premenne.
Ale dufam, ze pri citlivych datach nejde o zdielany hosting.
a všechny formuláře jsou ve složce s oprávněním 644.
To vyzera na problem so zdielanym hostingom. Tam mozu byt aj ine problemy - bud amatersky hoster pusta vsetky skripty pod 1 uzivatelom alebo mu to niekto exploituje a 644 nepomoze. Aj u vacsich zdielanych hostingov som videl aj ine problemy, ktore umoznovali napriklad ziskat zdrojak lubovolneho PHP suboru, takze sa na ochranu nespoliehajte na 100%.
Předávání dat mezi registrační stránkou a stránkou, která provádí kontrolu dat a odeslání dat je provedeno pomocí "post"
Na POST nezalezi, ak to nie je skombinovane s niecim inym.
-
Máme vlastní server, kvůli odesílání informačních mailů...
Takže s oprávněním 644 by neměl být problém.
Cestou pro SESSIONS mám nastavenou i jejich platnost...
Co se týče:
$hodnota = mysql_real_escape_string($_POST['hodnota']);
$q = mysql_query("SELECT * FROM tabulka WHERE stlpec=$hodnota");
Tak já používám:
$hodnota = mysql_real_escape_string($_POST['hodnota']);
$q = mysql_query("SELECT * FROM tabulka WHERE stlpec='$hodnota'");
Je to chyba ?
K té validaci ...
Pokud se uživatel registruje MYSQL mu automaticky nastaví, že není jeho profil schválen, což může provést jenom uživatel,
který má v SESSION['admin']==true;
-
Tak já používám:
$hodnota = mysql_real_escape_string($_POST['hodnota']);
$q = mysql_query("SELECT * FROM tabulka WHERE stlpec='$hodnota'");
V MySQL v default nastaveni to tak AFAIK vzdy funguje az na extremy ako stlpec s cislami typu VARCHAR a pouzitie nerovnosti. Mimo MySQL alebo pri inom nastaveni MySQL sa u stringov uvodzovky vyzaduju, ale u cisel s tym moze byt (vo vseobecnosti) problem.
K té validaci ...
Pokud se uživatel registruje MYSQL mu automaticky nastaví, že není jeho profil schválen, což může provést jenom uživatel,
který má v SESSION['admin']==true;
Tam bol skor problem s tym, ci zly uzivatel (neadmin) nemoze pri registracii zadat za meno nieco ako
<script>document.getElementById('schval').submit()</script>
co by ho potvrdilo hned pri nacitani stranky adminom, keby sa neescapovali entity < a >.
-
Ta validace je dělána tak, že uživatel jako admin se přihlásí...
Vyhledá si v mysql prostřednictvím web console uživatele a schválí ho ...
Proces je následujicí:
Admin se přihlásí: je volán vyhledávání v mysql, kde pokud je shoda tak se nastaví SESSION['admin']=true jinak je false.
Pak se přepne na stránku s vyhledáváním uživatelů: Stránka ověří jestli je SESSION['login']=true a jestli je SESSION['admin'] true.
Pokud ano stránka se zobrazí.
Při příkazu vyhledávání se znovu SESSION ověří a při příkazu MYSQL SET ... se znovu před vykonáním příkazu ověří jestli je admin opravdu admin a jestli je stránka přihlášena....
-
Little Tip: na mysql etc... existuje knihovna Dibi, ktera spoustu veci resi za tebe... tj. hlavne pro tebe podstatne bezbecnostni otazky ;-) nicmene zalezi samozrejmne na tobe, je to jen tip lineho programatora :D
-
Použij nějaký Framework (Zend, Nette, ...) nebo samotné ORM (NotORM, Doctrine, ...) pro zápis dat do DB. Framework ti pohlídá/ovaliduje obsah formuláře (většinou mají i antispam formulářovou komponentu) a ORM obálka zajistí korektní uložení do DB. Nemusiš pak tyto problémy vůbec řešit...
-
no já si po dvou letech předělal web tak sem si to chtěl i v hlavě oživit a proto se raději ptám jestli sem něco nezapomněl
-
... Pokud ano stránka se zobrazí.
A ako funguje zobrazenie tej stranky? A co presne sa uklada do DB? Tam je problem, ze keby sa ako 1 udaj do mena (alebo niekam) zadal "rozkaz" pre uzivatelov prehliadac, aby sa potvrdili vsetci neaktivni, tak sa to vykona s pravami cloveka, ktory navstevuje tu stranku na schvalenie.
-
Squirrel: kdyz uz, tak PDO
Jakub: ano, je to chybne, protoze to vicemene temer vubec nebrani sql injekci, mysql_real_escape_string dela pouze to, ze escapuje specialni znaky pouzivane v query, takze tim nespustia druhou query... porad ale muzes vyresetovat podminku, pokud nepouzijes to PDO, tak pouzij jeste sprintf
tj
$prepared = sprintf("SELECT * FROM tabulka WHERE stlpec='%s'", mysql_real_escape_string($_POST['hodnota']));
$q = mysql_query($prepared);
ale ani toto neni 100%, zato u pdo je to bezpecne
-
Uživatel zadává položky které nejsou pro administraci webu směrodatné.
Všechny údaje které se vkládají jsou předem prohnány nejprve přes mysql_realy_string a
pak jsou teprve vloženy do query... Tak nevím jestli sem teď správně odpověděl ....
pokud chapu co napsal DK tak pokud mám přikaz:
$promena1=mysql_real_escape_string($POST_['data1']);
$promena2=sprintf(formatovaci prikaz,($promena1));
$prikaz=mysq_query("INSERT INTO user (jmeno) VALUES ('$promena2')");
-
tak bych měl navýšit možnost zabránění injekci MYSQL
-
Jakub: ne, vubec to nechapes
$data=mysql_real_escape_string();
$prikaz=sprintf("mysql query s pouziti %s, %d apod, viz manual",$data);
$query=mysql_query($prikaz);
timhle navysis moznost zabraneni mysql injection, ale PORAD to nebude stoprocentni, zatimco pri pouziti pdo by to bylo takhle
$pdo=new PDO(...);
$prepared = $pdo->prepare("SELECT * FROM tabulka WHERE id = :id);
$prepared->bindParam(":id",$id,PDO::PARAM_INT); //PDO::PARAM_STR pro vsechno ostatni
$prepared->execute();
$row=$prepared->fetch(PDO::FETCH_ASSOC); //->fetchAll(...) pro vice radku
-
A už je mi to jasné, takže místo proměnných sprintf odfiltruje přímo z příkazu nevhodné znaky :o)
O PDO slysším bohužel poprvé :O/
Takže to musí ještě počkat, pač web už musí dnes běžet.
-
ano, presne tak
a do budoucna -> http://php.net/manual/en/book.pdo.php
je to v php od verze 5
-
Jakub: ne, vubec to nechapes
$data=mysql_real_escape_string();
$prikaz=sprintf("mysql query s pouziti %s, %d apod, viz manual",$data);
$query=mysql_query($prikaz);
timhle navysis moznost zabraneni mysql injection, ale PORAD to nebude stoprocentni
Aky attack vector tam zostava, ak sa pouzije mysql_real_escape_string() a parametre su v uvodzovkach? Skus napisat konkretny dotaz a konkretny utok funkcny na aktualnych MySQL a PHP. (nejake diery tam boli, ale tie boli AFAIK zaplatane; nieco este mohlo ostat pri zmene kodovania medzi mysql_real_escape_string a samotnym dotazom, ale to zase robi malokto)
Inak aj ja som za PDO, ale ked uz je nieco napisane inak a "nejak" to funguje, tak by som to asi len tak neprerabal.
-
Ok ok ja myslím že jsme to tedy nějak shrnuli :o)
Každopádně díky za rady a názory !
Vím že je toho plný google určitě, ale nějaký vzor sprintf který se Vám osvědčil by někdo po ruce neměl ?
-
PJ: momentalne ti to z hlavy nereknu, ale zjistoval jsem si o tom par informaci a na stackoverflow jsme vykoumali neco malo, nicmene moje informace jsou vice nez rok stare (od te doby pouzivam pouze PDO)
Jakub: no jak vzory? proste tam narves ty sql query a misto promennych dosadis %X (kdy X je typ promenne, viz http://php.net/manual/en/function.sprintf.php )
-
PJ: momentalne ti to z hlavy nereknu, ale zjistoval jsem si o tom par informaci a na stackoverflow jsme vykoumali neco malo, nicmene moje informace jsou vice nez rok stare (od te doby pouzivam pouze PDO)
PDO pouzivam aj ja, ale ide tu o to, ci sa oplati prerabat stare weby, ktore som robil este v dobach PHP4 alebo som ich ani nerobil a len sa mi nejak dostali pod ruky. Keby tam bola funkcna SQL injection, tak by to urcite malo zmysel.
Jakub: no jak vzory? proste tam narves ty sql query a misto promtennych dosadis %X (kdy X je typ promenne, viz http://php.net/manual/en/function.sprintf.php )
Jednoducho povedane: sprintf funguje skoro ako v C, akurat sa mu nedava prvy parameter a tento je vrateny funciou.
Z pohladu funkcnosti je uplne jedno, ci pouzije sprintf alebo kludne aj obycajne zretazovanie stringov alebo obycajne dosadzovanie premennych do stringov zapisanych v uvodzovkach. Akurat v druhom a tretom pripade si musi dat pozor na to, aby niekam omylom nedal podstrceny retazec namiesto cisla.
-
Co se jinak ještě těch formulářů týče, tak obsahují skryté prvky jako "username" atd... které když jsou vyplněny tak se stane formulář neplatným.
Tohle bych nedoporucil, prohlizec/plugin to muze dolpnit automaticky
-
Dlouho jsem tu nebyl tak se omlouvám za tak pozdní odpověď.
Nic méně děkuju za Vaše názory a příspěvky !
-
... zatimco pri pouziti pdo by to bylo takhle
$pdo=new PDO(...);
$prepared = $pdo->prepare("SELECT * FROM tabulka WHERE id = :id);
$prepared->bindParam(":id",$id,PDO::PARAM_INT); //PDO::PARAM_STR pro vsechno ostatni
$prepared->execute();
$row=$prepared->fetch(PDO::FETCH_ASSOC); //->fetchAll(...) pro vice radku
Tohle je jen jedna z možností, kterou ale nedoporučuji. Vázání proměnných je de facto variací na globální proměnné.
Daleko víc mi vyhovuje:
$pdo=new PDO(...);
$prepared = $pdo->prepare("SELECT * FROM tabulka WHERE id = :id");
$prepared->execute(array(":id"=>$id));
$row=$prepared->fetch(PDO::FETCH_ASSOC); //->fetchAll(...) pro vice radku
nebo v jednodušších případech
$pdo=new PDO(...);
$prepared = $pdo->prepare("SELECT * FROM tabulka WHERE id = ?");
$prepared->execute(array($id));
$row=$prepared->fetch(PDO::FETCH_ASSOC); //->fetchAll(...) pro vice radku
-
Kit: prave ze ne, v mojem pripade definujes i typ vlozenych dat, zatimco u tvojich se to nastavuje automaticky (nebo rovnou na string, coz by mohl by celkem problem u nekterych query)
s globalnimi promennymi to nema spolecneho vubec nic, ale samozrejme kazdemu vyhovuje neco jineho, ja pouzivam mnou zminene pouziti, ale to neznamena, ze nemuzes pozivat svoje :)
-
Kit: prave ze ne, v mojem pripade definujes i typ vlozenych dat, zatimco u tvojich se to nastavuje automaticky (nebo rovnou na string, coz by mohl by celkem problem u nekterych query)
PDO si s tím poradí. Pokud je použit string tam, kde je očekáván integer, PDO provede konverzi na integer. Pokud konverzi není možné provést, použije se NULL. Problém jsem nezjistil. Zkus najít příklad, kdy se to bude chovat chybně.