Veiligheid Inlogsysteem
Ik ben bezig met het schrijven van een inlog systeem en wil deze graag zo veilig mogelijk. Ik gebruik al een salt, en mysql_real_escape_string. Maar nu wil ik graag weten wat ik kan doen om mijn passwords en databases nog veiliger te maken.
Ook check ik op elke pagina of de users zijn ingeloged door middel van een session.
Vervolgens controleer ik of de session met het ip adres overeenkomt met de cookie en het ip adres wat daarin is opgeslagen. Is dit veilig of zijn er nog andere dingen die ik moet doen om dit veiliger te maken?
Session hijacking?
En welke functies gebruiken jullie nog meer om user input te controleren?
En het is belangrijk om onderscheid te maken tussen cookies en sessions (zijn ook cookies, maar dan serverside). Dit om misverstanden te voorkomen.
Gewijzigd op 14/04/2011 21:15:27 door Arjan -
Ik heb dit geschreven:
------------------------------------------------
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php session_start();
function check_login($id, $session_id, $ip) {
include_once('connection.php');
$error = FALSE;
if($id == '') {
$error = TRUE;
}
if ($session_id == ''){
$error = TRUE;
}
if ($ip == ''){
$error = TRUE;
}
else {
$query = "SELECT ip, session_id FROM users WHERE id = '" . mysql_real_escape_string($id) . "'";
$result = mysql_result($query);
$result = mysql_fetch_assoc($result);
if($_SERVER['REMOTE_ADDR'] != $ip) {
$error = TRUE;
}
if ($session_id != $result['session_id']) {
$error = TRUE;
}
if ($error == TRUE) {
return FALSE;
} else {
return TRUE;
}
}
}
------------------------------------
In deze functie zijn id, session_id, ip allemaal sessions, maar is dit veilig?
function check_login($id, $session_id, $ip) {
include_once('connection.php');
$error = FALSE;
if($id == '') {
$error = TRUE;
}
if ($session_id == ''){
$error = TRUE;
}
if ($ip == ''){
$error = TRUE;
}
else {
$query = "SELECT ip, session_id FROM users WHERE id = '" . mysql_real_escape_string($id) . "'";
$result = mysql_result($query);
$result = mysql_fetch_assoc($result);
if($_SERVER['REMOTE_ADDR'] != $ip) {
$error = TRUE;
}
if ($session_id != $result['session_id']) {
$error = TRUE;
}
if ($error == TRUE) {
return FALSE;
} else {
return TRUE;
}
}
}
------------------------------------
In deze functie zijn id, session_id, ip allemaal sessions, maar is dit veilig?
Gewijzigd op 14/04/2011 22:05:43 door Pjotter Prins
Je hebt dus geen hash wat je met elkaar controleert? Lijkt mij niet verstandig. Maak tijdens het inloggen een unieke hash aan die je zowel in de database stopt en in de sessie. Deze dien je dan ook te vergelijken met elkaar. Wat je nu doet is alleen controleren op id (is eenvoudig te veranderen) en het ipadres.
Gewijzigd op 14/04/2011 22:13:46 door Arjan -
Arjan - op 14/04/2011 22:12:42:
dan zit je al aardig veilig.
Thx. Dit heb ik nu gedaan. Maar ik wil niet aardig veilig. Het moet echt super veilig. Ik wil namelijk wat persoonlijke dingen op een pagina zetten.. Zijn er dan nog extra's die ik kan doen? tips & tricks?
Laat je code eens zien...
--------------------
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
$session_id = sha1(salt1(uniqid(rand(), true)));
$query = "INSERT INTO users (session_id, ip) VALUES ('" . $session_id . "','" . $_SERVER['REMOTE_ADDR'] . "') WHERE email = '" . $result['email'] . "';";
$_SESSION['id'] = $id;
$_SESSION['session_id'] = $session_id;
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
?>
$session_id = sha1(salt1(uniqid(rand(), true)));
$query = "INSERT INTO users (session_id, ip) VALUES ('" . $session_id . "','" . $_SERVER['REMOTE_ADDR'] . "') WHERE email = '" . $result['email'] . "';";
$_SESSION['id'] = $id;
$_SESSION['session_id'] = $session_id;
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
?>
------------------
Vervolgens controleer ik op elke pagina aan de hand van de volgende functie:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php session_start();
function check_login($id, $session_id, $ip) {
include_once('connection.php');
$error = FALSE;
if($id == '') {
$error = TRUE;
}
if ($session_id == ''){
$error = TRUE;
}
if ($ip == ''){
$error = TRUE;
}
else {
$query = "SELECT ip, session_id FROM users WHERE id = '" . mysql_real_escape_string($id) . "'";
$result = mysql_result($query);
$result = mysql_fetch_assoc($result);
if($_SERVER['REMOTE_ADDR'] != $result['ip']) {
$error = TRUE;
}
if ($session_id != $result['session_id']) {
$error = TRUE;
}
if ($error == TRUE) {
return FALSE;
} else {
return TRUE;
}
}
}
?>
function check_login($id, $session_id, $ip) {
include_once('connection.php');
$error = FALSE;
if($id == '') {
$error = TRUE;
}
if ($session_id == ''){
$error = TRUE;
}
if ($ip == ''){
$error = TRUE;
}
else {
$query = "SELECT ip, session_id FROM users WHERE id = '" . mysql_real_escape_string($id) . "'";
$result = mysql_result($query);
$result = mysql_fetch_assoc($result);
if($_SERVER['REMOTE_ADDR'] != $result['ip']) {
$error = TRUE;
}
if ($session_id != $result['session_id']) {
$error = TRUE;
}
if ($error == TRUE) {
return FALSE;
} else {
return TRUE;
}
}
}
?>
En je controle kan een stuk korter:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
session_start();
function check_login($id, $session_id, $ip) {
include_once('connection.php');
$error = FALSE;
if(trim($id) == '' OR trim($session_id) == '' OR trim($ip) == '') {
$error = TRUE;
}
if($error === false) {
$query = "
SELECT
ip,
session_id
FROM
users
WHERE
id = '" . mysql_real_escape_string($id) . "'
AND
session_id = '".mysql_real_escape_string($session_id)."'
AND
INET_ATON('".mysql_real_escape_string($_SERVER['REMOTE_ADDR']."')
LIMIT 1
";
$result = mysql_result($query);
if($result) {
if(mysql_num_rows($result) > 0) {
$data = mysql_fetch_assoc($result);
return $data;
} else
return false;
} else {
return false;
}
}
}
?>
session_start();
function check_login($id, $session_id, $ip) {
include_once('connection.php');
$error = FALSE;
if(trim($id) == '' OR trim($session_id) == '' OR trim($ip) == '') {
$error = TRUE;
}
if($error === false) {
$query = "
SELECT
ip,
session_id
FROM
users
WHERE
id = '" . mysql_real_escape_string($id) . "'
AND
session_id = '".mysql_real_escape_string($session_id)."'
AND
INET_ATON('".mysql_real_escape_string($_SERVER['REMOTE_ADDR']."')
LIMIT 1
";
$result = mysql_result($query);
if($result) {
if(mysql_num_rows($result) > 0) {
$data = mysql_fetch_assoc($result);
return $data;
} else
return false;
} else {
return false;
}
}
}
?>
Wat ik heb aangepast:
- Logischer volgorde
- Controles laten uitvoeren door de database
- Simpele foutafhandeling toegevoegd (je had geen eens een controle ingebouwd om te controleren hoeveel records retourneert worden door de query)
- INET_ATON toegevoegd: Beter is om je ipadressen op te slaan in een unsigned integer veld, waarbij je telkens de functie INET_ATON gebruikt om een "normaal" ipadres om te zetten naar een integer. Dus ook bij het toevoegen / wijzigen (INSERT INTO / UPDATE) van het ipadres moet je dan deze functie gebruiken.
- In plaats van een boolean retourneert de functie nu, indien succesvol geauthenticeerd, de uitkomst van de query.
En ik raad je aan om eens te kijken naar PDO voor de databaselaag: http://phptuts.nl/view/27/
Als je PDO namelijk juist gebruikt (prepared statements) hoef je je geen zorgen meer te maken over sql injections (ideaal)!
Gewijzigd op 15/04/2011 10:05:33 door Arjan -
Beetje laat, maar bedankt voor je reactie!!