PHP en MYSQL injection

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Sven Thijssen

Sven Thijssen

09/11/2013 14:46:11
Quote Anchor link
Hallo allemaal

Ik probeer momenteel mijn invoervelden veilig te maken tegen MYSQL injection. Is dit goed genoeg beveiligd?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
$link = mysqli_connect($db_hostname, $db_username, $db_password, $db_database) or die("Error " . mysqli_error($link));
$bloopp = $_POST['bloopp'];
$bloopp = htmlspecialchars($bloopp);
$bloopp = mysqli_real_escape_string($link, $bloopp);
$bloopp = strip_tags($bloopp);
$search = array("'", '"', "--");
$replace = array("´", "$acute;", "_");
$bloopp = str_replace($search, $replace, $bloopp);


Alvast bedankt om een kijkje te nemen!
Sven
 
PHP hulp

PHP hulp

16/11/2024 17:00:24
 
Erwin H

Erwin H

09/11/2013 15:43:08
Quote Anchor link
Het beveiligen van een applicatie start altijd met weten wat je doet, niet zo maar iets doen en dan hopen dan het veilig is. Als ik dit soort lijnen code zie vraag ik me altijd af of de kennis er wel is. Dus als eerste de vraag: waartegen wil je beveiligen? Probeer bij elke regel dan ook eens te vermelden waarom je die regel nodig denkt te hebben.
 
Ward van der Put
Moderator

Ward van der Put

09/11/2013 15:49:10
Quote Anchor link
Je mist vooral controles. Ik zal ze voor je nummeren.
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
<?php
// (1) Is $_POST['bloopp'] ingesteld en (2) is $_POST['bloopp'] niet leeg?
if (isset($_POST['bloopp']) && !empty($_POST['bloopp'])) {
    // (3) Is $_POST['bloopp'] een string?
    if (is_string($_POST['bloopp'])) {
        // (4) Gebruikt deze server nog verouderde magic quotes?
        if (get_magic_quotes_gpc()) {
            $_POST['bloopp'] = strip_slashes($_POST['bloopp']);
        }

        $_POST['bloopp'] = strip_tags($_POST['bloopp']);
        $_POST['bloopp'] = htmlspecialchars($_POST['bloopp']);
        $link = mysqli_connect($db_hostname, $db_username, $db_password, $db_database);
        // (5) Is er geen fout opgetreden bij het openen van de databaseverbinding?
        if (!mysqli_connect_error()) {
            // (6) Kan de juiste MySQL-karakterset worden ingesteld?
            if (mysqli_set_charset($link, 'utf8')) {
                $_POST['bloopp'] = mysqli_real_escape_string($link, $_POST['bloopp']);
                // Hier een prepared statement opstellen en uitvoeren.
                // <...>

            }
        }
    }
}

?>
 
Sven Thijssen

Sven Thijssen

09/11/2013 16:40:02
Quote Anchor link
Beste Erwin

Ik heb inderdaad weinig kennis van beveiliging. Nu weet ik hoe ik duidelijk een script moet opstellen!

Beste Ward

Hartelijk dank voor het opstellen van een veilige code! Ik zal deze zo onmiddellijk veranderen!

Op de regel 'hier een prepared statement opstellen en uitvoeren', kan ik mijn eigenlijke code uitvoeren, zoals het controleren of het tijdverschil met de vorige bloopp groot genoeg is en vervolgens $_POST['bloopp'] naar de database verzenden?

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
$check="SELECT TIMESTAMPDIFF(MINUTE, send_time, CURRENT_TIMESTAMP) AS 'diff' FROM bloopp WHERE email = '$email' ORDER BY bloopp_id DESC LIMIT 1";
 $res = mysqli_query($link, $check) or die("Error " . mysqli_error($res));
 $data = mysqli_fetch_array($res, MYSQLI_ASSOC);


Nogmaals erg bedankt! Het is altijd fijn om zeker te zijn dat je website veilig is! ;-)

Met vriendelijke groet
Sven
 
Ward van der Put
Moderator

Ward van der Put

09/11/2013 17:02:53
Quote Anchor link
Sven, waarom voer je een query uit als ik tip dat een prepared statement veel veiliger is? Waarom verwerk je een array als je maar één record ophaalt?

Je gooit er ineens ook een onbekende en ongecontroleerde variabele $email in.

Wat Erwin zegt dus: probeer eerst te begrijpen wat je per regel doet.
 
Erwin H

Erwin H

09/11/2013 17:48:38
Quote Anchor link
Sven Thijssen op 09/11/2013 16:40:02:
Nogmaals erg bedankt! Het is altijd fijn om zeker te zijn dat je website veilig is! ;-)

Dat weet je helemaal niet....
 
Sven Thijssen

Sven Thijssen

09/11/2013 18:19:28
Quote Anchor link
Ward

Omdat ik niet wist wat een prepared statement is. Ik dacht dat dit gewoon de verdere code was, wat dus blijkbaar niet zo blijkt te zijn. Dit heb ik nu opgezocht op Wikipedia en ik heb dit gevonden:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
$stmt = $dbh->prepare("SELECT * FROM users WHERE USERNAME = ? AND PASSWORD = ?");
$stmt->execute(array($username, $password));

Is zoiets in het algemeen wat U bedoelt?

Mijn kennis PHP is zeer gebrekkig en vind het meestal nogal moeilijk om ergens een verschil in te zien, zoals die array.
Ik hoop verder dat ik uit deze fouten kan leren. :)

Bedankt!
 
Pieter Jansen

Pieter Jansen

09/11/2013 23:30:36
Quote Anchor link
Wat je in je voorbeeld hierboven hebt aangegeven is inderdaad een prepared statement. Wat het voordeel hiervan is is dat de input, oftewel je $username en je $password, door de statement afgehandeld worden. Dat betekent dat er niet per ongeluk platte tekst of gekke tekens in je query komen te staan die gevaarlijke zaken kunnen uitvoeren op je database.

@Ward maakt het echt uit? Hoe dan ook moet de output van de query buffer nog geleegd worden
@Erwin lekker constructief, geef ook aan waarom dat dan niet zo is
 
Ward van der Put
Moderator

Ward van der Put

10/11/2013 08:21:15
Quote Anchor link
Juist als je niet exact weet wat je wanneer moet controleren, helpt een prepared statement. De query wordt strikt gescheiden van de data die je er later insteekt: iets anders uitvoeren dan jouw query wordt onmogelijk.

Dus even praktisch: ja, herschrijf je MySQLi-code naar een prepared statement.
 
Erwin H

Erwin H

10/11/2013 10:03:40
Quote Anchor link
Pieter Jansen op 09/11/2013 23:30:36:
@Erwin lekker constructief, geef ook aan waarom dat dan niet zo is

Lees mijn eerste post en je hebt je antwoord.
 
Sven Thijssen

Sven Thijssen

11/11/2013 09:58:24
Quote Anchor link
Oké, is zal binnenkort opnieuw schrijven als een prepared statement! Erg bedankt allemaal voor de hulp! ;)
 
Erwin H

Erwin H

11/11/2013 11:30:42
Quote Anchor link
En weet je nu wat je doet en waarom je het doet? Weet je nu op welke momenten je wel een prepared statement kan gebruiken en op welke momenten niet? Welke extra maatregelen je nog moet nemen? Tegen welke risico's een prepared statement je kan beschermen en tegen welke niet?
Echt, beveiligen van je scripts is niet een kwestie van een paar trucjes uitvoeren en dan ben je veilig. Als dat zo was dan hoefde geen enkele website ooit meer gehackt te worden. Helaas is dat niet zo. Er zijn altijd uitzonderingen en als je die niet weet ben je nog net zo kwetsbaar.

Maar goed, uit je totale gebrek aan serieuze reactie op mijn opmerkingen ga ik ervanuit dat het je blijkbaar geen bal uitmaakt. Prima, dan ga ik verder ook niet aan een dood paard trekken.
 
Ger van Steenderen
Tutorial mod

Ger van Steenderen

11/11/2013 13:12:43
Quote Anchor link
Let er overigens ook op dat de prepared statements in MySQLi gewooon twee queries zijn, want die zijn server-side.
 
Sven Thijssen

Sven Thijssen

12/11/2013 12:26:08
Quote Anchor link
@Erwin

Uit de context kan ik afleiden dat ik een prepared statement gebruik als laatste stap om te controleren of een variabele veilig of onveilig is. Wat me nog onduidelijk is, is of de gehele prepared statement de query vervangt of dit nog eens extra moet opgegeven worden.

Ik vind het spijtig dat ik misschien een verkeerde indruk heb opgewekt, maar ik apprecieer zeker uw hulp. Het neemt soms enige tijd voor mij om alles te begrijpen en te combineren met school.
Sven
 
Erwin H

Erwin H

12/11/2013 12:39:08
Quote Anchor link
Een prepared statement is niet de laatste stap om te controleren of de input veilig is. Een prepared statement controleert helemaal niets. Het doel van een prepared statement is om een query al voor te bereiden zonder deze uit te voeren. Zie het als de database laten weten dat er een query aan gaat komen, maar nog zonder te vertellen met welke gegevens. Na het voorbereiden kan je dan de waardes doorgeven aan de database waarbij alles, zonder verdere checks rechtstreeks in de database zal worden gezet.

Het grote voordeel van een prepared statement is dat deze het mogelijk maakt om grote aantallen insert, update of delete acties achter elkaar uit te voeren, met telkens andere data, zonder dat elke keer de query opnieuw hoeft te worden aangemaakt. Heb je dus vele identieke queries achter elkaar dan scheelt dit veel tijd. Voor eenmalige queries is het eigenlijk helemaal niet bedoelt en kost het alleen maar tijd.

Waarom het dan toch wordt aangeraden is omdat een prepared statement een bijkomend voordeel heeft, namelijk dat er door de manier van uitvoeren van de query, geen sql injectie meer mogelijk is. Omdat de query instructies en de data strikt gescheiden zijn, kan een sql injectie poging geen effect hebben op de query instructies. Maar anders dan dat biedt een prepared statement geen enkele beveiliging op andere mogelijke aanvallen. Je gebruikt in je allereerste post bijvoorbeeld htmlspecialchars. Waarom doe je dat? Normaal gesproken doe je dat om jezelf te beschermen tegen XSS of html injectie (en dan niet voor het invoeren in de database, maar na het er weer uithalen). Een prepared statement zal hier niet bij helpen. Hoe ga je dit nu tegengaan, of was je je er uberhaupt wel van bewust dat je dat daarvoor gebruikte?

Daarom: begrijp wat je doet en 'sleur en pleur' niet zomaar code zonder te weten wat het doet en, vooral, wat het niet doet.
 
Sven Thijssen

Sven Thijssen

13/11/2013 21:57:09
Quote Anchor link
Beste Erwin

U hebt me absoluut duidelijk gemaakt wat prepared statements inhouden. Ik wist ook niet dat htmlspecialchars bij de opgehaalde gegevens toegepast moest worden.

Ik heb in elk geval geleerd minder snel conclusies te nemen ;-).

Ik ben U ook voor deze uitgebreide en duidelijke uitleg zeer dankbaar!

Mvg Sven
 



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.