От автора: простая JavaScript инъекция, такая как ‘-alert(1)-’ или даже \’-alert(1)//, как правило, справляется с тем, чтобы выскочило окно предупреждения об уязвимой странице, когда отражение input происходит внутри блока скрипта и HTML-инъекция невозможна.
Но есть случаи, когда точка инъекции находится в середине более сложного кода JS: внутри функций и условий (if или if+else), вложенных друг в друга. Давайте рассмотрим пример такой инъекции, шаг за шагом.
Вам будет легко сделать это с помощью взаимодействия с пользователем, но все может стать сложнее, если вы не имеете навыков JS. Итак, у нас есть следующая точка отражения. Он находится в середине некоторого кода JS (keyword=aaaaa).
Затем мы пытаемся выполнить простую инъекцию JS, но перед каждой двойной кавычкой она экранируется обратной косой чертой.
Payload: “-confirm1
-”
Как мы знаем из Основных примеров XSS (пример #7), следующая хитрость — добавить обратную косую черту перед нашей первой кавычкой, чтобы «предотвратить предотвращение». Также необходимо закомментировать остальную часть строки.
Payload: \”-confirm1
//
Это работает, если мы изменим (через взаимодействие с пользователем) элемент select на странице.
Но есть лучший способ сделать это, так как эта «функция» будет доступна не во всех случаях, а также для этого требуется взаимодействия с пользователем.
План следующий: мы закроем все вложенные условия функций, а затем вставим наш код (confirm1
). Затем мы должны исправить оставшийся синтаксис, чтобы иметь возможность запускать нашу полезную нагрузку, поскольку весь блок скрипта не будет работать, если в нем есть какая-либо синтаксическая ошибка.
Мы начинаем нашу новую попытку с \”}})}) , которые являются последними 3 строками нашего фрагмента кода (без точек с запятой), чтобы закрыть «if », функцию «on+change» и функцию «document.ready». Остальное остается таким же, как и в предыдущей попытке.
Payload: \”}})})-confirm1
//
Конечно, это не работает, так как выполняется только половина построения полезной нагрузки (самая простая часть). Но ошибки, возвращаемые в консоли JS (в инструментах разработчика браузера нажмите F12), помогут нам разобраться.
Нажав на ссылку в правой части сообщения, мы обнаружим проблему.
Ошибка возникает в строке «else», потому что ее там не должно быть. Мы уже закрыли оператор if вместе с двумя функциями, поэтому нам нужно от нее избавиться.
В данном конкретном случае мы имеем дело с двойным отражением, поэтому мы попытаемся собрать их вместе, чтобы они стали единым целым, открыв комментарий в первом отражении и закрыв его во втором. Этого будет достаточно, чтобы избавиться от кода между этими двумя отражениями: строкой «else» и атрибуцией «document.location».
Многострочные комментарии в JS обозначаются /* и */, поэтому простое /* / в конце выполнит эту работу (оно парсируется, как /* в 1-м отражении и как */ во 2-м).
Payload: \”}})})-confirm1
/*/
Давайте проверим, что может означать эта ошибка.
Как мы видим, конец первого отражения до конца второго теперь отображается зеленым цветом. Таким образом, в конце нашего confirm1
код продолжается &pageIndex=1&startFrom=0, что интерпретируется как побитовый оператор AND (&) с недопустимым назначением переменной (pageIndex = 1).
Это можно просто решить, закомментировав оставшуюся часть строки с помощью // , добавленных в конец текущей полезной нагрузки. В результате мы получаем (с добавлением точки с запятой):
Payload: \”}})})-confirm1
;/*///
Теперь все, как и ожидалось, весь код после нашей введенной точки с запятой и до закрывающей «}» из оператора «if» комментируется. Итак, давайте добавим «{» в конец нашей полезной нагрузки, прямо перед комментарием.
Payload: \”}})})-confirm1
;{/*///
Бинго, парсер перешел на следующую строку с ошибкой в следующем закрытии!
Итак, давайте продолжим, пытаясь исправить «})», открыв новый с содержимым «({» перед «{», чтобы соблюдать синтаксис.
Payload: \”}})})-confirm1
;({{/*///
Что случилось? Из-за нового добавленного «({«, теперь наш первый «{» перестает работать, как «исправление» для оператора «if». Вернемся к экспериментам с добавленным «if ()» между «( {» а также «{«.
Payload: \”}})})-confirm1
;({if(){/*///
Отлично, мы сейчас на последней строчке! Мы просто повторяем то, что сделали на предыдущем шаге, добавляя еще одни «({» сразу после точки с запятой и перед «({if () {«.
Payload: \”}})})-confirm1
;({({if(){/*///
Что мы испортили на этот раз? Это происходило и раньше, мы просто сломали предыдущее «исправление». Чтобы исправить это, давайте добавим «function()» между недавно добавленными «(» и «{«.
Payload: \”}})})-confirm1
;(function(){({if(){/*///
Круто, мы только что разобрались с этим! Теперь мы сократим нашу полезную нагрузку.
Мы удаляем точку с запятой (заставляя синтаксический анализатор выдавать «непонятную ошибку», но все еще выполняться), и заменяем «if()» на метку «b:», а «function ()» на параметр функции стрелки «a =>». Имена «а», и «б» абсолютно произвольны.
Final Payload: \”}})})-confirm1
(a=>{({b:{/*///
Полный блок JS выглядит, как показано выше. Миссия выполнена.
Источник: https://brutelogic.com.br/
Редакция: Команда webformyself.