Контроль изменение файлов сайта

Среди множества файлов системы управления сайта (CMS) существует один файлик, который был взломан и в котором содержится чужеродный код. Чтобы отыскать этот файлик среди множества себе подобных необходимо потратить не одну минуту, не один час. Самым лучшим решением в этой ситуации является восстановление с архива (бэкапа) сайта. Но это далеко не выход, поскольку при повторном взломе снова придется воспользоваться бекапом.
Исходя с такой ситуации напрашивается вопрос — можно ли в целом осуществить мониторинг изменения файлов CMS и в случаи изменения содержания одного, двух файлов информировать владельца сайта?

Мониторинг изменения файлов

Каким образом можно следить за файлами, их изменением? Первым что приходит в голову – это размер и дата создания/изменения. Именно эти параметры файла являются основой для создания мониторинга.
Представленный ниже код позволит отслеживать состояния файлов системы и если ”целостность” какого то из них будет нарушена, на почту придет сообщение об изменении содержания файла.

Настройка и установка скрипта проверки файлов на изменение

Основным и самым главным условием для полноценной работы скрипта является наличие PHP 5. Еще одним немаловажным моментом является верное определение корня сайта. Но об этом по порядку.

И так, чтобы установить скрипт, создаем папку в корне сайта, назовем ее Security и в ней же создадим такой же файл с расширением .php
Копируем представленный ниже код и вставляем в только что созданный файл

<?php

/*
-------------------------------------------------------------------------
*                                                                       *
*       http://blog.portal.kharkov.ua/2008/06/27/belavir/               *
*       http://artdev.org/skript-proverki-faylov-na-izmenenie.html      *
*                                                                       *
-------------------------------------------------------------------------
*/

$md5_root_path = '/var/www/user/data/www/site.ru/';  
// укажите путь до корня сайта

$md5_path = array(
'/var/www/user/data/www/site.ru/templates/',   
// укажите путь до файлов шаблона сайта
'/var/www/user/data/www/site.ru/plugins/',      
// укажите путь до файлов плагинов сайта
);

$md5_file = '/var/www/user/data/www/site.ru/uploads/.md5';      // укажите путь до файла записи

$ext = array('php', 'tpl', 'js', 'htm', 'html');   
// укажите расширения файлов

$pochta = 'mailbox@gmail.com';              
// укажите почту на gmail.com

if ( !file_exists($md5_file) ) write_md5();

$md5 = dir_md5();

if (file_exists($md5_file)) {
        $mdf = file($md5_file);

        if ( !$mdf ) {
                write_md5();
                $mdf = file($md5_file);
        }

        $i = 1;
        $text = "";
        while (list($ln, $line) = each($mdf))
        {
                list($md, $ff) = explode("\t", trim($line));
                if ($md != $md5[$ff]) {
                        if ($i == 1) $text .= "Целостность нарушена. 
Изменены файлы:";
                        $fp = str_replace($md5_root_path, '/', $ff);
                        $fp = str_replace('//', '/', $fp);
                        $text .= "\r\n$i. $fp";
                        $i++;
                }
                unset($md5[$ff]);
        }
        foreach ($md5 as $key=>$val) {
                if ($i == 1) $text .= "Целостность нарушена. Изменены файлы:";
                $fp = str_replace($md5_root_path, '/', $key);
                $fp = str_replace('//', '/', $fp);
                $text .= "\r\n$i. $fp - новый";
                $i++;
        }
        if ($i != 1)
                mail($pochta, 'Изменение файлов', 
$text, 'From:robot@mail.ru'."\r\n".
'Content-type: text/plain; charset=utf-8'."\r\n");
}

function write_md5(){
        global $md5_file;
        $md5 = dir_md5();
        $mdf = @fopen($md5_file, 'w');
        foreach ($md5 as $key=>$val) @fwrite($mdf, "$val\t$key\n");
}

function dir_md5() {
        global $md5;
        global $md5_path;
        global $md5_root_path;
        xdir($md5_root_path, 0);
        for ($i = 0; $i < count($md5_path); $i++) {
                xdir($md5_path[$i], 1);
        }
        $md5[$md5_root_path.'/.htaccess'] = md5(join ('', 
file($md5_root_path.'.htaccess')));
        return $md5;
}

function xdir($path, $recurs) {
        global $md5;
        global $ext;
        if ($dir = @opendir($path)) {
                while($file = readdir($dir)) {
                        if ($file == '.' or $file == '..') continue;
                        $file = $path . '/' . $file;
                        if (is_dir($file) && $recurs)  {
                                xdir($file, 1);
                        }
                        if (is_file($file) && in_array(
strtolower(pathinfo($file, PATHINFO_EXTENSION)), $ext)) {
                                $md5[$file] = md5(join ('', file($file)));
                        }
                }
                closedir($dir);
        }
}

?>

Как видите, этот срипт написан давно и базируется на коде плагина для CMS WordPress belavir, но все же содержит несколько своих нюансов, изменения.
В начале представленного кода, как показывают приведенные комментарии, можно задать какие именно папки и их содержание необходимо контролировать, а также указать расширение файлов, которые стоит просматривать. Только вот все эти тонкости задаются строкой от root-а.
Многие спросят, где его посмотреть, где взять? Посмотреть эту строку можно в файле конфигурации системы управления или же в крайней случаи, спросить у Хостера.
Если все прописано верно, в строке браузера прописываем www.сайт/security/security.php и после успешного сканирования файлов системы, в этой же папке появится файл .MD5 – оттиск нашей CMS

В завершении, несколько слов о работе скрипта. То что можно указать непосредственно папки и расширение файлов для сканирования является хорошим плюсом. Но в плане негатива данного скрипта – это то, что если файл был изменен и его размер и дата (MD5 сумма) отличается от предыдущий, сообщение будет приходить на почту до тех пор, пока не произведете новое сканирование системы и не произойдет обновление данных MD5 сумм. Чтобы обновить оттиск, удалите файл .MD5 и запустите скрипт снова.
И еще, для автоматического запуска сканирования CMS, данный скрипт можно повесить на CRON