Автор: miserylord
Эксклюзивно для форума: xss.pro
CVE, связанные с плагинами CMS WordPress, публикуются десятками в месяц, а иногда и в день. Но почему почти ничего не слышно о подобных уязвимостях в других CMS? Стоит ли просто предполагать, или лучше проверить?
Давайте разберёмся на примере 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.
Далее проходим по каждой ссылке на предмет поиска параметра href в кнопке btn btn-primary btn-large span12 main-download. Если в ней присутствует github.com – сохраняем найденное, если нет – пропускаем. GitHub есть примерно у каждого 10–15 расширения, без учёта платных или бесплатных.
В итоге вызовем для каждой GitHub-ссылки функцию, которая создаст новую папку, клонирует туда репозиторий, инициализирует Psalm, запустит анализ с флагами --report=res1.txt --taint-analysis и общим выводом в лог-файл, переходим на папку выше, и так для всех ссылок.
В результате, проверив около 50 репозиториев, результат получился довольно скромным.
Первая находка в расширении – https://extensions.joomla.org/extension/pesapal-for-hikashop/ – интеграция платёжки Pesapal к магазину Hikashop. В логах указан тип найденной уязвимости TaintedHtml: Detected tainted HTML, а также TaintedTextWithQuotes: Detected tainted text with possible quotes – обе эти уязвимости указывают на потенциальное XSS.
Это не выглядит так, словно у пользователя есть контроль над параметрами, поскольку код вставляет исключительно параметры, полученные в качестве ответа от мерчанта.
Да, впрочем, это совсем не важно – этот код в целом не может работать и никогда не делал этого:
Происходит присвоение вместо сравнения, и операция присвоения приводится к истине, так что проверка всегда 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
Вроде как тут параметр img получается от GET-запроса, но речь идёт об участке кода, который отвечает за капчу – что весьма абсурдно. Psalm не показывает, как идут данные, но они действительно идут из этого запроса:
Да, судя по коду, здесь и в правду может быть обход путей, но не загрузка файла, поскольку никакой загрузки не происходит.
Psalm — весьма интересный инструмент, но у меня есть ощущение, что он пропустит добрую половину уязвимостей. Или их нет в плагинах Joomla. Я проверил не все 5000, из которых примерно 300–500 будут со ссылками на GitHub, но из них хоть сколько-нибудь востребованных – возможно, около 50. Найденные же плагины –немного непопулярные.
Следующий способ анализа — это поиск сигнатур в коде, которые могут указывать на уязвимости. В сравнении с WordPress примеры практически недоступны. Явно можно взять разве что пример с XSS-уязвимостью из https://manual.joomla.org/docs/security/common-vulnerabilities/. Ещё несколько примеров:
Таким способом попадётся действительно много потенциальных XSS-уязвимостей, но при проверке становится понятно, что данные попадают не от пользователя – как, например, в расширении Thumbnail Mini Carousel, by Alvin Gil Saldaña - Joomla Extension Directory – но контроль $imageUrl вне поля пользовательского ввода.
Поиск 0day в CMS Joomla требует хорошего знания PHP, опыта и базы приватных сигнатур. Ввиду того что плагинов значительно меньше, чем в WordPress (и бесплатных, и с открытыми репозиториями — ещё меньше), найти уязвимость сложнее, но всё же возможно!
Эксклюзивно для форума: 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.
Это не выглядит так, словно у пользователя есть контроль над параметрами, поскольку код вставляет исключительно параметры, полученные в качестве ответа от мерчанта.
Да, впрочем, это совсем не важно – этот код в целом не может работать и никогда не делал этого:
Происходит присвоение вместо сравнения, и операция присвоения приводится к истине, так что проверка всегда 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
Вроде как тут параметр img получается от GET-запроса, но речь идёт об участке кода, который отвечает за капчу – что весьма абсурдно. Psalm не показывает, как идут данные, но они действительно идут из этого запроса:
Да, судя по коду, здесь и в правду может быть обход путей, но не загрузка файла, поскольку никакой загрузки не происходит.
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 вне поля пользовательского ввода.
Поиск 0day в CMS Joomla требует хорошего знания PHP, опыта и базы приватных сигнатур. Ввиду того что плагинов значительно меньше, чем в WordPress (и бесплатных, и с открытыми репозиториями — ещё меньше), найти уязвимость сложнее, но всё же возможно!
Последнее редактирование модератором: