GET id in url beveiligen
Hoe zorg ik er voor dat je geen id uit je hoofd kan invoeren en overbodige letters met andere leestekens blokkeren?
Dit helpt bij mij niet:
en dit:
Beetje opgeschoond om het kleiner te krijgen:
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?PHP
session_start();
if (!(isset($_SESSION['user_login_status']) && $_SESSION['user_login_status'] != '')) {
header ("Location: index.php");
}
else {
try {
$dbc = new PDO('mysql:host=localhost; dbname=', '', '');
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
if(isset($_POST['submit_btn'])) {
$query = "UPDATE tabel SET name=? WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1, $_POST['name']);
$stmt->bindParam(2, $_POST['uid']);
if($stmt->execute()) {
echo "<script>alert('Record updated.');location.href='index.php'</script>";
} else {
die('Unable to update record.');
}
} else {
try {
$query = "SELECT * FROM tabel WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1,$_GET['id']);
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
$username = $row['user_name'];
$id = $row['id'];
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
?>
<form id=".$row["id"]." action="" method="POST">
<input type="hidden" value="<?php echo $id; ?>" name="uid">
<div class="container">
<div class="panel-heading">
<h3 class="panel-title">Gegevens</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<table class="table">
<tbody>
<tr>
<td>Naam</td>
<td><input class="form-control" type="text" id="formGroupInputSmall" placeholder="Naam"name="username" value="<?php echo $username; ?>"/></td>
</tr>
</tbody>
</table>
<input class="btn btn-default" type="submit" name="submit_btn" value="Bevestigen"/>
</form>
</div>
</div>
</div>
</div>
</body>
<?php
}?>
</html>
<?php
}
?>
session_start();
if (!(isset($_SESSION['user_login_status']) && $_SESSION['user_login_status'] != '')) {
header ("Location: index.php");
}
else {
try {
$dbc = new PDO('mysql:host=localhost; dbname=', '', '');
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
if(isset($_POST['submit_btn'])) {
$query = "UPDATE tabel SET name=? WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1, $_POST['name']);
$stmt->bindParam(2, $_POST['uid']);
if($stmt->execute()) {
echo "<script>alert('Record updated.');location.href='index.php'</script>";
} else {
die('Unable to update record.');
}
} else {
try {
$query = "SELECT * FROM tabel WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1,$_GET['id']);
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
$username = $row['user_name'];
$id = $row['id'];
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
?>
<form id=".$row["id"]." action="" method="POST">
<input type="hidden" value="<?php echo $id; ?>" name="uid">
<div class="container">
<div class="panel-heading">
<h3 class="panel-title">Gegevens</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<table class="table">
<tbody>
<tr>
<td>Naam</td>
<td><input class="form-control" type="text" id="formGroupInputSmall" placeholder="Naam"name="username" value="<?php echo $username; ?>"/></td>
</tr>
</tbody>
</table>
<input class="btn btn-default" type="submit" name="submit_btn" value="Bevestigen"/>
</form>
</div>
</div>
</div>
</div>
</body>
<?php
}?>
</html>
<?php
}
?>
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
if(is_numeric($_GET['id'])) {
// her is een ID, voer de rest van het script + de query uit.
} else {
// het script bevat geen ID, try again....
}
?>
if(is_numeric($_GET['id'])) {
// her is een ID, voer de rest van het script + de query uit.
} else {
// het script bevat geen ID, try again....
}
?>
Dit moet gewoon werken.
Verder nog een paar tips:
- Gebruik geen alerts's, maar laat gewoon met een echo zien dat het record is geupdated
- Gebruik geen die(), je script moet niet doodgaan als de query niet werkt.
- Op lijn 36 vergeet je PHP te starten voor die variabele
Zo sluit je tevens een negatief id of een id=0 uit:
Ik gebruik die ook in mijn is_int()-functie. Er zijn genoeg aan is_array(), is_numeric() etc, maar is_int() miste:
Inderdaad Eddy, nooit bij stilgestaan :-)
- Aar - op 16/05/2015 08:26:33:
Dit moet gewoon werken.
Verder nog een paar tips:
- Gebruik geen alerts's, maar laat gewoon met een echo zien dat het record is geupdated
- Gebruik geen die(), je script moet niet doodgaan als de query niet werkt.
- Op lijn 36 vergeet je PHP te starten voor die variabele
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
if(is_numeric($_GET['id'])) {
// her is een ID, voer de rest van het script + de query uit.
} else {
// het script bevat geen ID, try again....
}
?>
if(is_numeric($_GET['id'])) {
// her is een ID, voer de rest van het script + de query uit.
} else {
// het script bevat geen ID, try again....
}
?>
Dit moet gewoon werken.
Verder nog een paar tips:
- Gebruik geen alerts's, maar laat gewoon met een echo zien dat het record is geupdated
- Gebruik geen die(), je script moet niet doodgaan als de query niet werkt.
- Op lijn 36 vergeet je PHP te starten voor die variabele
Vanaf welke regel moet ik je script plaatsen?
Dank je wel:
- Alerts is vervangen door echo.
- Die() is vervangen door echo.
- Regel 36 heb ik PHP toegevoegd.
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?PHP
session_start();
if (!(isset($_SESSION['user_login_status']) && $_SESSION['user_login_status'] != '')) {
header ("Location: index.php");
}
else {
try {
$dbc = new PDO('mysql:host=localhost; dbname=', '', '');
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
if(isset($_POST['submit_btn'])) {
$query = "UPDATE tabel SET name=? WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1, $_POST['name']);
$stmt->bindParam(2, $_POST['uid']);
if($stmt->execute()) {
echo "Geupdated";
} else {
echo "Probeer nogmaals";
}
} else {
try {
$query = "SELECT * FROM tabel WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1,$_GET['id']);
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
$username = $row['user_name'];
$id = $row['id'];
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
?>
<form id="<?php $row["id"] ?>" action="" method="POST">
<input type="hidden" value="<?php echo $id; ?>" name="uid">
<div class="container">
<div class="panel-heading">
<h3 class="panel-title">Gegevens</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<table class="table">
<tbody>
<tr>
<td>Naam</td>
<td><input class="form-control" type="text" id="formGroupInputSmall" placeholder="Naam"name="username" value="<?php echo $username; ?>"/></td>
</tr>
</tbody>
</table>
<input class="btn btn-default" type="submit" name="submit_btn" value="Bevestigen"/>
</form>
</div>
</div>
</div>
</div>
</body>
<?php
}?>
</html>
<?php
}
?>
session_start();
if (!(isset($_SESSION['user_login_status']) && $_SESSION['user_login_status'] != '')) {
header ("Location: index.php");
}
else {
try {
$dbc = new PDO('mysql:host=localhost; dbname=', '', '');
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
if(isset($_POST['submit_btn'])) {
$query = "UPDATE tabel SET name=? WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1, $_POST['name']);
$stmt->bindParam(2, $_POST['uid']);
if($stmt->execute()) {
echo "Geupdated";
} else {
echo "Probeer nogmaals";
}
} else {
try {
$query = "SELECT * FROM tabel WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1,$_GET['id']);
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
$username = $row['user_name'];
$id = $row['id'];
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
?>
<form id="<?php $row["id"] ?>" action="" method="POST">
<input type="hidden" value="<?php echo $id; ?>" name="uid">
<div class="container">
<div class="panel-heading">
<h3 class="panel-title">Gegevens</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<table class="table">
<tbody>
<tr>
<td>Naam</td>
<td><input class="form-control" type="text" id="formGroupInputSmall" placeholder="Naam"name="username" value="<?php echo $username; ?>"/></td>
</tr>
</tbody>
</table>
<input class="btn btn-default" type="submit" name="submit_btn" value="Bevestigen"/>
</form>
</div>
</div>
</div>
</div>
</body>
<?php
}?>
</html>
<?php
}
?>
Toevoeging op 16/05/2015 13:37:22:
Frank Nietbelangrijk op 16/05/2015 11:27:30:
Welke regel(s) moet ik vervangen door je aangepaste script?
Gewijzigd op 16/05/2015 13:35:08 door johan de wit
Regel 36 $row["id"] => echo $row["id"];
- SanThe - op 16/05/2015 13:46:13:
Regel 36 $row["id"] => echo $row["id"];
Dank je wel, ik heb het meteen aangepast.
- $_GET['id'] wel bestaat
- $_GET['id'] wel een juiste waarde heeft. (numeriek en groter dan nul)
Dat kan dus beter:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
if(isset($_GET['id']) && intval($_GET['id']) > 0)
{
// je query
try {
$query = "SELECT * FROM tabel WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1, intval($_GET['id'])); // met intval aub
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
$username = $row['user_name'];
$id = $row['id'];
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
} else {
// een nette foutmelding
echo "Geen of ongeldig ID opgegeven.";
exit;
}
?>
if(isset($_GET['id']) && intval($_GET['id']) > 0)
{
// je query
try {
$query = "SELECT * FROM tabel WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1, intval($_GET['id'])); // met intval aub
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
$username = $row['user_name'];
$id = $row['id'];
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
} else {
// een nette foutmelding
echo "Geen of ongeldig ID opgegeven.";
exit;
}
?>
Gewijzigd op 16/05/2015 14:33:48 door Frank Nietbelangrijk
Frank Nietbelangrijk op 16/05/2015 14:32:23:
Op regel 26 injecteer je $_GET['id'] in één keer in je query terwijl je nog helemaal niet weet of:
- $_GET['id'] wel bestaat
- $_GET['id'] wel een juiste waarde heeft. (numeriek en groter dan nul)
Dat kan dus beter:
- $_GET['id'] wel bestaat
- $_GET['id'] wel een juiste waarde heeft. (numeriek en groter dan nul)
Dat kan dus beter:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
if(isset($_GET['id']) && intval($_GET['id']) > 0)
{
// je query
try {
$query = "SELECT * FROM tabel WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1, intval($_GET['id'])); // met intval aub
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
$username = $row['user_name'];
$id = $row['id'];
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
} else {
// een nette foutmelding
echo "Geen of ongeldig ID opgegeven.";
exit;
}
?>
if(isset($_GET['id']) && intval($_GET['id']) > 0)
{
// je query
try {
$query = "SELECT * FROM tabel WHERE id=?";
$stmt = $dbc->prepare($query);
$stmt->bindParam(1, intval($_GET['id'])); // met intval aub
$stmt->execute();
$row=$stmt->fetch(PDO::FETCH_ASSOC);
$username = $row['user_name'];
$id = $row['id'];
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
} else {
// een nette foutmelding
echo "Geen of ongeldig ID opgegeven.";
exit;
}
?>
Aangepast: bij regel 9 krijg ik de volgende foutmelding.
Ik krijg dit keer netjes foutmelding zodra ik 0 achter id= en als ID niet bestaat dan krijg ik geen melding, onbevoegde kunnen wel bij anderemanse ID komen, welke oplossingen kan ik hiervoor gebruiken? Ik dacht aan iets als base64_encode() maar dat kan je makkelijk omzetten met base64_decoder().
Gewijzigd op 16/05/2015 16:08:16 door johan de wit
Johan de wit op 16/05/2015 16:04:58:
Oh oké ja dat kan.
Dan moet dat dus in twee stappen
Gewijzigd op 16/05/2015 16:54:19 door Frank Nietbelangrijk
Frank Nietbelangrijk op 16/05/2015 16:50:45:
Heeft geholpen. Dank je wel.
Johan de wit op 16/05/2015 16:04:58:
Ik krijg dit keer netjes foutmelding zodra ik 0 achter id= en als ID niet bestaat dan krijg ik geen melding, onbevoegde kunnen wel bij andermans ID komen, welke oplossingen kan ik hiervoor gebruiken? Ik dacht aan iets als base64_encode() maar dat kan je makkelijk omzetten met base64_decoder().
Nee dit dien je anders op te lossen.
Per (deel van een) pagina kun je bepalen wie het wel mag zien en wie niet.
Laten we uitgaan van een profielpagina waar een aantal privacy gevoelige gegevens te zien zijn.
In het voorbeeld gaan we uit van drie soorten gebruikers:
a) bezoekers (niet ingelogd)
b) normale gebruikers (enige rechten)
c) administrators (alle rechten)
Om type b en c van elkaar te kunnen scheiden zul je een extra kolom in je tabel users moeten aanmaken. De naam van de kolom zou role kunnen zijn en je vult dan per gebruiker ROLE_ADMIN of ROLE_USER in. Je kunt later altijd nog meer rollen toevoegen.
Dan de profielpagina. Wie mag nou een profielpagina bekijken of bewerken?
Code (php)
1
2
3
4
5
2
3
4
5
ROL | RECHTEN
====================================
niet ingelogd | verboden
ROLE_USER | alleen eigen pagina
ROLE_ADMIN | alle profielpagina's
====================================
niet ingelogd | verboden
ROLE_USER | alleen eigen pagina
ROLE_ADMIN | alle profielpagina's
Nu in PHP:
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
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
<?php
// get variabele id is verplicht!
if(!isset($_GET['id']) && intval($_GET['id']) > 0) {
echo 'Geen geldig id opgegeven';
exit;
}
$id = intval($_GET['id']);
// gebruiker moet ingelogd zijn
if(!isset($_SESSION['id'])) {
{
header('Location: login.php');
exit;
}
//Haal de gegevens van de ingelogde gebruiker uit de database
$conn = mysqli_connect(/* bla bla */);
$result = mysqli_query($conn, "SELECT * FROM users WHERE id=" . $SESSION['id']);
$loggedIn = mysqli_fetch_assoc($result);
//dan moet de gebruiker nog voldoende rechten hebben
if($loggedIn['role'] != 'ROLE_ADMIN' && loggedIn['id'] != $id)
{
echo 'U heeft onvoldoende rechten';
exit;
}
// laat de profielpagina zien
?>
// get variabele id is verplicht!
if(!isset($_GET['id']) && intval($_GET['id']) > 0) {
echo 'Geen geldig id opgegeven';
exit;
}
$id = intval($_GET['id']);
// gebruiker moet ingelogd zijn
if(!isset($_SESSION['id'])) {
{
header('Location: login.php');
exit;
}
//Haal de gegevens van de ingelogde gebruiker uit de database
$conn = mysqli_connect(/* bla bla */);
$result = mysqli_query($conn, "SELECT * FROM users WHERE id=" . $SESSION['id']);
$loggedIn = mysqli_fetch_assoc($result);
//dan moet de gebruiker nog voldoende rechten hebben
if($loggedIn['role'] != 'ROLE_ADMIN' && loggedIn['id'] != $id)
{
echo 'U heeft onvoldoende rechten';
exit;
}
// laat de profielpagina zien
?>
Gewijzigd op 17/05/2015 10:45:08 door Frank Nietbelangrijk
Regel 22 heeft deze foutmelding:
Moet $id niet tussen de haken?
Gewijzigd op 16/05/2015 18:11:05 door johan de wit
WHERE `{tabelnaam}`.`id` = MD5("{die geobfuscate ID}")
Dan is het al lastiger om oplopende ID's te voorspellen voor de eindgebruiker.
MD5 is oud wnat je kan overal decoderen.
Je kunt zelfs nog een willekeurig aangemaakt (metadata) ID gebruiken, dan kan het helemaal gissen zijn voor iemand die kwaad wil.
Inderdaad je hebt daar gelijk in. Willekeurige metadata? Wil je wat meer daar over vertellen?
Willekeurig aangemaakte tekenreeksen zijn databasetechnisch geen vervanger voor ID's en hoogstens visueel bedoeld. Je moet dus zowel een INT (PK) veld voor je ID hebben als een veld voor je willekeurige tekenreeks.
Gewijzigd op 16/05/2015 23:56:49 door johan de wit