Написать нам
Связаться с нами
Мы ценим каждого клиента и гордимся тем, что 60% клиентов снова возвращаются к нам.
Мы в социальных сетях
Запомните эту тавтологию, потому что это главное правило веб-безопасности. Хакеры могут месяцами тихо сидеть в вашей системе, не выдавая себя ни единым логом, пока не наступит "день Х". А когда вы наконец заметите проблему, стандартная автоматика окажется слепа.
Если вы думаете, что для очистки сайта от вирусов достаточно нажать кнопку "Сканировать" в панели хостинга или запустить популярный AIbolit — у меня для вас плохие новости. Сегодня автоматический софт пасует перед умной маскировкой. Вредоносный код прячется под системные файлы так изящно, что выковырять его можно только хирургическим путем — через SSH-терминал.
В этой статье я делюсь своим свежим "окопным" опытом полной зачистки связки Joomla 3.x + CiviCRM после взлома через старую RCE-уязвимость. Без воды, только живой опыт, логика поиска и готовые команды, которые спасут ваш сайт и ваши нервы.
Все началось со старой уязвимости в популярном плагине JCE Editor (ветка 2.9.6). Через нее злоумышленники получили удаленный доступ и начали заливать дорвеи.
Первым делом я пошел по стандартному пути:
/media/com_menus/wp/)../index.php в корне сайта перезаписал чистой копией из бэкапа и закрыл главный конфиг configuration.php правами 444.Казалось бы, автоматическая генерация мусора прекратилась. На всякий случай я натравил на сайт AIbolit и внутренний антивирус хостинга Beget. Результат? "Угроз не обнаружено, ваш сайт чист".
Но интуиция подсказывала: ручная зачистка папок "wp" убрала лишь следствие. Главный "скрипт-загрузчик" (downloader) остался на сервере под другим именем. И я пошел искать его руками через SSH.
Когда я подключился по SSH и начал ковырять файлы, стало понятно, почему автоматика спасовала. Хакеры использовали хитрую обфускацию (запутывание кода).
Вот пример одного из скрытых загрузчиков, который я вытащил на свет:
<?php
$a="ba"; $b="se"; $c="64"; $g="d"; $h="ec"; $i="o"; $j="de";
$k=$a.$b.$c."_".$g.$h.$i.$j;
$q=$k("aHR0cHM6Ly9...[вредоносная_ссылка]...");
eval("?>".$k($hh));
?>
Что здесь происходит:
base64_decode — но в коде её нет! Она склеивается на лету из кусочков переменных.eval().goto — код превращается в "спагетти", ломая алгоритмы автоматических антивирусов.Если вы подозреваете взлом, забудьте про экранные сканеры. Открывайте терминал, переходите в корень сайта (cd ~/ваш_домен/public_html) и включайте режим детектива.
В папках картинок, кэша и временных файлов PHP-скриптов быть не должно. Вообще. Никогда. Запускаем жесткий поиск:
find images/ media/ cache/ tmp/ templates/ -type f -name "*.php"
В моем случае команда выдала кучу легитимного кэша Smarty от CiviCRM (это нормально), но среди них ярко подсветился файл:
images/2021/07/LKfvaMQRVb.php
Случайное имя файла из букв разного регистра в папке картинок — это 100% приговор. Уничтожаем его:
rm images/2021/07/LKfvaMQRVb.php
Поскольку хакеры умеют прятать файлы глубоко в системное ядро Joomla (например, в /libraries/), ищем маркеры обфускации.
Ищем использование оператора goto (легитимный код Joomla его практически не использует):
grep -rnw . --include="*.php" -e "goto "
Ищем скрытый вызов функций выполнения кода:
grep -rnw . --include="*.php" -e "eval(" -e "base64_decode(" -e "gzinflate("
Как анализировать вывод: В результатах будет много системных файлов (компоненты голосования, платежные шлюзы). Но если среди них вы видите чужака, например: libraries/vendor/joomla/application/src/Cli/Output/Processor/IctrrIMEw.php — это бэкдор. В оригинальной Joomla файла с таким бредовым названием не существует.
Хакеры ленивы. Они генерируют один и тот же бэкдор и раскидывают его по разным папкам под разными именами.
Когда вы нашли один подтвержденный вирус, посмотрите в файловом менеджере его точный размер в байтах (например, 91195 байт или 35477 байт). И запустите поиск по точной маске размера:
find . -type f -size 91195c
find . -type f -size 35477c
(Буква c на конце обязательна — она указывает искать именно в байтах).
Этот финт помог мне найти еще несколько скрытых бэкдоров, которые запрятались на 5 уровней вглубь папок шаблонов и административных компонентов, куда обычный вебмастер в жизни не заглянет.
Вычистить файлы — половина дела. Хакеры часто создают скрытого Супер-администратора прямо в MySQL, чтобы спокойно зайти через админку позже. Обычно они используют неприметные логины вроде demo или system.
Вытаскиваем доступы из конфига и делаем прямой запрос в базу:
PASS=$(grep "public \$password" configuration.php | cut -d"'" -f2)
mysql -u ЮЗЕР_БД -p"$PASS" ИМЯ_БД -e "SELECT u.id, u.name, u.username, u.email, u.registerDate FROM jos_users u JOIN jos_user_usergroup_map m ON u.id = m.user_id WHERE m.group_id = 8;"
Группа 8 — это высшие права Super User. Внимательно изучите список. Если нашли старый неиспользуемый аккаунт demo с админскими правами — лишайте его прав немедленно:
mysql -u ЮЗЕР_БД -p"$PASS" ИМЯ_БД -e "DELETE FROM rq3nl_user_usergroup_map WHERE user_id = ID_ПОЛЬЗОВАТЕЛЯ;"
После того как повторный поиск по опасным функциям выдал абсолютную чистоту, нужно поставить "железный щит".
Даже если в будущем хакеры найдут уязвимость в другом компоненте, мы запретим серверу запускать PHP-код из папок, предназначенных только для картинок и кэша. Для этого создаем в папках images/, media/ и tmp/ файл .htaccess с кодом:
<Files *.php>
Deny from all
</Files>
Теперь при попытке вызвать любой загрузчик из этих папок сервер выдаст ошибку 403 Forbidden.
Итоговый чек-лист безопасности:
configuration.php.Взлом сайта — это огромный стресс, который может полностью пересрать рабочий день. Но ручной аудит через SSH возвращает контроль в ваши руки. Не надейтесь на автоматические сканеры: комбинируйте поиск по дате изменения, точным размерам файлов и опасным PHP-конструкциям. Только так можно выжечь заразу до последнего байта.
Когда все бэкдоры были уничтожены, а база проверена, я решил залить этот кейс в админку Joomla. Нажал кнопку "Сохранить" и тут же поймал по лбу новой ошибкой:
Не удалось сохранить из-за ошибки: Table 'v33387w4_botlab.#__finder_tokens' doesn't exist
Что это за чертовщина и при чем тут взлом?
Хакеры часто намеренно или случайно ломают, забивают мусором или полностью стирают таблицы компонента com_finder («Умный поиск»). Таблица #__finder_tokens хранит поисковые индексы, весит больше всего и при агрессивной работе хакерских скриптов часто "отваливается". Поскольку плагин умного поиска пытается индексировать любой новый материал в момент сохранения, отсутствие таблицы намертво блокирует работу с контентом.
Жизнь меня к этому не готовила, но лечится это дерьмо буквально в два клика прямо из панели Joomla, без ковыряния в phpMyAdmin:
Движок за пару секунд пересоздал отсутствующую rq3nl_finder_tokens, синхронизировал индексы, и статья успешно сохранилась с первого раза. Если кнопка "Исправить" не помогает, этот плагин (Умный поиск - Контент) можно временно отключить в Менеджере плагинов, чтобы вернуть сайту способность сохранять материалы.
Мы ценим каждого клиента и гордимся тем, что 60% клиентов снова возвращаются к нам.
Мы в социальных сетях