SQL-injection

Zodra je gaat werken met een database, moet je rekening houden met beveiliging. Het belangrijkste is om alle input van de gebruiker te controleren en te filteren!

Wat is SQL-injection?
SQL-injection komt erop neer dat de gebruiker (voor de programmeur dus ongewild) eigen code kan injecteren in de query, iets wat je absoluut niet wilt. Wat SQL-injection precies is ga ik niet uitleggen omdat ik alleen de protectie ervan uitleg, maar voor precieze uitleg verwijs ik je graag door naar deze tutorial.

Een fout voorbeeld
In het onderstaande voorbeeld laten we een gebruiker een bericht aanmaken voor een shoutbox, maar we escapen de input van de gebruiker nog niet. (op de foutenafhandeling komen we later nog terug)

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
<?php
// Kijken of er gepost is
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{

    // Controleren of het bericht is ingevuld
    if (empty($_POST['bericht']))
    {

        echo 'Je hebt geen bericht ingevuld!';
    }

    else
    {
        // Query maken en invoegen
        $sQuery = "
        INSERT INTO berichten
        (
            bericht,
            datum
        )
        VALUES
        (
            '"
. $_POST['bericht'] . "',
            NOW()
        )
        "
;
        $qSql = mysql_query($sQuery);
        if ($qSql === false)
        {

            echo 'Er gaat iets fout tijdens het invoegen!';
        }

        else
        {
            echo 'Je bericht is toegevoegd!';
        }
    }
}

// Form op het scherm tonen
?>

<form method="post" action=""><p>
Bericht: <input type="text" name="bericht" /><br />
<input type="submit" value="Versturen" />
</p></form>


Op het eerste zicht ziet dit er misschien goed uit, maar het mag duidelijk zijn dat het script lek is. Vult de gebruiker bijvoorbeeld 's Hertogenbosch in, dan gaat het fout. De quote wordt dan namelijk al afgesloten in de query en komt er tekst buiten de quote te staan. Dit komt er dan namelijk te staan:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
INSERT INTO berichten
(
    bericht,
    datum
)
VALUES
(
    ''s Hertogenbosch',
    NOW()
)


Het is duidelijk te zien dat er iets fout gaat, want er wordt na bosch een quote afgesloten die nooit gestart is, wat dus een fout oplevert.

Voor dit soort problemen (en uiteraard voor de beveiliging) escapen we de input van de gebruiker.

Hoe doen we dat?
De input filteren, dat doen we met mysql_real_escape_string (of een variant in MySQLi of PDO). Deze functie zet een backslash (\) voor iedere quote, zodat een quote ge-escaped wordt en deze de query niet kan verpesten.

Dat ziet er in de praktijk zo uit:
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
<?php
// Kijken of er gepost is
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{

    // Controleren of het bericht is ingevuld
    if (empty($_POST['bericht']))
    {

        echo 'Je hebt geen bericht ingevuld!';
    }

    else
    {
        // Query maken en invoegen
        $sQuery = "
        INSERT INTO berichten
        (
            bericht,
            datum
        )
        VALUES
        (
            '"
. mysql_real_escape_string($_POST['bericht']) . "',
        NOW()
        )
        "
;
        $qSql = mysql_query($sQuery);
        if ($qSql === false)
        {

            echo 'Er gaat iets fout tijdens het invoegen!';
        }

        else
        {
            echo 'Je bericht is toegevoegd!';
        }
    }
}

// Form op het scherm tonen
?>


Onze query ziet er dan zo uit, en kan dan niet fout lopen op dat stuk:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
INSERT INTO berichten
(
    bericht,
    datum
)
VALUES
(
    '\'s Hertogenbosch',
    NOW()
)


Let er wel op dat input van een gebruiker NOOIT te vertrouwen is, zelfs niet als het een administratiepaneel is dat je alleen voor persoonlijk gebruik ontwikkelt. Beveilig alle input die je voor je database gebruikt!

Referenties

« Lees de omschrijving en reacties

Inhoudsopgave

  1. Leesbaarheid
  2. SQL-injection
  3. XSS-injection
  4. Gebruik van backticks in MySQL
  5. Correcte foutenafhandeling
  6. Geheugenefficiƫnt programmeren
  7. Slot

PHP tutorial opties

 
 

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.