SQL injection: как се проверява и защитава уеб приложение

Какво е SQL injection, пример с уязвима заявка, до какви данни може да стигне нападателят и как параметризираните заявки и ограничените права предотвратяват атаката.

OfSec 3 мин. четене

SQL injection е уязвимост, при която въведен от потребителя текст става част от заявка към базата данни. Тя е сред най-старите и най-добре описаните уязвимости в уеб приложенията и присъства във всяко издание на OWASP Top 10. Въпреки това продължава да се среща, най-често в стари системи, собствени разработки и набързо написани интеграции.

Пример

Формулярът за вход проверява потребителя със заявка, сглобена от текст:

SELECT * FROM users WHERE email = '<въведен имейл>' AND password_hash = '<хеш>'

Ако в полето за имейл се въведе admin@example.com' --, кавичката затваря текста, а -- превръща останалата част от заявката в коментар. Проверката на паролата изчезва и приложението пуска нападателя в профила на администратора.

До какво може да стигне нападателят

Това зависи от правата на потребителя, с който приложението се свързва с базата данни:

  • четене на цели таблици: клиенти, поръчки, хешове на пароли;
  • промяна или изтриване на данни;
  • при прекалено широки права и неправилно настроен сървър: четене на файлове или изпълнение на команди на сървъра.

Изтичането на клиентска база по този начин е нарушение на сигурността на личните данни. В повечето случаи то трябва да бъде съобщено на КЗЛД в срок от 72 часа.

Защита

  1. Използвайте параметризирани заявки (prepared statements) навсякъде. Стойността се подава отделно от текста на заявката и базата данни никога не я изпълнява като код:

    db.QueryRow("SELECT id FROM users WHERE email = $1", email)
    

    ORM библиотеките правят това по подразбиране, но повечето позволяват и ръчно написани заявки, в които уязвимостта се връща.

  2. Когато част от заявката не може да бъде параметър, например име на колона за сортиране, допускайте само стойности от предварително определен списък.

  3. Приложението се свързва с потребител, който има достъп само до своите таблици и само до нужните операции. Администраторският потребител на базата данни не се използва от приложението.

  4. Не показвайте на посетителите грешките от базата данни. Те разкриват структурата на таблиците и улесняват атаката.

  5. Защитната стена за уеб приложения (WAF) спира известните шаблони на атаки, но е само допълнителен слой. Уязвимият код остава уязвим.

  6. Хеширайте паролите с Argon2id или bcrypt, за да не могат да бъдат използвани веднага, ако таблицата изтече. Подробности има в статията за разбиването на пароли.

Как се проверява

При проверка на приложение се тестват всички входни точки: полета във формуляри, параметри в адресите, бисквитки, HTTP заглавки и API заявки. Автоматични инструменти като sqlmap намират очевидните случаи. Сляпата SQL injection, при която приложението не връща данни, а само реагира различно на заявките, често се открива при ръчна проверка и преглед на кода.

Уеб приложенияЗащита на данни