Гид по технологиям

Сканер устаревших установок Joomla на сервере

• 6 min read • Безопасность • Обновлено 21 Nov 2025
Сканер устаревших Joomla на сервере
Сканер устаревших Joomla на сервере

Зачем это важно

Устаревшие установки CMS часто становятся входной точкой для взломов, рассылки спама и других инцидентов безопасности. Этот гайд фокусируется на Joomla — популярной CMS, особенно часто встречающейся на shared hosting — и описывает простой способ массовой проверки версий по файловой структуре сайтов.

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

Предпосылки

  • На сервере должны быть установлены утилиты bc и sed. Они не всегда присутствуют по умолчанию. Установите через менеджер пакетов, если нужно (apt, yum, pacman и т.п.).
  • У вас есть доступ к shell и правами на чтение сайтов (обычно root или администратор).

Короткая методология

  1. Найти каталоги с именем components (характерно для Joomla).
  2. Извлечь путь до корня установки (dirname).
  3. Внутри установки прочитать файл с версией (несколько возможных мест).
  4. Сравнить главную версию и минор с текущими ветками (используем bc для сравнения нецелочисленных значений).
  5. Вывести предупреждения и опционально записать CSV-отчёт.

Какие файлы содержат версию Joomla

В разных версиях Joomla информация о версии хранится в одном из следующих файлов:

  • /libraries/joomla/version.php
  • /libraries/cms/version/version.php
  • /includes/version.php

В этих файлах важны две переменные: RELEASE (главная версия) и DEV_LEVEL (минор, или build). Пример содержимого:

var $RELEASE = ‘1.0’; var $DEV_LEVEL = ‘12’;

Поиск установок Joomla на сервере

Общая идея — найти все папки с именем components, но игнорировать административные каталоги:

find /var/www/ -type d -name ‘components’ ! -wholename ‘/administrator/components’

Замените /var/www/ на базовый путь сайтов на вашей машине. Если у вас ISPConfig 3, базовый путь обычно выглядит как /var/www/clients/client/web (см. совет ниже).

Чтобы перебрать все найденные каталоги в цикле и получить путь до корня установки:

for L in find /var/www/ -type d -name 'components' ! -wholename '/administrator/components' ; do D=dirname $L ; done

Получение главной и минорной версии из файла

Сначала проверяем, какой из трёх возможных файлов с версией присутствует, затем извлекаем значения переменных RELEASE и DEV_LEVEL с помощью grep и sed:

F=$D/libraries/joomla/version.php ; F2=$D/libraries/cms/version/version.php ; F3=$D/includes/version.php ; if [[ -e “$F” || -e “$F2” || -e “$F3” ]] ; then if [[ -e “$F” ]] ; then F=$F ; elif [[ -e “$F2” ]] ; then F=$F2 ; elif [[ -e “$F3” ]] ; then F=$F3 ; fi else echo “No joomla version file found.” ; fi

VERSION=grep '$RELEASE' $F | sed -r "s/^.*=\s*'(.*)'.*$/\1/g" ; SUBVERSION=grep '$DEV_LEVEL' $F | sed -r "s/^.*=\s*'(.*)'.*$/\1/g" ;

Примечание: конструкция sed извлекает содержимое кавычек; она устойчива к пробелам вокруг знака =.

Сравнение версий

Поскольку версии в виде 1.5, 2.5 и т.п. не всегда корректно сравниваются как целые числа в bash, используем утилиту bc для арифметических сравнений. Пример логики:

ISOK=1 ; if [[ $(echo “if (${VERSION} < 1.5) 1 else 0” | bc) -eq 1 ]] ; then

ISOK=0 ; elif [[ $(echo “if (${VERSION} == 1.5) 1 else 0” | bc) -eq 1 && $(echo “if (${SUBVERSION} < 26) 1 else 0” | bc) -eq 1 ]] ; then

ISOK=0 ;

further checks

else ISOK=1 ; fi

Эту логику удобно вынести в отдельный блок, где вы задаёте «текущие» версии для каждой ветки (например, CUR15, CUR25, CUR3) и сравниваете найденную установку с этими константами.

Готовый скрипт для проверки (joomlascan.sh)

Ниже приводится полный пример скрипта. Сохраните его как joomlascan.sh и запустите через bash joomlascan.sh. Если передать имя файла как аргумент, скрипт создаст CSV-отчёт.

#!/bin/bash

# текущая минорная версия для ветки 1.5
CUR15=26
# текущая минорная версия для ветки 2.5
CUR25=17
# текущая минорная версия для ветки 3.2
CUR3=1

# базовый путь для сайтов
BASEPATH="/var/www/"

# файл CSV для вывода (опционально)
OUTFILE=$1

if [[ "$OUTFILE" != "" ]] ; then
    # очистить/создать CSV
    echo -n "" > $OUTFILE ;
fi

for L in `find ${BASEPATH} -type d -name 'components' ! -wholename '**/administrator/components' | grep -v '/tmp/'` ; do
    D=`dirname $L` ;
    F=$D/libraries/joomla/version.php ;
    F2=$D/libraries/cms/version/version.php ;
    F3=$D/includes/version.php ;
    ISOK=0 ;
    SHOWNEWEST="" ;
    IMPORTANCE=0 ;
    if [[ -e "$F" || -e "$F2" || -e "$F3" ]] ; then
        if [[ -e "$F" ]] ; then
            F=$F ;
        elif [[ -e "$F2" ]] ; then
            F=$F2 ;
        elif [[ -e "$F3" ]] ; then
            F=$F3 ;
        fi
        VERSION=`grep '$RELEASE' $F | sed -r "s/^.*=\s*'(.*)'.*$/\1/g"` ;
        SUBVERSION=`grep '$DEV_LEVEL' $F | sed -r "s/^.*=\s*'(.*)'.*$/\1/g"` ;
        if [[ $(echo "if (${VERSION} < 1.5) 1 else 0" | bc) -eq 1 ]] ; then
            # версия ниже 1.5
            SHOWNEWEST="1.5.${CUR15}" ;
            IMPORTANCE=3 ;
        elif [[ $(echo "if (${VERSION} == 1.5) 1 else 0" | bc) -eq 1 && $(echo "if (${SUBVERSION} < ${CUR15}) 1 else 0" | bc) -eq 1 ]] ; then
            # версия 1.5.x, но не самая свежая из ветки
            SHOWNEWEST="1.5.${CUR15}" ;
            IMPORTANCE=2 ;
        elif [[ $(echo "if (${VERSION} == 1.6) 1 else 0" | bc) -eq 1 ]] ; then
            # версия 1.6 — рекомендовать 2.5
            SHOWNEWEST="2.5.${CUR25}" ;
            IMPORTANCE=2 ;
        elif [[ $(echo "if (${VERSION} == 1.7) 1 else 0" | bc) -eq 1 ]] ; then
            # версия 1.7 — рекомендовать 2.5
            SHOWNEWEST="2.5.${CUR25}" ;
            IMPORTANCE=2 ;
        elif [[ $(echo "if (${VERSION} > 1.7) 1 else 0" | bc) -eq 1 && $(echo "if (${VERSION} < 2.5) 1 else 0" | bc) -eq 1 ]] ; then
            # версия между 1.7 и 2.5
            SHOWNEWEST="2.5.${CUR25}" ;
            IMPORTANCE=2 ;
        elif [[ $(echo "if (${VERSION} == 2.5) 1 else 0" | bc) -eq 1 && $(echo "if (${SUBVERSION} < ${CUR25}) 1 else 0" | bc) -eq 1 ]] ; then
            # ветка 2.5, но не самая свежая
            SHOWNEWEST="2.5.${CUR25}" ;
            IMPORTANCE=1 ;
        elif [[ $(echo "if (${VERSION} >= 3) 1 else 0" | bc) -eq 1 && $(echo "if (${VERSION} < 3.2) 1 else 0" | bc) -eq 1 ]] ; then
            # версия 3.0 или 3.1 — рекомендовать 3.2
            SHOWNEWEST="3.2.${CUR3}" ;
            IMPORTANCE=2 ;
        elif [[ $(echo "if (${VERSION} == 3.2) 1 else 0" | bc) -eq 1 && $(echo "if (${SUBVERSION} < ${CUR3}) 1 else 0" | bc) -eq 1 ]] ; then
            # версия 3.2, но минорная сборка ниже текущей
            SHOWNEWEST="3.2.${CUR3}" ;
            IMPORTANCE=1 ;
        else
            ISOK=1 ;
            echo "[INFO] version $VERSION.$SUBVERSION in $D is ok." ;
        fi
    else
        # похоже, это не Joomla
        ISOK=1 ;
    fi ;
    
    if [[ $ISOK -eq 0 ]] ; then
        echo "[WARN] outdated Joomla version $VERSION.$SUBVERSION in $D" ;
        if [[ "$OUTFILE" != "" ]] ; then
            # записать в CSV
            echo "\"$D\";$VERSION.$SUBVERSION;$SHOWNEWEST;$IMPORTANCE" >> $OUTFILE ;
        fi
    fi
done

exit 0 ;

Пример вывода

[INFO] version 1.5.26 in /var/www/xxx is ok. [WARN] outdated Joomla version 1.0.12 in /var/www/yyy [WARN] outdated Joomla version 1.5.14 in /var/www/zzz [WARN] outdated Joomla version 2.5.8 in /var/www/aaa [WARN] outdated Joomla version 1.5.10 in /var/www/bbb

Если вы указали имя CSV-файла при вызове, он будет содержать строки вида:

“/var/www/yyy”;1.0.12;1.5.26;3

Где последний столбец — условный индекс важности (чем больше — тем критичнее обновление).

Что делать после обнаружения устаревших установок

  • Оцените критичность: публичный сайт, административная панель доступна извне, использует ли сайт плагины с уязвимостями.
  • Если возможно — выполните резервное копирование файлов и базы данных перед обновлением.
  • Для больших различий между ветками (например, 1.5 → 2.5 или 3.x) изучите документацию по миграции: просто обновить может быть недостаточно — часто требуется перенос данных и тестирование.
  • Для быстро устраняемых уязвимостей ищите security-патчи или временные обходы (удаление уязвимого компонента, отключение модулей).

Важно: не обновляйте «вживую» без тестовой среды, если сайт критичен для бизнеса.

Альтернативные подходы и инструменты

  • Netcraft, Wappalyzer, WhatWeb — позволяют определить CMS по HTTP-ответам, но могут ошибаться.
  • Использовать автоматизированные сканеры уязвимостей (Nessus, OpenVAS) для оценки рисков, но они требуют настройки и дают много «шумных» результатов.
  • Управляемые решения: панели хостинга (cPanel/ISPConfig) иногда предоставляют централизованный список версий.

Преимущество данного файлового подхода — он локален, не зависит от внешних HTTP-заголовков и работает без запуска сайта.

Когда метод не сработает (примеры)

  • Если файловая структура модифицирована владельцем сайта и файлы версий переименованы или удалены.
  • Если сайт — кастомная сборка на базе Joomla с изменёнными путями.
  • Для Mambo (старый форк) скрипт не различает Mambo и помечает их как OK. Это известное ограничение.

Чеклист для администратора (role-based)

  • Системный администратор:
    • Убедиться в наличии bc и sed.
    • Запустить скрипт с правами, достаточными для чтения сайтов.
    • Просмотреть CSV-отчёт, сортировать по важности.
  • DevOps/разработчик:
    • Подготовить тестовую среду и план миграции для критичных сайтов.
    • Проверить плагины и расширения на совместимость.
  • Менеджер проекта/владелец сайта:
    • Утвердить окно технического обслуживания.
    • Принять решение об обновлении или о переносе в новую ветку CMS.

Мини-руководство по миграции (high-level)

  1. Создайте резервную копию файлов и БД.
  2. Разверните копию на тестовом сервере.
  3. Обновите расширения, отключите неподдерживаемые плагины.
  4. Последовательно обновите Joomla по официальной инструкции (межшаговые обновления, если требуется).
  5. Протестируйте функциональность и производительность.
  6. Запланируйте перенос на продакшн при подтверждённой работоспособности.

Ограничения и известные проблемы

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

Рекомендации по безопасности

  • Регулярно сканируйте серверы и обновляйте CMS и плагины.
  • Закрывайте доступ к административной панели (IP-ограничения, двухфакторная аутентификация).
  • Минимизируйте набор установленных расширений — чем меньше кода, тем меньше возможных уязвимостей.

Краткое резюме

  • Поиск по каталогу components и чтение файлов версии — надёжный и простой способ массово обнаружить установки Joomla.
  • Скрипт помогает быстро получить список устаревших версий и подготовить план обновлений.
  • Для миграции между крупными ветками требуются тестирование и подготовка.

Коротко: запуск joomlascan.sh даст вам показательный список потенциально уязвимых сайтов и облегчит приоритизацию работ по обновлению.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Несколько аккаунтов Skype: Multi Skype Launcher
Программное обеспечение

Несколько аккаунтов Skype: Multi Skype Launcher

Журнал для работы: повысить продуктивность
Productivity

Журнал для работы: повысить продуктивность

Персональные звуки уведомлений на Android
Android.

Персональные звуки уведомлений на Android

Скачивание шоу Hulu для офлайн‑просмотра
Стриминг

Скачивание шоу Hulu для офлайн‑просмотра

Microsoft Start: персонализированная новостная лента
Новости

Microsoft Start: персонализированная новостная лента

Как изменить имя в Epic Games быстро
Гайды

Как изменить имя в Epic Games быстро