Kiedyś robiłem trochę w PHP. Wszystko było fajnie i w ogóle, do momentu, gdy usłyszałem o sql injection. Padł blady strach, przetestowałem jedną z moich witryn i okazało się, że jest na to podatna. Zacząłem szukać jakiegoś rozwiązania ale prawdę mówiąć kiepsko mi szło… w końcu skleciłem funkcję która, jak mi się wydawało, dawała pełne bezpieczeństwo. Okazuje się jednak, że to zabezpieczenie można było łatwo obejść… na szczęście w owych czasach chyba nikt na to jeszcze nie wpadł. Anyway, jeśli chcecie się dobrze zabezpieczyć to znalazłem takie coś: $arrArguments = array(); function parseArgument($arrMatches) { $strMatch = $arrMatches[0]; function SQL($strSql) { $arrArgs = func_get_args(); ?>
$intArgumentIndex = 0;
global $arrArguments, $intArgumentIndex;
$strArgument = @$arrArguments[$intArgumentIndex++];
switch ($strMatch) {
case '%d': return (int)$strArgument;
case '%s': return '"'.mysql_real_escape_string($strArgument).'"';
case '%b': return (int)((bool)$strArgument);
}
}
global $arrArguments, $intArgumentIndex;
array_shift($arrArgs);
$arrArguments = $arrArgs;
$intArgumentIndex = 0;
return preg_replace_callback('/(%[dsb])/', 'parseArgument', $strSql);
}
Zastosowanie:
// Przyjmujemy, dla przykładu:
$_POST['uid'] = 1;
$_POST['name'] = ‘Łukasz “anAKiN” Lach’;
$_POST['username'] = ‘anakin’;
$_POST['password'] = ‘an4kin’;
$_POST['newsletter'] = 1;
$sql = SQL(’INSERT INTO users (id, uid, name, username, password, newsletter) ‘.
‘VALUES (NULL, %d, %s, %s, %s, %b)’, $_POST['uid'], $_POST['name'],
$_POST['username'], md5($_POST['password']), $_POST['newsletter']);
Wynikowa wartość (zapytanie wynikowe):
INSERT INTO users (id, uid, name, username, password, newsletter)
VALUES (NULL, 1, "Łukasz \"anAKiN\" Lach", "anakin",
"97296eca657a093aa379778c237e292d", 1)
Autor: Łukasz Lach.
To co mi się podoba w tym rozwiązaniu to bardzo ładna konstrukcja funkcji, emulująca znaną programistom składnię i ograniczająca kłopotliwość definiowania typu przekazywanych do bazy danych do minimum. Jednocześnie, jako że wszystko dzieje się tuż przed wysłaniem do bazy łatwo sobie przyswoić nawyk stosowania tej funkcji zamiast “gołego” zapytania SQL.