
CalderaForms 1.5.9.1 XSS (плагин WordPress) - руководство
CalderaForms 1.5.9.1 XSS (WordPress плагин) - учебное руководство
CalderaForm — это плагин для WordPress, позволяющий легко создавать формы с помощью drag and drop. Во время недавней работы мне довелось тестировать несколько порталов, один из которых содержал контактную форму, созданную с помощью этого плагина. Особая конфигурация данного инстанса позволила мне найти уязвимость: благодаря своей простоте, похожей на учебную, я думаю, это хороший повод проиллюстрировать некоторые механизмы новичкам.
Исключительно в образовательных целях - не используйте эту информацию для тестирования целей без явного разрешения и для незаконных целей - не ныряйте в холодную воду после еды - одевайтесь как луковица в жару
Полный эксплойт:
https://www.exploit-db.com/exploits/44489/
CVE:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-7747
В анализируемой конфигурации форма была настроена отвечать пользователю благодарственным сообщением, обращаясь к нему по только что введённому имени.
Чтобы воспроизвести тестовую среду, установите локально экземпляр WordPress и установите плагин CalderaForms версии 1.5.9.1 (доступен здесь или здесь).
После установки: в консоли администратора WordPress > левая колонка > "Caldera Forms" > верхние кнопки > "New Form" > выберите Contact Form, переименуйте и "Create Form"

После создания можно изменить его конфигурацию: верхние кнопки > "Form Settings" > измените Success Message так, чтобы он включал одно из введённых пользователем данных. Нажмите на поле, и появится выпадающий список подсказок.
Добавьте %first_name%

Верхние кнопки > "Save Form"
Чтобы вставить форму на страницу: левая колонка > "Pages" > "Sample Page" > "Edit" > "Caldera Form" > выберите созданную форму > "Insert Form" > правая колонка > "Update"

Готово.
Разберём по одному все шаги, необходимые для построения такой атаки, следуя парадигме «разделяй и властвуй».
При тестировании, когда вы взаимодействуете с компонентом, всегда нужно обращать внимание на его реакции на подаваемые стимулы; в частности, мы сосредоточимся на «пути» введённых нами данных и возможных преобразованиях, которым они подвергаются.
Конкретный пример для нашего случая следующий:
Посещаем страницу, содержащую форму: http://127.0.0.1/wordpress/sample-page/
Заполняем форму следующими данными
"First Name": myName
"Last Name": myLast
"Email Address": my@e.mail
"Comments": myComm
Данные обрабатываются согласно логике плагина
Полученное благодарственное сообщение содержит строку, которую мы ввели в поле First Name
"Thank you myName, form has been successfully submitted."

Строка, введённая нами в поле "First Name", возвращается нам в благодарственном сообщении.
В частности, строка содержится в HTML-теге div.
Наш ввод попадает в HTML страницы.
Вывод: «Нам это нравится. У нас есть точка контакта.»
Сделаем шаг вперёд. Как обрабатывается наш ввод на этапе, который мы назвали «обработкой» (пункт 2)? В частности, мы хотим узнать: есть ли ограничения на символы (и их комбинации), которые мы можем использовать?
Очевидно, цель — суметь внедрить «что-нибудь». При попытке выполнить инъекцию нужно помнить, где заканчивается наш ввод, и использовать подходящий «язык».
Наш ввод обрабатывается SQL-интерпретатором? Нужно говорить на его языке
Наш ввод обрабатывается PHP-скриптом? Нужно говорить на его языке
Наш ввод попадает на HTML-страницу? ...
Поэтому нам интересно понять, можем ли мы использовать типичные для HTML символы и конструкции, и в частности, учитывая способность этого языка содержать/интерпретировать код JavaScript, понять, найдём ли мы стратегию для размещения нашего кода в «зоне приземления», то есть в отмеченном ранее теге div.
Для этого вставим в поле "First Name" простой HTML-тег и посмотрим, будет ли он «санитизирован» (от sanitized), то есть изменён так, чтобы стать безвредным/неинтерпретируемым, или же будет возвращён как есть. Используем для этого тег <br>, который применяется для вставки разрыва строки в текст.
Следуя предыдущей нумерации:
Заполняем форму следующими данными
"First Name": m<br>yName
"Last Name": myLast
"Email Address": my@e.mail
"Comments": myComm
Благодарственное сообщение содержит наш HTML-тег, который не был изменён и корректно интерпретирован, вставляя разрыв строки в середину сообщения
"Thank you m
yName, form has been successfully submitted."

Вывод: «Нам это нравится. Мы можем использовать символы „меньше“ и „больше“, можем вставлять HTML-теги, которые не санитизируются и интерпретируются.»
Шаг вперёд. Заменим тег форматирования на что-то более полезное, например на тег <script>, который позволяет вставлять и выполнять код JavaScript внутри страницы.
Заполняем форму следующими данными
"First Name": m<script>alert(1);</script>yName
"Last Name": myLast
"Email Address": my@e.mail
"Comments": myComm
Благодарственное сообщение содержит наш HTML-тег, который не был изменён и корректно интерпретирован, показывая нам окно alert

Вывод 1: «Нам это нравится. Мы можем выполнять произвольный код JavaScript в контексте браузера пользователя.»
Вывод 2: «Нам это не нравится. Пользователь, выполняющий JavaScript, — мы сами»
Ситуация такая: мы можем выполнять JavaScript через сайт, который не контролируем, в контексте браузера пользователя, но этот пользователь в данный момент — тот же, кто вводит значения в форму. Всё это довольно бесполезно.
Идея в следующем: существует ли способ вызвать благодарственное сообщение, содержащее наш код, который нужно выполнить?
Вернёмся к нашей первой отправке, «разведывательной» (или заново выполним первые шаги).
Анализируя сетевой трафик или исходный код страницы, мы понимаем, что форма выполняет POST-запрос на адрес
http://127.0.0.1/wordpress/cf-api/CF5ad9b3176c0f4
(последняя часть может меняться; измените её соответствующим образом во всех следующих примерах)
то есть на адрес
http://<target>/cf-api/<form-id>
и что ответ на этот запрос — JSON, содержащий некоторые данные, включая благодарственное сообщение, со следующей структурой:
{
"data":
{"cf_id":"48"},
"html":"<div class=\" alert alert-success\">Thank you myName, form has been successfully submitted.<\/div>",
"type":"complete",
"form_id":"CF5ad9b3176c0f4",
"form_name":"MyContactForm",
"status":"complete"
}
Отложим эту информацию в сторону, скоро мы к ней вернёмся; особенно обратите внимание на поля "form_id" и "cf_id".
Что находится по адресу, на который выполняется POST? Не будем строить догадок — посмотрим, что произойдёт, если выполнить GET, то есть посетить страницу по адресу http://127.0.0.1/wordpress/cf-api/CF5ad9b3176c0f4, и обнаружим, ни много ни мало, HTML этой формы.
и проверяем сетевой трафик, возникающий после отправки

На этот раз мы получаем код HTTP 302 (redirect) на location /wordpress/cf-api/CF5ad9b3176c0f4/?cf_su=1&cf_id=49, который возвращает нам, ни много ни мало, HTML, содержащий тег div благодарственного сообщения.
Обратим внимание на формат этого адреса:
http://<target>/cf-api/<form-id>/?cf_su=1&cf_id=<cf-id>
где значения <form-id> и <cf-id> — это именно те, что содержались в ранее проанализированном JSON, а именно "form_id" и "cf_id".
Ответили ли мы на исходный вопрос? Да. Мы нашли способ вызвать содержимое благодарственного сообщения.
Вывод: «Нам это нравится. Мы можем при необходимости вызывать сообщение, содержащее наши данные.»
Подведём итоги, объединив всю собранную нами информацию, и соберём атаку.
1) сохраняем наш вредоносный код на target
2) собираем данные, необходимые для получения этого кода
3) строим URL, подходящий для «запуска» (от "to trigger") нашей атаки
Заполняем форму (с любой из двух страниц, неважно) следующими данными
"First Name": m<script>document.body.innerHTML=String.fromCodePoint(128046);</script>yName
"Last Name": myLast
"Email Address": my@e.mail
"Comments": myComm
Анализируя созданный трафик — либо читая JSON, полученный в случае страницы sample-page, либо читая redirect в случае страницы, содержащей только форму, — извлекаем идентификаторы form_id и cf_id
{
"data":
{"cf_id":"69"},
"html":"...",
"type":"...",
"form_id":"CF5ad9b3176c0f4",
"form_name":"...",
"status":"..."
}
http://127.0.0.1/wordpress/cf-api/CF5ad9b3176c0f4/?cf_su=1&cf_id=69

Некоторые замечания:
Читателю предлагается, если интересно:
' (апостроф, single quote), символа " (двойные кавычки, double quotes) или символа ` (гравис, backtick или backquote, grave accent), отсутствующего на раскладке итальянских клавиатур