05. januar 2010 - 20:28Der er
58 kommentarer og 1 løsning
Kan ikke finde fejl.
Jeg har disse to filer her under. Det er noget jeg er ved at prøve af til et login system. Planen er så at brugernavet bliver gemt som session og en nøgle bliver gemt som cookie. Det er for at være sikker på der er tale om den rigtige person. Min test login side er "1.php", derfra går man til "2.php" som er en side der tjekke om du er logget ind og opdater nøglen for at være helt sikker på den ikke bliver opsnappet. Der skal også noget ip ind over for at gøre det mere sikkert. Men problemet er at når man står på 2.php og trykker F5 (opdater) kommer der til at stå "fejl", der skulle gerne stå "Du er stadig online". For jeg har jo ikke slettet min session eller cookie, blot opdateret cookie. Håber i kan hjælpe.
//1.php <?php session_start(); //Starter session $_SESSION['brugernavn'] = "lalalllala"; include "connect.php"; $key=time().rand(); setcookie("key", $key); mysql_query("INSERT INTO online (id,brugernavn,nøgle)VALUES(NULL,'".$_SESSION['brugernavn']."','".$key."')"); ?> <a href="2.php">Gå nu til 2.php</a>
\\ 2.php <?php session_start(); include "connect.php"; if(isset($_SESSION['brugernavn']) && isset($_COOKIE['key'])) { $q=mysql_query("SELECT * FROM online WHERE brugernavn='".$_SESSION['brugernavn']."' AND nøgle='".$_COOKIE['key']."' "); if(mysql_num_rows($q)==1) { $key=time().rand(); mysql_query("UPDATE online WHERE brugernavn='".$_SESSION['brugernavn']."' SET key='".$key."'"); setcookie("key", $key); echo "Du er stadig online"; die; } else { echo "Fejl"; } } ?>
Prøv at benytte if(mysql_num_rows($q)>=1) i stedet for if(mysql_num_rows($q)==1)
Det ser ud til, at brugeren opretter en online entry hver gang der logges på, men de bliver ikke slettet. Derfor kan du ikke regne med, der kun er 1 entry.
Synes godt om
Slettet bruger
05. januar 2010 - 21:19#5
Hvis det ikke virker, er det altid en god ide at debugge ved at udskrive dine variable i stedet for at teste om det hele virker på en gang:
<?php session_start(); include "connect.php"; print_r($_SESSION); print_r($_COOKIE); if(isset($_SESSION['brugernavn']) && isset($_COOKIE['key'])) { $q=mysql_query("SELECT * FROM online WHERE brugernavn='".$_SESSION['brugernavn']."' AND nøgle='".$_COOKIE['key']."' "); if(mysql_num_rows($q)==1) { $key=time().rand(); mysql_query("UPDATE online WHERE brugernavn='".$_SESSION['brugernavn']."' SET key='".$key."'"); setcookie("key", $key); echo "Du er stadig online"; die; } else { echo "Fejl"; } } ?>
#3 session_regenerate_id() er en rigtigt god ide, for at gøre det nemmere. Men det ændre ikke på problemet.
#4 Du skal bare gå ud fra der er 1 i min lille test.
#5 Har testet det på en helt masse måder for at finde fejlen.
#6 Brugernavnet skal gerne være helt unikt.
#7 Jo brugernavet skal gerne være unikt ellers giver det problemer her "if(mysql_num_rows($q)== 1)".
#8 Det er i min lille test ikke vigtigt i hvorfor en tabel jeg lægger min data i.
Jeg har nu rette lidt og det ser ud som her under. Det virker lidt bedre. Problemet er nu at hvis jeg opdaterer (trykker F5) en helt masse så skriver den stadig "Fejl". Det virker dog hvis jeg skriver "if(mysql_num_rows($q)>=1)" i stedet for "if(mysql_num_rows($q)==1)". Men det vil jo sige at der kan være mere end en bruger med disse oplysninger? og sådan skal det ikke være. Håber i kan finde fejlen.
//1.php <?php session_start(); //Starter session $_SESSION['brugernavn'] = "lalalllala"; include "connect.php"; $key=time()+rand(); setcookie("key", $key); mysql_query("INSERT INTO online (id,brugernavn,nøgle)VALUES(NULL,'".$_SESSION['brugernavn']."','".$key."')"); ?> <a href="2.php">Gå nu til 2.php</a>
//2.php <?php session_start(); include "connect.php"; if(isset($_SESSION['brugernavn']) && isset($_COOKIE['key'])) { $q=mysql_query("SELECT * FROM online WHERE brugernavn='".$_SESSION['brugernavn']."' AND nøgle='".$_COOKIE['key']."' "); if(mysql_num_rows($q) == 1) { $key=time()+rand(); mysql_query("UPDATE online SET nøgle = '".$key."' WHERE brugernavn = '".$_SESSION['brugernavn']."'"); setcookie("key", $key); echo "Du er stadig online"; } else { echo "Fejl"; } } ?>
#10 Ja det er jeg godt klar over. Men dette er en test så jeg kører kun 1.php 1 gang hvor efter jeg kører 2.php. Og jeg tømme tabellen efter hvert forsøg. Du skal se 1.php som en login-side og 2.php som en side der tjekker om du er logget ind.
#14 Ja, jeg har testet det så meget jeg kan. Ved ikke lige hvordan jeg skulle kunne teste det mere. Min eneste ide til at der kan fejlen skulle være at mysql er for langsomt. Men det tror jeg ikke.
#13 Det var nu ikke fordi det var et problem jeg havde tænkt mig at imødekomme; men hvis det endelig er synes jeg da at #3 kom med et fremragende alternativ som simpelt kunne løse dit problem - endda på en pæn måde...
#17 Jeg har også tænkt mig at benytte session_regenerate_id() men det løser bare ikke mit problem.
Synes godt om
Slettet bruger
06. januar 2010 - 16:58#19
#15 Du kunne jo udskrive de fundne værdier sammen med session og cookie og paste det ind her. Benyt dette script og paste det fra kildekoden (I IE: højreklik -> view source)
//1.php <?php session_start(); //Starter session $_SESSION['brugernavn'] = "lalalllala"; include "connect.php"; $key=time()+rand(); setcookie("key", $key); mysql_query("INSERT INTO online (id,brugernavn,nøgle)VALUES(NULL,'".$_SESSION['brugernavn']."','".$key."')"); ?> <a href="2.php">Gå nu til 2.php</a>
//2.php <?php session_start(); include "connect.php";
print_r($_SESSION); print_r($_COOKIE['key']);
if(isset($_SESSION['brugernavn']) && isset($_COOKIE['key'])) { $q=mysql_query("SELECT * FROM online WHERE brugernavn='".$_SESSION['brugernavn']."' AND nøgle='".$_COOKIE['key']."' ");
#18 Problemet ligger nok i din database. Det eneste jeg har gjort er at oprette en tabel der hedder online og navngive felterne anderledes. Og så brugte jeg de oprindelige scripts fra #0 og rettede kun feltnavnene til i dine SQL sætninger. Det virker fint. SQL:
CREATE TABLE IF NOT EXISTS `online` ( `oId` int(11) NOT NULL auto_increment, `oBrugernavn` varchar(255) NOT NULL, `oKey` varchar(255) NOT NULL, PRIMARY KEY (`oId`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
#21 Mit forslag har jeg testet og konstateret at det virker; har du selv prøvet at teste det jeg har givet dig? Eller konstaterer du blot at det ikke er databasen der fejler noget?
#22 Det du har givet mig ligger på http://www.je1020.wep.dk/login2/ og det virker ikke.. Jeg får også fejlen Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in F:\HJEMMESIDER\JE1020\JE1020.WEP.DK\login2\2.php on line 7 ved din udgave.
Hvis du opdaterer meget hurtigt, kan du sikkert godt komme ud af sync med værdierne. Men hvad er der i databasen? Der er kun een linie for brugernavnet, ikke?
Er du sikker på det ikke er fordi at der sidder et par stykker af os - udover dig selv - og tester på 1.php og 2.php samtidig? For så skal det jo fejle (det var vel hensigten).
Udover det, så er der i 2.php, linie 7 også lige det krav at mysql resultatet SKAL returnere 1 række. Og i 1.php indsætter du faktisk bare en ny række for hver gang (ihvertfald inden du valgte at generere et unikt brugernavn for hver gang man besøgte 1.php).
Nej, den er god nok - at den fejler, altså. Du kan få 2 opdateringer af databasen, men kun een cookie værdi tilbage - og måske den forkerte, afhængig af hvordan det kører på serveren.
Men nu for tredie gang: Hvad står der i databasen? Er der tilfælde med mere end een række for samme brugernavn - i hvert fald efter det er blevet tilfældigt?
#32 Er ikke helt med på hvad du mener med "Du kan få 2 opdateringer af databasen, men kun een cookie værdi tilbage - og måske den forkerte, afhængig af hvordan det kører på serveren."
Nej, jeg kan ikke forklare ">="-problemet ud fra de givne data. Før du lavede tilfældige brugernavne, kunne der godt være et problem.
Når du laver 2 hurtige forespørgsler til webserveren, udføres begge i "tilfældig" rækkefølge. Dvs at du får begge opdateringer til databasen, men kun een af cookie-værdierne.
Som jeg også skrev tidligere var det ikke et problem jeg gad at imødekomme. Og som nævnt i #38, så ville en fin løsning være SSL, for at undgå packet sniffing, som nok er den eneste 'reelle' trussel i denne sammenhæng.
#38, #39 Så hvis jeg bare lave det sådan jeg gemmer en cookie eller bruger session_id(), som jeg som jeg gemmer værdien af i en tabel og brugens ip. Så kan jeg tjekke om bruger sidder på den samme ip hele tiden ellers skal han ikke have lov at være logget mere. så skal en hacker både lave sin ip om og og skaffe det session_id(). Er det ikke det mange andre gør og er det er god løsning? så kan jeg evt. bruge SSL hvis det skal være mere sikkert.. Men synes det er trælst jeg ikke kan skifte den cookie ud hele tiden.. :( Det kunne være dejligt at gøre det meget svært at få fat i den.
Lige en ting til. Ville det være dumt at bruge kode med if(mysql_num_rows($q)>=1)?
Synes godt om
Slettet bruger
06. januar 2010 - 23:02#41
2.php virker ikke mere.
Ja det vil være dumt at bruge løsningen if(mysql_num_rows($q)>=1), når du ikke ved, hvorfor det er nødvendigt.
#40 Jeg bliver nød til at vide, hvorfor du mener at du bliver nød til tackle problemet med session hijacking? Er det et problem du er stødt på? Og hvorfor kan du ikke løse problemet med teknikken nævnt i #3, hvis det er så vigtigt?
Det med IP-nummeret skal du nok tænke over en ekstra gang.
Der findes brugere som skifter IP hele tiden - I USA er/var AOL kendt for det. Det er nok ikke synderligt udbredt i Danmark. Måske vil mobilt Internet også kunne skifte IP-nummer. Det vil give dig utilfredse besøgende, hvis de bliver smidt af hele tiden.
Og på den anden side, så kan der jo sagtens sidde mange personer bag det samme IP-nummer.
Ganske overordnet skal du bestemme dig til hvor meget "sikkerhed" du vil have. Jo mere sikkerhed, jo mere bøvl.
#42 Jeg synes generelt alt sikkerhed er meget vigtigt. Derfor synes jeg også man skal lukke alle huller så godt som muligt som udvikler. Hvis du kan lave et eksempel med teknikken nævnt i #3 som virker. Så synes jeg det er meget flot og så vil jeg gerne have du skriver hvad ud gør. Om jeg bruger session_regenerate_id eller min løsning, så får jeg da det samme problem?
#43 Det er rigtigt nok at nogle skifter ip-nummer tit. Men hvis ikke jeg gør andet end at sige $_SESSION['loggetind'] = ja; så kan en hacker da let komme ind?
Ret simpelt egentlig - den cookie som er ansvarlig for at medsende session id'et skifter hver eneste gang session_regenerate_id() anvendes. parameteren true anvender jeg så for at slette den gamle session. Ved at give brugeren et nyt session id, overføre den aktuelle sessions data over i den nye og samtidig slette indholdet i den gamle, vil det blive tæt på umuligt for en 'hacker' at hijacke din session. Så slipper du for at lave det gøjl som du har gang i, når nu PHP egentlig basalt set selv gør hvad det er du forsøger.
$_SESSION["tal"]++ var blot for at illustrere at du bibeholdte din session, selvom du - nemt - skiftede session id. Men ja, du behøver ikke en database for at opretholde en sikker session på dette.
#49 Så hvis jeg gør som her under. Så undgår (gør et forsøg for at undgå)jeg session hijacking. Eller skal jeg give $_SESSION["logget_ind"] en ny værdi? så det ikke er "ja" hele tiden hvis brugeren er logget ind?
//login side <?php session_start(); //Starter session $_SESSION["logget_ind"] = ja;
der mangler en masse med kode tjek og sådan noget med lige meget. ?>
//tjek side <?php session_start(); //Starter session session_regenerate_id(true);
Altså, at have session variabler kaldet logget_ind med indhold som 1 eller true eller bare en statisk streng er - i min verden - ret tåbeligt. Anvend kun ting du rent faktisk kan bruge.
Session variablen "logget_ind" kan jo kun bruges til en ting - og det er at konstatere at en given bruger er logget ind.
Personligt foretrækker jeg at anvende variablen til noget praktisk.
// Kontroller om brugeren er logget ind. Kontrollen kan være mere omfattende. if(!isset($_SESSION["userId"])) { header("Location: ikke_logget_ind.php"); exit; }
// her kan du så hente informationer ud om brugeren, ud fra $_SESSION["userId"]
Det ser rigtigt godt ude og nu er jeg noget mere sikker på hvordan jeg skal gøre det. Mange tak. Har bare lige et spørgsmål mere hvad sker der her " $password = md5($salt.$_POST["password"]);". hvad bruger du $salt til?
$salt er en lang kompliceret streng bestående af en statisk tekst som jeg 'salter' et kodeord med. Det gør det (nærmest) umuligt at decrypte et kodeord f.eks vha af rainbow tables. F.eks. vil kodeordet 'test' få md5 værdien 098f6bcd4621d373cade4e832627b4f6 Et hurtigt lookup i en rainbow table fortæller at md5 strengen 098f6bcd4621d373cade4e832627b4f6 svarer til ordet test. Men hvis jeg nu salter den med en x antal tegn lang sætning med tilfældigt udvalgte tegn:
så vil du opnå en en anden md5 værdi som ikke bare kan slås op i en rainbow table.
Årsagen til jeg havde det med er at jeg bruger den teknik til alt hvad der har med mine brugere at gøre; det er god etik at værne om sine brugeres privatliv.
#55 Det er en mulighed. Jeg kontrollerer - i et system hvor kunden mener brugerkontrollen er kritisk - for hvert sidekald om brugeren er logget ind,herefter om brugeren stadig eksister, dernæst om brugeren er aktiv og slutteligt om brugeren har rettigheder til at anvende siden (såfremt siden er omfattet af restriktioner).
Men du skal altid have i tankerne om din kode står mål til formålet; kan det forsvares at lave så omfattende brugerkontroller eller er det nok blot at kontrollere at det er en bruger der er logget ind? Eller er det nødvendigt for en administrator at kunne lukke for brugeren realtime?
Brugeren som sådan behøver ikke være en aktiv bruger i systemet. 'Aktiv' betyder ikke om brugeren foretager sig noget i denne sammenhæng - det skal forstås som om at en bruger kan have en aktiveret eller deaktiveret brugerkonto på sitet.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.