Современные хакеры редко “дефейсят” взломанные сайты, как правило, внедряют сторонний код в скрипты для осуществления дальнейших зловредных действий.
Как часто вы тратили часы, выискивая код, внедрённый в ваши скрипты, после атаки?
Некоторое время назад меня привлекли к администрированию десяти сайтов, расположенных на одном виртуальном хостинге. Сайты крутились на “полуразложившихся” движках, написанных в 2000-2003 годах. Сайты постоянно падали под натиском “скрипт-кидди” и изобиловали внедрёнными “зловредами”. Мои задачи были тривиальны: поддержать работу сайтов, перенести на новые движки или залатать дыры в старых движках.
Всё предельно просто, но в полевых условиях было необходимо анализировать текущее состояние файлов, чтобы не дать возможности внедрить код ни в один из сайтов, так как получение доступа к одному сайту на виртуальном хостинге ставило под прицел и сайты, уже перенесённые на новые версии движков. Реагировать на внедрение кода нужно было молниеносно, а проверять файлы вручную при наличии тысяч файлов не представлялось возможным.
В процессе работы родилось очень простое решение, которым я и хочу поделиться. Хочу оговориться, что данное решение простое и не претендует на гениальность и полноту реализации, но надеюсь, что будет кому-то полезно.
Алгоритм работы скрипта прост, он рекурсивно проходит все директории и файлы, начиная с директории, указанной при конфигурации и выводит список файлов, изменившихся за указанный промежуток времени. Вот и всё!
Пользоваться будем следующими функциями:
scandir()
stat()
Данные будем выводить в два столбца таблицы:
Дата модификации
Путь к файлу
Перед запуском необходимо провести небольшую конфигурацию нашего скрипта, переменной $start_folder задать значение, равное пути к каталогу, с которого мы начнём сканирование.
Скрипт поддерживает некий аналог фильтрации, если вам необходимо проигнорировать некую директорию при сканировании, вы можете передать необязательный параметр $filter — массив названий папок. Сканирование папок из массива производиться не будет.
При запуске мы можем указать GET параметр days=n, чтобы вывести изменённые файлы за n дней.
Простейшая реализация имеет огромное количество недостатков и неудобств, для меня одним из основных недостатков стало отсутствие общей сортировки по дате модификации файла. Данную проблему можно решить путём доработки скрипта, но проще мне показалось решение с подключением jQuery плагина TableSorter. Сканер работает достаточно долго, если файлов много, дальнейшая сортировка на стороне сервера требовала бы дополнительного времени и ресурсов, а jQuery позволяет сортировать таблицу на стороне клиента.
Для этого необходимо подключить плагин TableSorter, добавить нашей таблице следующие id и class.
Привязать к нашей таблице обработчик.
Можно автоматизировать процесс полностью, дописав отправку отчёта на электронную почту и запуская сканер через Cron по расписанию.
Надеюсь, моя статья будет полезна начинающим веб разработчикам и даст пищу для размышлений.
Update: Как правильно замечено в комментариях полагаться на дату изменения файла нельзя, так как команда touch() позволяет модифицировать дату.
В работе я использую функционал, встроенный в IDE PHP Storm — синхронизацию локального проекта и удалённого FTP сервера, особых знаний и умений это не требует и отлично подойдет начинающим разработчикам, изменения в файлах выводятся очень наглядно и удобно.
Как часто вы тратили часы, выискивая код, внедрённый в ваши скрипты, после атаки?
Некоторое время назад меня привлекли к администрированию десяти сайтов, расположенных на одном виртуальном хостинге. Сайты крутились на “полуразложившихся” движках, написанных в 2000-2003 годах. Сайты постоянно падали под натиском “скрипт-кидди” и изобиловали внедрёнными “зловредами”. Мои задачи были тривиальны: поддержать работу сайтов, перенести на новые движки или залатать дыры в старых движках.
Всё предельно просто, но в полевых условиях было необходимо анализировать текущее состояние файлов, чтобы не дать возможности внедрить код ни в один из сайтов, так как получение доступа к одному сайту на виртуальном хостинге ставило под прицел и сайты, уже перенесённые на новые версии движков. Реагировать на внедрение кода нужно было молниеносно, а проверять файлы вручную при наличии тысяч файлов не представлялось возможным.
В процессе работы родилось очень простое решение, которым я и хочу поделиться. Хочу оговориться, что данное решение простое и не претендует на гениальность и полноту реализации, но надеюсь, что будет кому-то полезно.
Общий алгоритм работы сканера
Алгоритм работы скрипта прост, он рекурсивно проходит все директории и файлы, начиная с директории, указанной при конфигурации и выводит список файлов, изменившихся за указанный промежуток времени. Вот и всё!
Пользоваться будем следующими функциями:
scandir()
stat()
Данные будем выводить в два столбца таблицы:
Дата модификации
Путь к файлу
Код функции с комментариями:
function scan_tree ($folder, $period, $filter = NULL) {
$files = scandir ($folder);
// Получаем массив папок и файлов в текущей папке
foreach ($files as $file) {
// В цикле обходим все папки и файлы в дериктории
if (($file == '.') || ($file == '..') || (is_array ($filter) && in_array ($file, $filter))) continue;
// Пропускаем текущую папку, родительскую папку и папки из фильтруемых
$item = $folder.DIRECTORY_SEPARATOR.$file;
// Формируем полный путь к папке или файлу
if (is_dir ($item)) {
// Если текущий элемент - папка, то рекурсивно вызываем функцию сканирования
scan_tree ($item, $period, $filter);
} else {
// Если текущий элемент - файл, то получаем информацию о файле
$stat_info = stat ($item);
if (time () - $stat_info['mtime'] < $period) {
// Если дата изменения файла не старше заданного отрезка времени, то выводим новую строку в таблицу
echo '<tr><td>'.date ("d-m H:i", $stat_info[9]).'</td><td>'.$folder.DIRECTORY_SEPARATOR.$file.'</td></tr>';
}
}
}
}
Конфигурация
if (!empty($_GET['days'])) $days = intval ($_GET['days']); else $days = 1;
// Получаем через GET отрезок времени
$period = 86400 * $days;
//Пересчитываем в секунды для сравнения с timestamp
//$start_folder = 'D:\www\htdocs';
$start_folder = '/home/www/';
// Задаём начальную директорию сканирования
$filter = array ('cache', 'logs.old', 'logs');
// Список фильтруемых папок, они будут игнорироваться при сканировании
Перед запуском необходимо провести небольшую конфигурацию нашего скрипта, переменной $start_folder задать значение, равное пути к каталогу, с которого мы начнём сканирование.
Скрипт поддерживает некий аналог фильтрации, если вам необходимо проигнорировать некую директорию при сканировании, вы можете передать необязательный параметр $filter — массив названий папок. Сканирование папок из массива производиться не будет.
При запуске мы можем указать GET параметр days=n, чтобы вывести изменённые файлы за n дней.
Запуск скрипта
<table>
<thead>
<tr>
<th title="Дата изменения">Дата</th>
<th title="Пути файла">Путь к файлу</th>
</tr>
</thead>
<tbody>
<?php scan_tree ($start_folder, $period, $filter); ?>
</tbody>
</table>
Возможные улучшения функционала
Простейшая реализация имеет огромное количество недостатков и неудобств, для меня одним из основных недостатков стало отсутствие общей сортировки по дате модификации файла. Данную проблему можно решить путём доработки скрипта, но проще мне показалось решение с подключением jQuery плагина TableSorter. Сканер работает достаточно долго, если файлов много, дальнейшая сортировка на стороне сервера требовала бы дополнительного времени и ресурсов, а jQuery позволяет сортировать таблицу на стороне клиента.
Для этого необходимо подключить плагин TableSorter, добавить нашей таблице следующие id и class.
<table id="data_table" class="tablesorter">
Привязать к нашей таблице обработчик.
$(document).ready(function () {
$("#data_table").tablesorter();
}
);
Можно автоматизировать процесс полностью, дописав отправку отчёта на электронную почту и запуская сканер через Cron по расписанию.
Результат работы сканера с плагином TableSorter
Надеюсь, моя статья будет полезна начинающим веб разработчикам и даст пищу для размышлений.
Спасибо и удачи!
Update: Как правильно замечено в комментариях полагаться на дату изменения файла нельзя, так как команда touch() позволяет модифицировать дату.
В работе я использую функционал, встроенный в IDE PHP Storm — синхронизацию локального проекта и удалённого FTP сервера, особых знаний и умений это не требует и отлично подойдет начинающим разработчикам, изменения в файлах выводятся очень наглядно и удобно.