[Q&A] Beveiliging algemeen
Buiten SQL Injecties zijn er natuurlijk nog veel meer dingen met betrekking tot beveiliging. Om die reden is het topic veranderd van SQL Injecties, naar beveiliging algemeen. Alle beveiliging-gerelateerde vragen kunnen hier worden gesteld.
Om het een beetje overzichtelijk te houden, wil ik het volgende voorstellen. Wanneer je een vraag hebt, stel je deze als volgt: (de quote moet je dus even zien als een losse reactie, maar laat het iets beter zien!)
Willekeurig - op 05/08/2013 17:45:00:
Vraag: Ik heb de volgende query. Is deze voldoende beveiligd?
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
include('configuration.php'); // Vanuit hier wordt de SQL-verbinding opgezet
$veld_3 = !empty($_GET['veld_3']) ? mysql_real_escape_string($_GET['veld_3']) : 1;
$resource = mysql_query("SELECT id, veld_1, veld_2 FROM willekeurige_tabel WHERE veld_3 = " . $veld_3);
?>
include('configuration.php'); // Vanuit hier wordt de SQL-verbinding opgezet
$veld_3 = !empty($_GET['veld_3']) ? mysql_real_escape_string($_GET['veld_3']) : 1;
$resource = mysql_query("SELECT id, veld_1, veld_2 FROM willekeurige_tabel WHERE veld_3 = " . $veld_3);
?>
Een antwoord zou dan zijn:
Quote:
Antwoord: Je gaat er op dit moment van uit dat veld_3 een integer is, aangezien je geen quotes gebruik. Controleer daarom met ctype_digit of de variabele een integer is:
Zolang je dit controleer, hoef je de variabele niet te escapen.
Willekeurig - op 05/08/2013 17:45:00:
Vraag: Ik heb de volgende query. Is deze voldoende beveiligd?
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
include('configuration.php'); // Vanuit hier wordt de SQL-verbinding opgezet
$veld_3 = !empty($_GET['veld_3']) ? mysql_real_escape_string($_GET['veld_3']) : 1;
$resource = mysql_query("SELECT id, veld_1, veld_2 FROM willekeurige_tabel WHERE veld_3 = " . $veld_3);
?>
include('configuration.php'); // Vanuit hier wordt de SQL-verbinding opgezet
$veld_3 = !empty($_GET['veld_3']) ? mysql_real_escape_string($_GET['veld_3']) : 1;
$resource = mysql_query("SELECT id, veld_1, veld_2 FROM willekeurige_tabel WHERE veld_3 = " . $veld_3);
?>
Antwoord: Je gaat er op dit moment van uit dat veld_3 een integer is, aangezien je geen quotes gebruik. Controleer daarom met ctype_digit of de variabele een integer is:
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
<?php
if (!empty($_GET['veld_3']) && ctype_digit($_GET['veld_3'])) {
$veld_3 = $_GET['veld_3'];
}
else {
$veld_3 = 1;
}
?>
if (!empty($_GET['veld_3']) && ctype_digit($_GET['veld_3'])) {
$veld_3 = $_GET['veld_3'];
}
else {
$veld_3 = 1;
}
?>
Zolang je dit controleer, hoef je de variabele niet te escapen.
Om gelijk wat interessant leesvoer aan te bieden, lees het volgende topic op StackOverflow maar eens: SQL-injection that gets around mysql_real_escape_string?
Gewijzigd op 06/08/2013 14:00:51 door Chris -
Volgens jouw bericht, en de genoemde link hoef ik dus geen mysqli_real_escape_string() te gebruiken, als ik er ctype_digit() over de input field zet. Dit deel begrijp ik nog niet helemaal, of begrijp ik het verkeerd?
Hiermee controlleer je dus of $getal een getal is. Zo ja, dan kun je query uitvoeren.
Als dat het enige user input is van je query, hoef je inderdaad geen mysqli_real_escape_string() te gebruiken.
Bedankt voor je snelle antwoord, hoe zit het dan met tekst. Is daarvoor mysqli_real_escape string() ook veilig genoeg, of kan je daarbij ook ctype_alnum() gebruiken zonder mysqli_real_escape_string() zoals getoont in de onderstaande code:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
if (!empty($_GET['veld_3']) && ctype_alnum($_GET['veld_3'])) {
$veld_3 = $_GET['veld_3'];
}
else {
$veld_3 = 'Geen geldige waarde!';
}
?>
if (!empty($_GET['veld_3']) && ctype_alnum($_GET['veld_3'])) {
$veld_3 = $_GET['veld_3'];
}
else {
$veld_3 = 'Geen geldige waarde!';
}
?>
Laten we hierbij dan zeggen dat veld_3 de teskt [Hallo 'OR 1=1 " mensen] is.
Gewijzigd op 05/08/2013 18:59:22 door Landleven Tips
Ook in dit geval als er geen speciale tekens mogelijk zijn voor user input, is ook hier mysqli_real_escape_string() niet nodig
Dus samengevat, als ik ctype_alnum($var) gebruik, of ctype_digit of een andere ctype_* hoeft er dus geen mysqli_real_escpae_string($var) erbij. Eigelijk wordt hierbij dus mysqli_real_escpae_string($var) overbodig.
Het ligt maar net aan de doelstelling van je script.
Als voorbeeld, een shoutbox, chatbox, gastenboek w.e
Soms is het dus wel handig / leuk / vriendelijk dat mensen ook , . ( ) enz. kunnen gebruiken.
Daarbij is het zeer zeker noodzakelijk dat je mysqli_real_escape_string($var) gebruik.
De overige functies waar het zojuist om ging, gebruik je om je input te controlleren.
Als een soort foutafhandeling, voordat je de query uitvoerd.
Toevoeging op 05/08/2013 19:13:37:
Het moet een toevoeging zijn (valideren van de input, zoals je dat altijd hoort te doen), geen volledige afhankelijk. Met ID's die vaak numeriek zijn kan het een stuk makkelijker. Gebruik verder altijd de laatste versies van MySQL en schrijf je queries gewoon goed. En het liefste PDO, maar dan wel op de manier die op SO is uitgelegd :)
Het gaat hierbij bijvoorbeeld om een input field waar de gebruiker een gebruikersnaam in kunnen voeren, hierbij wil ik geen ' () - enz in hebben. Daarvoor dus ctype_alnum() voldoende moeten zijn volgens Dennis WhoCares.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$error = array();
if(!ctype_alnum($_POST['login_username'])) {
$error[] = '<li>U heeft een ongeldige gebruikersnaam ingevoerd!</li>';
}
if(empty($error)) {
echo 'SQL query uitvoeren voor gebruikersnaam ' . $_POST['login_username'];
} else {
echo 'Foutmelding: <ul>' . implode($error) . '</ul>';
}
} else {
echo 'Login form...';
}
?>
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$error = array();
if(!ctype_alnum($_POST['login_username'])) {
$error[] = '<li>U heeft een ongeldige gebruikersnaam ingevoerd!</li>';
}
if(empty($error)) {
echo 'SQL query uitvoeren voor gebruikersnaam ' . $_POST['login_username'];
} else {
echo 'Foutmelding: <ul>' . implode($error) . '</ul>';
}
} else {
echo 'Login form...';
}
?>
Maar dan is het nog niet waar dat de gehele functie mysqli_real_escape_string() te verwaarlozen is.
Zoals ik al aangaf en Chris- dus ook. Het is geheel afhankelijk van de doelstelling van de user input.
Gewijzigd op 05/08/2013 19:28:19 door Dennis WhoCares
Oke, bedankt voor de uitleg nu snap ik het.
Is het beter om vóór prepared PDO statements ook met mysqli_real_escape string te beveiligen of onnodig?
Juist niet!! Anders heeft het geen nut..
Kan je ook een ander topics maken voor andere beveiligingpreventies zoals XSS
htmlentities over de variabele zetten op het moment dat je de variable in je document echo't!
Voor XSS is het nog simpeler ;-) En CSRF?
Da's inderdaad wel een heel ander topic! Heb ik ook iets meer tijd voor nodig...
Alvast Bedankt zou echt handig zijn!
Chris - op 05/08/2013 17:51:35:
SQL Injecties is de nummer één oorzaak van een gehackte website.
Niet mee eens, er wordt vaker code geinjecteerd in pagina's en advertenties dan dat er daadwerkelijk SQL injecties plaatsvinden. Anno 2013 weten mensen inmiddels dat je queries moet beveiligen, alle 'PHP and MySQL' boeken leggen ook uit dat je dit moet doen en hoe.
Chris, laat maar zien waar je dat vandaan haalt. Mijn ervaring (en ik heb redelijk wat ervaring) plus de statistieken vertellen nog steeds: SQL injecties staat op 1.
Hier een lijst die ik gevonden heb met de top 20 hacking methodes. SQL injection staat op 19.
Quote:
1.Bypassing Flash’s local-with-filesystem Sandbox
2.Abusing HTTP Status Codes to Expose Private Information
3.SpyTunes: Find out what iTunes music someone else has
4.CSRF: Flash + 307 redirect = Game Over
5.Close encounters of the third kind (client-side JavaScript vulnerabilities)
6.Tracking users that block cookies with a HTTP redirect
7.The Failure of Noise-Based Non-Continuous Audio Captchas
8.Kindle Touch (5.0) Jailbreak/Root and SSH
9.NULLs in entities in Firefox
10.Timing Attacks on CSS Shaders
11.CSRF with JSON – leveraging XHR and CORS
12.Double eval() for DOM based XSS
13.Hidden XSS Attacking the Desktop & Mobile Platforms
14.Rapid history extraction through non-destructive cache timing (v8)
15.Lotus Notes Formula Injection
16.Stripping Referrer for fun and profit
17.How to upload arbitrary file contents cross-domain (2)
18.Exploiting the unexploitable XSS with clickjacking
19.How to get SQL query contents from SQL injection flaw
20.XSS-Track as a HTML5 WebSockets traffic sniffer
2.Abusing HTTP Status Codes to Expose Private Information
3.SpyTunes: Find out what iTunes music someone else has
4.CSRF: Flash + 307 redirect = Game Over
5.Close encounters of the third kind (client-side JavaScript vulnerabilities)
6.Tracking users that block cookies with a HTTP redirect
7.The Failure of Noise-Based Non-Continuous Audio Captchas
8.Kindle Touch (5.0) Jailbreak/Root and SSH
9.NULLs in entities in Firefox
10.Timing Attacks on CSS Shaders
11.CSRF with JSON – leveraging XHR and CORS
12.Double eval() for DOM based XSS
13.Hidden XSS Attacking the Desktop & Mobile Platforms
14.Rapid history extraction through non-destructive cache timing (v8)
15.Lotus Notes Formula Injection
16.Stripping Referrer for fun and profit
17.How to upload arbitrary file contents cross-domain (2)
18.Exploiting the unexploitable XSS with clickjacking
19.How to get SQL query contents from SQL injection flaw
20.XSS-Track as a HTML5 WebSockets traffic sniffer
Waar is jou lijst?