• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья В поисках 0-day в плагинах Joomla

miserylord

RAID-массив
Пользователь
Регистрация
13.05.2024
Сообщения
97
Реакции
319
Автор: miserylord
Эксклюзивно для форума: xss.pro


CVE, связанные с плагинами CMS WordPress, публикуются десятками в месяц, а иногда и в день. Но почему почти ничего не слышно о подобных уязвимостях в других CMS? Стоит ли просто предполагать, или лучше проверить?

Давайте разберёмся на примере Joomla!

Joomla


Joomla уступает WordPress по популярности, но всё же входит в топ-10 CMS.

В Joomla есть понятие расширений, однако их функциональность ограниченнее и более структурирована по сравнению с WordPress.

Также существуют компоненты и модули (определения здесь). Публичные CVE, связанные с Joomla, чаще всего описывают уязвимости именно в компонентах или модулях.

Уязвимости в расширениях встречаются редко и публикуются в количестве 1-10 в год в официальном списке уязвимых расширений, несмотря на то, что общее количество расширений довольно велико – около 5000, включая как платные, так и бесплатные.

В отличие от WordPress, где плагины хранятся централизованно, имеют открытую кодовую базу, историю изменений и возможность скачать старые версии, в Joomla это больше напоминает витрину с произвольными ссылками на загрузку. Эти ссылки могут вести куда угодно – на сайт разработчика, на архив, на GitHub, или вообще на неработающий ресурс.

В рамках анализа я сосредоточусь на тех расширениях, которые ведут на GitHub – это даёт возможность просматривать код и взаимодействовать с репозиторием удобно и понятно.

Добавлю также, что у Joomla есть аналоги WPScan – JoomScan, в котором последний коммит был более 5 лет назад. Его функционал сосредоточен на разведке всяких фишек типа бэкап-файлов и c-панелей. Проект далеко не настолько раскрученный, как WPScan.


Статические анализаторы кода

Самым популярным бесплатным статическим анализатором кода является phpstan, и, несмотря на то что он ищет баги в коде, как заявляется, он вообще не ищет то, что относится к уязвимостям. Он больше похож на линтер, строгий код-чекер, но даже самую простую SQL уязвимость он не распознаёт.

Для тестирования и поиска багов, связанных с уязвимостями, необходимо использовать анализатор с функциональностью taint-анализа, который мониторит именно потоки данных – откуда пришли, куда ушли, как туда попали – и сообщает об этих моментах.

Из публичных решений существует Psalm, и его флаг taint-analysis (Introduction - Documentation, https://psalm.dev/).

Особых инструкций, как с ним работать, я не нашёл, но, вроде как, сперва делаем ./vendor/bin/psalm --init, потом ./vendor/bin/psalm --taint-analysis. Если видим ошибки – исправляем, так как, скорее всего, чего-то не хватает, или не там запускается, или что-то ещё. Возможно, можно как-то оптимизировать результаты в плане его эффективности.

Я вспомнил, что видел много CVE в духе "найденная уязвимость в системе для доставки пиццы с 3 звездами на GitHub", и решил, прежде чем переходить к расширениям Joomla, проверить такие проекты.

Забегая вперёд, скажу, что проверять расширения Joomla я буду в чистом виде, не в рамках общей кодовой базы Joomla. Если запустить такую проверку на phpstan, он будет ругаться, что не хватает части кода, функций. Для этого можно задать моки этих функций (которые называются стабы). Пакеты этих стабов можно найти в Composer, либо запускать всё в рамках CMS. Поскольку мне не до конца было понятно, как это лучше сделать, пошёл проверять всякие системы, в которых точно не будет этих моментов.

Практически сразу нашёл 0day SQL-инъекции в какой-то системе для продажи автомобилей с ненулевым количеством звёзд (предполагаю, что накрученных). Ещё через пару репозиториев – в системе, связанной с образованием, которая, вроде как, имеет какой-то локальный спрос – ещё с десяток потенциальных 0day. Не столь явных, как в первой, но в целом выглядящих эксплуатируемыми. Psalm работает – возвращаемся к плагинам.

Сперва спарсим ссылки на страницы с расширениями. Шаг – 18 в параметре строки, поиск по классу extension-link.

Bash:
> all_ext.txt

for ((i=0; i<=954; i+=18)); do
    echo "Парсим страницу: $i"
    curl -s "https://extensions.joomla.org/category/photos-a-images/?start=$i" | \
    grep -oP '<a href="\K(/extension/[^"]+)(?=" class="extension-link")'
done | sort -u >> all_ext.txt

echo "Ссылки сохранены в all_ext.txt"

Далее проходим по каждой ссылке на предмет поиска параметра href в кнопке btn btn-primary btn-large span12 main-download. Если в ней присутствует github.com – сохраняем найденное, если нет – пропускаем. GitHub есть примерно у каждого 10–15 расширения, без учёта платных или бесплатных.

Bash:
> github_links.txt

while read -r ext_path; do
    full_url="https://extensions.joomla.org${ext_path}"
    echo "Проверяем: $full_url"

    html=$(curl -s "$full_url")

    download_link=$(echo "$html" | grep -oP '<a[^>]+class="btn btn-primary btn-large span12 main-download"[^>]+href="\K[^"]+')

    if [[ "$download_link" == *github.com* ]]; then
        echo "Найдено GitHub-сопровождаемое расширение:"
        echo "$full_url" >> github_links.txt
        echo "$download_link" >> github_links.txt
        echo "" >> github_links.txt
    fi

done < all_ext.txt

echo "Готово. GitHub-ссылки сохранены в github_links.txt"

В итоге вызовем для каждой GitHub-ссылки функцию, которая создаст новую папку, клонирует туда репозиторий, инициализирует Psalm, запустит анализ с флагами --report=res1.txt --taint-analysis и общим выводом в лог-файл, переходим на папку выше, и так для всех ссылок.

Bash:
LINK_FILE="github_links_only.txt"


counter=1

while read -r repo_url; do

    [[ -z "$repo_url" ]] && continue

    echo "[$counter] Обрабатываем репозиторий: $repo_url"

    dir_name="$counter"
    mkdir "$dir_name" && cd "$dir_name" || { echo "Ошибка входа в $dir_name"; exit 1; }

    echo "[$counter] Клонируем репозиторий..."
    git clone "$repo_url" . || { echo "Ошибка клонирования $repo_url"; cd ..; ((counter++)); continue; }

    echo "[$counter] Инициализация psalm..."
    psalm --init . || echo "[$counter] Ошибка инициализации psalm (возможно, уже инициализирован)"

    echo "[$counter] Запускаем анализ..."
    psalm --report=res1.txt --taint-analysis . > log.txt || echo "[$counter] Ошибка анализа psalm"

    echo "[$counter] Завершено. Возвращаемся на уровень выше."
    cd ..

    ((counter++))

done < "$LINK_FILE"

echo "✅ Обработка завершена."

В результате, проверив около 50 репозиториев, результат получился довольно скромным.

Первая находка в расширении – https://extensions.joomla.org/extension/pesapal-for-hikashop/ – интеграция платёжки Pesapal к магазину Hikashop. В логах указан тип найденной уязвимости TaintedHtml: Detected tainted HTML, а также TaintedTextWithQuotes: Detected tainted text with possible quotes – обе эти уязвимости указывают на потенциальное XSS.

Это не выглядит так, словно у пользователя есть контроль над параметрами, поскольку код вставляет исключительно параметры, полученные в качестве ответа от мерчанта.

1.png


Да, впрочем, это совсем не важно – этот код в целом не может работать и никогда не делал этого:

2.png


Происходит присвоение вместо сравнения, и операция присвоения приводится к истине, так что проверка всегда COMPLETED.

Второй результат — в плагине RWCards, by Ralf Weber - Joomla Extension Directory с описанием TaintedFile: Detected tainted file handling в файле https://github.com/loadbrain/joomla_rwcards/blob/master/site/captcha/captcha_image.php

3.png


Вроде как тут параметр img получается от GET-запроса, но речь идёт об участке кода, который отвечает за капчу – что весьма абсурдно. Psalm не показывает, как идут данные, но они действительно идут из этого запроса:
5.png


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

Psalm — весьма интересный инструмент, но у меня есть ощущение, что он пропустит добрую половину уязвимостей. Или их нет в плагинах Joomla. Я проверил не все 5000, из которых примерно 300–500 будут со ссылками на GitHub, но из них хоть сколько-нибудь востребованных – возможно, около 50. Найденные же плагины –немного непопулярные.


Regex’ы


Следующий способ анализа — это поиск сигнатур в коде, которые могут указывать на уязвимости. В сравнении с WordPress примеры практически недоступны. Явно можно взять разве что пример с XSS-уязвимостью из https://manual.joomla.org/docs/security/common-vulnerabilities/. Ещё несколько примеров:
  • move_uploaded_file($_FILES – как указание на потенциальный File Upload,
  • include $_GET['page'] . '.php'; – как указание на потенциальный LFI,
  • $db->query("SELECT – как на потенциальную SQL-инъекцию.
Bash:
#!/bin/bash

LINK_FILE="github_links_only.txt"
LOG_FILE="riuq.txt"
counter=11

> "$LOG_FILE"

while read -r repo_url; do
    [[ -z "$repo_url" ]] && continue

    echo "[$counter] Обрабатываем репозиторий: $repo_url"

    dir_name="$counter"
    mkdir "$dir_name" && cd "$dir_name" || { echo "Ошибка входа в $dir_name"; exit 1; }

    echo "[$counter] Клонируем репозиторий..."
    git clone "$repo_url" . || { echo "Ошибка клонирования $repo_url"; cd ..; ((counter++)); continue; }

    echo "[$counter] Ищем PHP-файлы и анализируем..."

    find . -type f -name "*.php" | while read -r file; do
        while IFS= read -r line; do

            if [[ "$line" == *'move_uploaded_file($_FILES'* ]]; then
                echo "[$counter][Потенциальный File Upload] $file: $line" | tee -a "../$LOG_FILE"
            fi

            if [[ "$line" =~ echo\ *\$[a-zA-Z0-9_]+- ]]; then
                echo "[$counter][Потенциальная XSS] $file: $line" | tee -a "../$LOG_FILE"
            fi

            if [[ "$line" =~ include\ *\$_GET\ *\[.*\] ]]; then
                echo "[$counter][Потенциальная LFI] $file: $line" | tee -a "../$LOG_FILE"
            fi

            if [[ "$line" == *'$db->query("SELECT'* ]]; then
                echo "[$counter][Потенциальная SQL-инъекция] $file: $line" | tee -a "../$LOG_FILE"
            fi

        done < "$file"
    done

    echo "[$counter] Готово. Возвращаемся..."
    cd ..

    ((counter++))

done < "$LINK_FILE"

echo "✅ Проверка завершена. Лог сохранён в $LOG_FILE"

Таким способом попадётся действительно много потенциальных XSS-уязвимостей, но при проверке становится понятно, что данные попадают не от пользователя – как, например, в расширении Thumbnail Mini Carousel, by Alvin Gil Saldaña - Joomla Extension Directory – но контроль $imageUrl вне поля пользовательского ввода.

6.png


Поиск 0day в CMS Joomla требует хорошего знания PHP, опыта и базы приватных сигнатур. Ввиду того что плагинов значительно меньше, чем в WordPress (и бесплатных, и с открытыми репозиториями — ещё меньше), найти уязвимость сложнее, но всё же возможно!

4.png
 
Последнее редактирование модератором:
В Joomla был специальный класс JRequest - https://api.joomla.org/cms-2.5/classes/JRequest.html, то есть в коде хреново фильтруемые переменные можно так же искать с помощью парсинга исходников на предмет getstring и getvar.
Например наличие переменной, полученной через GetString в SELECT, означает инъекцию.
 
Давно искал нормальный статический анализатор кода, который бы мне смог с сурс кода вывести потенциальные уязвимости. По итогу много перепробовал, ничего не подошло. Попробую ещё этот psalm,но чувствую, что все равно буду искать все по классике regex -> ручная обработка -> chatgpt -> тесты
 
regex -> ручная обработка -> chatgpt -> тесты
Дык это и есть бест вей, только лучше все-таки понимать, что в коде написано без gpt, оно иногда такую дичь несет, что у меня глазки кровоточат...
 
Дык это и есть бест вей, только лучше все-таки понимать, что в коде написано без gpt, оно иногда такую дичь несет, что у меня глазки кровоточат...
Ну с этим у меня проблем нет, но чатгпт все равно использовать приходится, когда совсем без идей остаюсь.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх