GET id in url beveiligen

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: 1 2 3 4 volgende »

Johan de wit

johan de wit

16/05/2015 03:41:27
Quote Anchor link
Ik heb een pagina aangemaakt dat gebruikers gegevens kunnen bewerken maar er viel mij iets op dat je vanaf urlbalk andere regels (en ook ids wat nog niet bestaat) van tabellen kunt bewerken terwijl dat de bedoeling niet is of je voert zomaar bijvoorbeeld letters er achter id= dan zie je nog steeds geen foutmelding.

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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
bindParam(1,is_numeric($_GET['id']))

en dit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
is_numeric(bindParam(1,$_GET['id']))


Beetje opgeschoond om het kleiner te krijgen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?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
}
?>
 
PHP hulp

PHP hulp

29/03/2024 00:09:51
 
- Ariën  -
Beheerder

- Ariën -

16/05/2015 08:26:33
Quote Anchor link
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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....
}
?>


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
 
Frank Nietbelangrijk

Frank Nietbelangrijk

16/05/2015 11:27:30
Quote Anchor link
Kleine aanvulling op Aar:

Zo sluit je tevens een negatief id of een id=0 uit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
if(intval($_GET['id']) > 0) {
    // her is een ID, voer de rest van het script + de query uit.
} else {
    // het script bevat geen GELDIG ID, try again....
}
?>
 
Eddy E

Eddy E

16/05/2015 11:49:00
Quote Anchor link
Dat is een hele mooie Frank!
Ik gebruik die ook in mijn is_int()-functie. Er zijn genoeg aan is_array(), is_numeric() etc, maar is_int() miste:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
<?php

function is_int($string)
    {

    if(intval($string) > 0)
        {

        return true;
        }

    return false;
    }

?>
 
Frank Nietbelangrijk

Frank Nietbelangrijk

16/05/2015 11:56:23
Quote Anchor link
Inderdaad Eddy, nooit bij stilgestaan :-)
 
- SanThe -

- SanThe -

16/05/2015 12:24:23
Quote Anchor link
Die function bestaat gewoon al.
Zie http://php.net/is_int
 
Johan de wit

johan de wit

16/05/2015 13:33:51
Quote Anchor link
- Aar - op 16/05/2015 08:26:33:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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....
}
?>


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)
PHP script in nieuw venster Selecteer het PHP script
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
<?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:
Kleine aanvulling op Aar:

Zo sluit je tevens een negatief id of een id=0 uit:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
if(intval($_GET['id']) > 0) {
    // her is een ID, voer de rest van het script + de query uit.
} else {
    // het script bevat geen GELDIG ID, try again....
}
?>


Welke regel(s) moet ik vervangen door je aangepaste script?
Gewijzigd op 16/05/2015 13:35:08 door johan de wit
 
- SanThe -

- SanThe -

16/05/2015 13:46:13
Quote Anchor link
Regel 36 $row["id"] => echo $row["id"];
 
Johan de wit

johan de wit

16/05/2015 14:12:06
Quote Anchor link
- SanThe - op 16/05/2015 13:46:13:
Regel 36 $row["id"] => echo $row["id"];


Dank je wel, ik heb het meteen aangepast.
 
Frank Nietbelangrijk

Frank Nietbelangrijk

16/05/2015 14:32:23
Quote Anchor link
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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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;
}

?>
Gewijzigd op 16/05/2015 14:33:48 door Frank Nietbelangrijk
 
Johan de wit

johan de wit

16/05/2015 16:04:58
Quote Anchor link
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:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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;
}

?>


Aangepast: bij regel 9 krijg ik de volgende foutmelding.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
$stmt->bindParam(1, intval($_GET['id'])); // met intval aub

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
Strict Standards: Only variables should be passed by reference in


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
 
Frank Nietbelangrijk

Frank Nietbelangrijk

16/05/2015 16:50:45
Quote Anchor link
Johan de wit op 16/05/2015 16:04:58:
Bij regel 9 krijg ik de volgende foutmelding.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
Strict Standards: Only variables should be passed by reference in

Oh oké ja dat kan.

Dan moet dat dus in twee stappen

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$safeId
= intval($_GET['id']);
$stmt->bindParam(1, $safeId);
?>
Gewijzigd op 16/05/2015 16:54:19 door Frank Nietbelangrijk
 
Johan de wit

johan de wit

16/05/2015 17:05:34
Quote Anchor link
Frank Nietbelangrijk op 16/05/2015 16:50:45:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<?php
$safeId
= intval($_GET['id']);
$stmt->bindParam(1, $safeId);
?>

Heeft geholpen. Dank je wel.
 
Frank Nietbelangrijk

Frank Nietbelangrijk

16/05/2015 17:19:05
Quote Anchor link
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)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
ROL           | RECHTEN
====================================
niet ingelogd | verboden
ROLE_USER     | alleen eigen pagina
ROLE_ADMIN    | alle profielpagina's


Nu in PHP:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?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
?>
Gewijzigd op 17/05/2015 10:45:08 door Frank Nietbelangrijk
 
Johan de wit

johan de wit

16/05/2015 18:07:48
Quote Anchor link
Regel 3 mist ")":
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
if(!isset($_GET['id'] && intval($_GET['id']) > 0) {


Regel 22 heeft deze foutmelding:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
Parse error: syntax error, unexpected '[' in

Moet $id niet tussen de haken?
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
if($loggedIn['role'] != 'ROLE_ADMIN' && loggedIn['id'] != $id)
Gewijzigd op 16/05/2015 18:11:05 door johan de wit
 

16/05/2015 21:09:18
Quote Anchor link
Nog een tactiek om ID-s te obfuscaten is door ze te door de MD5-functie te halen. Je krijgt dan een tekenreeks van 32 karakters als ID. Vervolgens kan je die terug laten rekenen door de database met WHERE-clause als:
WHERE `{tabelnaam}`.`id` = MD5("{die geobfuscate ID}")
Dan is het al lastiger om oplopende ID's te voorspellen voor de eindgebruiker.
 
Johan de wit

johan de wit

16/05/2015 23:34:45
Quote Anchor link
MD5 is oud wnat je kan overal decoderen.
 

16/05/2015 23:38:29
Quote Anchor link
Als je lang genoeg doorgaat is iets nooit 100% veilig natuurlijk. Maar het werpt een extra barricade op. En het gaat om het principe, wat weerhoudt je om andere encryptie-algoritmes te gebruiken?
Je kunt zelfs nog een willekeurig aangemaakt (metadata) ID gebruiken, dan kan het helemaal gissen zijn voor iemand die kwaad wil.
 
Johan de wit

johan de wit

16/05/2015 23:47:34
Quote Anchor link
Inderdaad je hebt daar gelijk in. Willekeurige metadata? Wil je wat meer daar over vertellen?
 
- Ariën  -
Beheerder

- Ariën -

16/05/2015 23:52:37
Quote Anchor link
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.
 
Johan de wit

johan de wit

16/05/2015 23:54:15
Quote Anchor link
Dus dat raad je af. Is het niet beter om over te gaan naar POST functie en dan MD5 inschakelen?
Gewijzigd op 16/05/2015 23:56:49 door johan de wit
 

Pagina: 1 2 3 4 volgende »



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.