- PVSM.RU - https://www.pvsm.ru -
Использование npm — пакетного менеджера NodeJS — сопряжено с проблемами безопасности. Штатными средствами невозможно контролировать права доступа, предоставляемые библиотекам. Вкупе с обилием микромодулей это может привести к непредсказуемым последствиям, часть из уже случившегося описана здесь [1], и в лучших традициях экосистемы npm я на неё сошлюсь.
Под катом описывается proof-of-concept библиотеки, реализующей механизм загрузки npm-модулей с возможностью установить права подобно тому, как на Android можно выдавать приложению конкретные разрешения.
Вместо
var lib = require('untrusted-lib');
предлагается писать где-нибудь
var paraquire = require('paraquire')(module);
и затем
var lib = paraquire('untrusted-lib');
или же
var lib = paraquire('untrusted-lib', {builtin:{https:true}});
Исходный код доступен на гитхабе [2] под LGPLv3.
Кроме того я, не будучи достаточно опытным NodeJS-разработчиком, прошу у сообщества советов и обсуждения.
В настоящее время известно несколько векторов атаки на npm и его пакеты. Для атаки наиболее привлекательны те пакеты, от которых зависят многие другие пакеты.
npm install --ignore-scripts
Впрочем, интерактивный вариант (желательно с показом содержимого скрипта) был бы тоже не лишним.
Именно для борьбы с последним вектором и создана библиотека paraquire. Код недоверенных библиотек изолируется в отдельные контексты исполнения [6]. Активно используются внутренние средства [7] самой NodeJS для управления модулями. Иначе говоря, создана альтернативная система управления модулями, на возможность чего недвусмысленно указывают сами разработчики NodeJS.
В настоящее время API весьма небогато.
Итак, для начала загрузим саму библиотеку paraquire где-нибудь в относительно доверенном коде, т.е. коде нашего приложения:
var paraquire = require('paraquire')(module);
Обратите внимание на "(module)". Так как paraquire занимается управлением модулями, ему требуется знать, к какому именно модулю придётся подключать зависимости, поэтому подключение paraquire выглядит несколько необычно. Вы можете подключить paraquire к любому количеству модулей из вашего проекта.
Подключим теперь зависимости. Например, пусть untrusted-lib — библиотека, которой, по идее, ничего требоваться не должно (например, leftpad [8] или imurmurhash [9]). Тогда мы можем вовсе не давать ей доступ ни к чему, подключив её так:
var lib = paraquire('untrusted-lib');
Всё, попытка сделать require('fs') в коде untrusted-lib вызовет ошибку.
У функции paraquire есть и второй, опциональный, параметр-объект. Например, вот так можно предоставить библиотеке untrusted-lib доступ к встроенным модулям http и https, а также к консоли console и process.argv:
var lib = paraquire('untrusted-lib', {
builtin: {
http: true,
https: true,
},
sandbox: {
console: console,
process: {argv:process.argv}
},
});
Кстати, давать доступ ко всему process настоятельно не рекомендуется, в частности, из-за process.env и process.bindings('fs').
Как уже было сказано выше, я не являюсь достаточно опытным разработчиком, и потому эта краткая публикация имеет своей целью скорее инициировать обсуждение. Актуальна ли эта тема? Как подобные проблемы решаются в других языках, в частности, в Ruby и Python? Может быть, кто-то может предложить способ обойти paraquire и получить повышенные привилегии?
В каком направлении следует развивать API? Может быть, стоит проконсультироваться у кого-то из зарубежных мэтров? Какие вопросы осветить в дальнейших статьях и стОит ли их вообще писать?
Автор: NickKolok
Источник [10]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/262740
Ссылки в тексте:
[1] здесь: https://habrahabr.ru/company/ruvds/blog/335602/
[2] на гитхабе: https://github.com/nickkolok/paraquire
[3] SDSWanderer: https://habrahabr.ru/users/sdswanderer/
[4] комментарий: https://habrahabr.ru/post/336334/#comment_10382450
[5] здесь: https://habrahabr.ru/post/307822/
[6] контексты исполнения: https://nodejs.org/api/vm.html
[7] внутренние средства: https://github.com/nodejs/node/blob/master/lib/module.js
[8] leftpad: https://www.npmjs.com/package/leftpad
[9] imurmurhash: https://www.npmjs.com/package/imurmurhash
[10] Источник: https://habrahabr.ru/post/336334/
Нажмите здесь для печати.