Атака на сайт с wordpress через javascript и xss

Tartuga

Бывалый
ПРОВЕРЕННЫЙ ПРОДАВЕЦ
PREMIUM USER

Tartuga

Бывалый
ПРОВЕРЕННЫЙ ПРОДАВЕЦ
PREMIUM USER
Регистрация
7 Фев 2020
Сообщения
525
Реакции
98
Репутация
147
Недавно Nemesida WAF заблокировал довольно занимательную попытку атаки с использованием XSS и JavaScript. Несмотря на то, что я не являюсь JS-разработчиком, ради интереса решил разобраться в сути атаки. Особенность вектора заключается в специфике работы самого WordPress — возможность редактировать файлы тем через админ-панель, позволяя незаметно для администратора внедрить вредоносный код.

Пейлоад, представленный в виде JS, размещается на сайте через XSS-уязвимость, после чего ждет своего исполнения. Отработанный на стороне администратора веб-ресурса, код модифицирует содержимое файла темы WordPress (header.php), позволяя злоумышленнику закрепиться в системе и полностью скомпрометировать веб-приложение.

Первым делом код проверяет, есть ли у жертвы cookie, содержащие какие-нибудь значения из wp-settings, wp-admin и т.д. Если их нет, то выполняется переадресация на некоторые сайты, которые рекламировать я не буду, за рекламу мне не доплачивали.


Если cookie существуют, то создается несколько переменных. Например, в переменной e хранится имя домена, а в a — полезная нагрузка. В переменной p будет храниться XML-запрос.


Когда переменные созданы, выполняется GET-запрос на адрес из переменной t, в которой в это время хранится путь для редактирования темы в файле header.php. В нашем случае содержимое переменной будет выглядеть так: example.com/wp-admin/theme-editor.php?file=header.php

Если код ответа на GET-запрос равен 200, переменные t, p, d, i будут установлены, а если их нет — установятся или переопределятся. В переменную t попадет текст ответа, а переменные p, d, i заносят в массив данные согласно регулярным выражениям на основе информации, хранящейся в переменной t.


При этом, если переменные p, d, i не равны null, то скрипт ищет в 1-ом элементе массива переменной p значение chr(109).chr(46).chr(116).chr(120).chr(116). Если находит, то отправляет еще один GET-запрос в виде содержимого переменной e (переменная с доменом) + /wp-content/themes/d[1]/header.php (где первый элемент в массиве d — название темы). Если не находит элемент, то создается переменная r c HTML-элементом textarea, в который помещается значение элемента массива p[1], и создаются переменные:

  • c = a + o + encodeURIComponent(r.value), которая соединяет a (PHP-код), o (загрузку внешнего JS-скрипта), а также закодированное в URI значение переменной r;
  • s = d[1] — первый элемент масива d.

А вот содержимое запроса в переменной m = "nonce=" + encodeURIComponent(h) + "&_wp_http_referer=" + encodeURIComponent("/wp-admin/theme-editor.php?file=

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

") + "&theme=" + encodeURIComponent(s) + "&file=

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

&action=edit-theme-plugin-file&newcontent=" + c, вероятно, больше похоже на добавление/замену в header.php на значение переменной c.

Чтобы продемонстрировать, как это работает, основная полезная нагрузка (для наглядности) была заменена на пейлоад, позволяющий выполнить произвольный код на сервере. Если поместить пейлоад на странице сайта в виде какой-нибудь хранимой XSS, то при посещении страницы авторизованным пользователем сработает скрипт, который, в нашем случае, выполняет внешний JS, находящийся на удаленном сервере

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.


После выполнения скрипта, в

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

вносятся изменения в первую строчку.


И, как результат, мы можем выполнить произвольный код на стороне сервера, например, прочитать содержимое файла /etc/passwd.

 
Сверху