• XSS.stack #1 – первый литературный журнал от юзеров форума

Продвинутые JavaScript-инъекции

pablo

(L2) cache
Пользователь
Регистрация
01.02.2019
Сообщения
433
Реакции
1 524
Простая JavaScript инъекция, такая как
Код:
‘-alert(1)-’
или даже
Код:
\’-alert(1)//
, как правило, справляется с тем, чтобы выскочило окно предупреждения об уязвимой странице, когда отражение input происходит внутри блока скрипта и HTML-инъекция невозможна.


Но есть случаи, когда точка инъекции находится в середине более сложного кода JS: внутри функций и условий (if или if+else), вложенных друг в друга. Давайте рассмотрим пример такой инъекции, шаг за шагом.

Вам будет легко сделать это с помощью взаимодействия с пользователем, но все может стать сложнее, если вы не имеете навыков JS. Итак, у нас есть следующая точка отражения. Он находится в середине некоторого кода JS (keyword=aaaaa).

pH3h13Hx8bg.jpg

Затем мы пытаемся выполнить простую инъекцию JS, но перед каждой двойной кавычкой она экранируется обратной косой чертой.

Код:
Payload: “-confirm1-”

f8s8tDk-WF8.jpg

Как мы знаем из Основных примеров XSS (пример #7), следующая хитрость — добавить обратную косую черту перед нашей первой кавычкой, чтобы «предотвратить предотвращение». Также необходимо закомментировать остальную часть строки.

Код:
Payload: \”-confirm1//

Cmv4uz3oKdc.jpg

Это работает, если мы изменим (через взаимодействие с пользователем) элемент select на странице.

IdVq8t1vkGc.jpg

Но есть лучший способ сделать это, так как эта «функция» будет доступна не во всех случаях, а также для этого требуется взаимодействия с пользователем.

План следующий: мы закроем все вложенные условия функций, а затем вставим наш код (confirm1). Затем мы должны исправить оставшийся синтаксис, чтобы иметь возможность запускать нашу полезную нагрузку, поскольку весь блок скрипта не будет работать, если в нем есть какая-либо синтаксическая ошибка.

Мы начинаем нашу новую попытку с \”}})}) , которые являются последними 3 строками нашего фрагмента кода (без точек с запятой), чтобы закрыть «if », функцию «on+change» и функцию «document.ready». Остальное остается таким же, как и в предыдущей попытке.

Код:
Payload: \”}})})-confirm1//

2zUdwOxA9AE.jpg

Конечно, это не работает, так как выполняется только половина построения полезной нагрузки (самая простая часть). Но ошибки, возвращаемые в консоли JS (в инструментах разработчика браузера нажмите F12), помогут нам разобраться.

RBbz94-J3aM.jpg

Нажав на ссылку в правой части сообщения, мы обнаружим проблему.

c3-Ez6ztfdw.jpg

Ошибка возникает в строке «else», потому что ее там не должно быть. Мы уже закрыли оператор if вместе с двумя функциями, поэтому нам нужно от нее избавиться.

В данном конкретном случае мы имеем дело с двойным отражением, поэтому мы попытаемся собрать их вместе, чтобы они стали единым целым, открыв комментарий в первом отражении и закрыв его во втором. Этого будет достаточно, чтобы избавиться от кода между этими двумя отражениями: строкой «else» и атрибуцией «document.location».

Многострочные комментарии в JS обозначаются /* и */, поэтому простое /* / в конце выполнит эту работу (оно парсируется, как /* в 1-м отражении и как */ во 2-м).

Код:
Payload: \”}})})-confirm1/*/

rIL_m-HMvSw.jpg

Давайте проверим, что может означать эта ошибка.

J9qRWFNpZhQ.jpg

Как мы видим, конец первого отражения до конца второго теперь отображается зеленым цветом. Таким образом, в конце нашего confirm1 код продолжается &pageIndex=1&startFrom=0, что интерпретируется как побитовый оператор AND (&) с недопустимым назначением переменной (pageIndex = 1).

Это можно просто решить, закомментировав оставшуюся часть строки с помощью // , добавленных в конец текущей полезной нагрузки. В результате мы получаем (с добавлением точки с запятой):

Код:
Payload: \”}})})-confirm1;/*///

bCiKOULvSKQ.jpg

Теперь все, как и ожидалось, весь код после нашей введенной точки с запятой и до закрывающей «}» из оператора «if» комментируется. Итак, давайте добавим «{» в конец нашей полезной нагрузки, прямо перед комментарием.

Код:
Payload: \”}})})-confirm1;{/*///

wTQeYzTPihw.jpg

Бинго, парсер перешел на следующую строку с ошибкой в следующем закрытии!

Итак, давайте продолжим, пытаясь исправить «})», открыв новый с содержимым «({» перед «{», чтобы соблюдать синтаксис.

Код:
Payload: \”}})})-confirm1;({{/*///

ryXnVSOxYvw.jpg

Что случилось? Из-за нового добавленного «({«, теперь наш первый «{» перестает работать, как «исправление» для оператора «if». Вернемся к экспериментам с добавленным «if ()» между «( {» а также «{«.

Код:
Payload: \”}})})-confirm1;({if(){/*///

gC9Fd8tgbBQ.jpg

Отлично, мы сейчас на последней строчке! Мы просто повторяем то, что сделали на предыдущем шаге, добавляя еще одни «({» сразу после точки с запятой и перед «({if () {«.

Код:
Payload: \”}})})-confirm1;({({if(){/*///

Jk84JGr4hDk.jpg

Что мы испортили на этот раз? Это происходило и раньше, мы просто сломали предыдущее «исправление». Чтобы исправить это, давайте добавим «function()» между недавно добавленными «(» и «{«.

Код:
Payload: \”}})})-confirm1;(function(){({if(){/*///

PSJ_6cQzAZM.jpg

Круто, мы только что разобрались с этим! Теперь мы сократим нашу полезную нагрузку.

Мы удаляем точку с запятой (заставляя синтаксический анализатор выдавать «непонятную ошибку», но все еще выполняться), и заменяем «if()» на метку «b:», а «function ()» на параметр функции стрелки «a =>». Имена «а», и «б» абсолютно произвольны.

Код:
Final Payload: \”}})})-confirm1(a=>{({b:{/*///

8PC9AKjfGh4.jpg

Полный блок JS выглядит, как показано выше. Миссия выполнена.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх