Gå til innhold

Sjekkeliste for login scripts


Anbefalte innlegg

Videoannonse
Annonse
Ok. Men det bør iallfall opp på sjekklisten da, å pakke inn i addslashes() eller lignende.

Hva er forresten forskjellen på addslashes() og mysql_real_escape() ? Gjør de akkurat det samme?

5725184[/snapback]

Ja, for de fleste her vil de gjøre eksakt det samme. En kverulant vil raskt rette meg og si at mysql_real_escape også tar et par tegn til, men disse har ingen praktisk betydning og escapes bare for at loggen ikke skal fuckes helt opp. mysql_real_escape vil være å foretrekke hvis man benytter mysql-database.

 

edit:
[*]Ikke bare sjekke brukernavn og passord. Skriv innlogginstida og ip, og sjekke om ipen stemmer (dette er for å hindre session hijacking, leste om det i en artikkel) og om tida er innenfor en bestemt timeout. (mulig dette er fiksbart med session_cache_expire, er ikke sikker)

5724029[/snapback]

Så at Ernie (tror jeg det var) skrev en annen plass at det også var lurt å sjekke ting som browser osv. Vet ikke hvor mye sikkerhet det gir med sånne småting akkurat, men kan kanskje være verdt å ta med.

5725184[/snapback]

Ja, det kan være lurt å notere seg ned nettleser samt også kjøre den igjennom en hash-funksjon (dvs. md5 eller sha1). Grunnen til dette er for å hindre at noen kan kapre session hvis man benytter en proxy-server eller delt IP.

Lenke til kommentar

Mitt login script

 

 

<?php

function Login()

{

global $screen, $SYS, $DB, $LOGIN, $lang, $COOKIE, $Login, $user;

 

// Do we allready is Logged in?

if($user->Login == 1)

{

// Header to index

header("Location:index.php");

}

if(!isset($_POST['submit']))

{

$HTML['L_Username'] = $lang['Username'];

$HTML['L_Password'] = $lang['Password'];

$HTML['L_Remember'] = $lang['Remember'];

$HTML['L_Hide'] = $lang['Hide'];

$screen->Add_HTML('Login', $HTML);

}

else

{

$Username = $_POST['username'];

$Password = $_POST['password'];

$Remember = 0;

if(isset($_POST['remember'])) $Remember = 1;

$Hide = 0;

if(isset($_POST['hide'])) $Hide = 1;

// Include hash driver

require ($SYS['Path'] . '/Includes/HASH/' . $LOGIN['Hash_Driver'] . '.php');

 

// Get user id (if user exist)

$Id = $DB->Get_User_Id($Username);

if(!$Id)

{

$Msg = $lang['Login_Fail_User_Pass'];

}

else

{

// Check if a user is logged in with this IP

$IP = $_SERVER['REMOTE_ADDR'];

if($DB->Check_IP_Login($IP))

{

// Do a logout

$timeout = time()- 31536000;

setcookie('wep_session_id', '', $timeout, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_uid', '', $timeout, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_theme', '', $timeout, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_language', '', $timeout, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_visit', '', $timeout, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

 

// Unset Session

$DB->Remove_Session(null, $IP);

}

// Get salt and password

$Data = $DB->Get_User_Login($Id);

$Salt = $Data->salt;

$DB_Password = $Data->password;

 

// Calculate Password and check if it match

 

$Password = Hash($Password, $Salt);

if($Password == $DB_Password)

{

$time = time();

 

 

$DB->Update_Last_Login($time, $Id);

$DB->Set_Session(md5($IP . $time), $Id, $IP, $time, $Remember, $Hide);

 

if($Remember != "")

{

setcookie('wep_session_id', md5($IP . $time), $time+31536000, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_uid', $Id, $time+31536000, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

}

else

{

setcookie('wep_session_id', md5($IP . $time), null, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_uid', $Id, null, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

}

 

header("Location:index.php");

}

}

// If not user is send to index page by now, print error page.

$screen->Add_HTML('Error', array('MSG' => $Msg));

 

}

}

 

function Logout()

{

global $DB, $user;

 

// Must be logged in to log out.

if($user->Login == 1)

{

$time = time()- 31536000;

setcookie('wep_session_id', '', $time, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_uid', '', $time, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_theme', '', $time, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_language', '', $time, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

setcookie('wep_visit', '', $time, $COOKIE['Path'], $COOKIE['Domain'], $COOKIE['Secure']);

// Unset session

$DB->Remove_Session($user->Session);

}

header("Location:index.php");

 

}

 

 

Database fungsjonene:

 

 

function Get_User_Login($id)

{

$this->Query("SELECT password, salt FROM {$this->Prefix}users WHERE id = '$id' LIMIT 1");

return $this->row();

}

 

function Update_Last_Login($Time, $id)

{

$this->Query("UPDATE {$this->Prefix}users SET `last_login` = '$Time' WHERE id = '$id' LIMIT 1");

}

 

function Set_Session($SID, $UID, $IP, $Time, $Remember, $Hide)

{

$this->Query("INSERT INTO {$this->Prefix}session ( `sid` , `uid` , `time` , `ip` , `stayin` , `hide` ) VALUES ( '$SID', '$UID', '$Time', '$IP', '$Remember', '$Hide' )");

 

}

 

function Check_Session($SID, $UID)

{

$IP = $_SERVER['REMOTE_ADDR'];

$this->Query("SELECT * FROM {$this->Prefix}session WHERE sid='$SID' AND ip='$IP' AND uid='$UID' LIMIT 1");

return $this->row();

}

 

function Remove_Session($SID, $IP = 0)

{

if($IP == 0)

{

$this->Query("DELETE FROM {$this->Prefix}session WHERE `sid` = '$SID'");

}

else

{

$this->Query("DELETE FROM {$this->Prefix}session WHERE `ip` = '$IP'");

}

}

 

function Check_IP_Login($IP)

{

$this->Query("SELECT ip FROM {$this->Prefix}session WHERE `ip` = '$IP'");

$Match = $this->row();

$Match = $Match->ip;

if($Match == $IP)

{

return true;

}

 

return false;

}

 

 

 

Gjort før med $_GET, $_POST og $_COOKIE:

 

 

foreach($_GET as $row => $value)

{

if(!get_magic_quotes_gpc())

{

$value = addslashes($value);

}

$row = trim($row);

$value = trim($value);

$_GET[$row]= $value;

}

 

foreach($_POST as $row => $value)

{

if(!get_magic_quotes_gpc())

{

$value = addslashes($value);

}

$row = trim($row);

$value = trim($value);

$_POST[$row]= $value;

}

 

foreach($_COOKIE as $row => $value)

{

if(!get_magic_quotes_gpc())

{

$value = addslashes($value);

}

$row = trim($row);

$value = trim($value);

$_COOKIE[$row]= $value;

}

 

 

Endret av hotstian
Lenke til kommentar

Tror jeg fant ut en måte å motstå "man-in-the-middle" attacks, uten å ty til https. Mulig det går å legge inn et javascript md5 hasher som krypterer passordet mens brukeren skriver for så og sende den krypterte strengen til servern.

 

fant flere sånne scripts på google: http://pajhome.org.uk/crypt/md5/md5src.html

 

men problemet kommer da til de som har javascript deaktivert...

 

er dette lurt eller poengløst?

Lenke til kommentar
Tror jeg fant ut en måte å motstå "man-in-the-middle" attacks, uten å ty til https. Mulig det går å legge inn et javascript md5 hasher som krypterer passordet mens brukeren skriver for så og sende den krypterte strengen til servern.

 

fant flere sånne scripts på google: http://pajhome.org.uk/crypt/md5/md5src.html

 

men problemet kommer da til de som har javascript deaktivert...

 

er dette lurt eller poengløst?

5730496[/snapback]

Vil tro det er rimelig poengløst. Har man reel grunn til å tro at noen gidder å lytte på trafikken så bruker man https. Vil man vite om js er aktivert så sender du jo bare med en ekstra variabel som f.eks js_aktiv og setter i utgangspunktet lik false, men til true gjennom js.

 

Dog åpner man et nytt hull med det her. Sett et bruker kjenner hash-en, men ikke hva passordet egentlig er? ;)

Endret av Ernie
Lenke til kommentar
  • 5 måneder senere...

For å videre sikre passord er det lurt å bruke salting. Dette vil praktisk talt ødelegge dictionary lookup metdoen, rainbow tables og sakte ned en bruteforcer.

 

Det som gjøres er at hvis en person har "hei" som passord vil det ikke ta lenge for en angriper (som har hashen) å finne passordet via en rainbow table eller dictionary lookup. Mens bruteforcing på en normal pc kanskje bare tar en dag eller noe. Altså, for å hindre at dette skjer lagrer man saltet (som er en tilfeldig streng) i tillegg til brukernavn og passord-hash i databasen. Så hvis en bruker har "hei" som passord legger man til saltet foran sånn at det blir "S#GH'l5!iy3p'cJ15$~F!6XxR3z$O2n0hei" og hasher denne strengen istedet. Det finnes nok ingen rainbowtables som har hashet en sånn streng. Og hvis angriperen har saltet ville det ikke hjelpe heller. For å kunne bruke dictionary lookup metoden må han re-hashe hele ordboka med saltet foran (eller bak som også er en mulighet). I tillegg vil bruteforcing fort bli utrolig tidkrevende. Problems solved. :D

 

<?php
/*
SALTER

Designed for "salting hashes".

Returns a 32 character long random string including a-z,A-Z,0-9 and
some special characters.
Function can be used to generate random passwords.
*/

function make_salt() {
// a secure password needs a-z,A-Z,0-9 and some special characters
// (actually, it doesn't really matter since the hash will be very
// different no matter... But, it makes it harder to bruteforce.)
$az	= array("a","b","c","d","e","f","g","h","i","j","k","l","m",
 	"n","o","p","q","r","s","t","u","v","w","x","y","z");
$AZ	= array("A","B","C","D","E","F","G","H","I","J","K","L","M",
 	"N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
$chars	= array(".",",","/","&",":",";","-","_","*","(",")","[","]",
 	"{","}","+","?","%","#","!","<",">","~","$",'"',"'",
 	"@",";","=");

// lets have 8 random numbers
for($i=0; $i<8; $i++) {
 $str[]	= rand(0,9);
};

// lets have 8 random a-z
for($i=0; $i<8; $i++) {
 $str[]	= $az[rand(0,count($az)-1)];
};

// lets have 8 random A-Z
for($i=0; $i<8; $i++) {
 $str[]	= $AZ[rand(0,count($AZ)-1)];
};

// lets have 8 random special characters
for($i=0; $i<8; $i++) {
 $str[]	= $chars[rand(0,count($chars)-1)];
};

// lets shuffle it
//$str	= preg_split('//',$str,-1,PREG_SPLIT_DELIM_CAPTURE);
shuffle($str);
$str	= implode("",$str);

return	$str;
};



header("Content-type: text/plain; charset=UTF-8");
var_dump(make_salt());
echo "\n";
var_dump(make_salt());
echo "\n";
var_dump(make_salt());
echo "\n";
var_dump(make_salt());
echo "\n";
var_dump(make_salt());
echo "\n";
var_dump(make_salt());
echo "\n";
var_dump(make_salt());
echo "\n";



?>

aiiii, la til for loops istedet.

Endret av MC2
Lenke til kommentar

Login2:

function createSession($uid)
{
 global $DB;
 // First create a SID
 $time = time();
 $IP = $_SERVER['REMOTE_ADDR'];
 $SID = sha1($IP . $time . $_SERVER['HTTP_USER_AGENT']);

 // Then Put it into DB
 $DB->query('INSERT INTO '.SESSION_TABLE." ( `session_id` , `session_uid` , `session_started` , `session_ip`) VALUES ( '$SID', '$uid', '$time', '$IP')", 0);

 return $SID;
}

if(isset($_POST['submit']))
{
$Username = addslashes($_POST['username']);
$Password = addslashes($_POST['password']);
$Remember = (empty($_POST['remember']) ? 0 : 1);
$Hide = (empty($_POST['hide']) ? 0 : 1);

// Make it take some time
sleep(1); // Maybe like 5sec for extra securitty

// Get user data (if user exist)
$DB->query('SELECT id, password, active, salt FROM '.USER_TABLE.' WHERE username = \''.$Username.'\' LIMIT 1');
$data = $DB->fetch();
$id = $data['id'];

// Username or password wrong?
if(!$id || $data['password'] != pwhash($Password, $data['salt']))
{
 $Message = $lang['Login_Fail_User_Pass'];
}

// User not activated?
if(!$data['active'])
{
 $Message = $lang['User_Not_Activated'];
}

$SID = createSession($id);

if($Remember != "")
{
 setcookie($conf['Cookie_Prefix'] . 'sid', $SID, time()+31536000, $conf['Cookie_Path'], $conf['Cookie_Domain'], $conf['Cookie_Secure']);
}
else
{
 setcookie($conf['Cookie_Prefix'] . 'sid', $SID, null, $conf['Cookie_Path'], $conf['Cookie_Domain'], $conf['Cookie_Secure']);
}

// Redirect back to index
redirect("index.php");
}


//$template->add_javascript('sha2'); valgfri

// If not user is send to index page by now, print error page.
if(isset($Message)) $template->body('Error', array('MESSAGE' => $Message));


$template->body('Login');
?>

 

$template->body => Legg til html coden (du kan bruke include())

$lang => Språk arrayen (For multispråk, du kan inline)

$conf => Enkel configurasjon (Se scriptet, kan inlines)

$DB->Query() => Utfør database query (mysql(i)_query())

$DB->fetch() => mysql(i)_fetch_assoc()

SESSION_TABLE => sesions tabelen

USER_TABLE => bruker tabelen

 

Elsker kode der folk må gjøre noe for å bruke det.

 

Eksempel form

<form action="login.php" method="POST"">
 	USERNAME: <input type="text" name="username" /><br />
 	PASSWORD: <input type="password" name="password" /><br />
 	REMEMBER: <input type="checkbox" name="remember" /> HIDE: <input type="checkbox" name="hide" /><br />
 	<input type="hidden" name="submit" value="1" />
 	<input type="submit" />
 </form>

Konfig

$dbprefix = 'login_';
define('USER_TABLE', $dbprefix.'users');
define('SESSION_TABLE', $dbprefix.'session');

$conf['Cookie_Domain'] = '';
$conf['Cookie_Path'] = '/wep/';
$conf['Cookie_Secure'] = 0;
$conf['Cookie_Prefix'] = 'wep_';

Funsjoner

function pwhash($pw, $salt)
{
 return sha1($salt.$pw); //Custom your way
}

 

Resten fikser du selv. (Loginscript er best slik)

Endret av hotstian
Lenke til kommentar

Enklere salt (kortere kode):

 

$chars = array( 'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F', 'g', 'G', 'h', 'H', 'i', 'I', 'j', 'J',  'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'o', 'O', 'p', 'P', 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T',  'u', 'U', 'v', 'V', 'w', 'W', 'x', 'X', 'y', 'Y', 'z', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', ':', '.', '-', '_', '?', '+', '/', '\'', '"', '}', '{', '[', ']', '(', ')');

$max_chars = count($chars) - 1;

$rand_str = '';
for($i = 0; $i < $length; $i++)
{
 $rand_str .= $chars[mt_rand(0, $max_chars)];
}

return $rand_str;

 

Generer SID

function createSession()
{
 // create a SID
 $time = time();
 $IP = $_SERVER['REMOTE_ADDR'];
 $SID = sha1($IP . $time . $_SERVER['HTTP_USER_AGENT']);

 return $SID;
}

Lenke til kommentar
Generer SID

function createSession()
{
 // create a SID
 $time = time();
 $IP = $_SERVER['REMOTE_ADDR'];
 $SID = sha1($IP . $time . $_SERVER['HTTP_USER_AGENT']);

 return $SID;
}

6732670[/snapback]

Den der tviler jeg på om blir tilfeldig nok. Sett at noen sitter på jobb bak en proxy, begge bruker samme nettleser og logger seg inn på eksakt det samme tidspunktet? Da vil faktisk session være eksakt lik. Dessuten vil den i aller høyeste grad være forutsigbar. Skal du lage sessionid selv så må den være så tilfeldig som du overhode klarer å få den.

$session_id = sha1(uniqid(mt_rand(), true));

Stort mer tilfeldig enn det der tror jeg ikke du får det.

Lenke til kommentar

Skal en del til før de treffer på akkurat samme sekundet, og evt. kan du jo bruke microtime(), men resten er faktisk ganske sannsynlig. (browser og proxy)

Virker egentlig for meg som at å mikse inn browser gir litt falsk følelse av sikkerhet. Ihvertfall med tanke på at det bare er 3 browsere på markedet, hvorav 2 deler 98%, og igjen én sitter med 80-90% av det igjen. IP fungerer vel også dårligere ettersom fler og fler ender bak en ruter/gateway/proxy.

Lenke til kommentar
Bedre en uniqid()?
function createSession()
{
// create a SID
$time = microtime();
$IP = $_SERVER['REMOTE_ADDR'];
$string_num = mt_rand(6, 22);
$string = '';
for($i = 0; $i <= $string_num; $i++) $string += chr(mt_rand(0, 255));
$SID = sha1($IP . $time . $string . $_SERVER['HTTP_USER_AGENT'] . $string_num);

return $SID;
}

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...