# Занятие 2. SQL injection. ###### tags: `Intro to Web Security` ![](https://i.imgur.com/Wgm6kqA.png) #### Материалы и описание для самостоятельного изучения: - язык SQL - [Что такое SQL и как он работает](https://gb.ru/posts/chto-takoe-sql-i-kak-on-rabotaet) - [w3schools](https://www.w3schools.com/sql/default.asp) - [sql-ex](https://sql-ex.ru) - инъекции SQL - [PortSwigger academy](https://portswigger.net/web-security/sql-injection) - [sqlinjection.net](https://www.sqlinjection.net/tutorial/) - [hacksplaining.com](https://www.hacksplaining.com/lessons) ## Слепая SQL инъекция Возникает, когда приложение уязвимо для инъекции SQL, но его HTTP-ответы не содержат результатов соответствующего SQL-запроса или сведений о каких-либо ошибках базы данных. С уязвимостями слепой SQL инъекции многие методы, например UNION attacks, неэффективны, поскольку они основаны на возможности видеть результаты введенного запроса в ответах приложения. Все еще возможно использовать слепую инъекцию SQL для доступа к несанкционированным данным, но необходимо использовать другие методы. ![](https://i.imgur.com/2x89Omf.png) ## Использование слепой инъекции SQL путем запуска условных ответов Рассмотрим приложение, которое использует cookie отслеживания для сбора аналитических данных об использовании. Запросы к приложению включают заголовок cookie, подобный этому: `Cookie: TrackingId=u5YD3PapBcR4lN3e7Tj4` Когда обрабатывается запрос, содержащий TrackingId cookie, приложение определяет, действительный ли этот пользователь, используя такой SQL-запрос: `SELECT TrackingId FROM TrackedUsers WHERE TrackingId = 'u5YD3PapBcR4lN3e7Tj4'` Этот запрос уязвим для SQLi, но результаты запроса не возвращаются пользователю. Однако приложение ведет себя по-разному в зависимости от того, возвращает ли запрос какие-либо данные. Если он возвращает данные (поскольку был отправлен распознанный идентификатор отслеживания), то на странице будет отображаться сообщение. Этого поведения достаточно, чтобы использовать уязвимость слепой инъекции SQL и извлекать информацию, вызывая различные ответы, в зависимости от введенного условия. ![](https://i.imgur.com/JgmmETT.png) ## Получение условных ответов путем запуска ошибок SQL В следующем примере предположим, что приложение выполняет один и тот же SQL-запрос, но не ведет себя по-разному в зависимости от того, возвращает ли запрос какие-либо данные. Предыдущий метод не будет работать, потому что введение различных логических условий не влияет на ответы приложения. В этой ситуации часто можно заставить приложение возвращать условные ответы, вызывая ошибки SQL условно, в зависимости от введенного условия. Это включает в себя изменение запроса таким образом, чтобы он вызывал ошибку базы данных, если условие истинно, и не вызывал если условие ложно. Очень часто необработанная ошибка, вызванная базой данных, вызывает некоторую разницу в ответе приложения (например, сообщение об ошибке), что позволяет нам сделать вывод об истинности введенного условия. ![](https://i.imgur.com/tJpQvye.png) ## Использование слепой инъекции SQL путем запуска временных задержек Предположим, что приложение теперь улавливает ошибки базы данных и корректно их обрабатывает. Запуск ошибки базы данных при выполнении введенного SQL-запроса больше не вызывает никаких изменений в ответе приложения, поэтому предыдущий метод создания условных ошибок не будет работать. В этой ситуации часто можно использовать уязвимость слепой инъекции SQL, вызывая временные задержки условно, в зависимости от введенного условия. Поскольку SQL-запросы обычно обрабатываются приложением синхронно, задержка выполнения SQL-запроса также приведет к задержке HTTP-ответа. Это позволяет нам сделать вывод об истинности введенного условия на основе времени, затраченного до получения HTTP-ответа. ![](https://i.imgur.com/G8XZwch.png) ## Использование слепой инъекции SQL с использованием out-of-band (OAST) Теперь предположим, что приложение выполняет один и тот же SQL-запрос, но делает это асинхронно. Приложение продолжает обработку запроса пользователя в исходном потоке и использует другой поток для выполнения SQL-запроса с использованием отслеживания cookie. Запрос по-прежнему уязвим для внедрения SQL, однако ни один из методов, описанных до сих пор, не будет работать: ответ приложения не зависит от того, возвращает ли запрос какие-либо данные, или от того, возникает ли ошибка базы данных, или от времени, затраченного на выполнение запроса. В этой ситуации часто можно воспользоваться уязвимостью слепой инъекции SQL, запустив out-of-band сетевое взаимодействие с системой, которой вы управляете. Как и ранее, они могут запускаться условно, в зависимости от введенного условия, для вывода информации по одному биту за раз. Но что еще более важно, данные могут быть эксфильтрированы непосредственно в рамках самого сетевого взаимодействия. Для этой цели можно использовать различные сетевые протоколы, но, как правило, наиболее эффективным является DNS (служба доменных имен). Это связано с тем, что очень многие производственные сети допускают свободный выход DNS-запросов, поскольку они необходимы для нормальной работы производственных систем. ![](https://i.imgur.com/XT2MZba.png) ## Как предотвратить слепые атаки SQL-инъекций? Хотя методы, необходимые для поиска и использования уязвимостей слепой инъекции SQL, отличаются и более сложны, чем для обычной инъекции SQL, меры, необходимые для предотвращения инъекции SQL, одинаковы независимо от того, является ли уязвимость слепой или нет. Как и в случае обычной SQL-инъекции, слепые атаки SQL-инъекции можно предотвратить за счет тщательного использования параметризованных запросов, которые гарантируют, что вводимые пользователем данные не могут повлиять на структуру предполагаемого SQL-запроса. ![](https://i.imgur.com/hMwRBIc.png) ## Как предотвратить внедрение SQL Большинство случаев внедрения SQL можно предотвратить, используя параметризованные запросы (также известные как подготовленные операторы) вместо объединения строк в запросе. Следующий код уязвим для внедрения SQL, поскольку вводимые пользователем данные объединяются непосредственно в запрос: `String query = "SELECT * FROM products WHERE category = '"+ input + "'";` `Statement statement = connection.createStatement();` `ResultSet resultSet = statement.executeQuery(query);` Этот код можно легко переписать таким образом, чтобы пользовательский ввод не мешал структуре запроса: `PreparedStatement statement = connection.prepareStatement("SELECT * FROM products WHERE category = ?");` `statement.setString(1, input);` `ResultSet resultSet = statement.executeQuery();` ![](https://i.imgur.com/TRrIxxj.png) ## Вывод Чтобы параметризованный запрос эффективно предотвращал внедрение SQL, строка, используемая в запросе, всегда должна быть жестко запрограммированной константой и никогда не должна содержать никаких переменных данных из любого источника. Слишком легко ошибиться в отношении возможного происхождения данных или внести изменения в другой код, чтобы нарушить предположения о том, какие данные испорчены. ![](https://i.imgur.com/6ppVAmb.png) ## Домашнее задание ### 1. Практика на PortSwigger > Сдавать преподавателю в лс ВКонтакте - [Влад Соколов](https://vk.com/vavizh) Решить лабу ["Атака с использованием SQL-инъекции, перечисляющая содержимое базы данных в бд, отличных от Oracle"](https://portswigger.net/web-security/sql-injection/examining-the-database/lab-listing-database-contents-non-oracle)