Mijn DB beschermen, maar hoe?

Status
Niet open voor verdere reacties.

Systemizer X100

Terugkerende gebruiker
Lid geworden
24 mei 2003
Berichten
1.636
Ik ben nu bezig met het leren van MySQL met PHP, en ik las iets over een sql injection attack. Het is me niet echt duidelijk wat het precies is, maar men kan zo controle krijgen over je database met weinig middelen (zoiets was het volgens mij).

Hoe bescherm ik me hier tegen? Ik heb al een aantal dingen opgezocht op internet, maar de meeste dingen zijn voor ASP en de uitleg is niet echt duidelijk.
 
SQL injection is een algemeen begrip dat geldt voor elke database-server die samen kan werken met een andere applicatie, wat dus vrijwel elke database-server is, zowel MySQL als Access als Oracle, etc.

Beschermen hiertegen: zorgen dat men je query's niet kan beïnvloeden.

Neem deze ASP code waarin ik een query opstel:
Code:
dim query
query = "SELECT wachtwoord FROM gebruikers WHERE gebruikersnaam = '" & request.form("gebruikersnaam") & "'"
Een dergelijke query voert men uit bij loginsystemen, hierbij komt gebruikersnaam van de waarde die men invult in het loginformulier.

Stel ik zou bij het loginformulier dit invullen:
De query zou er dan als volgt uit zien:
Code:
SELECT wachtwoord FROM gebruikers WHERE gebruikersnaam = 'bla ' bla'
Zie je die ' tussen bla en bla in ? Die verstoort de query.

Pas dit trucje op de juiste manier toe en je kan idd heel wat bereiken, met de nieuwste MySQL versies nog meer dan met de oude (denk aan het UNION statement). Om dit te voorkomen gebruik je simpelweg de ASP functie Replace() om de ' te escapen. Toen ik voor school een project in ASP moest schrijven (met enkele anderen, uiteraard), heb ik deze functie geschreven:
Code:
function verwerkInvoer( string )
  verwerkInvoer = Trim( Replace( string, "'", "''" ) )
end function
En deze functie pastte ik toen als volgt toe:
Code:
gebruikersnaam = verwerkInvoer( request.form( "gebruikersnaam" ) )
wachtwoord = verwerkInvoer( request.form( "wachtwoord" ) )
Call recordset.Open( "SELECT * FROM gebruikers WHERE gebruikersnaam = '" & gebruikersnaam & "' AND wachtwoord = '" & wachtwoord & "'", connection)
Let er wel op dat dit het simpelste van het simpelste loginsysteem is en dat dit loginsysteem verre van veilig is, maar zo heb je SQL injection al wel voorkomen ;)

Succes !
 
Laatst bewerkt:
SQL-injection is niet ingewikkeld:P

Persoonlijk vind ik de beste manier om je ertegen te beschermen, het zelf leren en proberen je eigen database kapot te krijgen.

Anyway, SQL injection kan je tegenhouden door:

- Elke string die je van php in de sql-query zet te omringen met aanhalingstekens!
- htmlspecialchars te gebruiken voor alle inkomende stringen
- quote's filteren, bv:
PHP:
 str_replace($inkomendestring,"'","");
str_replace($inkomendestring,'"','');
 
Hmm, ik zal dit allemaal even eigelijk uit moeten proberen.

@JPeetje:

verwerkInvoer = Trim( Replace( string, "'", "''" ) )

Dan wordt een ' dus vervangen door een '', maar dan zou je toch dit krijgen?

SELECT wachtwoord FROM gebruikers WHERE gebruikersnaam = 'bla " bla'

zorgt dat dan niet voor problemen? Ik zet die queries eerst altijd in een variable, dus zo

$query = "SELECT wachtwoord FROM gebruikers WHERE gebruikersnaam = 'bla ' bla'";
mysql_query($query);

dan zou 'bla ' bla' 'bla " bla' worden, en wordt deze code gebruikt door mysql:

"SELECT wachtwoord FROM gebruikers WHERE gebruikersnaam = 'bla " bla'"

:confused: Volgens mij geeft dat ook een fout.

Trouwens ik gebruik php :P
 
VB van succesvolle SQL-injecties:

PHP:
 $query = "SELECT allowed from userstabel where user='$user'"
$result = mysql_blabla( );
if(error == true){
echo "unknown user";
}
else{
if($result == "dasecretpassword"){
// gevoelige data :P
}
else{
echo "Not allowed...";
}
}

als user neem je bv :
' OR 1='1
Wat resulteert in:
PHP:
$query = "SELECT allowed from userstabel where user='' OR 1='1'"

En sinds 1 altijd 1 is zal je hoogstwaarschijnlijk de eerste user in de tabel tegenkomen wie admin zou moeten zijn --> heeft toegang.
Je kan dit uitbreiden door user te kiezen als:

' OR 1='1' AND id='5

wat de vijfde user uit de tabel zal selecteren...

Er zijn nog tal van voorbeelden... Volg mijn tips op en je ben vrij veilig:)
 
- Elke string die je van php in de sql-query zet te omringen met aanhalingstekens!
Doe ik :p

- htmlspecialchars te gebruiken voor alle inkomende stringen
Interessant, heb ik al wel iets over gelezen, miscschien komt dat dan nu van pas :)

- quote's filteren, bv:
PHP:
 str_replace($inkomendestring,"'","");
str_replace($inkomendestring,'"','');[/QUOTE]
:( Okay, ik snap dat het veiliger is, maar dan kun je dus niet quoten. Is htmlspecialchars niet genoeg :p
 
met htmlspecialchars wordt een quote omgezet in '/ of zoiets...
Dit is handig om XSS tegen te gaan, maar het genereert nogaltijd errors in je query...

mss omzetting in ascii?
 
een ' wordt met htmlspecialchars omgezet naar &#039 en " naar &quot volgens php.net die vervolgens gewoon normaal weergegeven worden, dus als een ' of ".

Omzetten naar ascii? Hoe?
 
oh, wel dan htmlspecialchars :P
sorry dacht dat het anders ging
 
Geplaatst door Systemizer X100
@JPeetje:

verwerkInvoer = Trim( Replace( string, "'", "''" ) )

Dan wordt een ' dus vervangen door een '', maar dan zou je toch dit krijgen?

SELECT wachtwoord FROM gebruikers WHERE gebruikersnaam = 'bla " bla'

zorgt dat dan niet voor problemen? Ik zet die queries eerst altijd in een variable, dus zo
Nee, dat zorgt niet voor problemen, dat is de manier waarop je zo'n ' escaped ;)

Althans, dat denk ik. Nu ik er bij stil sta, dit gebruikte ik bij ASP i.c.m. Access, dus dit is de manier waarop je een quote escaped in Access. In MySQL is het \'.

Replace( string, "'", "\'" );
Trouwens ik gebruik php :P
Ow :8-0:

Onderin je eerste post stond ASP, dus ja ... :D

In PHP hoef je alleen maar addslashes() toe te passen, geen str_replace() dus :)
Althans, dat is het enige wat je moet doen op voorwaarde dat de magic quotes uitstaan.

En verder, ik weet niet wat jullie over htmlspecialchars() zitten te discusseren, maar heeft niets, maar dan ook niets te maken met SQL injection :)
 
Geplaatst door Systemizer X100
Magische quotes? Waar zet ik die uit?
php.ini of met .htaccess.

Met een PHP functie kun je het niet doen, de GPC magic quotes althans. De runtime magic quotes kun je wel uitschakelen.
 
Geplaatst door Systemizer X100
Okee... en waarvoor dienen die Magic Quotes eigelijk?
Goeie vraag, persoonlijk vind ik 't ook walgelijk dat PHP ze ooit heeft uitgevonden. Maar die magic quotes, mits ze aanstaan, passen addslashes() toe op de GET, POST en COOKIE waarden (GPC) (onder COOKIE waarden vallen sessies ook geloof ik, maar voor de zekerheid kun je dat 't beste ff testen). Dit doen ze omdat PHP uitgegroeid is tot een taal waarmee vele mensen beginnen te leren programmeren. Deze beginners houden in 't begin ook zeer weinig rekening met beveiliging, hiervoor heeft PHP 't waarschijnlijk gedaan.
 
Hmm...

eh. Volgens mij kan ik niet eens bij de PHP.ini van mijn webhost :confused:

Maar over wat je zei, GET en POST enzo, die werken dan toch nog wel? Die zal ik wel nodig hebben namelijk :p
 
Geplaatst door Systemizer X100
Volgens mij kan ik niet eens bij de PHP.ini van mijn webhost :confused:

Maar over wat je zei, GET en POST enzo, die werken dan toch nog wel? Die zal ik wel nodig hebben namelijk :p

ini file, most likely:) daar kan je zowat alles afzetten:P

$_GET[] enzo werken meestal wel. Dat staat meestal standaard aan
 
Een eenvoudige en ook al redelijke manier om je tegen SQL insertion te beschermen, is zorgen dat je invoerveld niet te lang kan worden.

Een SQL insertion heeft over het algemeen best wat tekens nodig en dat kun je al redelijk voorkomen door invoer niet langer dan nodig te houden.

bv een gebruikersnaamveld max 10-12 char en wachtwoord 6-10

In 10 tekens is nagenoeg geen insertion mogelijk.


Hier nog een voorbeeld van een formulier waar user/pass aangemaakt gaan worden:


Zorg er verder voor dat je de rechten van de pagina zoveel mogelijk beperkt tot de tabellen en velden die op die pagina gebruikt worden. Dus niet laten inloggen als DBadmin, maar gewoon aparte gebruiker met alleen lees (en evt schrijf) rechten op de velden die nodig zijn.

Mocht er dan al sql insertion plaatsvinden, dan blijft de schade beperkt :)
 

Bijlagen

Geplaatst door buick
Een eenvoudige en ook al redelijke manier om je tegen SQL insertion te beschermen, is zorgen dat je invoerveld niet te lang kan worden.
dat lijkt mss wel een mooie optie, maar het is gemakkelijk te omzeilen. Je kan simpelweg zelfs met wat inURL javascript, die max_length aanpassen, of door zelf het paketje te sturen met zoveel data als je maar wil...

Je zou dan ook nog in je php file bij de 'post' code moeten checken dat de invoer niet te lang is enzo krijg je heel veel code als je zo alles gaat dubbel checken...

Anyway, hij heeft wel volledig gelijk over het feit dat je best een aparte user zou moeten aanmaken voor elke database, wiens wachtwoord verschillend is van de rest + wiens permissies beperkt zijn...
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan