Делюсь наработкой, родившейся в результате чистки последствий двух хакерских атак (включая одну с внедрением WSO web shell).
Всем понятно, что одним из средств своевременного обнаружения атаки является мониторинг файлов на предмет возможных несанкционированных изменений в них. Вот я и сделал средство для такого мониторинга для своих нужд.
Средство заточено под хостинг NIC, но может быть легко подогнано под другой хостинг, использующий UNIX-подобную ОС и позволяющий пользователям использовать ssh и cron.
Особенности конкретной CMS используются только в одном месте. Так что можно легко подогнать средство под другие CMS.
На хостинге каждому арендатору дается идентификатор. Арендатор на своем хостинге может держать несколько сайтов. В соответствии с правилами хостинга сайт живет в каталоге:
(скрытая часть)/home/идентификатор_пользователя/домен_сайта
Часть полного пути хостинг каким-то образом от пользователя скрывает. Но для нас она не существенна.
Для файлов, составляющих непосредственно сайт, выделен каталог
(скрытая часть)/home/идентификатор_пользователя/домен_сайта/docs
Другие подкаталоги основного каталога сайта предназначены для разного рода обвязки (вроде конфигов, логов и т.п.)
Для установки системы мониторинга на хостинг нужно сделать следующее:
1. Зайти на хостинг по ssh
2. Создать каталог
/home/идентификатор_польователя/домен_сайта/.security
и прописать ему права доступа 0700
3. Перейти в только что созданный каталог и в нем создать файл с именем check.sh следующего содержания:
UPD от 8.06.2013: по сравнению с первой версией добавил еще 2 строки в конецcd $HOME/домен_сайта/docs
find . -ls | grep -v " ./cache" | grep -v " ./administrator/cache" | grep -v " ./tmp" | sort -k 11 > ../.security/filelist
cd $HOME/домен_сайта/.security
#diff -bw -c0 filelist.prev filelist
cp filelist filelist.prev
cp filelist filelist.`date +"%Y%m%d-%H%M%S"`
find . -name "filelist*[0-9]" -mtime +1 -exec gzip {} \;
find . -name "filelist*gz" -mtime +15 -exec rm {} \;
обратите внимание на сочетание обратных апострофов, двойных кавычек и регистр букв в последней строке - все это существенно.
4. Присвоить этому файлу права доступа 0700
5. Один раз запустить этот файл
6. Снова открыть этот файл в редакторе и в 4-й строке убрать знак "#" в самом начале строки.
Основной рабочий файл готов. Теперь необходимо организовать его регулярный запуск. Так что продолжаем.
7. Войти на хостинг через панель управления хостингом, в предлагаемом меню выбрать "Веб-сервер", затем "Планировщик заданий".
8. В поле ввода "создать новое задание" написать какое-либо имя для задания и кликнуть в кнопку "создать".
9. В появившейся форме ввести:
- в поле "выполняемая программа" - /home/идентификатор_пользователя/домен_сайта/.security/check.sh
- в списке выбора "выполнение" - "разрешено"
- в списке выбора "выводить сообщения" - "да"
- в наборе чекбоксов "время выполнения" - как пожелаете (я поставил ежечасно)
после чего кликнуть в кнопку "сохранить".
Система готова. Теперь для тех, кто совсем плохо знает *NIX-системы объясняю как она работает.
Про запуск контролирующего скрипта по cron'у все более-менее понятно. Тонкостью тут является настройка "выводить сообщения": если она включена - то хостинг перехватывает стандартный вывод запущенного скрипта, и если этот вывод не равен нулю - посылает его письмом контактному лицу, указанному в договоре хостинга. Если же вывод пустой - то никаких писем не посылается.
Теперь непосредственно по контролирующему скрипту.
1-я строчка - просто переход в каталог, где живет сайт.
2-я строчка - сцепленные между собой "конвейером" команды:
- find . -ls - найти все файлы в каталоге и его подкаталогов и для каждого вывести в стандартный вывод строчку информации. Далеко не все из того, что будет выведено, нам интересно. Но некоторое количество интересных вещей тоже имеется. А именно: пользователь-владелец, группа, права доступа, размер в байтах, время последней модификации, имя файла и путь к нему относительно каталога, указанного в параметре команды (т.е. в нашем случае - относительно корневого каталога видимой части сайта)
- 3 команды grep -v - удалить из получившегося списка каталоги, которые могут на законных основаниях менять свое содержимое, и файлы из них. Это необязательная часть скрипта (например, у меня один из сайтов на Wordpressе - для него эта часть не понадобилась)
- sort -k 11 - отсортировать получившийся набор строк по 11-му полю (полем считается группа непробельных символов, разделенная любым количеством пробелов), т.е. в данном конкретном случае по пути к файлу и имени файла
- > - записать результат выдачи команды в заданный файл
3-я строчка - перейти в тот каталог, где живет система контроля и создаваемые ей файлы
4-я строчка - сравнить получившийся файл построчно с файлом, который получился при предыдущем запуске скрипта. Из-за этого в самом начале эта строчка закрыта комментарием - ведь нет предыдущего запуска, т.е. не с чем сравнивать.
5-я строчка - сохранить получившийся при этом запуске скрипта файл для использования при следующем запуске скрипта
6-я строчка - сохранить получившийся при этом запуске скрипта файл для истории и возможного анализа. При этом в имя файла выносятся текущие дата и время с точностью до секунды.
UPD по добавленным строкам:7-я строчка - файлы, полученные скриптами, запущенными более суток назад, сжимаются архиватором gzip (чтобы меньше места занимали).
8-я строчка - сжатые файлы, полученные скриптами, запущенными более 15 суток назад, удаляются (чтобы не тратить место для хранения откровенного старья).
Конечно, эта система не предотвратит атаку на сайт. Но непременно обнаружит ее при следующем запуске скрипта. И уведомит владельца сайта письмом примерно такого содержания:
Cron: /home/идентификатор_пользователя/домен_сайта/.security/check.sh
*** filelist.prev Thu Jun 6 19:40:01 2013
--- filelist Thu Jun 6 20:40:02 2013
***************
*** 829 ****
! 131686506 4 -rw-r--r-- 1 user_id group_id 1321 May 27 23:52 ./wp-content/themes/twentyten/index.php
--- 830 ----
! 131686506 4 -rw-r--r-- 1 user_id group_id 333 Jun 6 20:36 ./wp-content/themes/twentyten/index.php
***************
*** 842 ****
! 131687374 4 -rw-r--r-- 1 user_id group_id 247 May 23 22:52 ./wp-content/themes/twentyten/page-contacts.php
--- 843 ----
! 131687374 4 -rw-r--r-- 1 user_id group_id 381 Jun 6 20:39 ./wp-content/themes/twentyten/page-contacts.php
Пример - реальный, я только отредактировал колонки с именем пользователя и группы. Это я сегодня на одном из своих сайтов изменения вносил. В данном конкретном случае показано, что были изменения в двух файлах. Но появление новых файлов и исчезновение существующих файлов тоже будет замечено.
Все. До уровня "мышь не проскочит", конечно, не дотягивает. Но кошка для этой мыши уже на страже.
PS. Чуть не забыл. У системы есть один недостаток. На мой взгляд несущественный, но все-таки есть. Заключается он в том, что время модификации файла выводится по-разному в зависимости от его давности: если оно менее полугода назад - то выводятся месяц, число, часы и минуты, если же более полугода назад - то месяц, число и год. Из-за этого когда какому-нибудь файлу исполнится ровно полгода от последней модификации, система выдаст ложное предупреждение о том, что файл изменился, хотя он не изменялся. Устранить этот недостаток можно путем применения параметра "-printf" в команде find, но не во всех UNIX-подобных системах этот параметр поддерживается.