В данном курсе я планирую рассказать о защите от SQL инъекций, так как до сих пор большое количество сайтов подвержено данному типу атак. Начнем мы курс с теории по внедрению sql кода, а затем перейдем к реализации на различных языках программирования.
SQL – инъекция – это уязвимость, которая возникает на стыке приложения и базы данных. При обращении к базе данных мы используем язык запросов SQL, но вызываем данные конструкции мы из кода приложения, путем подстановки значений, которые передал нам пользователь. Для того, чтобы разобраться в природе SQL уязвимостей рассмотрим конкретный пример. Допустим у нас существует некоторая база данных, которая содержит таблицу Users, в которой содержатся имена и пароли пользователей. Для того, чтобы проверить находится ли данный юзер в нашей базе данных мы используем sql запрос следующего вида:
1
|
SELECT * FROM Users WHERE Name = 'name' AND Password = 'password'
|
Где name и password значения переменных, которые пользователь передал нам через интерфейс программы. Обычно для того, чтобы вставить значения этих переменных в различных языках используется конкатенация строк.
Опасность SQL – Injection заключается в том, что если не проверять значения переменных, которые передает нам пользователь, то он может вместо имени(name) или любого другого значения передать нам управляющую последовательность SQL. Таким образом, если пользователь в нашем примере вместо имени укажет ‘ OR 1 = 1—
То наш запрос примет следующий вид:
1
|
SELECT * FROM Users WHERE Name = '' OR 1 = 1-- AND Password = 'password'
|
В языке SQL— обычно является комментарием и весь код, который расположен после него не выполнится. Следовательно данный запрос вернет нам всех пользователей, так как выражение 1 =1 всегда истинно. Обычно дальше в коде идет проверка на количество результатов, который выдает данный набор. Таким образом злоумышленник не зная ни имени, ни пароля сможет авторизоваться в нашей системе.
Рассмотрим процесс поиска и использования SQL инъекций на примере страницы news. Пусть данная страница получает на вход параметр id, который сообщает ей какую новость следует отобразить. Таким образом для того, чтобы отобразить первую новость параметр id нужно сделать равным единице. Все новости содержатся в таблице, которая имеет три поля: id, title, text. Допустим, что для отображении новости используется следующий запрос:
1
|
SELECT * FROM News WHERE ID = myid
|
Где myid переменная, которую нам передают через строку запроса на страницу. Тогда злоумышленник начнет поиск уязвимостей следующим образом. Сначала он попробует отдать некорректное значение переменной id, допустим id = 1′. Тогда в зависимости от защищенности приложения он сможет получить информацию об ошибке. Если ему вернется сообщения, что произошла ошибка в базе данных без дальнейших подробностей, то это будет хорошо, так как в противном случае он смог бы узнать о структуре запроса дополнительную информацию.
Для дальнейшего поиска уязвимостей хакер может использовать вычисляемые выражения: id = 2 – 1, тогда если данная SQL команда выполнится то, это будет говорить о наличие уязвимостей на сайте, которые можно использовать. После определения наличия уязвимости злоумышленник начнет анализ количества полей в запросе. Для этого он укажет заведомо неверный id и начнет объединять SELECT с другим запросом, который будет содержать null:
1
|
SELECT * FROM News WHERE ID = -1 UNION SELECT NULL, NULL, NULL
|
Количество null подбирают такое, чтобы приложение перестало выдавать ошибку. После подбора количества параметров в SQL запросе хакер выведет в них информацию, которая его интересует. Например:
1
|
id=-1 UNION SELECT 1, name, password FROM Users
|
Данный запрос выведет имя и пароль первого пользователя в таблице Users вместо ожидаемой новости.
Не только Select запросы являются уязвимыми. При регистрации пользователей с помощью следующей строки:
1
|
INSERT INTO Users (Name, Password, ROLE) VALUES (myname, mypassword, 0)
|
Где myname, mypassword передаются через форму регистрации. Тогда его можно модефицировать следующим образом:
1
|
INSERT INTO Users (Name, Password, ROLE) VALUES ('admin', '12345', 1), ( '1', '1', 0)
|
Таким образом мы смогли добавить в базу данных пользователя, который является администратором.
Таким же видам атак подвержены и другие операторы SQL.
|