Jump to content
php.lv forumi

"Atceries mani!" fīča


daGrevis

Recommended Posts

"Atceries mani!" fīča ir jāsaprot kā cepumu saglabāšana, ja ir atķeksēts attiecīgais check-box pie ielogošanās.

 

Pašlaik sistēma ir tāda, kad cepumos tiek glabāti...

 

[*] Lietotājvārds (plain text),

[*] Parole (SHA-1 hashed).

 

Nākamreiz atverot pārlūkā manu lapu tiek pārbaudīts, vai pastāv tādi cepumi, ja jā, tad vai dotie dati atbilst datubāzē esošajiem. Ja jā, tad viss ok, esam iekšā.

 

Viss strādā, esmu laimīgs! =D

 

Bet, protams, man kaut kur bija jāizlasa, kad tādas "jūtīgas" lietas cepumos glabāt nav ok. =/ Tad nu kas reāli var notikt? Ja kāds ir aizmirsis izlogoties kaut kādā bibliotēkā, viņa cepumi ir pieejami jebkuram, kurš vēlās, t.i., viņa lietotājvārds un parole arīdzan. Labi, ka parole ir hash'ota, tādēļ vismaz nezinam īsto paroli, bet uzminēt varam un pārbaudīt vai parole ir īstā - kāpēc gan nē?

 

Tad nu es lasīju, ka labāk ir ģenerēt kaut kādu random stringu. Šo iemetam db pie lieotāja, rindiņā "salt", piemēram. Tad cepumos iemest...

 

[*] Lietotājvārds (plain text),

[*] Salt (SHA-1 hashed).

 

Nu, un pēc tam, pārbaudam vai attiecīgais salt ir īstais.

 

Bet vai tad zinot salt, ja šams ir aizmirsis izlogoties, mēs tāpat nevaram ielogotes iekšā? =/

Link to comment
Share on other sites

Ja cilvis buus iekjekseejis "Atceries mani" un kaads cits pieies pie taa pasha PC, tad tu tur neko nevari izdariit. Toties kukijus var nozagt (XSS). Tas vairs nav forshi.

 

Lai vai kaa - glabaat cepumos paroli (pat hashotu) nav forshi.

 

Parasti glabaa kaut kaadu random veertiibu kas veidota no, piemeeram IP un/vai User Agent, utt...to glabaa kaadaa DB field'aa un ja nav ielogojies un ir kukijs, tad samekle to ieksh DB un autorizee ja viss ir OK.

Link to comment
Share on other sites

Ne jau pliku rand. Tai veertiiba var buut, piemeeram md5($lietotaaja_ip . $lietotaaja_username . $kaut_kas_random);

 

+ uzliec kaut kaadu timeout tai veertiibai (ja nedeelju nav iets tajaa lapaa, tad tas strings ir nederiigs).

 

 

Kaa jau teicu - tas nepaliidzees pret to, ka kaads pieseezhas pie taa pasha datora kur jau ir kukijs, kursh ir deriigs. Tur tu neko izdariit nevari. Ja lietotaajs pats ir padumsh un atstaaj sevi ielogotu, tad pats vien ir vainiigs. Vai taisi automatiskus logoutus.

Link to comment
Share on other sites

Pirmais variants ir cepumos glabāt kaut kādu

- hash=md5($userid.$slat.$ip)

- id

un tad, kad pieprasa datus, pārbaudīt vai ar id var uzģenerēt hash.

Mīnusi:

- teorētiski atklājot funkciju ar kuru veido hash, var saģenerēt visu lietotāju id hashus un piekļut viņu kontiem.

- ja vienreiz nozog cepumu, tad no tās ip vienmēr varēs ielogoties ar tā lietotāja kontu, izmantojot to cepumu.

 

Otrs variants ir glapāt cepumos un user tabulā kaut kādu unikālu randomu:

- hash = uniqueid().md5(rand())

un tad, kad pieprasa datus, pēc cepuma atras user tabulā atbilstošo lietotāju.

Mīnusi:

- servera pusē jāglabā hash, kas mysql gadījumā bišķi iebremzē katru pieprasījumu, bet, ja izmanto memcached, tad risinājumam nav ne vainas.

Edited by codez
Link to comment
Share on other sites

Ir dizgan debīli glabāt pliku ID cepumā, jo:

Pieņemsim, es esmu kkāds žurķis, tur lienu skatos un volā - atradu, ka cepuma info var nomainīt, volā - uzlieku ID uz admina ID un volā - esmu iekšā admina acc, volā - webam pakaļā....

 

Labāk izveidot kkādu funkciju, kas enkodo un dekodo stringu, jo ar 64base var nepietikt, tbš iepin kkādus mēslus iekšā un izdomā kā vienu attiecīgu dekodotā stringa fragmentu savāk un ievietot par ID, bet sanāk arī baigā šaize, ja urķim ir tāda pati enkodošanas funkcija, tāpēc labāk ir pašam savu uzrakstīt

 

 

Mans lepnums (nav pilna, jo nācās apgraizīt, pēc tam, kad hostplex sāka trakot, par to, ka par smagu priekš viņa):

function encode($value) {
$value = rand(1,145).rand(1,145).$value."#".md5("asdasd123asd".md5($value))."#".md5($value.md5("jarhtgiuhq346t9785cthwrt7h5"));
$value = base64_encode($value."fdhw5Lbv43");
return $value;
}
function decode($value) {
$value = base64_decode($value);
$value = preg_replace("/(.+)(\fdhw5Lbv43)/","\\1",$value);
$value = explode("#",$value);
return $value[2];
}

EDIT: runa iet par varianu bez haša!!

Edited by emsy
Link to comment
Share on other sites

@emsy, tā gan nebūs! cepumā lietotāja ID ir tikai identifikators pārbaudei un vērtība ko jāpārbauda ir otrs cepurs ar hešu, mainot id nekas nenotiks. protams ja sistēmas uzrakstītājam locekļi aug no pareizajām vietām.

Link to comment
Share on other sites

emsy, ja tu nesūti savam ūber encodētajam stringam līdzi hashu, tad to uzlaust ir elementāri:

Ieeju es ar savu kontu savā lapā, ieeju savā profilā un paskatos savu stringu, tad paskatos tavu encodēto cookiju, kurš pieredzējušam programmētājam acīmredzami izskatīsies pēc base64 sakodēta stringa. atkodēju, nomainu to daļu, kur redzu savu id un logojos ar ko gribu.

Variantā, kad sūta pliku id, tiek sūtīts līdzi hash, kurš ir atkarīgs no id, ja id nomainīsi, tad autorizācja neizdosies, jo id nesakritīs ar hash-u.

Ja negrib to darīt divojs cookijos, tad var arī sabāzt vienā.

 

 

$cookie=$id.'.'.hash('sha512',$id.$salt.$ip);

 

un pie pārbaudes:

 

$a=explode('.',$cookie);
$id=$a[0];
$hash=$a[1];
if ($hash==hash('sha512',$id.$salt.$ip)){
 echo 'Lietotājs ar id='.$id;
}

Edited by codez
Link to comment
Share on other sites

Vienkārša hash() vietā labāk būtu izmantot hash_hmac():

Piemēram kā autentificēšanās sistēmā, kuras piemēru devu:

auth_common.php failā

function maketoken($uid,$parole,$autorenew,$expire,$info){
$key = pack('H*','86b6de905bbee18b3425f7e5974c1cad7e24ec06a707a2766c5988c20ebc7337');//šī ir slepenā šifrēšanas atslēga HEX formā, NOMAINĪT OBLIGĀTI!!!!
$hmac_key = pack('H*','8412789462918462123861789234612378964123763412781273467252347564735');//šī ir slepenā HMAC atslēga NOMAINĪT OBLIGĀTI!!!!
$td = mcrypt_module_open('rijndael-256', '', 'cbc', '');
srand();
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);//ja tiek izmantots Linux/BSD* tad izmantojiet MCRYPT_DEV_URANDOM
mcrypt_generic_init($td, $key, $iv);
$data=$uid.','.bin2hex($parole) .','.intval($autorenew).','.intval($expire). ','.ip2long($_SERVER['REMOTE_ADDR']) . ',' . bin2hex($info);//info - papildus mainīgie utt, kas jāsaglabā no vienas lapas uz otru
$data=$data.',' . hash_hmac('sha512',$data,$hmac_key,false);//Pievienojam imitoaizsardzību
//echo "kukijaa baazamais: $data <br>";
$data = mcrypt_generic($td, $data);//šifrējam
$data = bin2hex($iv) . ',' . bin2hex($data);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $data;
}

Šeit gan jāpiebilst, ka manis apskatītās sistēmas pamatā bija daudzkārtēja paroles hashošana, līdz ar ko funkcijai maketoken() tiek padota jau daudzkārtēji hashota parole. Un pat, ja tiktu padota parole atklātā tekstā, lietotājam cepumā visa tiek glabāta šifrēta (AES-256 CBC režīmā). Lietotājs nezina $key mainīgo un tāpat nezina $hmac_key mainīgo.

Link to comment
Share on other sites

Aleksej, visas šīs kodēšanas jēga būtu tad, ja autentifikācijas procesā nevienu reizi negrieztos pie datu bāzes, jo savādāk, vienkāršāk ir cookijos ielikt unikālu random ģenerētu stringu, kurš tiek ierakstīts, piemēram, users tabulā un tad ar vienu kveriju tiek atrast ielogotais lietotājs.

 

Tas, kur šāda kodēšana būtu noderīga, būtu, ja mēs negribētu katrā autentifikācijas reizē griezties pie db, bet bez id mums būtu vajadzīgi vēl kādi dati, kurus klienta pusē nedrīkstētu redzēt plain formā. Ja vienīgais, kas mums vajadzīgs ir userid, tad šāda kodēšanas nav vajadzīga, jo userid mums nav jāslēpj un varam vienkārši pie userid pievienot uz kaut kādiem papildus parametriem balstītu hash-u.

Link to comment
Share on other sites

Kuru no šīm lietām tu sauc par kodēšanu?

Autentificēšanas procesā šajā gadījumā jāgriežas vienu reizi pie DB pie tokena izveidošanas. Pēc tam, var tikai pārbaudīt vai:

a) veiksmīgi var atšifrēt

b) atšifrētajai daļai ir pareiza hmac kontrolsumma.

 

Līdz ar to nav jāglabā nekāds ID datu bāzē un pie datu bāzes nav jāvēršas.

 

Konkrētais piemērs bija demonstrācija "hardened stateless cookies", kura mērķis bija parādīt, kā var iztikt bez jebkādu sesijas datu glabāšanas serverpusē.

 

Ar tiem randomā ģenerētajiem stringiem... Manuprāt ir problēma, ka vēl jādomā viņu iztīrīšanas process no datu bāzes, jo noteikti būs gadījumi, kad lietotājs izdzēš visus cepumus, bet neveic normālu "logout" procedūru...

Link to comment
Share on other sites

Kuru no šīm lietām tu sauc par kodēšanu?

Autentificēšanas procesā šajā gadījumā jāgriežas vienu reizi pie DB pie tokena izveidošanas. Pēc tam, var tikai pārbaudīt vai:

a) veiksmīgi var atšifrēt

b) atšifrētajai daļai ir pareiza hmac kontrolsumma.

 

Līdz ar to nav jāglabā nekāds ID datu bāzē un pie datu bāzes nav jāvēršas.

 

Konkrētais piemērs bija demonstrācija "hardened stateless cookies", kura mērķis bija parādīt, kā var iztikt bez jebkādu sesijas datu glabāšanas serverpusē.

Ar kodēšanu šijā gadījumā bija domāta šifrēšana.

Konkrēti tavā dotajā piemērā funkcija checktoken() satur divas griezšanās pie db. http://paste.php.lv/7692?lang=php

Protams es saprotu, ka var iztik arī bez šīm 2-vām griezšanām pie db, jo tās būtībā pārbauda cookijos glabāto datu "svaigumu", bet runājot reģistrētu lietotāju kontekstā, parasti mums vienīgais, ko vajag iegūt autentifikācijas procesā ir reģistrētā lietotāja id. Pārējā iegūstamā informācija parasti ir dinamiska un ir jāiegūst tā vai tā no db, lai dati būtu "svaigi".

 

 

Ar tiem randomā ģenerētajiem stringiem... Manuprāt ir problēma, ka vēl jādomā viņu iztīrīšanas process no datu bāzes, jo noteikti būs gadījumi, kad lietotājs izdzēš visus cepumus, bet neveic normālu "logout" procedūru...

Kāpēc viņi būtu jātīra ārā?

Users tabulā tas aizņem tikai papildus lauku.

Ja lietotājs izdzēš cookijus manuāli, tad šis random strings pie ieraksta users tabulā var mierīgi palikt, jo uzminēt viņu būtu grūtāk kā lietotāja paroli.

Ja mūs uztrauc tas, ka kāds varētu nozagt šo cookiju stringu un izmantot vēlāk arī, ja lietotājs domā, ka ir izlogojies, izdzēšot cookijus manuāli, varam glabāt papildus lauku ar timeout vērtību, tāpat varam glabāt vēlvienu papildus lauku - last_auth_ip, kuru ļautu autentifikāciju tikai no pēdējās autorizācijas ip adreses.

Link to comment
Share on other sites

manuprāt arī vienkāršākais variants ir pieglabāt random stringu iekš db un pie lapas ielādes pārbaudīt cepumu, ja cepums ir nedēļu vecss, tad prasam lietotājam pārbaudīt paroli. mācaties no googles tantes :)

piesiet IP adresei būtu muļķīgi. google to nedara.

 

es staigāju ar portatīvo un man ir atvērts google reader, es gan darbā gan mājās, + vēl 3 vietā (no 3 dažādām IP) varu ieet un esmu jau ielogots.

tā kā manuprāt būtu diezgan stulbi piesieties IP adresei

arī googles mails ir jau ielogots no visām vietām

 

principā googlei ir kkāds hash.

reizēm kad ilgāk neesu bijis googlē, tad izmetas "verify" kontam, jau lietotājs ir un jāievada parole un jāuzspiež "Verify"

kkā tā :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...