<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://course.secsem.ru/w/index.php?action=history&amp;feed=atom&amp;title=%D0%92%D0%B5%D0%B1-%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C%2F%D0%A3%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8_SQLi</id>
	<title>Веб-безопасность/Уязвимости SQLi - История изменений</title>
	<link rel="self" type="application/atom+xml" href="https://course.secsem.ru/w/index.php?action=history&amp;feed=atom&amp;title=%D0%92%D0%B5%D0%B1-%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C%2F%D0%A3%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8_SQLi"/>
	<link rel="alternate" type="text/html" href="https://course.secsem.ru/w/index.php?title=%D0%92%D0%B5%D0%B1-%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C/%D0%A3%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8_SQLi&amp;action=history"/>
	<updated>2026-05-21T16:05:28Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>https://course.secsem.ru/w/index.php?title=%D0%92%D0%B5%D0%B1-%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C/%D0%A3%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8_SQLi&amp;diff=310&amp;oldid=prev</id>
		<title>Dzeni: /* Ссылки */</title>
		<link rel="alternate" type="text/html" href="https://course.secsem.ru/w/index.php?title=%D0%92%D0%B5%D0%B1-%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C/%D0%A3%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8_SQLi&amp;diff=310&amp;oldid=prev"/>
		<updated>2020-10-12T12:02:06Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Ссылки&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ru&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Предыдущая версия&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Версия от 12:02, 12 октября 2020&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l49&quot;&gt;Строка 49:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 49:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==Ссылки==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==Ссылки==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [https://drive.google.com/file/d/1dekLK3xKPO_zQ31W5aZ-FdpGF3pnhvjh/view?usp=sharing презентация &amp;quot;SQL injection&amp;quot;]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [https://drive.google.com/file/d/1dekLK3xKPO_zQ31W5aZ-FdpGF3pnhvjh/view?usp=sharing презентация &amp;quot;SQL injection&amp;quot;]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [https://yadi.sk/d/o4cFtxls-WlUAw?w=1 видео &quot;SQL injection&quot;]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [https://yadi.sk/d/o4cFtxls-WlUAw&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;/%D0%A1%D0%B5%D0%BC%D0%B8%D0%BD%D0%B0%D1%80%203.%2001%20%D0%BE%D0%BA%D1%82%D1%8F%D0%B1%D1%80%D1%8F.mp4&lt;/ins&gt;?w=1 видео &quot;SQL injection&quot;]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Dzeni</name></author>
	</entry>
	<entry>
		<id>https://course.secsem.ru/w/index.php?title=%D0%92%D0%B5%D0%B1-%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C/%D0%A3%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8_SQLi&amp;diff=302&amp;oldid=prev</id>
		<title>Dzeni: Новая страница: «== SQL Injection ==  Веб-приложения нередко используют SQL-базы данных, т. е. такие БД, взаимодейств…»</title>
		<link rel="alternate" type="text/html" href="https://course.secsem.ru/w/index.php?title=%D0%92%D0%B5%D0%B1-%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D1%81%D1%82%D1%8C/%D0%A3%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8_SQLi&amp;diff=302&amp;oldid=prev"/>
		<updated>2020-10-12T09:55:19Z</updated>

		<summary type="html">&lt;p&gt;Новая страница: «== SQL Injection ==  Веб-приложения нередко используют SQL-базы данных, т. е. такие БД, взаимодейств…»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== SQL Injection ==&lt;br /&gt;
&lt;br /&gt;
Веб-приложения нередко используют SQL-базы данных, т. е. такие БД, взаимодействие с которыми осуществляется через запросы на языке SQL ([https://ru.wikipedia.org/wiki/SQL Википедия]). Поиграться с SQL можно просто в [http://sqlfiddle.postgrespro.ru/#!17//5814 SQL Fiddle] или с помощью [https://linux.die.net/man/1/sqlite3 sqlite3].&lt;br /&gt;
&lt;br /&gt;
Веб-приложение формирует и отправляет базе SQL-запросы, которые могут зависеть от параметров, пришедших от клиента (взятых из HTTP-запроса). SQL-запросы текстовые и простой способ сделать запрос, зависящий от параметра - просто подставить этот параметр в текст запроса. Пример кода (на языке [https://www.python.org/ Python]), подставляющего параметр из HTTP-запроса в SQL-запрос к базе:&lt;br /&gt;
[[Файл:Sqli-code.png|650px]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt; &lt;br /&gt;
Здесь &amp;quot;request.args.get(&amp;#039;login&amp;#039;)&amp;quot; считывает значение параметра &amp;quot;login&amp;quot; query string запроса. Вот какой вид примет запрос, если параметр login будет иметь значение &amp;quot;testuser&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[File:Sql-req.png|650px]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt; &lt;br /&gt;
Значение &amp;quot;testuser&amp;quot; подставилось в строковый литерал в одинарных кавычках. Говорят, что значение попало в контекст строкового литерала. После такой подстановки может оказаться, что смысл SQL-запроса изменился и данные, подставленые в запрос стали не просто значением параметра запроса (скажем, числовым или стокововым литералом), а какими-то еще конструкциями языка SQL. Вот какой запрос будет сформирован, если параметр &amp;quot;login&amp;quot; будет иметь значение &amp;lt;code&amp;gt;&amp;#039; or 1=1 --&amp;lt;/code&amp;gt;:&lt;br /&gt;
[[File:Sqli-annot.png|650px]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
В результате выражение в &amp;lt;code&amp;gt;WHERE&amp;lt;/code&amp;gt;-части приняло вид &amp;lt;code&amp;gt;login=&amp;lt;nowiki&amp;gt;&amp;#039;&amp;#039;&amp;lt;/nowiki&amp;gt; or 1=1&amp;lt;/code&amp;gt;, оно будет истинным для любой строки таблицы, в результате чего в ответ на этот запрос будут возвращены все строки таблицы. Так же можно изменить смысл запроса и передав специфическое значение параметра id для этого кода (для этого даже не придётся добавлять в значение параметра кавычку):&lt;br /&gt;
[[File:Sql-id.png|650px]]&lt;br /&gt;
&amp;lt;br clear=all&amp;gt;&lt;br /&gt;
Возможность передать такое значение параметра HTTP-запроса, которое подставится в текст SQL-запроса и при подстановке изменит смысл этого запроса называется &amp;#039;&amp;#039;&amp;#039;SQL injection&amp;#039;&amp;#039;&amp;#039; ([https://www.owasp.org/index.php/SQL_Injection OWASP]). Хорошие статьи про SQL injection можно найти [https://rdot.org/forum/showthread.php?s=f4292383c9896b773bd98d827eb9411f&amp;amp;t=124 тут] и еще [http://pentestmonkey.net/cheat-sheet/sql-injection/mysql-sql-injection-cheat-sheet тут].&lt;br /&gt;
&lt;br /&gt;
Фактически, SQLi это один из представителей класса уязвимостей injection, которые получаются, если в какие-то управляющие команды подставляются параметры-данные от пользователя и эти данные могут выйти из контекста, куда подставляются, перестав быть просто данными, и поменять смысл команды.&lt;br /&gt;
&lt;br /&gt;
== Полезные трюки ==&lt;br /&gt;
&lt;br /&gt;
=== SQL-комментарий ===&lt;br /&gt;
Супер простой трюк. В конце своей инъекции можно добавить символы однострочного SQL-комментария, тогда всё что идет дальше (как правило, остаток исходного SQL-запроса) будет считаться комментарием и проигнорируется. В разных БД символы комментария могут разными, см. документацию, чаще всего это двойной минус &amp;lt;code&amp;gt;--&amp;lt;/code&amp;gt; и/или решетка &amp;lt;code&amp;gt;#&amp;lt;/code&amp;gt;, также бывает классический двойной слеш &amp;lt;code&amp;gt;//&amp;lt;/code&amp;gt;. Фактически, этот трюк уже был использован в примере в предыдущем разделе, двойной минус в конце там заставил базу данных проигнорировать оставшуюся от исходного запроса одинарную кавычку в конце.&lt;br /&gt;
&lt;br /&gt;
=== UNION SELECT ===&lt;br /&gt;
Очень полезным может быть &amp;lt;code&amp;gt;UNION&amp;lt;/code&amp;gt; ([https://ru.wikipedia.org/wiki/Union_(SQL) вики],[https://www.postgresql.org/docs/current/typeconv-union-case.html доки postgres]), который позволяет присоединить к результату одного &amp;lt;code&amp;gt;SELECT&amp;lt;/code&amp;gt; запроса результат еще одного. Если инъекция в операторе &amp;lt;code&amp;gt;SELECT&amp;lt;/code&amp;gt; (что в реальности довольно часто), с помощью &amp;lt;code&amp;gt;UNION&amp;lt;/code&amp;gt; можно добавить в его результат вывод нового, полностью написанного атакующим &amp;lt;code&amp;gt;SELECT&amp;lt;/code&amp;gt; - запроса из другой таблицы, с другими колонками, условиями и т. д.&lt;br /&gt;
Чтобы &amp;lt;code&amp;gt;UNION&amp;lt;/code&amp;gt; сработал, требуется чтобы количество и типы колонок совпадали. Помочь с этим может то что в SQL можно писать на месте колонок просто константы (и тогда они просто проставятся на эти места в каждой из строк результата запроса) и то что чаще всего можно использовать вместо любого значения &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt;. Если количество колонок в исходном запросе неизвестно, можно просто подбирать его.&lt;br /&gt;
&lt;br /&gt;
Еще при использовании &amp;lt;code&amp;gt;UNION&amp;lt;/code&amp;gt; бывает проблема что код приложения отдаёт не все строки результата, а только часть, например только первую (так обычно бывает когда разработчик предполагал что запрос вернет только одну строку). В этом случае можно просто сделать невыполнимое условие в &amp;lt;code&amp;gt;WHERE&amp;lt;/code&amp;gt; исходного запроса - тогда он вернёт 0 строк и в выдачу попадёт строка из присоединенного &amp;lt;code&amp;gt;SELECT&amp;lt;/code&amp;gt;&amp;#039;а.&lt;br /&gt;
&lt;br /&gt;
=== Метаданные ===&lt;br /&gt;
Как правило, при эксплуатации SQL injection мешает то что неизвестны имена таблиц, имена и типы колонок. Может помочь то что в современных базах данных как правило есть специальные таблицы с метаданными, которые содержат всю схему данных базы. У разных СУБД эти таблицы называются и устроены по-разному, про их устройство можно почитать в документации. Например, у MySQL таблицы с метаданными хранятся в базе &amp;lt;code&amp;gt;INFORMATION_SCHEMA&amp;lt;/code&amp;gt;([https://dev.mysql.com/doc/refman/8.0/en/information-schema.html документация]) - информация о существующих базах данных лежит в таблице &amp;lt;code&amp;gt;SCHEMATA&amp;lt;/code&amp;gt;, о таблицах - в &amp;lt;code&amp;gt;TABLES&amp;lt;/code&amp;gt;, о колонках - в &amp;lt;code&amp;gt;COLUMNS&amp;lt;/code&amp;gt; и так далее.&lt;br /&gt;
&lt;br /&gt;
=== Fingerprinting ===&lt;br /&gt;
Для атаки бывает необходимо понимать, какая именно СУБД используется - чтобы понимать, как называются таблицы с метаданными какие функции/механизмы/особенности БД можно использовать и т. д. Если из других источников (скажем, доступных исходных кодов приложения или вывода приложением подробной информации о себе) узнать, какая СУБД, не удаётся, это можно узнать от неё самой. Во-первых, если выдаются SQL-ошибки, часто по виду ошибки, который обычно содержит числовой идентификатор, можно однозначно определить базу. Если даже ошибки не выводятся, зафингерпринтить базу можно по её реакции на конструкции SQL, которые работают только в некоторых базах или работают в разных БД по-разному. Яркими примерами является то что в MySQL можно в качестве строковой колонки указать переменную &amp;lt;code&amp;gt;@@version&amp;lt;/code&amp;gt; и функцию &amp;lt;code&amp;gt;version()&amp;lt;/code&amp;gt; и на её место в обоих случаях подставится версия базы, в PostgreSQL и SQLite оператор &amp;lt;code&amp;gt;||&amp;lt;/code&amp;gt; работает как оператор конкатенации строк, при этом в PostgreSQL поддерживается база &amp;lt;code&amp;gt;information_schema&amp;lt;/code&amp;gt;, а в SQLite - нет. Почитать про database fingerprinting можно на [https://www.owasp.org/index.php/OWASP_Backend_Security_Project_DBMS_Fingerprint OWASP], [https://null-byte.wonderhowto.com/how-to/sql-injection-101-fingerprint-databases-perform-general-reconnaissance-for-more-successful-attack-0184562/ здесь], и еще много где, это довольно легко гуглится.&lt;br /&gt;
&lt;br /&gt;
=== Error-based вывод ===&lt;br /&gt;
В случае, если мы в ответ сервера не выводятся данные, полученные из SQL-запроса, но выводятся ошибки, вытаскивать информацию бывает всё равно можно - через сообщения об ошибке. Про это написано в [https://intsystem.org/security/error-based-sql-injection-in-mysql/ этой статье], [https://xakep.ru/2010/05/27/52222/ ещё этой], [https://habr.com/ru/post/235287/ этой] и еще много где.&lt;br /&gt;
Кстати, если даже не выводится ошибка, а есть только бинарный признак (приложение даёт в зависимости от полученных из SQL-запроса данных ответ да/нет) и даже если нет и его вытягивать данные всё равно можно. Как именно - задача на подумать или нагуглить -).&lt;br /&gt;
&lt;br /&gt;
=== Stacked queries ===&lt;br /&gt;
Иногда бывает можно в одном запросе от приложения к базе данных передать несколько SQL-запросов через &amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;. В этом случае SQL injection позволяет сделать уже вообще любой SQL-запрос. Доступность stacked queries зависит от БД и используемого драйвера, к примеру c базами sqlite3 и MySQL обычно нельзя, с базой PostgreSQL и стандартным питоновским драйвером &amp;#039;&amp;#039;&amp;#039;psycopg2&amp;#039;&amp;#039;&amp;#039; - можно.&lt;br /&gt;
&lt;br /&gt;
=== Изменения в БД ===&lt;br /&gt;
Часто клиентские библиотеки для баз данных (драйверы) при выполнении SQL-запроса автоматически начинают новую транзакцию (выполняя оператор BEGIN). Любые изменения, сделанные SQL-запросом в транзакции, не будут видны за пределами текущей транзакции, пока она не будет успешно завершена (оператором &amp;lt;code&amp;gt;COMMIT&amp;lt;/code&amp;gt;). Однако, если программист делал запрос, достающий что-то из базы, то есть &amp;lt;code&amp;gt;SELECT&amp;lt;/code&amp;gt;, ему не нужно применять никакие изменения и вполне возможно он не делал COMMIT после своего запроса - поэтому, даже если вставить какой то изменяющий базу запрос после &amp;lt;code&amp;gt;SELECT&amp;lt;/code&amp;gt;&amp;#039;а, он не повлияет на ее состояние, так как не будет подтверждена транзакция. (Про то как это работает в [http://initd.org/psycopg/docs/connection.html#connection.commit доках psycopg2], см. про функции commit и close). Однако, эту проблему можно (по крайней мере в некоторых случаях) победить - если работают stacked queries, можно просто вставить после своего запроса оператор &amp;lt;code&amp;gt;COMMIT&amp;lt;/code&amp;gt;, и это приведет к подтверждению транзакции (&amp;lt;code&amp;gt;SELECT ... WHERE ... ; INSERT INTO ... ; COMMIT; --&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
* [https://drive.google.com/file/d/1dekLK3xKPO_zQ31W5aZ-FdpGF3pnhvjh/view?usp=sharing презентация &amp;quot;SQL injection&amp;quot;]&lt;br /&gt;
* [https://yadi.sk/d/o4cFtxls-WlUAw?w=1 видео &amp;quot;SQL injection&amp;quot;]&lt;/div&gt;</summary>
		<author><name>Dzeni</name></author>
	</entry>
</feed>