Введение

25 марта 2024 года в рамках программы Bug Bounty Extravaganza исследователь под ником 1337_wannabe обнаружил уязвимость типа SQL-injection в одном из популярных плагинов для WordPress - LayerSlider.

Уязвимость получила идентификатор CVE-2024-2879 и балл CVSS равный 9,8 (критический).

Данный недостаток хоть и является по большей части SQL-инъекцией типа blind основанной на времени, всё равно позволяет злоумышленнику легко получить конфиденциальную информацию из базы данных.

Стоит выделить, что плагин LayerSlider достаточно популярен среди пользователей WordPress и насчитывает более 1 миллиона установок. Из чего можно сделать вывод, что на данный момент остается огромное количество уязвимых сайтов в сети, которые пока не обновились до последней версии, так как автоматические обновления данным плагином не поддерживаются.

Тестовый стенд

Для тестирования данной уязвимости мы подняли WordPress версии 6.5 и установили туда уязвимый плагин LayerSlider версии 7.9.11.

Чтобы проверить работоспособность плагина, создали из имеющихся шаблонов простой Popup и разместили его на тестовой странице.

Разбор уязвимости

В исходном коде плагина нас интересует функция ls_get_popup_markup(), находящаяся в файле assets/wp/actions.php.

Она является обработчиком HTTP GET запроса /wp-admin/admin-ajax.php?action=ls_get_popup_markup.

Из исходного кода видно, что плагин использует данную функцию для получения popup’a по id, где идентификатор может быть указан с помощью GET параметра. И если id не является числом, то он напрямую попадает в функцию find() класса LS_Sliders.

В самой функции find(), аргумент проходит несколько проверок. Первая из них - это проверка на тип. Прочитав конструкцию условного ветвления, становится понятно, что поддерживаются несколько вариантов аргумента, но нам интересен только последний, когда аргументом является map.

Начиная с 80 строки кода, мы можем наблюдать, как формируется запрос к базе данных. Примечательным местом тут является цикл со 102 строки по 107. Он написан с целью так называемого эскейпа спец символов SQL из пользовательского ввода. В результате такой процедуры все спецсимволы SQL синтаксиса просто экранируются. Но если обратить внимание на условие внутри данного цикла, становится ясно, что это не происходит с элементом стоящим под ключом 'where'. Скорее всего это было сделано с целью поддержки каких-то пользовательских фильтров на языке SQL, так как в коде ниже мы видим, как из этого элемента формируются дополнительные условия запроса.

В конце все части аргументов собираются в один запрос и он отправляется базе данных.

В итоге получается, что любые специальные символы и слова языка SQL, оставленные пользователем в параметре GET-запроса под ключом 'where', без изменений попадут напрямую в запрос к базе данных, а это означает, что в данном функционале присутствует уязвимость под названием SQL-инъекция.

Остаётся отметить, что из-за специфики того, как формируется данный запрос и какой ответ доходит до пользователя, здесь не получится реализовать UNION-based инъекцию и получить данные напрямую. Но это не исключает возможность воспользоваться time-based методом слепой SQL-инъекции.

Практическая эксплуатация

Опираясь на информацию полученную из разбора выше, можно составить подобный HTTP-запрос, где в URI, в параметре id, будет находиться наш пэйлоад.

http://192.168.3.10:32768/wp-admin/admin-ajax.php?action=ls_get_popup_markup&id[where]=1)

Обратите внимание как задается параметр id. Таким образом PHP поймет, что это тип данных array, а точнее map.

Для эксплуатации слепой SQL инъекции типа time-based мы будем использовать автоматизированный инструмент SQLmap.

В качестве аргументов укажем сформированный URI, а также параметры --level=3 и --risk=2, чтобы SQLmap проверил большее количество пэйлоадов.

Для демонстрации мы получали такие данные как имя текущего пользователя и имя хоста, для этого следует указать параметры --current-user и --hostname.

Итоговая команда получилась следующая:

sqlmap "http://192.168.3.10:32768/wp-admin/admin-ajax.php?action=ls_get_popup_markup&id[where]=1)" --level=3 --risk=2 --current-user --hostname

Из результата работы инструмента, помимо данных, можно увидеть, что он определил тип SQL-инъекции как time-based blind и использовал SLEEP в своих пэйлоадах.

Меры защиты

К счастью, эта уязвимость уже устранена в версии 7.10.1 LayerSlider, и всем пользователям данного плагина настоятельно рекомендуется обновиться до последней версии. Если обновление невозможно, тогда есть шанс, что удастся снизить некоторые риски с помощью WAF, который должен быть настроен на блокирование попыток внедрения SQL-кода, хотя на это не следует полагаться.

Заключение

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

Подписывайтесь на наш Telegram-канал

Комментарии (2)


  1. FanatPHP
    07.04.2024 04:51
    +2

    Боже, какая скука. Очередной плагин для уордпресс, разработанный немытым индусом. И крутой хакир, который умеет эксплуатировать уязвимости с помощью ключиков sqlmap (в результате получая не гордо заявленную "любую чувствительную информацию", а только бесполезную инфу, которую выдает sqlmap по умолчанию).

    При этом в самих инъекциях наш эксперт является специалистом 80 уровня, выдавая гениальные умозаключения типа

    так называемого эскейпа спец символов SQL из пользовательского ввода. В результате такой процедуры все символы SQL синтаксиса просто удаляются.

    Что такое "символы SQL синтаксиса" и куда они "удаляются" история умалчивает. Как и про осмысленность применения "так называемого эскейпа" к большинству элементов массива $args.


  1. windser
    07.04.2024 04:51

    А обновление действительно невозможно в случае вхождения этого плагина как бандл в состав темы, например, в The7 LayerSlider WP, а разработчик темы https://the7.io/ забанил РФ, хотя приобреталась бессрочная лицензия с обновлением! (( Повезло, что этот плагин не использовался, поэтому его деактивировали, забекапили и удалили во избежании несчастных случаев...