Introductie
phpBB3 heeft goede veiligheidsmaatregelen. Een daarvan is de functie request_var om gebruikersingaves te controleren. De functie is gemaakt om een gemakkelijke controle te hebben over datgene dat gebruikers ingeven.
SQL Injectie
SQL injectie is een van de gevaarlijkste die er is, maar ook een die het gemakkelijkst te voorkomen is. Alles van de gebruikersingave's $_GET, $_POST, $_COOKIE, or $_SERVER verreist controlle om voor een veilige website te zorgen. Om SQL injectie te voorkomen is een goed gebruik van request_var verreist. Daarom kan je ook opgeven welk soort datatype je verwacht bij het aanroepen van de functie. request_var zal je gebruikersingave dan casten naar het juiste type.
Voorbeeld
Request_var gebruikt de gebruikersingave en draait daarmee en query. Om aan te geven dat je een nummer verwacht geef je in de tweede parameter het getal 0 mee. Bestaat de opgevraagde gebruikersingave niet retouneert request_var de tweede parameter die in dit geval 0 is.
- Code: Selecteer alles
-
$user_id = request_var('user_id', 0);
-
-
$sql = 'SELECT username
-
FROM ' . USERS_TABLE . '
-
WHERE user_id = ' . $user_id;
-
$result = $db->sql_query($sql);
-
$row = $db->sql_fetchrow($result);
-
$db->sql_freeresult($result);
-
-
Wat kan er fout gaan
Hieronder een voorbeeld hoe het toch fout kan gaan. Gebaseerd op het vorige voorbeeld hebben we nu de tweede parameter als een variabele ingezet.
- Code: Selecteer alles
-
$user_id = request_var('user_id', $user->data['user_id']);
-
-
$sql = 'SELECT username
-
FROM ' . USERS_TABLE . '
-
WHERE user_id = ' . $user_id;
-
$result = $db->sql_query($sql);
-
$row = $db->sql_fetchrow($result);
-
$db->sql_freeresult($result);
-
-
De fout
$user->data['user_id'] is een waarde die direct van de database afkomt en php retouneert altijd strings. $user_id wordt nu niet gecast naar een integer maar blijft een string en dat houdt in dat je de query kan beinvloeden. Bijvoorbeeld door in $user_id de GET parameter te wijzigen in:
- Code: Selecteer alles
-
0 UNION SELECT user_email as username FROM phpbb_users WHERE user_id = 2
De query zal er dan uiteindelijk zo uitzien:
- Code: Selecteer alles
-
SELECT username FROM phpbb_users WHERE user_id = 0 UNION SELECT user_email as username FROM phpbb_users WHERE user_id = 2
Op deze manier kan je dus het emailadres van de gebruiker met id nummer 2 verkrijgen. Natuurlijk zijn er ook nog veel meer kwalijke dingen die op deze manier te doen zijn. Den k aan het verwijderen van alle gebruikers.
Hoe moet het dan wel
Heel gemakkelijk, cast de tweede parameter naar een integer.
- Code: Selecteer alles
-
$user_id = request_var('user_id', (int) $user->data['user_id']);
En bij strings
Request_var beveiligd de meeste gebruikersingaves maar bij strings is het toch aan te bevelen om de string te escapen. Gebruik daarvoor de $db->sql_escape() functie die voor alle types databases die phpbb gebruikt is uitgelegd.
- Code: Selecteer alles
-
$foo = request_var('foo', 'bar');
-
$sql = 'SELECT username
-
FROM ' . USERS_TABLE . '
-
WHERE foo = ' . $db->sql_escape($foo);