Найти в Дзене
Kangaroo

SQL - инъекции, как защитить Django-проект?

Инъекция SQL - это широко распространенная атака, при проведении которой злоумышленник изменяет параметры веб-страницы (такие как данные в запросе GET/POST или в URL), чтобы ничего не подозревающее приложение выполнило неожиданный SQL-запрос к базе. Это очень опасная уязвимость. Такая уязвимость возникает, когда SQL-запрос строится вручную с использованием поступивших от пользователя данных. Представим что у нас есть форма в которую мы требуем ввести имя пользователя, чтобы узнать о нем больше. Однако в нашей функции, отвечающей за нахождение пользователя, используется прямой SQL-запрос: … user = request.GET['username']
sql = "SELECT * FROM user_data WHERE username = {}".format(user) … Подумайте, что произойдет, если злоумышленник введет в поле запроса строку " '' OR 'a'= 'a' ". Результатом станет такой SQL-запрос: SELECT * FROM user_data WHERE username = '' OR 'a' = 'a'; Поскольку мы допустили возможность добавления в строку произвольных данных, злоумышленник сумел добавить фразу OR

«Мы не должны просить наших пользователей, чтобы они сделали выбор между безопасностью и приватностью. Мы должны просто предложить им лучшее, что доступно в обеих этих областях. В конце концов, защита чьих-то данных — защита всех нас». Тим Кук
«Мы не должны просить наших пользователей, чтобы они сделали выбор между безопасностью и приватностью. Мы должны просто предложить им лучшее, что доступно в обеих этих областях. В конце концов, защита чьих-то данных — защита всех нас». Тим Кук

Инъекция SQL - это широко распространенная атака, при проведении которой злоумышленник изменяет параметры веб-страницы (такие как данные в запросе GET/POST или в URL), чтобы ничего не подозревающее приложение выполнило неожиданный SQL-запрос к базе. Это очень опасная уязвимость.

Такая уязвимость возникает, когда SQL-запрос строится вручную с использованием поступивших от пользователя данных. Представим что у нас есть форма в которую мы требуем ввести имя пользователя, чтобы узнать о нем больше. Однако в нашей функции, отвечающей за нахождение пользователя, используется прямой SQL-запрос:

user = request.GET['username']
sql = "SELECT * FROM user_data WHERE username = {}".format(user)

Подумайте, что произойдет, если злоумышленник введет в поле запроса строку " '' OR 'a'= 'a' ". Результатом станет такой SQL-запрос:

SELECT * FROM user_data WHERE username = '' OR 'a' = 'a';

Поскольку мы допустили возможность добавления в строку произвольных данных, злоумышленник сумел добавить фразу OR, и получившийся в результате запрос возвратит все строки таблицы.

А теперь давайте представим, что случится, если злоумышленник введет в поле строку:

" '' DELETE FROM user_data WHERE 'a' = 'a' "

Тогда получится такой запрос, состоящий из двух SQL-команд:

SELECT * FROM user_data WHERE username = ''
DELETE FROM user_data WHERE 'a' = 'a';
Фиаско! Мы потеряли все данные!
Фиаско! Мы потеряли все данные!

Решение.

Никогда не доверяйте данным, полученным от пользователя, и всегда экранируйте их перед вставкой в SQL-запрос.

API доступа к базе данных в Django выполняет подобную задачу: экранирует все параметры SQL-запроса, применяя соглашения об употреблении кавычек, действующие в используемой СУБД.

Например:

foo.get_list(bar__exact="'' OR 1=1")

Django экранирует входные данные, в результате чего формируется безопасный SQL-запрос. Поэтому, в Django, при обращении к базам данных, правильнее и безопаснее использовать API доступа к БД… Т.е. выборку данных о которой я уже упоминал.

Вот теперь все безопасно…
Вот теперь все безопасно…