Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Отключить History API (https://javascript.ru/forum/misc/73230-otklyuchit-history-api.html)

brizing 30.03.2018 13:54

Отключить History API
 
На беке проверяется реферер, который указан в ajax запросе.
На фронте посетители могут исполнять JS.
Я заметил, что на фронте можно сделать history.pushState() и обратиться к серверу с нужным реферером.

Я знаю, что на этой странице History никогда не понадобится.

History = function() {};
history.__proto__.pushState = function() {};
history.__proto__.replaceState = function() {};
history.__proto__.back = function() {};
history.__proto__.forward = function() {};
history.__proto__.go = function() {};


После этого кода History API восстановить не получится?

Aetae 30.03.2018 16:10

Клиенту доверять нельзя. Если у сторонних скриптов есть доступ к вашему домену - вам можно только смириться.

brizing 30.03.2018 19:26

Aetae, тема не посвящена защите от XSS :) Но я пока уверен, что мы нашли защиту от любого способа атаки.
А входные данные очень простые:
1) есть страница /project/123, вы можете разместить на ней скрипт.
2) есть страница /account, с этой страницы админ может выполнить запрос по адресу /del с параметром {id: 123}
Вопрос: что сделает ваш скрипт, чтобы я (админ) при посещении страницы /project/123 случайно её удалил?

Сабж актуален. History API можно восстановить?

Белый шум 30.03.2018 21:11

document.body.append( document.createElement('iframe') );
history.__proto__.pushState = window.frames[0].history.pushState;

Aetae 30.03.2018 22:07

Вариантов куча на самом деле. Под чужие скрипты - только заводить отдельный домен.

Белый шум 31.03.2018 03:01

Вообще, стандартная защита - сессионные токены: https://learn.javascript.ru/csrf
А свои велосипеды лучше не изобретать если не являешься эскпертом в данной области.

brizing 31.03.2018 09:55

Белый шум, сессионный токен есть на другой странице.
Но с помощью JS можно получить код другой страницы и спарсить хеш :)

Против этого сервер отфутболивает все запросы, которые приходят от страницы с пользовательским скриптом.
Судя по всему, есть только один способ подменить referer в запросах.

Против вашего кода я попробовал сделать так:
function overrideContentAccess(iface) {

    var contentWindowDescriptor = Object.getOwnPropertyDescriptor(iface.prototype, "contentWindow");

    // По-видимому, в HTMLObjectElement.prototype.contentWindow не существует
    // в более ранних версиях Chrome, таких как 42.
    if (!contentWindowDescriptor) {
        return;
    }

    var getContentWindow = Function.prototype.call.bind(contentWindowDescriptor.get);

    contentWindowDescriptor.get = function () {
        return false;
    };

    Object.defineProperty(iface.prototype, "contentWindow", contentWindowDescriptor);
}

var interfaces = [HTMLFrameElement, HTMLIFrameElement, HTMLObjectElement];
for (var i = 0; i < interfaces.length; i++) {
    overrideContentAccess(interfaces[i]);
}

var iframe = document.createElement('iframe');
document.body.append( iframe );
console.log('iframeWindow:', iframe.contentWindow);


Но frames[0] по прежнему возвращает объект.

Белый шум 31.03.2018 10:39

brizing,
Это как можно спарсить код другой вкладки? Пример покажите, а то я не в курсах.

brizing 31.03.2018 10:47

Белый шум,
$.get('/account', function(data) {
  console.log(data);
});

brizing 31.03.2018 10:48

Я же не о вкладке говорю.

Белый шум 31.03.2018 13:42

brizing,
тогда у вас как-то неправильно токен реализован, ибо такой запрос должен выдавать страницу авторизации. Правильный запрос должен выглядеть как-то так:
$.get('/account?token=jtd9876vglijhkyrf53phj0');
- конкретное значение токена хранится в сессии, а ссылки с токеном присутствовать только на страницах админки (после авторизации).

Aetae 31.03.2018 16:24

Белый шум,
Если "админ после авторизации" зайдёт на страницу на том же домене с "юзерским" скриптом - то всё, гейм овер, скрипту доступно всё.
brizing,
Для недоверенных скриптов - только другой домен. Помимо очевидных вариантов, что вам указали, есть ещё сотни неочевидных.

Белый шум 31.03.2018 18:19

Aetae,
токены не должны содержаться в ссылках на неадминскую часть сайта (или где-либо ещё в неадминской части).
Ребята, ну вы чего - токенов никогда в действии не видели?

Aetae 31.03.2018 18:49

Белый шум, это ты путаешь.
Юзер заливает скрипт в /user, админ логинется в /admin и идёт в /user, скрипт с /user спокойно запрашивает /admin и забирает токены. Конец.
Токены защищают от csrf, важное тут cs - cross site. В пределах сайта это никакой защиты не даёт.

Белый шум 31.03.2018 18:58

Aetae,
ещё раз: если скрипт с /user запрашивает /admin, то в ответ получает страницу авторизации. Смысл токенов в том и состоит, что получить его можно только при авторизации, после чего его нужно передавать при каждом запросе к админской части сайта:
- запросил /admin?token=jtcvbliugkbk - получил содержимое страницы
- запросил /admin - получил сообщение "неверный токен" и форму авторизации

Aetae 01.04.2018 13:25

Белый шум, откуда админ возьмёт этот ваш jtcvbliugkbk?
Из куки? /user имеет доступ к куки.
Из ссылки в теле страницы? /user имеет доступ к телу страницы.
Человек переходя на /admin каждый раз заново авторизуется, а переходя по любой другой внутрисайтовой ссылке авторизацию теряет? Никто так делать не будет, т.к. неудобно. При том всё равно, если у такого "админа" случайно окажется висеть открытая вкладка с /user при заходе на /admin, то, как только авторизация пройдёт, скрипт с /user повторяющийся с интервалом получит все доступы.

Белый шум 01.04.2018 13:54

Цитата:

Сообщение от Aetae
откуда админ возьмёт этот ваш jtcvbliugkbk?

Из тела страницы в админке. Тупо все ссылки на админскую часть сайта уже идут с правильным токеном; ссылки на юзерскую часть - без токена (обычно их открывают в новой вкладке).
Цитата:

Сообщение от Aetae
/user имеет доступ к телу страницы.

/user - не админская страница, соответственно у неё нет доступа к токену.
Цитата:

Сообщение от Aetae
Человек переходя на /admin каждый раз заново авторизуется, а переходя по любой другой внутрисайтовой ссылке авторизацию теряет? Никто так делать не будет, т.к. неудобно.

Именно так и делают. Админская часть в одних вкладках, юзерская - в других. Немного неудобно, согласен, зато безопасно.
Цитата:

Сообщение от Aetae
При том всё равно, если у такого "админа" случайно окажется висеть открытая вкладка с /user при заходе на /admin, то, как только авторизация пройдёт, скрипт с /user повторяющийся с интервалом получит все доступы.

Не получит, ибо нет доступа к токену.

brizing 01.04.2018 14:38

Соглашусь, /admin?token=jtcvbliugkbk - это неудобно и, допустим, это крайний вариант.

Замечу также, что ссылка /admin?token=jtcvbliugkbk не должна давать доступ с другого устройства. Т.е. нужно ещё устанавливать авторизационную куку. Если кукак И токен валидные, выдавать админку.

Однако, document.referrer на странице /user может содержать "/admin?token=jtcvbliugkbk".
Чтобы этого избежать, на странице /admin необходимо размещать ссылку:
<a href="/redir?/user" target="_blank">

Aetae 01.04.2018 14:39

Белый шум,
Ну если ещё защитить referrer при переходе из админской части в юзерскую, то, наверное, такой колхоз работать будет, да.
Токен в каждой ссылке - жуть какая.
И всё равно яб такое использовать не стал, не ровен час очередная фича js поломает всю такую супер-безопасность.

brizing 01.04.2018 15:27

Даже при наличии в админке ссылки /redir?/user,
админ может, находясь на странице /admin?token=jtcvbliugkbk, вставить в адресную строку ссылку /user, перейти туда и будет доступен document.referrer (ой, ниже подсказали, что не будет).

Сервер должен блокировать /user, если HTTP_REFERER == /admin

Белый шум 01.04.2018 15:40

Цитата:

Сообщение от brizing
Соглашусь, /admin?token=jtcvbliugkbk - это неудобно и, допустим, это крайний вариант.

Активно работаю с движком опенкарт, где реализовано такое (правда, без защиты реферера) - вполне нормально на самом деле. Операторы, склад и хозяева сайтов проблем не испытывают.

Цитата:

Сообщение от brizing
<a href="/redir?/user" target="_blank">

Редирект не поможет, в реферере будет урл изначальной страницы. Если только там (на /redir?/user) будет редирект не http-заголовком, а яваскриптом - тогда поможет.
Или ещё такой вариант есть: https://caniuse.com/#feat=rel-noreferrer

Цитата:

Сообщение от brizing
админ может, находясь на странице /admin?token=jtcvbliugkbk, вставить в адресную строку ссылку /user, перейти туда и будет доступен document.referrer.

Нет.

Цитата:

Сообщение от Aetae
Токен в каждой ссылке - жуть какая.

Альтернативы какие?

Белый шум 01.04.2018 16:14

Цитата:

Сообщение от Белый шум
Или ещё такой вариант есть: https://caniuse.com/#feat=rel-noreferrer

Хотя в вашем случае всё-таки лучше яваскриптом.

Malleys 01.04.2018 20:55

Если контекст, где выполняются скрипты пользователей, находится внутри iframe, то возможно использовать атрибут sandbox.

Атрибут sandbox, если задан, включает набор дополнительных ограничений для любого содержимого, размещенного в iframe.

Когда атрибут установлен, содержимое обрабатывается как изолированный документ, формы, скрипты и различные потенциально мешающие API отключены, предотвращается переход ссылок на другие контексты браузинга, плагины безопасны.

Значение атрибута allow-same-origin заставляет считать содержимое происходящим из реального источника вместо того, чтобы считать его как изолированный документ, значение allow-top-navigation позволяет содержимому выполнять навигацию по его контексту браузинга верхнего уровня; а значения allow-forms, allow-pointer-lock, allow-popups и allow-scripts включают соответственно формы, API блокировки указателя, всплывающие окна и скрипты.

Пример:
<iframe sandbox="allow-scripts"></iframe>

В примере встроенное содержимое имеет включенный скриптинг, но отключены API, плагины, формы и не может выполняться навигация по фреймам или окнам, кроме самого себя (или по любым фреймам или окнам, которые оно само внедрило).


Часовой пояс GMT +3, время: 21:23.