Autor Zpráva
virgo
Profil *
Zdravím,
Mám na svých strankách možnost přihlašení.
Pokud uživatel zapomene heslo vygeneruji mu nové pomocí tohoto hlavního skriptu:
if ($password=reset_password($username))
  { 
    if (notify_password($username, $password))
      echo 'Vaše heslo bylo odesláno na Váš e-mail.';
    else
      echo 'Vaše heslo nebylo možné obnovit'
           .' Zkuste to později znovu.';
  }
  else
    echo 'Vaše heslo nebylo změněno zkuste to znovu.';

fukce reset_password($username)
function reset_password($username)
// nastaví heslo pro zadané uživatelské jmeno na náhodnou hodnotu
// vratí nové heslo nebo false, když se to nepodaří
{ 
  // získaní náhodného slova ze slovníku v délce 6 až 13 znaků
  $new_password = get_random_word(6, 13);
  
  if($new_password==false)
    return false;
  // ke slovu přida ještě číslo mezi 0 a 999
  // aby heslo bylo složitější
  srand ((double) microtime() * 1000000);
  $rand_number = rand(0, 999); 
  $new_password .= $rand_number;
 
  // nastaví heslo uživatelé v databazi na nově vygenerované nebo vratí false
  if (!($conn = db_connect()))
      return false;
  $result = mysql_query( "update user
                          set passwd = password('$new_password')
                          where username = '$username'");
  if (!$result)
    return false;  // nezměněno
  else
    return $new_password;  // heslo změněno
}

fukce pro ziskani slova ze slovníku:
function get_random_word($min_length, $max_length)
// vybere nějaké nahodné slovo ze slovníku v dělce omezené
// zadanými parametry a vratí je
{
   // nalezne náhodné slovo
  $word = '';
  //nastavit cestu aby odpovídala memu systému
  $dictionary = 'english.0';  // slovnik ispell
  $fp = fopen($dictionary, 'r');
  if(!$fp)
    return false; 
  $size = filesize($dictionary);

  // přechod na náhodné místo ve slovníku
  srand ((double) microtime() * 1000000);
//zde nasleduje ten radek 191
  $rand_location = rand(0, $size);
  fseek($fp, $rand_location);

  // získá ze slovníku další celé slovo požadované délky
  while (strlen($word)< $min_length || strlen($word)>$max_length || strstr($word, "'"))
  {  
     if (feof($fp))   
        fseek($fp, 0);        // je-li na konci přejde na začátek
     $word = fgets($fp, 80);  // přeskočí prvni slovo protože by to mohla být
     $word = fgets($fp, 80);  // část potencionalního hesla
  };
  $word=trim($word); // odstrani v fgets zavěrečne \n
  return $word;  
}

ale to mi ukáže chybu:
Warning: rand(): Invalid range: 0..489449 in c:\apache\htdocs\cnc\system\loginfce.php on line 191

Warning: Failed to Connect in c:\apache\htdocs\cnc\system\loginfce.php on line 170
Vaše heslo nebylo možné obnovit Zkuste to později znovu.

druhá chyba je ve skriptu pro zaslani hesla na mail:

function notify_password($username, $password)
// oznamý uživately že jeho heslo bylo změněno
{
    if (!($conn = db_connect()))
      return false;
    $result = mysql_query("select email from user
                            where username='$username'");
    if (!$result)
    {
      return false;  // nezměněno
    }
    else if (mysql_num_rows($result)==0)
    {
      return false; // uživatel neni v databázi
    }
    else
    {
      $email = mysql_result($result, 0, 'email');
      $from = "From: podpora@virgonet.cz \r\n";
      $mesg = "Vaše heslo bylo změněno na $password \r\n"
              ."Prosím co nejdříve si ho změňte. \r\n";
      
      //radek 170 nasleduje
      if (mail($email, 'Server CNC nové heslo', $mesg, $from))
        return true;      
      else
        return false;     
    }
} 


díky moc za radu
perun
Profil
Len ma zaujalo:
1. užívateľ klikne, že zabudol heslo
2. vygeneruje sa mu nové heslo zo slovníka
3. hneď sa mu nové heslo nastaví

Pokiaľ daný slovník obsahuje skutočné slová, čo ako som pochopil, skutočne obsahuje, tak je to veľké bezpečnostné riziko. Pretože mi stačí poznať jeho login (ktorý si môžem aj tipnúť) a viem mu resetovať heslo a následne s veľkou pravdepodobnosťou úspechu vykonať slovníkový útok.

Čo sa týka chýb, v prípade prvej by som skúsil znížiť hodnotu premennej size pred vkladaním ako parametra do rand na menšiu ako 32000. Len zo zvedavosti, či to prejde.
V prípade druhej chyby zrejme nie je k dispozícii emailový server.
virgo
Profil *
perun:
1. užívateľ klikne, že zabudol heslo
ano heslo se mu vygeneruje a zašle na mail pomocí zadaní jeho nicku.

2. vygeneruje sa mu nové heslo zo slovníka
Ano ze slovníku které obsahuje 47tisíc slov k tomu se přičte jeste ciselna hodnota hacker by musel zkusit asi cca 22 500 000 kombinaci což si myslím že na můj server je to dostačujicí bezpečí nebo snad ne?

3. hneď sa mu nové heslo nastaví
ano heslo se mu nastavy hned.

perun:
prvej by som skúsil znížiť hodnotu premennej size pred vkladaním ako parametra do rand na menšiu ako 32000.
Zkusil jsem to pokud myslíš hodnotu 1000000 v tomto skriptu změnit.
srand ((double) microtime() * 1000000);


V prípade druhej chyby zrejme nie je k dispozícii emailový server
Tak to asi není...já myslel že je v php knihovně funkce <b>mail </b>která tohle odešle?
perun
Profil
virgo:
Ano ze slovníku které obsahuje 47tisíc slov k tomu se přičte jeste ciselna hodnota hacker by musel zkusit asi cca 22 500 000 kombinaci což si myslím že na můj server je to dostačujicí bezpečí nebo snad ne?

á... ospravedlňujem sa, tiež som si mohol najsk;r poriadne pozrieť, čo ten skript vlastne robí :)

Zkusil jsem to pokud myslíš hodnotu 1000000 v tomto skriptu změnit.
Podľa manuálu nie je od verzie 4.2.0 potrbné srand() vôbec vykonávať, lebo sa robí automaticky. Ale to je jedno, išlo mi o tento riadok:
$rand_location = rand(0, $size);


Skús namiesto $size dať číslo menšie ako 32768. Ono by to malo fungovať na väčšie čísla a nemal by si tam mať teda žiadnu chybu. Ale zjavne to tu zlyháva. Skús. Možno je problém niekde priamo v php alebo úplne mimo PHP.
perun
Profil
virgo:
Tak to asi není...já myslel že je v php knihovně funkce <b>mail </b>která tohle odešle?
Nie je, aj mail() sa musí pripojiť na nejaký mailový server, ktorý je na systéme dostupný.
virgo
Profil *
Tak díky hodnota 32768 nešla ale když jsem napisal iba 32000 proslo to teraz akorat este ten mail skusim dotvorit.....zatial díky
fakeit
Profil *
perun:
Proč generovat náhodné heslo? Proč nevygenerovat klíč(s omezenou platností) pomocí kterého si uživatel heslo změní?..

Ten tvůj způsob se mi zdá fakt..nepěkný :)
fakeit
Profil *
Omlouvám se za špatnou reakci, má být směřována k virgovi. :)
virgo
Profil *
fakeit:
Ten tvůj způsob se mi zdá fakt..nepěkný :)
uplně tak můj skript to není jen upravený. ale pro me účely to stačí ale pokud máš k dispozici nějaký takový skript tak ho sem šoupni jestli to nebude vadit rád se naučím další možnost.
fakeit
Profil *
virgo:
No, zbytečně zatěžuješ server. Popíšu ti, jak na to:
<?php 
// 1. vytvoříš klíč
function getKey(){
$string = "abcdefghijklmnopqrstuvwxyz";
for($i = 0; $i < 40; $i++){

$y = rand(0, count($string));
if(!$key) $key = $string[$y];
  else $key .= $string[$y];

}
return $key;
}

function notify($email){
// 2. ověříš klíč
$key = getKey();
if(!query(...$key)->fetch()){
    // pokud klíč neexistuje, zapíšeš ho do DB
    query(INSERT $key, $time);
    // odešleš email na uvedenou emailovou adresu s odkazem ve tvaru: www.example.com/?keyactivation=$key
    mail(...); 
}else self::notify($email); // pokud klíč je, zavoláš funkci znova..

?>
Pak už jen zkontroluješ, jestli je platný klíč, když ano, tak uživateli nabídneš formulář pro změnu hesla.

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: