Подмена Content-Type даёт власть над миром

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

Был обычный зимний вечер. Я, как обычно, сидел за машиной, пил n-ю за день кружку кофе и слушал power-metal. Заказов в данный момент не имелось, так что я откровенно бездельничал.

Блуждая по инету в поисках порн... в поисках свежих скриптов, я между делом зашёл на сайт одной конторы, с которой в своё время сотрудничал. Насколько мне не изменяла память, ребята к вопросам безопасности относились довольно халатно ("не такая уж мы важная птица, чтоб нас ломать"). Я вообще-то человек добрый и к вредительству не склонный, однако, как известно, внутри каждого нормального программера живёт зародыш весьма тёмного существа, которое, если ему не противиться, в один прекрасный день превратит тебя в злого хацкера (или, по крайней мере, в его подобие). В тот вечер тёмная сторона Силы взяла верх, и я решил проверить бывших коллег "на вшивость".

Первым шагом на пути к заветной цели стало изучение структуры каталогов на сервере. Для этого была установлена волшебная программка под названием lftp, которая вообще-то является разновидностью консольного ftp-клиента, но может использоваться и для подключений к http-серверам. И в ней имеется команда ls - аналог той ls, что выдаёт список файлов в текущем каталоге. Препятствий на этом этапе не возникало абсолютно никаких - нога .htaccess явно здесь не ступала, а если и ступала, то без опций Options -Indexes и Allow/Deny.

Теперь картина немного прояснилась. На серваке присутствовала папочка, в которой местный народ складывал для тестирования различные скрипты - игры, календари, мини-фотогалереи etc. И всё это добро было доступно для выполнения всем желающим - а точнее, тем, кто найдёт.

Среди всего прочего обнаружился простенький PHP-скриптик под названием img_upload. Как следует из названия, это скрипт загрузки изображений на сервер. В моей голове сразу же шевельнулась гадкая вредительская мыслишка относительно того, как сие творение можно использовать не совсем по назначению. И я, не мудрствуя лукаво, нагло вставил в форму отправки вместо картинки файл с расширением *.php. И попытался отправить. Естественно, ничего из этого не вышло (я ничего и не ожидал, но попробовать стоило :)).

Тогда я потратил несколько минут на то, чтобы найти и скачать исходники вышеупомянутого скрипта. Изучение кода показало, что скрипт исправно проверяет заголовок Content-Type для загружаемого файла, который в данном случае обязательно должен быть равен "image/jpeg", "image/gif" или "image/png". Этим "суперзащита от хакеров" и ограничивалась. Ещё минут 10 было потрачено на гугление относительно Content-Type и того, как его можно использовать в своих целях. После этого было, наконец, принято решение действовать, запущен апач и изготовлен в домашних условиях следующий скриптик на Perl:

Код:

#!/usr/bin/perl
#
use LWP;
use HTTP::Request::Common;
$ua = LWP::UserAgent->new;;
$res = $ua->request(POST 'http://target-server/gallery/upload.php',
Content_Type => 'form-data',
Content => [filename => ["mywebadmin.php", "mywebadmin.php", "Content-Type" =>"image/jpeg"],],);

print $res->as_string();


Небольшой экскурс по коду. Мы используем класс UserAgent из библиотеки LWP (The World-Wide Web library for Perl), который позволяет выполнять HTTP-запросы к удалённому серверу и при этом даёт нам полный контроль над параметрами запроса. Первым делом мы указываем тип запроса - POST и путь к нашему скрипту загрузки. Строкой


Код:
Content_Type => 'form-data',

мы указываем тип передаваемых данных form-data (аналогично указанию атрибута enctype=multipart/form-data для HTML-формы). Это позволит нам загружать файлы. "filename" - это имя параметра в POST-запросе, который указывает на наш файл. Собственно, файл, который мы будем загружать - mywebadmin.php, является смесью удалённого шелла и файл-менеджера, также написанного мною на скорую руку за пару дней до этого. Ну, и заголовком Content-Type, принимающим значение "image/jpeg", мы говорим серверу: "Это типа рисунок, всё нормально, нечего переживать" :D Ну, а последняя строчка просто выводит ответ сервера (в данном случае не очень-то и нужно).

Итак, после исправления пары мелких ошибок и запуска скрипта я открыл в браузере папку с рисунками и убедился, что мой файл (о чудо) успешно загружен. Надо сказать, тут всё было сделано по-умному - при сохранении в начало имени файла дописывалось случайное число, и я бы фиг догадался, как именно называется мой файл... если бы, как я уже говорил, все папки на сервере не были доступны для просмотра.

После этого я, радуясь своей маленькой победе, запустил мой mywebadmin.php и убедился, что могу с его помощью успешно и безнаказанно выполнять команды и операции с файлами на сервере (естественно, в пределах прав пользователя, от имени которого выполняется apache). Позже, после блуждания уже с помощью этого скрипта по вышеупомянутым папкам и просмотра исходников обнаружилось несколько файликов а-ля config.inc.php, в которых хранились... правильно, логины и пароли к mysql.

Последнее событие этого своеобразного "эпоса" было вообще, что называется, из ряда вон. Глубоко в недрах файловой системы обнаружился скрипт, который (насколько я помнил) должен был запускаться через крон, к тому же с правами root'а, и имел при этом (о чудо) волшебные права доступа 777 (это, наверное, чтоб каждый раз sudo не писать, когда надо в нём что-то изменить :D ). Естественно, моё темное "я", радуясь возможности в кои-то веки сотворить ещё что-нибудь плохое, слегка подправило пару строчек в коде скрипта. Вследствие этого после следующего его запуска (а запускался он раз в полчаса) в индексном файле phpMyAdmin'а появилось пару лишних строчек, которые, в свою очередь, позже дали мне возможность "подсмотреть" root'овский пароль для mysql. Который, как я смутно и подозревал, оказался также паролем для удалённого доступа по ssh. Вот такие-то пироги...

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

Собственно, мораль сей басни такова:

1. Внимательно смотрите, что вы пишите в ваших скриптах. Они могут сработать совсем не так и не с той целью, как вы то изначально планируете...
2. Не приуменьшайте своё значение в глазах потенциальных взломщиков ("Да кому оно надо, ломать нас?..") Уж кому-то да надо...
3. Не бросайте файлы, где попало. Особенно, если в содержимом файла вы не до конца уверены, а местом бросания является вверенный вам сервер.
4. И самое, пожалуй, важное. Господа работодатели!!! Не оставляйте программистов без работы. А то они в свободное время чёрти чем начинают заниматься... Так, глядишь, и до вас доберутся когда-нибудь.

Всем осилившим до конца - большой человеческий респект)

Следующая запись

Предыдущая запись

Похожие записи

Комментарии

Еще нет комментариев.

Пингбэки

Оповещения открыты.

Трэкбэки

URL архива

Only authorized users can post comments