Avatar billede kentora Nybegynder
21. april 2010 - 15:48 Der er 20 kommentarer og
1 løsning

Hvor sikker er min beskyttelse?

Jeg er på det sidste kommet til at tænke på hvor sikker min kode beskyttelse egentlig er.

Selve siden er kodet i .PHP, data gemmes i MySQL.

Her er lidt facts:
Kodeord er gemt som md5 krypterede.
Når jeg tjekker om brugerens login er rigtigt krypterer jeg md5 og holder op imod koden i MySQL.
Jeg sætter så en session med brugernavnet.
På de beskyttede sider tjekker jeg om session til brugernavn er tom.

Men hvor sikkert er det egentligt? Hvis det skal forbedres skal det så tweakes, eller skal jeg kode et nyt system (hvilket) fra bunden?

point gives til den/dem der er kommet med de(n) bedste kommentar(er)
Avatar billede kirsten Nybegynder
21. april 2010 - 16:04 #1
Du kunne kryptere dine adgangskoder yderligere med salt:

function generatePasswordHash($string)
{

    //Bruges til at kryptere passwords i databasen

    $salt = sha1(md5($string));
    $string = md5($string . $salt);

    return $string;

}

I forhold til dine Sessions, kunne du måske sætte en ekstra variabel som feks is_logged_in = 1 så har du da en lille ekstra smule at tjekke om sessionen kommer fra login siden...
Avatar billede claes57 Ekspert
21. april 2010 - 16:11 #2
der er en gennemgang af et godt/enkelt system på
http://www.phpbuilder.com/columns/tim20000505.php3?page=1
Avatar billede repox Seniormester
21. april 2010 - 17:26 #3
#1
Jeg er enig i konceptet om at det at salte sine hashede kode øger sikkerheden hvad angår brugerens sikkerhed såfremt at databasen hvor disse opbevares er sårbar og der er risiko for at koderne er læsbare. Så kan de trods alt ikke bare slås op i rainbow tables uden videre.

Hvad angår dit forslag om at sætte endnu en variabel, må jeg erkende at jeg ikke forstår idéen med - det er da helt fint med en enkelt variabel om den så indeholder et tal eller et brugernavn. Det er simpelt - hvis sessionen brugernavn er sat er man logget ind, ellers ikke. Sikkerheden øges ikke af at have to session variabler som du kan kontrollere på (i den forstand som der omtales her).

#0
Som #1 omtaler er hashing en måde at beskytte dine brugeres data på - det øger dog ikke sikkerheden; det afhænger stærkt af den kode der ligger udenom, så at give et bud på om din 'sikkerhed er god nok' bliver et skud i tågen på baggrund af den information du giver.
Jeg har lavet et brugersystem - ment som en slags tilføjelse til hvad man nu er igang med at lave, som du kan hente her http://catalystcode.net/ - der kan du se eksempler på hvordan jeg logger brugere ind og ud, kontrollerer deres adgang og så videre. Det er mit bud på hvad der er sikkert. Og husk - der er ikke et facit til sådan noget her - der er mange forskellige løsninger.
Men lad os se noget kode, så kan vi bedre vurdere det...
Avatar billede dkfire Nybegynder
21. april 2010 - 22:44 #4
Sikkerheden ligger heller ikke kun i hvordan du gemmer password og brugere samt hvordan du logger dem ind. Det handler lige så meget om hvordan du håndtere en hver form for brug input på din side.
En enkelt åbenhed i din håndtering af brugerdata kan nemt koste dig din side.

Validere du alle bruger input ?
Bruger du prepared statement i til inde mysql query's ? (mysqli)
eller husker du at bruge mysql_real_escape_string(), hvis du bruger mysql, på alle bruger input som du bruger i dine query's ?

Bruger du $_GLOBAL ?
Er dit system sat med register_globals til on ?

Dette er nogle af de mest almindelige fejl.
Avatar billede kentora Nybegynder
22. april 2010 - 08:01 #5
#3
Login.php
<?
$brugernavn = $_POST['brugernavn'];
$password = $_POST['password'];
$pass = md5($password);
$hent_db = mysql_query("SELECT * FROM `users` WHERE `brugernavn` = '$brugernavn' ORDER BY `id` DESC");
$hent = mysql_fetch_array($hent_db);
if($pass = $hent['password']){
$_SESSION['user'] = $brugernavn;
$_SESSION['id'] = $hent['id'];
$_SESSION['status'] = $hent['medlems_status'];
?>
<script type="text/javascript">
<!--
window.location = "succes.php"
//-->
</script>
<?
} else {
?>
<script type="text/javascript">
<!--
window.location = "fail.php"
//-->
</script>
<?
}
?>

logout.php
<?
$_SESSION['user'] = "";
?>
<script type="text/javascript">
<!--
window.location = "index.php"
//-->
</script>

beskyttet_side.php
<?
if($_SESSION['user'] == ""){
?>
Du skal v&aelig;re logget ind for at se denne side.
<?
} else {
?>
Tekst til brugeren der er logget ind
<?
}
?>

#4
Har aldrig hørt om mysqli? xD
Jeg har arbejdet lidt mid mysql_real_escape_string(), men bruger det, som du kan se, ikke, selvom jeg helt sikkert burde. Jeg har haft lidt problemer med at finde en tutorial jeg kunne forstå.
Jeg bruger ikke $_GLOBAL og register er sat til off. Det kan jeg dog ikke ændre med, da det er et gratis host, der benytter samme php.ini filer til alle, og den kan ikke ændres.

Grunden til at jeg stiller det her spørgsmål er at jeg ikke rigtig har forbedret det i lang tid, og gerne vil have forslag til at gøre det sikrere.

Mange tak for svarene :D
Avatar billede woodydrn Nybegynder
22. april 2010 - 10:12 #6
$hent_db = mysql_query("SELECT * FROM `users` WHERE `brugernavn` = '$brugernavn' ORDER BY `id` DESC");

Her kan jeg skrive $brugernavn som ' or 'a' = 'a ... så den SQL bliver til:

SELECT * FROM `users` WHERE `brugernavn` = '' or 'a' = 'a' ORDER BY `id` DESC");

Nu har du dog ikke password med i din SQL, og du bruger også md5 på den, men ellers ville jeg kunne logge ind med et hvert brugernavn, og ' or 'a' = 'a som password, og den ville logge ind.

Som andre siger, er det vigtigt at du bruger mysql_real_escape_string() på brugernavn. Og jeg ville også sige at du skulle prøve at bruge en database class, f.eks PEARs DB eller en der kan prepare SQL, så du ikke selv skal tænke på at sanitize alle variabler først.
Avatar billede woodydrn Nybegynder
22. april 2010 - 10:27 #7
Det er stort set essensen i SQL injection, mysql_real_escape retter en del af arbejdet, men du skal også tage forhold for mysql CLIENT_MULTI_STATEMENTS... $brugernavn = " ' ; delete from users --";
Avatar billede kentora Nybegynder
22. april 2010 - 10:31 #8
Jeg har som sagt ikke fundet en tutorial til anti injection, som jeg har kunne forstå, mest fordi jeg ingenting fatter xD

Men, hvis man nu laver et felt mere i mysql, der hedder brugermd5, der bare er md5 af brugernavn og holder op i mod den, i stedet for det normale brugernavn, vil det vel fjerne alle specialtegn og multi statements?
Avatar billede woodydrn Nybegynder
22. april 2010 - 10:47 #9
normalt bruger jeg min egen DB class, så min ville se sådan ud:

$rs = $db->query("SELECT * FROM users WHERE brugernavn = ? AND password = ? LIMIT 1", array($brugernavn, md5($password)));

if ($rs && !$rs->is_error() && $rs->num()) {
... den fandt en
}

Så checker den brugernavn og password igennem for SQL injections og retter diverse ting, så behøver jeg aldrig at tænke over det.

Du kan skrive en mail til woodydrn@gmail.com hvis du vil have min DB class...

Du skal ikke lave et felt brugermd5, mysql har f.eks selv command MD5()
Avatar billede kentora Nybegynder
22. april 2010 - 12:02 #10
Kan jeg undvære mysql real escape ved brug af md5 på brugernavn også? eller skal jeg igang med at prøve at forstå det igen?
Avatar billede woodydrn Nybegynder
22. april 2010 - 12:19 #11
Det er da bedst at forstå det, jeg ville ikke gå en omvej for at undgå at bruge mysql_real_escape...

Bare kig på min besked igen:

Hvis jeg skriver (i input feltet, $_POST['brugernavn']):

' or 'a' = 'a

og du indsætter det i din SQL:

WHERE brugernavn = '$brugernavn'

Så bliver det jo til:

SELECT * FROM users WHERE brugernavn = '' or 'a' = 'a' ORDER BY id DESC

Hvilket betyder den tager alle brugernavne der er tomme, ELLER hvis a = a, og a er altid = a, så den tager bare alt fra users.

Hvis du nu brugte password = '$password' .. så ville jeg kunne skrive brugernavn = "admin" ... password = ' or 'a' = 'a og den ville glemme alt om password.

Men brug mysql_real_escape og is_numeric() til int, med mindre du bruger en DB class...
Avatar billede kentora Nybegynder
22. april 2010 - 15:59 #12
woodydrn, du kan jo ikke få den til at ignorere pass, da det bliver md5 krypteret. Hvis du skriver ' or 'a' = 'a' vil den se om password = e9fc0c452dff83d67aec691ea0c81634, og hvis den gjorde det samme med kodeord, ville du heller ikke kunne injecte den?
Avatar billede woodydrn Nybegynder
22. april 2010 - 16:06 #13
Nej, det var heller ikke det jeg sagde. Jeg sagde "Hvis du nu brugte password = '$password' .. " ... HVIS ;)

Der er dog mange sider der ikke kryptere deres passwords, f.eks jeg får emails fra buydomains med mit password i, så hvis de ikke bruger en eller anden form for sanitizing af den string - ville det kunne injectes.
Avatar billede woodydrn Nybegynder
22. april 2010 - 16:07 #14
"woodydrn, du kan jo ikke få den til at ignorere pass", men jeg kunne f.eks injecte brugernavnet og skrive 12345 ved password, så bare håbe på der er nogen med det password.
Avatar billede kentora Nybegynder
22. april 2010 - 16:10 #15
ja, som det er nu, men det beskytter såmænd da ligeså godt at md5 kryptere som at bruge escape real string?
Avatar billede woodydrn Nybegynder
22. april 2010 - 16:19 #16
Hvis du virkelig bare vil lave det på en anden måde ;) så ja - alt der ændrer hele $brugernavn string ville virke.
Avatar billede dkfire Nybegynder
22. april 2010 - 16:31 #17
Jeg har som sagt ikke fundet en tutorial til anti injection, som jeg har kunne forstå, mest fordi jeg ingenting fatter xD

Det du siger er: "jeg er kan ikke forstå sikkerhed, så jeg er ligeglad!"
http://en.wikipedia.org/wiki/SQL_injection

Der er ikke så meget at tage fejl af med mysql_real_escape_string(). Du bør bruge den på alle input fra en bruger, når du bruger mysql og du bruger inputtet direkte i din sql sætning!
Dette gælder for ALLE de sider hvor du har bruger input til mysql!

MySQLi er en nyere version af mysql. Du kan ved lejlighed prøve at læse om den i php manualen. Men det kræver nok at du har lidt kendskab til klasser.

Og så lige en ekstra ting, md5 er en hash værdi. Dette betyder at to forskellige "sætninger" teoretisk godt kan have den samme hash værdi.
Avatar billede olebole Juniormester
22. april 2010 - 22:07 #18
<ole>

Netop fordi der er så meget at tage fejl af, har man heldigvis lavet betydeligt mere skudsikre løsninger:
    http://dk2.php.net/manual/en/class.mysqli.php
    http://php.net/manual/en/book.pdo.php

MySQLI kan forøvrigt anvendes i både OOP og procedural sammenhæng

/mvh
</bole>
Avatar billede kentora Nybegynder
23. april 2010 - 08:31 #19
dkfire, jeg kan ikk helt se hvor det er jeg siger at jeg er ligeglad?!? Jeg har oprettet den her tråd for at forbedre sikkerheden i mit login script, jeg siger bare at jeg ikke har fundet en tutorial der har kunne forklare mig injection beskyttelse, så jeg har kunne forstå det.

Jeg vil lige tage et kig på mysqli...
Avatar billede kentora Nybegynder
24. april 2010 - 17:25 #20
Mange tak til alle der er kommet med gode råd og kunstriktiv kritik. Dem der selv mener de bør få point, skriv et svar, så vil jeg mandag morgen dele point ud :)
Avatar billede woodydrn Nybegynder
24. april 2010 - 20:09 #21
well jeg brugte da lidt tid på at forklarer SQL injection ;)
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester