Autor Zpráva
Kubas
Profil *
Zdravím. Chtěl bych se zeptat zda- li je mnou udělané řešení bezpečné proti session hijacking a dalším útokům, případně byl bych velmi rád, kdyby mi někdo poradil, jak bezpečnostní díru vyřešit. Děkuji za reakce

login

<?php
include "config.php";
$login = mysql_real_escape_string($_POST["nick"]);
$heslo = mysql_real_escape_string($_POST["heslo"]);
$SHA1heslo = sha1($login.$heslo);

 $dotaz = mysql_query("select * from uzivatele where login = '$login' and heslo = '$SHA1heslo'");
$overeni = mysql_num_rows($dotaz);
$row = mysql_fetch_array($dotaz);
if($overeni == 1) {
    session_start();
    $_SESSION['login'] = stripslashes($login);
    $_SESSION['id'] = $row["id"];
    header("Location: prihlasen.php");
    die();
} else {
    echo"Asi tu nemáš co dělat..";
}
?>

Na login se ptám scriptem

<form action="login.php" method="post">
<input type="text" name="nick" value="">
<input type="password" name="heslo" value="">
<p align="center"><input type="submit" type="submit" name="submit" value="Přihlásit"></p>
    </form>


Ve scriptech pak používám dotaz na session

<?php
session_start();
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
<body>
 
 <?php  
  if($_SESSION['login']){  
    $login = $_SESSION['login'];
    $id = $_SESSION['id'];
    
    .
   .
   Tu nějaký html nebo php script
   .
   .
   
   

  } else {
    echo'Asi tady nemáte co dělat..';
  }

 ?>

 </body>
</html>
SeparateSK
Profil
$_SESSION['login'] = base64_encode(stripslashes($login));
    $_SESSION['id'] = base64_encode($row["id"]);
a vypisanie
$login = base64_decode($_SESSION['login']);
    $id = base64_decode($_SESSION['id']);
takze id a login budu zasifrovane
blaaablaaa
Profil
SeparateSK:
A proc by mel pouzivat base64?
Jinak proti session hijackingu pouzij napr jeste kontrolu prohlizece apod.

Misto "select * from uzivatele where login = '$login' and heslo = '$SHA1heslo'" pouzij "select `id` from uzivatele where login = '$login' and heslo = '$SHA1heslo' LIMIT 1"

A proc $_SESSION['login'] = stripslashes($login); ? nechtels spis kdyz uz, tak htmlspecialchars pro vypis prezdivky?
SeparateSK
Profil
Viem nevýhoda base64 je,že sa da odsifrovat ,ale pouzijeme ho preto,aby sme session informácie zasifrovali.keby sme pouzili namiesto toho md5 alebo sha1 tak to id už asi nerozsifrujeme
Majkl578
Profil
Kubas:
sha1($login.$heslo)
Seš si vědom toho, že nikdy nesmíš změnit uživatelské jméno?

if($_SESSION['login']){
E_NOTICE při neexistujícím klíči.

SeparateSK:
base64_encode(stripslashes($login))
Chudáci ti s uvozovkou ve jménu.

Viem nevýhoda base64 je,že sa da odsifrovat ,ale pouzijeme ho preto,aby sme session informácie zasifrovali.
Neplácej tu nesmysly. Base64 není šifrování a jeho použití tady nedává smysl.
SeparateSK
Profil
ano a snad tu budeme robit toto:
$_SESSION[id]=md5($row[id]);
a potom ideme odsifrovat:
function odsifrujId($id){
$i=0;
while($zI!=$id){
$zI=md5($i);
$i+=1;
}
return $i;
}

 $id=odsifrujId($_SESSION[id]); //fakt skvely napad :) a to este neodsifruvávame text
BuGeR
Profil
SeparateSK:
To je fakt "super" řešení. Pokud bude mít uživatel id např. 10 000, tak se ten cyklus provede 10 000x, aby to ID našel?
SeparateSK
Profil
BuGeR
ved na toto som tymto chcel narazit , ze lepsie je pouzit base64
Tori
Profil
BuGeR:
Pokud bude mít uživatel id např. 10 000, tak se ten cyklus provede 10 000x, aby to ID našel?
No právě že se neprovede ani jednou, neboť před první iterací není definovaná proměnná $zI, takže funkce vždy vrátí nulu. (jestli dobře čtu). neplatí, špatně jsem četla, pardon.

SeparateSK:
Proč vlastně chcete šifrovat data v session - pro případ špatného zabezpečení filesystému, kdy by se jiný uživatel dostal k souborům, kam se sessions ukládají? To už bych snad radši použila vlastní session handler (session_set_save_handler), než u každého přístupu k datům relace volat nějakou funkci.
Ugo
Profil
Já bych se nesnažil o změnu dat v session, ale o lepší zabezpečení samotné session. base64 je navíc zcela zcestné, když šifrovat, tak vlastní funkcí, kažopádně když ohlídáš kdo smí k session s id xxxxx, tak víc potřebovat nebudeš.
SeparateSK
Profil
tak aby si mal nejaku vlastnu sifru alebo nieco take , mozes pouzit napr:

$_SESSION['login'] = strrev(stripslashes($login)); //prevratime znaky v logine, takze ahoj=joha
    $_SESSION['id'] = dechex(($row["id"]*10)); //id nasobime 10 a prevedieme do Hexadecimalnej sustavy - takze ak je id 2,tak nove bude 2x1O -> dechex = 14, ak id=1, tak nove je "A"
a pre zistenie povodnych hodnôt
$login = strrev($_SESSION['login']); //prevratime naspäť, takze joha=ahoj
   $id = (hexdec($_SESSION['id'])/10); //opacna cesta, zistime povodne id v decimalnej sustave a delime 10
BuGeR
Profil
Tori:
Já si právě říkal :-P
Alphard
Profil
SeparateSK:
Co to vymýšlíte za blbosti? Tyto údaje není nutné šifrovat, obvykle není problém zjistit si jméno uživatele a k ničemu to útočníkovi není. Heslo se do sessions samozřejmě ukládat nebude.
Při session hijacking se krade cookies, takže šifrování sessions dat je naprosto k ničemu. Částečně může pomoci kontrola prohlížeče ([#3] blaaablaaa), ale když někdo ukradne cookies, asi si zjistí i prohlížeč.
johnl
Profil
Alphard:
Poté by bylo vhodné i omezení na IP adresu, nebo ne?
Majkl578
Profil
johnl:
omezení na IP adresu, nebo ne?
Ne, je opravdu otravné, když za den jsi na třech různých místech (jiná IP) a z každého by ses musel znovu přihlašovat.
johnl
Profil
Majkl578:
Já bych řekl že když se budu přihlašovat ze tří různých počítačů, tak si session např. na flash disku přenášet nebudu (nebo to někdo dělá?) - snad jen u portable verze nějakého prohlížeče, spíš bych viděl problém na PC kde je dynamická IP adresa.
Majkl578
Profil
Já ale nemluvil o různých počítačích. Myslím, že pro člověka, který vlastní notebook, to není až tak vyjímečná situace.
johnl
Profil
Majkl578:
To je pravda, na to jsem nemyslel. :)
Kubas
Profil *
Děkuji za reakce - mám k tomu ještě pár dotazů -

U tohoto session se neukládá obsah do cookies. Čeká se pouze na vypršení doby session (cca 20 minut nekativity) - je to dobře, nebo je i toto nějakým způsobem chyba?
Když jako session používám ID a login - nevznikají mi tím pádem pro daného uživatele vždycky stejné řetězce? Jak by se toto dalo ošetřit?
Bylo by třeba vhodné řešení použít ještě $_SESSION['cas'] = date('d.n.Y H:i:s'); pro lepší zabezpečení?
Mělo by tu kdyžtak nějaký smysl použití třeba session_regenerate_id?


Jaký význam má teda šifrování těch session pomocí base64?


Omezení na IP adresy (přes htaccess?) možná není nějaký špatný nápad, nicméně co sem o tom četl, tak se to spíš nedoporučuje jako bezpečná metoda (proxy atd..) a navíc je to celkem dost otravné a asi ani moc dobře nepoužitelné..

blaaablaaa:
Jinak proti session hijackingu pouzij napr jeste kontrolu prohlizece apod.

Co se myslí tou kontrolou prohlížeče?

Ugo:
ale o lepší zabezpečení samotné session

Co bylo myšleno tímto?

Ugo:
kažopádně když ohlídáš kdo smí k session s id xxxxx, tak víc potřebovat nebudeš.

Jak?
Medvídek
Profil
Kubas:
U tohoto session se neukládá obsah do cookies.
Můžete si je ukládat třeba do mysql, ale PHPSSID je většinou v COOKIES.

Jaký význam má teda šifrování těch session pomocí base64?
Žádný

Omezení na IP adresy (přes htaccess?)
Ne, dělá se to tak, že při začátku sezení si uložíš informace o uživateli (browser a IP adresu), která se ti během toho sezení nesmí změnit, pokud jo, tak odhlásíš.

Výborně to mělo kdysi řešeno Líbimseti, které si předávalo PHPSSID v url a kamarád mi poslal odkaz s tím jeho PHPSSID a já byl hned přihlášen na něj :D
Majkl578
Profil
Medvídek:
Ne, dělá se to tak, že při začátku sezení si uložíš informace o uživateli (browser a IP adresu), která se ti během toho sezení nesmí změnit, pokud jo, tak odhlásíš.
Tohle je přesně to špatné řešení, za které tě budou nenávidět lidé s dynamickou IP, denními aktualizacemi prohlížeče nebo měnící často IP.
Medvídek
Profil
Majkl578:
Při změně verze prohlížeče se snad prohlížeč stejně restartuje, takže přijdeš o sezení. A abych pravdu řekl, tak se mi během posledních 2 let na našem firemní portále nestalo, že by si zákazník stěžoval, že ho aplikace odhlásila kvůli tomu, že najednou z čista jasna dostal jinou IP adresu. (Bavíme se tu samozřejmě o ochranu během jednoho sezení. Tj. od přihlášení po odhlášení (trvalé přihlášení z bezpečnostních důvodů nepodporuju)
Aleš Janda
Profil
Měl bych komentář k tomuto:

Kubas:
$login = mysql_real_escape_string($_POST["nick"]);
$heslo = mysql_real_escape_string($_POST["heslo"]);
$SHA1heslo = sha1($login.$heslo);
$dotaz = mysql_query("select * from uzivatele where login = '$login' and heslo = '$SHA1heslo'");

$_SESSION['login'] = stripslashes($login);

Proč login napřed zaescapováváš a pak zase odescapováváš? Je dost matoucí, ne-li přímo chyba používat funkci mysql_real_escape_string jinde než přímo v kontextu toho dotazu. Dej ty escapovací funkce přímo do dotazu (to platí univerzálně) a nebudeš se už nikdy muset drbat s tím, jestli něco už je nebo ještě není ošetřený. A taky už NIKDY nebudeš muset použít funkci stripslashes().

Dále, zbytečně vybíráš všechny řádky (může jich vůbec být než jeden?) a všechny sloupce dotazu. Přepsal bych to takto:
$dotaz = mysql_query("select 1 from uzivatele where login = '".mysql_real_escape_string($_POST["nick"])."' and heslo = '".mysql_real_escape_string(sha1($_POST["nick"].$_POST["heslo"]))."' LIMIT 1");

(Pozn.: u sha1heslo počítáš se zaescapovaným jménem a heslem (proč?). Výše uvedený můj řádek počítá s původním tvarem. Není problém kdyžtak upravit ;-))
Kubas
Profil *
Medvídek:
Při změně verze prohlížeče se snad prohlížeč stejně restartuje, takže přijdeš o sezení.

Ne, v tomto řešení je to řešeno tak, že je člověk přihlášený od přihlášení se do zavření stránky prohlížeče.. To byl účel nevytvářet nějaké dlouhodobé cookies..

Kubas:
Když jako session používám ID a login - nevznikají mi tím pádem pro daného uživatele vždycky stejné řetězce? Jak by se toto dalo ošetřit?
Bylo by třeba vhodné řešení použít ještě $_SESSION['cas'] = date('d.n.Y H:i:s'); pro lepší zabezpečení?
Mělo by tu kdyžtak nějaký smysl použití třeba session_regenerate_id?

?


Aleš Janda:
u sha1heslo počítáš se zaescapovaným jménem a heslem (proč?)

Heslo je ještě totiž osoleno (není zde uvedeno), tak přidání jména má za cíl zvýšit bezpečnost hesla
panther
Profil
Aleš Janda:
pokud je heslo hashováno, je zbytečné u něj přidávat mysql_real_escape_string. Hash je jako řetězec sám o sobě bezpečný.
Nox
Profil
panther:
Radši bych to tam nechal.... pokud tam nebude takto zadrátováno "sha1" ale třeba "getPasswordHash", už není jisté, jestli z toho vždy vyjde řetězec, který nebude mít v SQL nějaký význam
Kubas
Profil *
Chtěl bych poděkovat všem za reakce.
Těma řešeníma sem zjistil jak by měl teda vypadat ten MYSQL zápis, zacož Alešovi dík


Mám však ještě poslední dotaz na který mi zatím ještě nebylo odpovězeno, jelikož to ukradení session mě děsí nejvíc.
Nevím jestli řešení od SeparateSK je nějak použitelné, jelikož když si někdo zjistí jméno a id, tak by si měl být schopný vygenerovat vlastní session ne?

Proto sem dával ty svoje tři dotazy -
Když jako session používám ID a login - nevznikají mi tím pádem pro daného uživatele vždycky stejné řetězce? Jak by se toto dalo ošetřit?
Bylo by třeba vhodné řešení použít ještě $_SESSION['cas'] = date('d.n.Y H:i:s'); pro lepší zabezpečení?
Mělo by tu kdyžtak nějaký smysl použití třeba session_regenerate_id?

Díky za reakce
Nox
Profil
1) Identifikátor Session se neřídí podle obsahu, to si asi teď pleteš s hashováním ... Session ID se náhodně generuje na serveru
2) Viz (1)
3) Session_regenerate_id() se doporučuje

http://en.wikipedia.org/wiki/Session_fixation
http://en.wikipedia.org/wiki/Session_hijacking
Alphard
Profil
[#27] Kubas
Máte v tom pořád, zdá se mi, dost zmatek. Zkuste si pročíst http://php.vrana.cz/zabezpeceni-session-promennych.php.
Jakékoliv šifrování dat nebo přidávání času je k ničemu.

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:

0