2 Декабря, 2015

Поиск проблем и вирусной активности на сайте с помощью strace

revisium
В ОС семейства *nix (на которых работает большинство хостингов) есть замечательная утилита strace (и аналоги truss, ltrace), про которую мало кто из веб-мастеров слышал и еще меньше ей пользуются для диагностики проблем на сайте.

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

Данные модули вполне годные, но их целесообразно применять для определенного круга задач. А вот strace более универсален, и позволяет отслеживать не только сам php процесс, но и порожденные им (например, запущенные через exec).

В диагностике каких проблем помогает strace?

  • сайт «тормозит»: то есть страницы сайта медленно генерируются и нужно выяснить, какие операции выполняются долго (это может быть медленная работа с БД, много запросов к БД, подключения к внешним серверам и загрузка данных, долгая обработка каких-то данных и пр)
  • на сайте производятся несанкционированные изменения (добавляется код в файлы, изменяется содержимое файлов, удаляются, создаются новые, постоянно вставляется код в базу и т.п.)
  • посмотреть время генерации страницы: сколько времени тратит сервер на обработку запроса, вызовы в скрипте и пр.
  • веб-сервер сильно загружает процессор, нужно выяснить – чем именно
Нас в первую очередь интересует решение проблем безопасности, поэтому будем рассматривать работу с strace именно в этом ключе. Наиболее популярные проблемы, это

  • заражение сайта, в результате чего он начинает медленно открываться, так как внедренный в скрипты код может загружать данные с внешних серверов или отправлять данные в командный центр, расшифровывать обфусцированный код, обращаться к базе данных и пр.
  • спам-рассылка: при выполнении скриптов выполняется регулярная несанкционированная отправка писем
  • вставка спам-страниц или спам-ссылок: это может быть внедренный код бирж ссылок sape, trustlink, linkfeed и других, также это может быть система автоматической публикации статей на сайте, которыми пользуются black hat seo специалисты
  • изменение в файле .htaccess или внедрение кода в php скрипт (например, index.php) при обращении к сайту
  • динамическая вставка вирусного кода в html код страницы
Перечисленные проблемы часто можно решить, если просто просканировать файлы сайта на вредоносный код и вылечить их от вирусов и хакерских вставок. Но что, если вы проверили сайт сканером, он ничего не обнаружил, а проблема есть? Самое время воспользоваться утилитой strace. К сожалению, на виртуальном хостинге запустить ее без помощи администратора (службы тех поддержки) не удастся, так как в большинстве случаев системные вызовы, которыми она пользуется, заблокированы для пользователей (по соображениям безопасности). Поэтому для владельцев шаред-хостингов здесь есть два варианта:

  • временно настроить сайт (можно даже без переключения домена) на каком-нибудь облачном VPS сервере, сейчас его стоимость составляет порядка 250 руб в месяц
  • попросить тех поддержку хостинга запустить strace для вашего сайта и прислать вам лог для анализа (если они не знакомы с утилитой, дайте им ссылку на эту статью)
Для владельцев VPS и выделенных серверов все намного проще: если strace еще не установлена, просто установите ее и вперед.

Итак, что необходимо сделать для сбора информации о работе процесса: утилите strace нужно указать идентификатор процесса PID, имя файла, куда сохранять трейс-лог и несколько дополнительных параметров. Для анализа работы сайта нужно “натравить” strace на веб-сервер Apache или nginx (зависит от настроек вашего хостинга), открыть страницы сайта, собрать логи и завершить работу strace.

Проблема здесь в поиске PID веб-сервера, так как нужен идентификатор не worker’а, а дочернего процесса, который изменяется и заранее узнать его нельзя. Поэтому есть различные варианты сбора логов:

  • указать в настройках веб-сервера, что он работает в один поток и прицепиться к процессу
Опция в httpd.conf  StartServers 1
  • остановить веб-сервер и запустить его из strace
strace -r -f -o strace.log /etc/rc.d/init.d/httpd start
strace –r –f –o strace.log apache2ctl -k start
  • подключиться к серверу как в этом видео через telnet
  • (самый удобный способ) прицепиться сразу ко всем дочерним процессам без перезапуска веб-сервера, и снять логи, а затем выбрать нужный. Вариантов масса
ps auxw | grep sbin/apache | awk '{print"-p " }' | xargs strace -r -o strace.log
ps h --ppid $(cat /var/run/apache2.pid) | awk '{print"-p " }' | xargs strace -r -o strace.log
ps auxw | grep sbin/apache | awk '{print"-p " }' | xargs strace -f -r -o strace.log

А теперь примеры.

1. Страницы сайта открываются по 20 секунд. Почему?

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



Открываем страницу, ждем завершения загрузки и останавливаем strace.

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

Открываем его и смотрим, какие системные вызовы происходили в момент открытия страницы



Здесь можно увидеть обращения к файлам и директориям, операции с базой данных и сетевые запросы. Столбец слева от запроса отображает продолжительность запроса (опция -r в strace). Так можно определить время выполнения в миллисекундах. Удобно написать какой-нибудь скрипт, который бы отображал еще и суммарную статистику по времени вызовов (то, что сейчас отображается в первом столбце), так как изначально в отчете ее нет.  Итак, смотрим в отчет и проверяем, на что уходит время при генерации страницы.


Замечаем, что в процессе генерации стартовой страницы было отправлено 559 запросов к базе данных, что явно перебор. Именно из-за некорректной работы с базой данных тормозит сайт (в данном примере был сайт на opencart, у которого разработчики некорректно реализовали вывод товара на странице).

2. Страница зависает на 30 секунд, а затем завершается с ошибкой 500.

Делаем сбор лога strace, смотрим, где зависает процесс:

... connect(8, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("204.11.56.48"}, 16) = -1 EINPROGRESS (Operation now in progress)
... poll([{fd=8, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, 60000"
Видим, что из скрипта идет подключение к внешнему IP на 80й порт (то есть скрипт что-то пытается загрузить в процессе работы по HTTP), но удаленный хост ему не отвечает и скрипт завершается с ошибкой. Ищем в скриптах вставку и обнаруживаем хакерский код с указанным IP. Удаляем код – сайт начинает работать.

На сегодня все.

--

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