* Валидиране на типовете данни при SQL
Публикувано на 30 ноември 2008 в раздел ПТСК.
Дотук разгледахме най-често срещаният проблем, позволяващ вмъкване на нежелан SQL код – лошо филтриране на входните данни. Отбелязахме, че е по-добре да даваме множество от позволени стойности на входните данни, а не просто да забраняваме непозволените символи. За да обясним защо ще демонстрираме чрез пример, в който няма да използваме кавички при изпълнение на заявката. Нека например изпращаме следната заявка:
$sql = "SELECT * FROM stats WHERE id=$id"
В случая полето с име „id“ е от тип int и поради тази причина не е нужно ограждането на стойността в кавички. Ако подадем например числото „5″ ще се генерира следната заявка към базата от данни:
SELECT * FROM stats WHERE id=5;
Ако обаче подадем „23 OR 1=1″ ще се получи:
SELECT * FROM stats WHERE id=23 OR 1=1;
Тази заявка очевидно е винаги валидна и ще изкара всички данни от базата от данни. В нея не използвахме нито един непозволен символ. Възможностите за пробив са много, в зависимост от вида на заявката. При заявка от тип UPDATE или DELETE например може да се достигне до фатални за базата от данни резултати.
Как да се защитим? Отговорът е ясен – валидирайте не само подадените символи, но и самите типове данни:
if(is_numeric($id){
$sql = "SELECT * FROM stats WHERE id=$id"
...
}
else{
echo "Are you trying to do SQL injection?";
exit();
}
Възможно е и използване на вградените функции на сървъра за база от данни, но на практика е по-добре да валидирате в собственото приложение (а защо не и по двата начина?).
Друга широко използвана практика е използването на процедури на сървъра за базата от данни, вместо подаването на директни заявки. Тази практика не винаги може да гарантира коректно филтриране!
Отново ще припомним и едно друго, вече споменато основно правило за базите от данни – давайте толкова привилегии на потребителя, колкото са му нужни! Грешен подход е да имаме един потребител за базата от данни, който се използва за всички видове заявки.
2 коментара за “Валидиране на типовете данни при SQL”
Trackback URI | RSS за коментарите
Пусни коментар
Категории
- Бази от Данни (39)
- Вероятности (30)
- История (14)
- Кучета (67)
- Лада Нива (91)
- Математика (159)
- Методика (52)
- Общи работи (107)
- ПИК-3 Java (38)
- Политика (40)
- Програмни Среди (1)
- ПТСК (37)
- С/C++ (45)
- Семейни (15)
- Физика (35)
- ХHTML/JS (25)
- Храна (11)
Нови
- Как да разрежем хляба?
- Здравей бебе!
- Какво означават метеорологичните кодове?
- Берра проправя пътеки
- Задача от YES
28 януари 2011 на 17:42
Когато се очаква дадена променлива да е число, я минавам през (int). Примерно $id = (int)$_GET['id] и тя се превръща съответно в число. Това е малко по-бързо отколкото да се ползват готови функции от рода на intval() и is_nummeric. Ако пък се очаква да са някакви символи ги минавам през mysql_real_escape_string(). Евентуално, ако ще се добавя в базата данни някаква информация, е хубаво да се минава през функции за обезвреждане на html таговете от рода на strip_tags. Аз ползвам точно нея и ми изглежда сигурна.
28 януари 2011 на 18:19
О, не – това, което правиш не е добре. Пробвай например „echo (int)“1234abcd“;“. Резултатът е „1234″. Това няма да счупи SQL заявката, да. Но има един основен въпрос: „след като знаем, че дадена променлива е с невалидни данни, то защо въобще трябва да се изпълнява SQL заявка?“. И тук спорът приключва в полза на „is_numeric“ :)