Чем опасны сторонние модули Node.js
В проектах с npm-модулями, как правило, содержится много стороннего кода, что негативно сказывается на безопасности. Выясняем, что с этим можно сделать.
9К открытий9К показов
Согласно недавно проведённому опросу от npm (менеджер пакетов, входящий в состав Node.js), выяснилось, что 77% респондентов озабочены безопасностью стороннего кода. Эта статья посвящена уязвимостям, которым подвергаются приложения, использующие готовые сторонние решения.
Стоит ли мне волноваться из-за сторонних модулей?
Возможно, вы даже думаете: а с чего мне вообще переживать по поводу сторонних модулей? Программисты — достаточно дружелюбный народ, с чего мне сомневаться в модулях, которыми делятся другие программисты? К тому же, если каждый пакет на npm является open source, должно быть, есть море людей, проверивших каждую строку кода, не так ли? Кстати, у меня всего-то несколько чужих модулей, насколько сторонним можно считать этот код?
Прежде чем разбираться в ответах, давайте ознакомимся со статьей «Я краду ваши пароли и номера кредиток. И я расскажу как». Это придуманная история от автора модуля на Node.js, выложенном на npm, — модуль может незаметно красть информацию о кредитных картах с веб-сайтов. В материале также описываются различные методы скрытия этих действий. Например, код никогда не исполняется, когда хостится на localhost; он никогда не активируется, когда открыта консоль разработки. На самом деле по времени он работает очень мало. Код, опубликованный на npm, скрыт и отличается от кода, который хостится публично на GitHub. Хотя история и выдуманная, но технически она вполне реализуема.
Есть ли случаи, когда это действительно проворачивают? На npm недавно опубликовали статью «Reported Malicious module: getcookies». Эта статья описывает реальный случай, когда модуль был опубликован и стал популярным, и в дальнейшем люди наследовали его в новых модулях. Этот коварный модуль срабатывает, когда получает предопределённый заголовок и затем исполняет JavaScript-код из запроса.
Зависимыми от модуля getcookies стали несколько других модулей, но в глобальном масштабе урон несущественен. Вы, вероятно, сейчас задумались, каким мог бы быть ущерб или насколько большую власть над экосистемой npm мог получить атаковавший. В статье «Gathering weak nmp credentials» исследователь в области безопасности описывает, как ему удалось получить параметры доступа (следовательно и права на публикацию) одного из пользователей npm, что означало контроль над 14 % экосистемы npm. Это стало возможным благодаря утечке параметров доступа, наряду с использованием брутфорса. Так как эти пакеты связаны с другими пакетами, исследователю удалось по цепочке повлиять на 54 % всей экосистемы npm! Исследователь опубликовал патч для каждого контролируемого им пакета, а затем при выполнении команды npm install
пользователи выполнили и код самого исследователя.
Важно отметить, что даже авторы хороших пакетов могут стать жертвами попыток фишинга или утечки паролей. Как итог вышеупомянутого исследования, npm внедрила двухфакторную авторизацию (2FA) в свой сервис. Но несмотря на это, npm всё ещё не безопасна. Двухфакторная аутентификация опциональна, и не факт, что все авторы непременно будут ей пользоваться. И хотя 2FA намного надёжнее альтернатив, этот метод всё ещё остаётся уязвимым для фишинга.
Очевидно, что вероятность случайного возникновения уязвимости в модуле намного выше, чем если бы авторы модулей разрабатывали их целенаправленно. Исследователи нашли множество уязвимостей в модулях Node.js, которые, возможно, делают ваше приложение чуть более уязвимым. Мы только начинаем замечать исследования в этой области, и с увеличением числа экосистем и числа разработчиков на Node.js атаки, направленные на модули npm, становятся все более прибыльными.
Как часто вы используете сторонние модули?
Если бы вас спросили, какую часть кода в процентном соотношении составляет сторонний код, а какую — ваш, что бы вы ответили? Прямо сейчас, когда вам в голову пришли цифры, попробуйте задать следующую команду где-нибудь в вашем приложении. Эта команда считывает строки кода в вашем приложении и сравнивает их с кодом из директории node_modules:
$ npx @intrinsic/loc
Результат этой команды может вас немного удивить. Часто получается, что в проекте с тысячами строк кода, 50% и больше — сторонний код.
Насколько существенным может быть урон?
Вероятно, вы сейчас думаете, а насколько вообще это может быть опасно? Например, если ваше приложение зависит от модуля А, который в свою очередь зависит от модуля B, а тот зависит от модуля С, то каковы шансы, что мы реально передаём важную информацию на модуль С?
Коварному пакету совсем не важно, на какой позиции он находится в иерархии приоритетов, чтобы нанести ущерб, не имеет значения даже, передавал ли он важные данные. Единственное, что важно — это то, что модуль определён в require
. Дальше вы можете видеть пример того, как коварный модуль может незаметным образом модифицировать require
и какие последствия это будет иметь в контексте всего приложения:
Если этот модуль добавить в блок required, он будет перехватывать все запросы, выполненные через библиотеку request, и отправлять ответы на сервер злоумышленника.
Теперь представьте, если бы мы изменили этот модуль и сделали его ещё хуже. Как пример, он может подменить модуль (monkey-patch) и создать временный модуль, который будет запускаться при каждом входящем запросе. Эти данные впоследствии могут быть запросто перенаправлены злоумышленнику.
Что же делать?
Существует несколько способов, с помощью которых мы можем защитить себя от этих коварных модулей. Первый — это чётко понимать цели и задачи модулей, установленных в каждом приложении. Вы всегда должны знать, от скольких модулей зависит ваше приложение. Если вам удаётся найти два модуля с одинаковыми функциями, отдавайте предпочтение тому, который имеет меньшее количество зависимостей. Меньше зависимостей — меньше шанс злонамеренных действий.
Некоторые большие компании проводят ручные ревизии каждого пакета и составляют белые списки модулей, которыми впоследствии разрешено пользоваться всем остальным в компании. Этот подход не очень практичный, учитывая огромное количество доступных пакетов на npm, а также число новых релизов.
Недавно npm выпустила модуль npm audit. Это инструмент, который сканирует ваши установленные модули и сравнивает их с чёрным списком модулей/версий с известными уязвимостями. Запуск npm install
даже подскажет вам, подвержены ли ваши собственные модули известным уязвимостям. А запуская npm audit fix
, вы получаете возможность заменить уязвимые пакеты более защищёнными версиями, если таковые существуют.
Хотя этот инструмент действительно мощный, это всего лишь начальный этап в борьбе против коварных модулей! Это реакционный подход: он полагается на то, что уязвимости известны и о них сообщают. Для него важно, что разработчики запускают команду на своих компьютерах, видят результат, а затем заново деплоят.
Часто проблемы можно находить с помощью команды npm audit
для пакетов, на которые ещё не выпустили патчи (такие, как пакет stringstream, показанный на скриншоте). Например, если пакет А не получает частые обновления и зависит от уязвимого пакета B, а затем на него выкатывают патч с доработками, владелец приложения не может обновить версию пакета В, который зависит от пакета А. Другой недостаток состоит в том, что иногда аудит результатов выдаёт проблемы, решить которые не представляется возможным на данном этапе.
После прочтения этого текста вы, возможно, захотите и вовсе никогда не использовать сторонние модули. Разумеется, это нецелесообразно, потому что существует огромное количество рабочих модулей на npm, а попытки создать их с нуля потребуют слишком много сил. Большая экосистема модулей на npm и скорость, с которой можно строить готовые к запуску приложения, вызывают интерес разработчиков к Node.js.
Всегда будьте внимательны к модулям, которые используете, не забывайте о дереве своих зависимостей и модулях с большим количеством зависимостей. По возможности, чаще обновляйте свои модули. Это лучшее, что вы можете сделать, чтобы уберечь себя от коварных модулей.
Смотрите также: Node Hero — руководство по безопасности Node.js
9К открытий9К показов