Как да се предпазим от инжектиране на SQL код?
Първото правило е: Никога не се доверявайте в коректността на въведените от потребител данни! Лесно е да се каже, малко по-сложно е да се направи.
Най-лесния начин да се предпазите от SQL инжекции е да използвате опцията на
PHP „Magic Quotes” за представянето на специалните символи (като кавички, NULL, обратна наклонена черта и др.), които са част от SQL синтаксиса във вид на escape последователности. Тази възможност е предвидена и като средство за предпазване от SQL инжекции, но не във всички случаи е ефективна и вероятно няма да се развива в следващите версии на
PHP. Следващите примери не гарантират 100% защита (ако такава изобщо е възможна), но имат висока степен на защитеност срещу SQL инжекции.
Първото което трябва да направим е да премахнем ‘\’ от всички входни параметри, които евентуално са насложени от Magic Quotes:
CODE1
2
3
4
5
6
7
8
9
10
11
| <?php
if (get_magic_quotes_gpc())
{
$_REQUEST = array_map('stripslashes', $_REQUEST);
$_GET = array_map('stripslashes', $_GET);
$_POST = array_map('stripslashes', $_POST);
$_COOKIE = array_map('stripslashes', $_COOKIE);
}
?> |
вместо това използваме възможностите на mysql_real_escape_string() в
SQL заявката:
CODE1
2
3
4
5
6
7
| <?php
$query = mysql_query("SELECT * FROM `users` "
. "WHERE `username` = '"
. mysql_real_escape_string($username) . "' "
. "AND `password` = '"
. mysql_real_escape_string($password) . "'");
?> |
Нека да променим и метода на формата от GET на POST въпреки, че това не е голяма защита. Все пак ще ви спести изненадата от факта, че паролата ви се вижда в явен вид в историята на посещаваните сайтове на някои браузъри. Също така полето за въвеждане на парола е нормално да е от тип password:
CODE1
2
3
4
5
6
7
8
9
10
11
| <?php
if(empty($_POST['username'])) {
echo "<form method='POST' action='login.php'>"
."Username: <input type='text' name='username' /><br />"
."Password: <input type='password' name='password' /><br />"
."<input type='submit' value='Login' />"
."</form>";
}
$username = $_POST['username'];
$password = $_POST['password'];
?> |
Накрая скрипта ще изглежда така:
CODE1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| <?php
if (get_magic_quotes_gpc())
$_REQUEST = array_map('stripslashes', $_REQUEST);
$_GET = array_map('stripslashes', $_GET);
$_POST = array_map('stripslashes', $_POST);
$_COOKIE = array_map('stripslashes', $_COOKIE);
}
if(empty($_POST['username'])) {
echo "<form method='POST' action='login.php'>"
."Username: <input type='text' name='username' /><br />"
."Password: <input type='text' name='password' /><br />"
."<input type='submit' value='Login' />"
."</form>";
}
$username = $_POST['username'];
$password = $_POST['password'];
$link = @mysql_connect($dbhost, $dbuname, $dbpassword)
or die('Could not connect: ' . mysql_error());
mysql_select_db($mysqldb, $link)
or die('Could not select database.');
$query = mysql_query("SELECT * FROM `users` "
. "WHERE `username` = '"
. mysql_real_escape_string($username) . "' "
. "AND `password` = '"
. mysql_real_escape_string($password) . "'");
$row = mysql_fetch_assoc($query);
if((mysql_num_rows($query) == 1) && ($password == $row['password'])) {
echo "Hello {$row['username']}!<br />";
echo "Your credit card number is: {$row['creditcard']}";
}
?> |
Забележете последния „if()”. Очакваме само един ред. Това е добре, но таблицата ни с охота би приела 2 реда с еднакви имена и пароли. Просто поставете ограничение за уникалност на стойностите в колона „username” и проверка за грешка ( 1062: „Unique constraint violation” ) при INSERT.
И така login процеса е вече надеждно защитен от SQL инжекции.
Източник: codecall.net