Как стать автором
Обновить

UserJS. Часть 3: Безопасность

Время на прочтение2 мин
Количество просмотров1.3K
В этой статье описывается, чем опасны некоторые userjs трюки и как с этой опасностью справиться.

Другие статьи серии:

LiveConnect


Опасность этой технологии очевидна. Как только Вы разрешаете доступ с некоторого адреса к расширенным возможностям (например, работать с буфером обмена), как все скрипты с этого адреса могут использовать расширенные возможности в своих целях (например, отсылать содержимое буфера на сайт — вдруг там пароль).

Решение состоит в том, чтобы разрешить доступ только одному адресу — «http://0.0.0.0/», открыть фрейм с этим адресом и все действия производить через XDM. Неудобство состоит в том, что все вызовы становятся асинхронными. Но чего не сделаешь ради безопасности. Да и есть в этом некоторый плюс — скрипты на странице не повиснут в ожидании какого-нибудь долгого синхронного вызова.

Теперь нужно обезопасить XDM.

XDM


Любой скрипт на странице может найти iframe и отправить ему сообщение. Достаточно лишь знать формат сообщений. Узнать — не проблема, если userjs выложен в сети. Да даже если userjs написан Вами и для себя, часто формат угадать несложно.

Итак, задача — сделать формат неугадываемым. Для этого нужно:
  • для каждого пользователя сгенерировать пароль;
  • добавлять в начало каждого сообщения;
  • использовать событие «BeforeEvent.message», чтобы мы первым узнавали о сообщении;
  • обрабатывать только сообщения с подходящим паролем;
  • использовать функцию «Event.preventDefault» для предотвращения получения сообщений скриптом на странице.


Консервируем функции


Но и этого ещё недостаточно для обеспечения безопасности.

К сожалению, userjs выполняются в контексте страницы. А значит все модификации объектов скриптами со страницы отражаются и на userjs.

Предположим, что проверка пароля в userjs производится следующим образом:
if (ev.data.substring(0, password.length) == password) { ... }


Тогда скрипт на странице может выполнить:
String.prototype.substring = function(start, len) { alert(this); }

и получить пароль!

Необходимо сохранить функции, используемые в критических местах userjs:
// В самом начале скрипта.
var functionCall = Function.prototype.call;
var stringSubstring = String.prototype.substring;

// В обработчике события.
stringSubstring.call = functionCall;
if (stringSubstring.call(ev.data, 0, password.length) == password) { ... }
Теги:
Хабы:
Всего голосов 16: ↑14 и ↓2+12
Комментарии0

Публикации

Истории

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
26 октября
ProIT Network Fest
Санкт-Петербург
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань