Экспресс-анализ подозрительной активности в журнале веб-сервера

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

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

Я пропущу описание протокола и процесса подключения к аккаунту хостинга по SSH, в сети можно найти множество видео-уроков и статей по данной теме, скажу лишь что для подключения вам потребуется программа Putty (ОС Windows) / Терминал (Mac OS X) или аналогичные, и доступы к хостингу по SSH: хост, порт, логин и пароль (часто имя и пароль они совпадают с доступом в cPanel, ISPManager или аккаунтом панели управления хостингом).

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

Предположим, вы заметили подозрительную активность на сайте (стал медленно открываться, пропали доступы в админ-панель, с сайта рассылают спам и т.п.). Первое, что в этом случае нужно выполнить – это проверить файлы сайта на вредоносный код специализированными сканерами. Но пока сайт сканируется, можно провести экспресс-анализ логов веб-сервера с помощью команд find/grep, чтобы опеределить, не было ли обращений к каким-то подозрительным скриптам, попыток брутфорса (подбора пароля) или вызовов хакерских скриптов. Как это сделать? Об этом ниже.

Чтобы анализировать журналы (логи) веб-сервера нужно, чтобы эти логи были включены и доступны в пользовательской директории. Если по-умолчанию они отключены, необходимо их включить в панели управления хостингом и выставить, если есть такая настройка, максимально возможный период хранения (ротации). Если логов нет, но нужно выполнить анализ за последние несколько дней, их можно попробовать запросить в тех поддержке хостинга. На большинстве shared-хостингов логи можно найти в директории logs, которая расположена на один или два уровня выше директории public_html (www). Итак, будем считать, что логи на хостинге есть и путь до них известен.

Подключаемся по SSH и переходим в директорию с логами веб-сервера, которые на виртуальных хостингах хранятся обычно за последние 5-7 дней. Если вывести список файлов в директории, скорее всего там будет access_log за сегодняшний день, а также access_log.1.gz, access_log.2.gz,… — это архивированные логи за предыдущие дни.

Начать анализ лога можно с запросов, которые были выполнены методом POST:

grep ‘POST /’ access_log

или
cat access_log | grep ‘POST /’

Результат вывода можно сохранить в новый текстовый файл для дальнейшего анализа:

grep ‘POST /’ access_log > post_today.txt

Как сделать то же для лога, заархивированного gzip? Для этого есть команда zcat (аналогично cat, но распечатывает содержимое заархивированного файла).

zcat access_log.1.gz | grep ‘POST /’ > post_today.txt

Для анализа подозрительной активности желательно использовать выборку по всем доступным логам. Поэтому далее в примерах будем использовать команду find, которая выполнит поиск всех файлов, а затем выполнит для каждого соответствующую команду (например, zcat).

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

grep 'php HTTP.* 404' access_log
find . -name '*.gz' -exec zcat {} \; | grep 'php HTTP.* 404'

(вместо -exec можно использовать xarg для вызова zcat. )

Еще можно поискать все неуспешные обращения к скриптам php (к которым был закрыт доступ).

find . -name '*.gz' -exec zcat {} \; | grep 'php HTTP.* 403'

Здесь мы ищем запросы, в которых встречается расширение php и статус 403.

Далее посмотрим по всем доступным логам число успешных обращений к скриптам, отсортируем их по числу обращений и выведем ТОП-50 самых популярных. Выборку сделаем в три шага: сначала выполним поиск по access_log, затем по всем access_log.*.gz, выведем результаты в файл, а затем используем его для сортировки.

find . -name '*.gz' -exec zcat {} \; | grep 'php HTTP.* 200' > php.txt
grep 'php HTTP.* 200' access_log >> php.txt
cut -d '"' -f2 php.txt | cut -d ' ' -f2 | cut -d '?' -f1 | sort | uniq -c | sort -n | tail -50

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

   1 /wp-admin/edit.php
   1 /wp-admin/index.php
   1 /wp-admin/update-core.php
   1 /wp-admin/upload.php
   2 /wp-admin/users.php
   3 /wp-admin/plugins.php
   4 /wp-includes/x3dhbbjdu.php
   4 /wp-admin/profile.php
   4 /wp-admin/widgets.php
  38 /wp-admin/async-upload.php
  58 /wp-admin/post-new.php
1635 /wp-admin/admin-ajax.php
6732 /xmlrpc.php
14652 /wp-login.php


Из результата видно, что к файлу wp-login.php было более 14000 обращений, что ненормально. Судя по всему на сайт была (или еще идет) брутфорс атака с попыткой подобрать доступ к панели администратора.

Большое число обращений к xmlrpc.php также может свидетельствовать о подозрительной активности. Например, через сайт могут атаковать (DDOS’ить) другие Wordpress сайты при наличие XML RPC Pingback Vulnerability.

Еще в списке подозрительными выглядят успешные обращения к /wp-includes/x3dhbbjdu.php, так как такого файла в стандартном Wordpress быть не может. При анализе он оказался хакерским шеллом.

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

Теперь давайте посмотрим, не было ли попыток взлома сайта. Например, поиска уязвимых скриптов или обращения к хакерским шеллам. Найдем все запросы к файлам с расширением .php со статусом 404 Not Found:

find . -name '*.gz' -exec zcat {} \; | grep 'php HTTP.* 404' > php_404.txt
grep 'php HTTP.* 404' access_log >> php_404.txt
cut -d '"' -f2 php_404.txt | cut -d ' ' -f2 | cut -d '?' -f1 | sort | uniq -c | sort -n | tail -50

На этот раз результат может быть таким:

   1 /info.php
   1 /license.php
   1 /media/market.php
   1 /setup.php
   1 /shell.php
   1 /wp-admin/license.php
   1 /wp-content/218.php
   1 /wp-content/lib.php
   1 /wp-content/plugins/dzs-videogallery/ajax.php
   1 /wp-content/plugins/formcraft/file-upload/server/php/upload.php
   1 /wp-content/plugins/inboundio-marketing/admin/partials/csv_uploader.php
   1 /wp-content/plugins/reflex-gallery/admin/scripts/FileUploader/php.php
   1 /wp-content/plugins/revslider/temp/update_extract/revslider/configs.php
   1 /wp-content/plugins/ultimate-product-catalogue/product-sheets/wp-links-ompt.php
   1 /wp-content/plugins/wp-symposium/server/php/fjlCFrorWUFEWB.php
   1 /wp-content/plugins/wpshop/includes/ajax.php
   1 /wp-content/setup.php
   1 /wp-content/src.php
   1 /wp-content/themes/NativeChurch/download/download.php
   1 /wp-content/topnews/license.php
   1 /wp-content/uploads/license.php
   1 /wp-content/uploads/shwso.php
   1 /wp-content/uploads/wp-admin-cache.php
   1 /wp-content/uploads/wp-cache.php
   1 /wp-content/uploads/wp-cmd.php
   1 /wp-content/uploads/wp_config.php
   1 /wp-content/wp-admin.php
   1 /wp-update.php
   1 /wso2.php
   2 /wp-content/plugins/dzs-zoomsounds/ajax.php
   2 /wp-content/plugins/hello.php
   2 /wp-content/plugins/simple-ads-manager/sam-ajax-admin.php
   3 /wp-content/plugins/dzs-zoomsounds/admin/upload.php
   4 /2010/wp-login.php
   4 /2011/wp-login.php
   4 /2012/wp-login.php
   4 /wp-content/plugins/wp-symposium/server/php/index.php

Как видим из результата, подобные обращения были. Кто-то «на удачу» пытался обратиться к хакерскому шеллу в каталоге предположительно уязвимого компонента Revolution Slider /wp-content/plugins/revslider/temp/update_extract/revslider/configs.php и к WSO Shell в корне сайта и к ряду других хакерских и уязвимых скриптов. К счастью, безуспешно.
C помощью тех же find / cat / zcat / grep можно получить список IP адресов, с которых эти запросы выполнялись, дату и время обращения. Но практической пользы в этом мало.

Больше пользы от выборки всех успешных POST запросов, так как это часто помогает найти хакерские скрипты.

find . -name '*.gz' -exec zcat {} \; | grep 'POST /.* 200' > post.txt
grep 'POST /.* 200' access_log >> post.txt
cut -d '"' -f2 post.txt | cut -d ' ' -f2 | cut -d '?' -f1 | sort | uniq -c | sort -n | tail -50

Результат может выглядеть следующим образом:

  2 /contacts/
  3 /wp-includes/x3dhbbjdu.php
  7 /
   8 /wp-admin/admin.php
  38 /wp-admin/async-upload.php
 394 /wp-cron.php
1626 /wp-admin/admin-ajax.php
1680 /wp-login.php/
6731 /xmlrpc.php
9042 /wp-login.php

Здесь видно много обращений к wp-login.php и xmlrpc.php, а также 3 успешных POST запроса к скрипту /wp-includes/x3dhbbjdu.php, которого не должно быть в Wordpress, то есть скорее всего это хакерский шелл.

Иногда полезно посмотреть выборку всех 403 Forbidden запросов, выполненных методом POST

find . -name '*.gz' -exec zcat {} \; | grep 'POST /.* 403' > post_403.txt
grep 'POST /.* 403' access_log >> post_403.txt
cut -d '"' -f2 post_403.txt | cut -d ' ' -f2 | cut -d '?' -f1 | sort | uniq -c | sort -n | tail -50

В моем случае это выглядело так. Не очень много, хотя это могли быть попытки эксплуатации XML RPC Pingback.

   8 /xmlrpc.php

Наконец, можно выбрать TOP-50 популярных запросов к сайту за сегодня:

cut -d '"' -f2 access_log | cut -d ' ' -f2 | cut -d '?' -f1 | sort | uniq -c | sort -n | tail -50

Получаем:

   6 /wp-admin/images/wordpress-logo.svg
   6 /wp-admin/plugins.php
   7 /wp-admin/post-new.php
   8 /wp-admin/async-upload.php
   9 /sitemap.xml
  10 /wp-admin/users.php
  13 /feed/
  13 /wp-admin/
  20 /wp-admin/post.php
  22 /wp-admin/load-styles.php
  38 /favicon.ico
  52 /wp-admin/load-scripts.php
  58 /wp-cron.php
  71 /wp-admin/admin.php
 330 /wp-admin/admin-ajax.php
1198 /
2447 /wp-login.php

Статистика обращений к /wp-login.php в access_log подтверждает, что брутфорс атака на сайт еще идет (кто-то пытается подобрать пароль), поэтому следует ограничить доступ к wp-admin по IP или с помощью серверной аутентификации, а если на сайте Wordpress нет регистрации пользователей, то можно ограничить доступ и к wp-login.php.

Таким образом без каких-либо специализированных приложений и дополнительных инструментальных средств можно быстро выполнить анализ логов веб-сервера, найти подозрительные запросы и их параметры (IP адрес, User Agent, Referer, дату/время). Все что для этого нужно – подключение по SSH и базовые навыки работы с командной строкой.
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 6

    +2
    Откройте для себя zgrep, чтоли:

    zgrep --help
    Usage: /usr/bin/zgrep [OPTION]… [-e] PATTERN [FILE]…
    Look for instances of PATTERN in the input FILEs, using their
    uncompressed contents if they are compressed.

    Это такой пост «начинающим от начинающего»?
      0
      Да ладно прикапываться. Понимание стандартных команд новичкам хуже не сделает, даже лучше даст понять смысл.
      0
      Я б ещё добавил про tail пояснение и про команжу more, так как часто портянки бывают здоровые, для полноты картины и удобства. А так отличная статья. Друзьям скину :).
        0
        Почему именно more, а не less?
          0
          Чем больше, тем лучше. :)
        0
        «Из результата видно, что к файлу wp-login.php было более 14000 обращений, что ненормально.»
        Ключевой вопрос вот в чём: а как понять, что из зафиксированного в логе нормально, а что ненормально?

        Only users with full accounts can post comments. Log in, please.