Javascript инъекция идет не так - PullRequest
1 голос
/ 18 апреля 2020

В нашем проекте Android (менеджер загрузок) нам нужно показать встроенный веб-браузер, чтобы мы могли отслеживать загрузки со всеми данными (заголовками, файлами cookie, данными постов), чтобы мы могли обрабатывать их должным образом.

К сожалению, WebView элемент управления, который мы используем, не обеспечивает никакого доступа к POST данным запросов, которые он делает. Поэтому мы используем хакерский способ получить эти данные. Мы вводим этот код javascript в каждый код html, загружаемый браузером:

<script language="JavaScript">

    HTMLFormElement.prototype._submit = HTMLFormElement.prototype.submit;
    HTMLFormElement.prototype.submit = formSubmitMonitor;

    window.addEventListener('submit', function(e) {
        formSubmitMonitor(e);
    }, true);

    function formSubmitMonitor(e) {
        var frm = e ? e.target : this;
        formSubmitMonitor_onsubmit(frm);
        frm._submit();
    }

    function formSubmitMonitor_onsubmit(f) {
        var data = "";
        for (i = 0; i < f.elements.length; i++) {
            var name = f.elements[i].name;
            var value = f.elements[i].value;
            //var type = f.elements[i].type;
            if (name)
            {
                if (data !== "")
                   data += '&';
                data += encodeURIComponent(name) + '=' + encodeURIComponent(value);
            }
        }

        postDataMonitor.onBeforeSendPostData(
                f.attributes['method'] === undefined ? null : f.attributes['method'].nodeValue,
                new URL(f.action, document.baseURI).href,
                data,
                f.attributes['enctype'] === undefined ? null : f.attributes['enctype'].nodeValue);
    }

    XMLHttpRequest.prototype.origOpen = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
        // these will be the key to retrieve the payload
        this.recordedMethod = method;
        this.recordedUrl = url;
        this.origOpen(method, url, async, user, password);
    };

    XMLHttpRequest.prototype.origSend = XMLHttpRequest.prototype.send;
    XMLHttpRequest.prototype.send = function(body) {
        if (body)
        {
            postDataMonitor.onBeforeSendPostData(
                this.recordedMethod,
                this.recordedUrl,
                body,
                null);
        }
        this.origSend(body);
    };

    const origFetch = window.fetch;
    window.fetch = function()
    {
        postDataMonitor.onBeforeSendPostData(
                "POST",
                "test",
                "TEST",
                null);
        return origFetch.apply(this, arguments);
    }

</script>

Как правило, он работает нормально.

Но в веб-интерфейсе Почты Google это не работает по неизвестной причине. Например, когда пользователь вводит свое имя пользователя и нажимает Next. Я думал, что он использует Fetch API, поэтому я добавил перехват для него тоже. Но это не помогло. Обратите внимание, что нам не нужно перехватывать учетные данные пользователя, но мы должны иметь возможность перехватывать все или ничего. К сожалению, так работает вся система ...

Добавление №1. Я нашел другой способ: не переопределять shouldInterceptRequest, но переопределять onPageStarted вместо этого и позвоните evaluateJavascript там. Таким образом, это работает даже на веб-сайте Google Mail! Но почему первый метод не работает тогда? Мы как-то нарушаем HTML код?

...