«Антивирус на Linux не нужен» — распространённое мнение, и в исходном виде оно верное: вирусов, заражающих системные файлы Linux, действительно почти нет. Только задача у ClamAV на сервере другая, и формулируется она так: найти то, что загрузили через ваш сайт. В первую очередь веб-шеллы.

Что именно ищем

Веб-шелл — это небольшой PHP-файл, дающий возможность выполнять команды через браузер. Он попадает на сервер через форму загрузки, уязвимый плагин или подобранный пароль администратора, ложится в каталог загрузок среди картинок и живёт там месяцами. Ни фаервол, ни Fail2ban его не увидят: обращения к нему выглядят как обычные запросы к сайту.

Кроме этого ClamAV находит:

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

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

Установка и главная настройка

sudo apt install clamav clamav-daemon
sudo systemctl status clamav-freshclam

Вторая команда важнее первой. freshclam — служба обновления баз, и если она не работает, ClamAV становится бесполезен, продолжая при этом рапортовать об успешных проверках. Возраст баз проверяется так:

sudo ls -l /var/lib/clamav/*.c?d
sudo freshclam

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

Память: демон или разовый запуск

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

clamd — постоянно работающий демон, держащий базы в памяти. Он быстро отвечает, но занимает около гигабайта оперативной памяти. На VPS с одним или двумя гигабайтами это неприемлемо: демон вытеснит базу и PHP-FPM, и сервер начнёт тормозить без явной причины. Диагностируется по free -m и по активному swap.

Альтернатива — clamscan по расписанию. Он медленнее (загружает базы при каждом запуске, около минуты), но работает только во время проверки:

sudo clamscan -r -i --exclude-dir='^/(proc|sys|dev|run)' /var/www

Ключ -i печатает только найденное, иначе вывод — сотни тысяч строк.

Сканировать каталоги, а не диск

Полная проверка всего диска на слабом сервере идёт часами и создаёт нагрузку, из-за чего её ставят на ночь, а потом отключают совсем. Практичнее сканировать то, что действительно меняется извне:

0 3 * * * ionice -c3 nice -n19 clamscan -r -i --move=/var/quarantine /var/www/uploads

Три вещи в этой строке существенны. ionice и nice убирают влияние на работу сайта. --move вместо --remove — файл переносится в карантин, а не удаляется: ложные срабатывания бывают, и удалённый по ошибке файл клиента вернуть неоткуда. Каталог для проверки — тот, куда загружают файлы, а не корень.

Сигнатуры для веб-шеллов

Стандартные базы ClamAV на PHP-бэкдоры ориентированы слабо — они рассчитаны в основном на почтовый трафик. Заметно лучше эту задачу решает Linux Malware Detect (maldet): у него собственный набор сигнатур, собранный как раз по веб-шеллам, а сканирует он движком ClamAV, если тот установлен. Связка обычная: ClamAV как движок и обновляемая база, maldet как источник профильных сигнатур.

Что делать с находкой

Найденный веб-шелл — это не конец разбирательства, а его начало. Файл в каталоге загрузок означает, что кто-то смог туда что-то записать, и удаление файла эту возможность не отменяет.

  1. Не удалять сразу — сохранить копию и записать время изменения файла.
  2. По времени найти в логах веб-сервера, каким запросом он туда попал. Это и есть уязвимость.
  3. Поискать соседей: закладку почти никогда не оставляют в одном экземпляре.
  4. Проверить, что ещё изменилось на диске за тот же период, и не появилось ли новых заданий cron и ключей SSH.

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

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