* Валидиране на типовете данни при 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 за коментарите
Пусни коментар
Категории
- Бази от Данни (52)
- Вероятности (31)
- История (15)
- Кучета (69)
- Лада Нива (96)
- Математика (166)
- Методика (53)
- Общи работи (110)
- ПИК-3 Java (38)
- Политика (41)
- Програмни Среди (1)
- ПТСК (41)
- С/C++ (45)
- Семейни (16)
- Физика (35)
- ХHTML/JS (25)
- Храна (11)
Нови
- Извеждане на няколко произволни реда
- Full-Text търсене с InnoDB в MySQL
- Късметче от кафе
- Пред блока…
- Бушонно табло на Лада Нива
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” :)