Началась данная история довольно прозаично. Один из клиентов начал жаловаться, что на его сайте, работающем на CMS Битрикс, постоянно слетают то настройки модулей, то вообще сайт перестает работать с «выплевыванием ошибок» там, где они быть не должны. Сменил клиенту пароли, восстановил сайт из ночного бекапа и спокойно занялся своими делами, списав ситуацию на обычную компроментацию паролей и вандализм.
Но не через несколько часов симптомы повторились вновь, причем были в случайных местах затерты куски PHP кода, что давало основание полагать, что сайт пытаются выключить намеренно. Выводы кому же понадобилось потушить типичный государственный сайт небольшого поселения с посещаемость 5-6 человек в день оставим сотрудникам компетентых органов, я же расскажу вкратце для новичков как действовать в этом случае.
1) Смотрим на 2ip.ru либо другом подобном сервисе свой внешний ip адрес, а также просим всех администраторов сайта прислать ip, с которых они сейчас подключены к интернету. Тут правило простое — обращение к административным папкам 1С-Битрикс должно идти только с этих адресов.
2) Открываем файл журнала доступа вебсервера, для вебсервера apache он как правило лежит на сервере по пути /var/log/apache2/access.log. Ищем запросы файлов админки с адресов, не принадлежащих администраторам сайта. В моем конкретном случае меня смутила данная строчка:
xxx.xxx.xxx.xxx - - [xx/xx/2015:xx:xx:xx +0300] "POST /bitrix/admin/htmleditor2/bitrix_log.php HTTP/1.0" 200 4 "http://xxxxxxxxxxxxx/bitrix/admin/htmleditor2/bitrix_log.php" "Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0"
Здесь мало того, что доступ к файлу админки идет с IP-адреса, не присутствующего в списке из первого пункта, но еще и к файлу, которого изначально в поставке CMS Битрикс нет! Когда работаете с логами и файлам, желательно разверните отдельно эталонную копию CMS, на которой работает сайт, чтобы можно были сравнивать файлы на предмет изменены ли они или нет.
3) Открываем файл /bitrix/admin/htmleditor2/bitrix_log.php. Глазам предстает следюущая мешанина символов:
<?php
$auth_pass = "b1248f5dde2d214b74ef121288b61801";
$color = "#df5";
$default_action = 'FilesMan';
$default_use_ajax = true;
$default_charset = 'Windows-1251';
$o='HZzFksNKuoQ';//В ЭТОЙ ПЕРЕМЕННОЙ 20 страниц потока случайных символов, СОКРАТИЛ ЕЕ ДЛЯ УДОБСТВА ПОНИМАНИЯ
//eval("\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28\x24\x6F\x29\x29\x29\x3B");
функцию eval(), которую злоумышленник пытался спрятать за кучей символов (как оказалось дальше это текстовое представление zip архива), я сразу закомментировал.
В принципе для рядовых админов можно было просто удалить данный файл, сделать поиск функции eval по остальным скриптам и где ее не должно быть — удалить и закончить свои исследования. Но я решил посмотреть, что же данное произведение народного творчества делает с сайтом и сервером.
Сначала обращаем внимание на строку:
eval("\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28\x24\x6F\x29\x29\x29\x3B");
HEX символозаменители видны невооруженным взглядом. Превратить их в удобочитаемый невооруженным взглядом текст поможет любой HEX декодер, я пользовался этим.
После скармливания декодеру
eval(gzinflate(base64_decode($o)))
в
Код был немного переписан, после мешанки из символов добавляю код расшифровки:
$string = gzinflate(base64_decode($o));
после этого мы знаем что код циклически разархивирует сам себя и запускает разархивированный кусок, т.е. можно просто пройти тот же цикл но не выполняя код, а сбрасывая в какую-нибудь из переменных до полной разархивации. т.к. в каждой «итерации» архива код содержит начальную строку eval(gzinflate(base64_decode( после того как в разархивированном варианте не будет данной строки можно останавливать цикл. Распакованный код сливаем в какой нибудь файл для последующего анализа.
Вот реализация данного кода на PHP:
while (substr_count($string,"eval(gzinflate(base64_decode(")>0) {
$string = str_replace("eval(gzinflate(base64_decode('","",$string);
$string = str_replace("')));",");",$string);
$string =gzinflate(base64_decode($string));
}
file_put_contents("unpacked.dat",$string);
После окончания работы скрипта открываем unpacked.dat и видим типичный php шелл (каких море) с файл менеджером и прочими «пряниками». На сервере сайт каждого клиента работает под правами пользователя данного клиента, которые довольно сильно урезаны, плюс запрещена команда exec(). Поэтому злоумышленник глумился только над этим сайтом и не смог подлезть к остальным.
Да и метод обфускации своего шелла он выбрал не очень удачный — функция eval в битриксе используется довольно редко, и данный шел по этой функции очень легко отыскать, плюс «рандомные символы» сразу наводят на подозрение. Из за этого шелл выделяется в общей структуре сайта как клоун на похоронах.
Путь попадания шелла также оказался весьма нетривиальным — раньше у клиента на сервере весело 2 копии сайта, одна из них была старым вариантом сайта на на старой и «дырявой как решето» версии Joomla. Эту версию сайта оставили для удобного переноса контента на новый сайт. В этот момент через дыру в Joomla и был загружен шелл (сайты располагались под одним пользователем в соседних папках).
Поэтому я всегда старые версии сайтов размещаю на отдельной виртуалке, которую не жалко. Что и вам советую.
UPD Убрал формулировку «говносимволы», дабы не обижать особо впечатлительных.
Комментарии (14)
Temirkhan
16.04.2015 16:07Прямо чувствуется негодование и отвращение автора к тем, кто портит ему рабочий день отловом вредоносного кода.
Особенно смутило то, что автор, хоть и говорит, что в битриксе нет eval(), не удосужился в первую очередь пройтись поиском ключевых слов и шаблонов по директории сайта, а начал со сводки логов посещений с теми, у кого доступа быть не должно.MatasDragonV Автор
17.04.2015 01:09-1Я и не говорил что eval() в битриксе не используется вообще, он там используется значительно реже многих других популярных в битриксе конструкций.
kwolfy
16.04.2015 17:22+1Поиск по eval может и не помочь, если сделать например, вот так:
$text = 'echo "hello";'; $text = preg_replace( '((.*))e', 'e' . 'v' . 'a' . 'l' . '("$1")', $text );
Если не ошибаюсь, то до версии php 5.5 будет вполне работатьDarkByte
16.04.2015 18:12В самом простом случае закладка может выглядеть так:
<? $_REQUEST['func']($_REQUEST['param'])
Хотя в таком случае не будет работать eval. Но функция create_function позволяет обойти это ограничение:
<? $eval = create_function('$a','eval($a);');
Из обычной строки, которая может быть закодирована любым образом (или передана вместе с запросом), получается функция eval.
Stalker_RED
16.04.2015 18:22+1Еще
и overrride_function()create_function('$o', 'return ev'.'al($o);');
igordata
16.04.2015 19:41+2> eval("\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28\x24\x6F\x29\x29\x29\x3B");
> HEX символозаменители видны невооруженным взглядом. Превратить их в удобочитаемый невооруженным взглядом текст поможет любой HEX декодер, я пользовался этим.
Прям я сорву покровы сейчас: echo "\x65\x76...\x29\x3B"; выведет нам содержимое этой строки в читаемом виде так, как оно и будет передано в eval(). Иначе eval() не отработает же ж.Bo0oM
18.04.2015 12:40javascript:document.write("\x65\x76\x61\x6C\x28\x67\x7A\x69\x6E\x66\x6C\x61\x74\x65\x28\x62\x61\x73\x65\x36\x34\x5F\x64\x65\x63\x6F\x64\x65\x28\x24\x6F\x29\x29\x29\x3B"); в браузере
vlreshet
ИМХО, обфусцированый код можно было назвать более цензурно, пост просто пестрит словом «говносимвол», читать противно.
DarkByte
Учитывая что автор говносимволами назвал кодировку base64, можно предположить, что почта ему приходит по большей части в говне.
Bo0oM
А зачем деобфусцировать шелл, если разбираться в сортах кодировок можно и в другом месте?
MatasDragonV Автор
Выражение добавлено не отвращения ради а юмора для :)
igordata
> Убрал формулировку «говносимволы», дабы не обижать особо впечатлительных.
А такая формиулировка — это откровенное хамство уже.
Во-первых, обижать. Во-вторых «особо впечатлительных».
MrMmka
Вы бы знали какая дырявая битрикс…
Надо радоваться, что их уязвимости в паблик часто не сливают, иначе бы уже половина сайтов лежала бы.