Artikelen › Bekijken

Toevoegen | Categorie:


[PHP] Security voor beginners

Beste medeleden. Dit is mijn eerste artikel en is bedoeld voor school en beginnende PHP programmeurs.

Voor beginnende PHP ontwikkelaars is dit artikel bedoeld als eerste stap richting een veiligere website. Om te voorkomen dat deze ontwikkelaars in de toekomst (simpele) fouten maken gaat dit artikel in op de oplossing voor deze beveiligingslekken.

Veelvoorkomende beveiligingslekken
Tijdens het ontwikkelen van websites stuit elke ontwikkelaar wel op een van de volgende mogelijke beveiligingslekken:
- SQL-injectie;
- XSS;
- Zwakheden door verborgen invoervelden;
- Zwakheden bij het uploaden van gevaarlijke bestanden.

Dit zijn natuurlijk niet alle beveiligingslekken die ontwikkelaars tegenkomen, maar wel de meest voorkomende. SQL-injectie en XSS staan op plek één en twee in de top tien van OWASP (Open Web Application Security Project). De overige beveiligingslekken is de auteur zelf vaak tegengekomen.

1. SQL-injectie
SQL– injectie wordt gebruikt om kwetsbaarheden in webapplicaties te vinden. Applicaties die informatie in een database opslaan maken vaak gebruik van SQL (Structured Query Language) om met de database te communiceren. Een SQL-injectie is mogelijk wanneer invoer van gebruikers op onvoldoende gecontroleerde wijze wordt verwerkt in een SQL query.
SQL gebruikt de apostrof voor het afbreken van niet-numerieke gegevens / data (Strings). Wanneer (bijvoorbeeld) een persoon inlogt met de gebruikersnaam Piet dan wordt de volgende SQL query verstuurde naar de database:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
SELECT FROM gebruikers WHERE gebruikersnaam 'Piet'



Deze query wordt naar de database verzonden, die daarop in de tabel gebruikers zoekt naar de gebruikersnaam Piet.
Normale gebruikers zullen te allen tijde hun gebruikersnaam gewoon invullen waar het systeem normaal op reageert.
Kwaadaardige gebruikers daarentegen zullen proberen het systeem te kraken. Wanneer de kwaadaardige gebruiker Piet’ invult (dus met apostrof) dan wordt MySQL om de tuin geleid. Dit noemt men SQL-injectie.
Een kwaadaardige gebruiker zal waarschijnlijk het volgende invullen in plaats van zijn gebruikersnaam:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
Piet‘ OR --



Hierdoor wordt de volgende query uitgevoerd:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
SELECT FROM gebruikers WHERE gebruikersnaam Piet‘ OR 1 –-



De database probeert nu te zoeken naar een gebruiker met de gebruikersnaam Piet en er wordt gecontroleerd of één gelijk is aan één.
Daarnaast zorgt het gebruik van “--“ dat de rest van de query als commentaar wordt gezien, waardoor er geen foutmeldingen worden gegenereerd.

Aangezien één gelijk is aan één en we te maken hebben met een OF-vergelijking wordt de query juist uitgevoerd en krijgt de persoon die de SQL-injectie uitvoert alle gegevens uit de gebruikerstabel te zien.
Diezelfde persoon weet nu dat het systeem kwetsbaar is voor een SQL-injectie en kan hiermee andere tabellen aanroepen, rijen uit de database verwijderen of alle tabellen uit een database verwijderen.

Deze zwakheid is makkelijk te voorkomen in PHP. Om dit aan te tonen worden er twee voorbeelden getoond. Allereerst een voorbeeld zonder beveiliging.
Dit voorbeeld hieronder bevat de mogelijkheid om een SQL-injectie aanval uit te voeren.

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
$gebruikersnaam “Joost’ OR 1=1”;
$sql “SELECT FROM gebruikers WHERE gebruikersnaam =.$gebruikersnaam;

mysql_query($sql);




Deze SQL-injectie is makkelijk te voorkomen door in PHP de functie mysql_real_escape_string() te gebruiken. Deze functie zorgt ervoor dat bepaalde karakters (in dit geval de apostrof) onschadelijk worden gemaakt. Voor de apostrof wordt een backslash geplaatst waardoor de variabele als data wordt gezien en niet als onderdeel van een query.
De PHP code wordt dan als volgt:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
$gebruikersnaam “Joost’ OR 1=1”;
$sql “SELECT FROM gebruikers WHERE gebruikersnaam =.mysql_real_escape_string($gebruikersnaam);

mysql_query($sql);




Door alleen deze functie toe te voegen voorkom je dat kwaadaardige gebruikers aan gegevens komen die niet voor hen bestemd zijn. Ook kunnen gegevens niet verwijderd of gekopieerd worden. En dat allemaal door maar één woord toe te voegen.

2. XSS
Op naar de volgende beveiligingslek, namelijk XSS. XSS is een afkorting voor Cross Site Scripting en gebeurt, net als SQL-injectie, door de invoer van een gebruiker.
De gebruiker voert in een invulveld een code / script in dat wordt uitgevoerd in het scherm. Een simpel voorbeeld is wanneer een gebruiker het volgende invult.

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
<script>alert('Dit komt in het venster');</script>



Het bovenstaande JavaScript zal, indien er geen beveiliging tegen XSS is, uitgevoerd worden waardoor er een pop-up verschijnt met de tekst ‘Dit komt in het venster’.
Op zich kan het bovenstaande voorbeeld geen kwaad, maar het geeft kwaadaardige gebruikers een signaal dat het systeem kwetsbaar is voor XSS aanvallen.
Zij kunnen nu complete scripts neer zetten die:
- Cookies van andere gebruikers uitlezen;
- Gegevens van de gebruiker uitlezen;
- Andere gebruikers doorsturen naar kwaadaardige websites (met bijvoorbeeld malware).

Net als SQL-injectie is ook XSS met één regel te ‘voorkomen’. Wanneer een formulier verzonden wordt, stuurt deze een POST / GET HTTP request naar de server. Om een website te beveiligen tegen een XSS aanval moeten alle POST / GET waardes met de functie htmlentities() geconverteerd worden.
Hierdoor worden alle tekens geconverteerd naar HTML tags waardoor tekst niet als HTML wordt toegevoegd. Zoals hieronder weergegeven:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
5
//HTML tag zonder htmlentities() 
<a href='test'>Test</a>

//HTML tag met htmlentities() 
&lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt;




De functie htmlspecialchars()kan voor hetzelfde doeleinde gebruikt worden.

Door deze extra functie toe te voegen voorkom je dat kwaadaardige gebruikers scripts invoeren die andere gebruikers op het verkeerde spoor zetten.

3. Zwakheden door verborgen invoervelden
Zwakheden in verborgen invoervelden is een beveiligingslek die niet op de lijst van OWASP voorkomt. Wel is het een beveiligingslek dat de auteur van dit artikel vaak voorbij heeft zien komen. Zo werd de website just-eat.nl, een website waarop eten besteld kan worden, een aantal jaar geleden geteisterd door deze hack.

De hack werkt als volgt:
Binnen HTML is het mogelijk verborgen input (invoer) velden in een formulier te plaatsen. Wanneer het formulier verzonden wordt, worden deze verborgen velden ook meegestuurd.
Just-Eat had het bedrag van een product in een verborgen veld geplaatst, dat met het versturen van een formulier mee werd verzonden. Het probleem was echter dat Just-Eat.nl het bedrag niet controleerde en er vanuit ging dat het meegestuurde bedrag altijd klopte.
In de browser Firefox is het mogelijk om met een programma zoals Firebug, HTML elementen dynamisch te wijzigen. Verborgen velden (zoals het bedrag) kunnen gemakkelijk gewijzigd worden.
Een aantal studenten wisten dit ook en pasten dit toe bij Just-Eat. De studenten bestelden in een maand zo’n 30.000 euro aan pizza’s voor maar een paar cent.
Zo’n beveiligingslek is te voorkomen door alle data te controleren die verstuurd wordt.
In het geval van Just-Eat hadden zij, in plaats van het bedrag in een verborgen invoerveld te plaatsen, het bedrag op moeten halen aan de hand van (bijvoorbeeld) een unieke ID.
Dit unieke ID wordt aan de server kant bepaald waardoor kwaadaardige gebruikers er niet bij kunnen.

4. Zwakheden bij het uploaden van gevaarlijke bestanden
Een veiligheidslek dat voornamelijk voorkomt met het versturen van formulieren (denk aan formulieren waarbij je een CV uploadt).
Kwaadaardige gebruikers uploaden dan een gevaarlijk type bestand (denk aan een .PHP of .exe bestand) dat zij via een URL kunnen aanroepen.
Dit bestand voert dan een script uit dat (bijvoorbeeld) bestanden op een server verwijdert.

Een andere vorm van een zwakheid bij het uploaden van bestanden wordt ook wel Null Byte Exploit genoemd. De Null Byte Exploit is een veiligheidslek dat wordt gebruikt om delen van een String te laten wegvallen, door ervoor de hexadecimale waarde van de null byte te plaatsen, %00.
Stel, iemand probeert het bestand kwaadaardigbestand.php%00.jpg up te loaden. Wanneer een website alleen controleert op extensie zal dit bestand als een JPG-bestand worden beoordeeld en worden toegelaten. Terwijl het dus een .PHP bestand betreft, dat de kwaadaardige gebruiker, na het uploaden, kan aanroepen.
Dit is te beveiligen door bij het uploaden van bestanden niet te controleren op de extensie van een bestand, maar op het MIME Type. Voorbeelden van MIME Types zijn:

text/plain
MIME Type voor gewone tekstdocumenten. Hiermee worden geen Word documenten bedoeld, maar gewone, platte ASCII teksten.

image/jpeg
MIME Type voor JPEG afbeeldingen.

Het controleren op MIME Types kan als volgt opgelost worden in PHP:

Code tonen/verbergenCodeDeze code in een nieuw vensterDeze code in een tekstveldDeze code in een zip file downloaden
1
2
3
4
5
6
//naamuploadveld is hoe het veld heet in het formulier
$mime $_FILES['naamuploadveld']['type']; 

if(
$mime == "text/plain" || $mime == "image/jpg"){ 
    
//Hier komt code om het bestand op te slaan
}




Door het bovenstaande PHP script toe te voegen aan een formulier waar een gebruiker kan uploaden wordt er voorkomen dat er gevaarlijke bestanden worden opgeslagen.

4 reacties | reageren


Rating

Stemmen: 1Je moet ingelogd zijn om te stemmen!