SQL injection: как се проверява и защитава уеб приложение
Какво е SQL injection, пример с уязвима заявка, до какви данни може да стигне нападателят и как параметризираните заявки и ограничените права предотвратяват атаката.
SQL injection е уязвимост, при която въведен от потребителя текст става част от заявка към базата данни. Тя е сред най-старите и най-добре описаните уязвимости в уеб приложенията и присъства във всяко издание на OWASP Top 10. Въпреки това продължава да се среща, най-често в стари системи, собствени разработки и набързо написани интеграции.
Пример
Формулярът за вход проверява потребителя със заявка, сглобена от текст:
SELECT * FROM users WHERE email = '<въведен имейл>' AND password_hash = '<хеш>'
Ако в полето за имейл се въведе admin@example.com' --, кавичката затваря текста, а -- превръща останалата част от заявката в коментар. Проверката на паролата изчезва и приложението пуска нападателя в профила на администратора.
До какво може да стигне нападателят
Това зависи от правата на потребителя, с който приложението се свързва с базата данни:
- четене на цели таблици: клиенти, поръчки, хешове на пароли;
- промяна или изтриване на данни;
- при прекалено широки права и неправилно настроен сървър: четене на файлове или изпълнение на команди на сървъра.
Изтичането на клиентска база по този начин е нарушение на сигурността на личните данни. В повечето случаи то трябва да бъде съобщено на КЗЛД в срок от 72 часа.
Защита
-
Използвайте параметризирани заявки (prepared statements) навсякъде. Стойността се подава отделно от текста на заявката и базата данни никога не я изпълнява като код:
db.QueryRow("SELECT id FROM users WHERE email = $1", email)ORM библиотеките правят това по подразбиране, но повечето позволяват и ръчно написани заявки, в които уязвимостта се връща.
-
Когато част от заявката не може да бъде параметър, например име на колона за сортиране, допускайте само стойности от предварително определен списък.
-
Приложението се свързва с потребител, който има достъп само до своите таблици и само до нужните операции. Администраторският потребител на базата данни не се използва от приложението.
-
Не показвайте на посетителите грешките от базата данни. Те разкриват структурата на таблиците и улесняват атаката.
-
Защитната стена за уеб приложения (WAF) спира известните шаблони на атаки, но е само допълнителен слой. Уязвимият код остава уязвим.
-
Хеширайте паролите с Argon2id или bcrypt, за да не могат да бъдат използвани веднага, ако таблицата изтече. Подробности има в статията за разбиването на пароли.
Как се проверява
При проверка на приложение се тестват всички входни точки: полета във формуляри, параметри в адресите, бисквитки, HTTP заглавки и API заявки. Автоматични инструменти като sqlmap намират очевидните случаи. Сляпата SQL injection, при която приложението не връща данни, а само реагира различно на заявките, често се открива при ръчна проверка и преглед на кода.