Gå til innhold

session_id sikkerhet intraweb


Anbefalte innlegg

Skal lage et intraweb der det skal være mulig å poste saker og ting, der (selvfølgelig) det kun er innloggede brukere som skal ha tilgang.

 

I den forbindelse tenkte jeg å begynne med sikkerhetsdelen. Tidligere har jeg brukt session-variabler, og sjekket dem for hver eneste side om de er satt. Dette kan jo være enkelt å "lure" seg forbi dersom man har en eksisterende session fra en annen side(?).

 

Har lest noe om at enkelte bruker hashing av IP + brukernavn + passord, og bruker dette som session_id. Hvordan gjør man dette?

 

I tillegg vil man jo at det skal være en begrenset tid fra forrige gang brukeren var inaktiv. Det vil si at brukeren timer ut.

 

Setter pris på alle innspill :)

Lenke til kommentar
Videoannonse
Annonse

Er vel enklere med .htaccess her?

 

Men hvis jeg skal bruke sessions pleier jeg å sjekke IP og User-Agent i tillegg:

 // han tastet riktig passord:
session_start();
$_SESSION['logged_in'] = 1;
$_SESSION['logged_in']['ip'] = md5($_SERVER['REMOTE_ADDR']);
$_SESSION['logged_in']['ua'] = md5($_SERVER['HTTP_USER_AGENT']);

session_start();
if ($_SESSION['logged_in'] != 1 && $_SESSION['logged_in']['ip'] != md5($_SERVER['REMOTE_ADDR']) && $_SESSION['logged_in']['ua'] != md5($_SERVER['HTTP_USER_AGENT'])) {
die("Sorry mate. No hacking!");
}

Endret av Judofyr
Lenke til kommentar

Det blir jo det alternativet jeg har hatt før..

 

Problemet her blir sikkerhetsmessig at hvis man har to sider som kjører det samme systemet (totalt uavhengige av hverandre), så kan man vel bare "hoppe" innom den andre siden som kjører samme system uten innlogging...

 

Tar jeg helt feil her?

 

Det jeg tenker da er evt. å gjøre det slik jeg har gjort det før (og Judofyr gjør) å lagre ip og ua i databasen, for å så teste oppimot disse i stedet for.

 

Men jeg har forstått at man kan ha en session_id som inneholder ip,ua,bruker,tidspunkt osv.. Hadde vært litt "bedre" med kun en ssid å sjekke mot.

 

 

Noen som har en ide hvordan løse dette med timestamp? Den skal jo oppdateres _hver_ gang brukeren foretar seg noe. Er dette "innebygd" i session, eller må man lage dette selv?

Lenke til kommentar

Jeg har også lurt litt på mulighetene rundt sessions, men slik jeg tror det fungerer:

 

ADVARSEL:

Dette er slik jeg TROR det fungerer, det er ikke dermed sagt at det faktisk ER slik det fungerer

 

Alle brukere blir tildelt en SESSID som er en random hash på X antall tegn (32 elns.). Resten av sessioninformasjonen lagres på serveres, med SESSID'en som en slags referanse (tenk db). Dvs. at det eneste klienten faktisk har tilgang til fra sin egen maskine er SESSID'en da den enten lagres som cookie, eller sendes med GET/POST.

For å kunne komme inn på ditt system, må han gjette SESSID'en til noen som har logget inn, og sette sin egen cookie/GET/POST til å bruke denne. Det sier seg selv at dette ikke er så lett å gjete når vi snakker en 32-bits hash.

 

Kan ikke få presisert nok at dette kun er slik jeg TROR det fungerer, skulle gjerne hatt en skikkelig oppklaring rundt dette.

Lenke til kommentar

Nazgul: Jeg tror du har helt rett i det du sier.

 

Problemet er imidlertid hvor sessionfiler lagres. Jeg tror de fleste hoster lagrer disse i mappen /tmp. Dersom serveren siden ligger på kjører PHP som apache modul, vil alle sessionfiler for alle siter på serveren kunne leses (via usikkert skript eller av en som har tilgang til en konto på serveren). Kjører PHP som CGI kan kun ditt eget nettsteds filer leses via usikkert skript.

 

Det kan være greit å spesifisere hvor sessionfiler skal lagres.

Lenke til kommentar

Vel, skal man ha det sikkert så går du for SSL og database-basert session (altså "lager" det selv). Nå er vel SSL-biten litt vanskelig å få til, og en smule over-kill for de fleste. Derimot er database-basert session relativt lett å få til og gir enkelt en mulighet til å sjekke hvor mange som er logget inn f.eks.

 

CREATE TABLE `tabell` (
 `sessionid` char(40) collate utf8_unicode_ci NOT NULL default '',
 `userid` smallint(5) unsigned NOT NULL default '0',
 `ip` char(40) collate utf8_unicode_ci NOT NULL default '',
 `browser` char(40) collate utf8_unicode_ci NOT NULL default '',
 `expire` int(10) unsigned NOT NULL default '0',
 PRIMARY KEY  (`sessionid`)
) ENGINE=MEMORY;

Trenger ikke være noe verre enn det der. Merk at den tar utgangspunkt i sha1. Har du tenkt å bruke md5 så skal sessionid, ip og browser være på 32.

Så kommer ørten linjer for å "administrere" det her som jeg ikke orker å skrive nå, men her er nå iallfall litt "pseudokode":

Fjern whitespace og sikre (dvs. fjern/ufarliggjøre alle uønskede tegn) brukernavn og passord
Hent ut rad fra bruker-tabellen med brukernavnet og passordet
Hvis det returnerte en rad
{
  $session_id = sha1(uniqid(mt_rand(), true)); //Dette genrerer en session-id som er så og si garantert å være unik. md5 kan brukes i stedet for sha1
  Sett en cookie med $session_id
  Sett inn en rad i tabellen jeg limte inn over. IP ($_SERVER['REMOTE_ADDR']) og nettleser ($_SERVER['HTTP_USER_AGENT']) hashes. expire bør inneholde nå (dvs. time()) + hvor lenge session skal være gyldig
  Redirect bruker til ny side
}
Hvis ikke var passordet og/eller brukernavnet ikke gyldig

 

Så var det å sjekke om en bruker er logget inn:

Hvis cookie finnes
{
  Sikre (dvs. fjern/ufarliggjøre alle uønskede tegn) fra cookie-variablen (Tipper en del ikke tenker på den her med det første ... )
  Hent ut rad fra tabellen jeg limte inn over hvor sessionid, ip og browser stemmer overens med "virkeligheten" samt at expire er større enn nuh (dvs. time())
  Hvis dette returnerer en rad
  {
     Hvis time() - expire - sessionlengde > 60
     {
        Slett alle rader hvor expire er mindre enn time()
     }
     Oppdater raden (dvs. sett expire til time + sessionlengde)
  }
  Hvis ikke er brukeren ikke logget inn (Fjern gjerne cookie siden den er ugyldig)
}
Hvis ikke er bruker ikke logget inn sender du vedkommende til en innloggingsside og/eller gir feilmelding

 

En ting igjen, og det er utlogging:

Slett rad med sessionid (hentet fra cookie)
Fjern cookie
Flytt bruker

Post gjerne koden du ender opp med ;)

 

Nazgul: Korrekt bortsett fra at ID er hex-encoded hash på 128bit (sannsynligvis md5) tilsvarende en linje langt oppi innlegget her ( $session_id = sha1(uniqid(mt_rand(), true)); ).

Endret av Ernie
Lenke til kommentar

Vist scriptet skal brukes av andre folk i andre land, spesielt usa (men også england, frankrike og andre europeiske land som har aol/msn isp) så vil du få problemer vist du låser sessionene til iper. Grunnen er at aol og msn kjører med eit proxy system som gjør at ein bruker kan skifte ip under kvar page load på det verste (Dette er ekstrem tilfeller, men det kan skje).

 

Isteden for lås sessionen til for eksempel dns og browser id (ikkje like sikker men bedre enn ingenting).

 

I tillegg til Ernie sin gode forklaring så vil du kansje finne det enda litt lettere etter å ha lest dokumentasjonen for denne featuren i php.

 

http://no2.php.net/manual/en/function.sess...ave-handler.php

Lenke til kommentar

Takker for all hjelp, her er det jeg foreløpig har kommet frem til:

 

Hvis brukernavn og passord godtas

$session_id = md5(uniqid(mt_rand(), true));
$ip= md5($_SERVER['REMOTE_ADDR']);
$ua= md5($_SERVER['HTTP_USER_AGENT']);
$timestamp=time()+30; // 30 sec

$sql_query="INSERT INTO loggedin VALUES('$session_id','bruker','$ip','$ua','$timestamp')";

$_SESSION['sid']=$session_id;

$sqlRes=mysql_query($sql_query);
echo $sqlRes;

 

For å sjekke at session er gyldig (kjøres på alle sider/ved oppdatering)

if(isset($_SESSION['sid']))
{
$sid=$_SESSION['sid'];
$sql_query="SELECT * from loggedin where sessionid='$sid'";

$sqlRes=mysql_query($sql_query);

$rad=mysql_fetch_array($sqlRes);

if(($_SESSION['sid']==$rad['sessionid'])&&(md5($_SERVER['REMOTE_ADDR'])==$rad['ip'])&&(md5($_SERVER['HTTP_USER_AGENT'])==$rad['browser']))
{
 if($rad['expire']<time())
 {
 	echo 'session har timet ut';
 	session_destroy();
 }
 else
 {
 	$newtime=time()+30;
 	$sql_query="UPDATE loggedin SET expire='$newtime' WHERE sessionid='$sid'";
 	mysql_query($sql_query);
 }
}
}

 

loggedin er altså tabellen ernie kalte 'tabell' med litt modifiseringer. Virker dette greit, eller er det noen store feil med det oppsettet?

 

Legg merke til at jeg bruker sessions i stedet for cookie, og lagrer brukerdataene der.

 

Nok en gang; alle forslag mottas med takk. Ideen er nå og lage dette en gang for å så kunne ta gjenbruk av systemet til senere sider. Derfor vil jeg at det skal være så sikkert og optimalt som mulig. :)

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å
×
×
  • Opprett ny...