Как npm обеспечивает безопасность


Всем привет! В предыдущих постах мы подробно поговорили про выбор зависимостей и использование lock-файлов в npm, однако я только вскользь касался вопросов безопасности. Пришло время исправить этот недочет: этот и следующий посты будут полностью посвящены безопасности в npm! И для начала мы рассмотрим, как безопасность обеспечивается на уровне инфраструктуры npm и экосистемы в целом.


Мы живем в опасное время


В наше сложное время, когда частные данные утекают рекой, а крупные скандалы со взломами происходят чуть ли не каждую неделю, вопрос безопасности становится как никогда актуальным. С каждым годом технологии усложняются, количество различных API и библиотек растет безумными темпами, а следовательно, увеличивается и поверхность для возможных хакерских атак. Несмотря на всё это, разработчики очень редко действительно задумываются о безопасности и откладывают её в самый дальний угол (сразу за исправлением багов, написанием тестов и рефакторингом архитектуры). То есть до безопасности руки у разработчиков часто доходят только тогда, когда случается какой-то реальный взлом или его попытка, уже после того, как компания понесла финансовые и, что более важно, репутационные потери.


Я предлагаю не дожидаться того момента, когда ваша компания пополнит печальный список взломанных ресурсов, и принять меры для обеспечения безопасности прямо сейчас. Ведь тот, кто предупрежден — вооружен.


npm как источник угроз


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


Однако, у меня для вас есть и хорошие новости: разработчики npm относятся к вопросам безопасности очень серьезно, и предпринимают активные меры, чтобы поддерживать здоровье экосистемы.



Малоизвестно, но разработчики npm активно использовали помощь компании ^Lyft Security (эксперта по компьютерной безопасности) с самого начала разработки платформы: специалисты из Lyft не только активно проверяли исходный код npm на наличие уязвимостей, но и проводили регулярные аудиты безопасности и pen-тесты серверной инфраструктуры. Помимо прочего, консультанты из Lyft активно участвовали в разработке так называемой Node Security Platform (NSP) [платформы безопасности Node], которая отвечает за безопасность экосистемы Node и npm-пакетов. Партнерство двух компаний оказалось настолько удачным, что в начале 2018-го года npm Inc. просто купила ^Lyft Security, и её эксперты по безопасности напрямую влились в команду npm.


Таким образом, компания npm обладает выделенной командой экспертов по безопасности, которые занимаются исключительно этими вопросами, существенно улучшая здоровье самой крупной в мире экосистемы (JavaScript). За всё время работы над Node Security Platform компании npm удалось внедрить много важных решений и инструментов, которые значительно повышают безопасность и позволяют нам чуточку лучше спать по ночам.


Кроме того, в начале 2020 года компания GitHub (Microsoft) купила npm Inc., что автоматически увеличило ресурсы компании и открыло прямой путь для интеграции между npm и GitHub. А, как известно, у GitHub также имеется своя серьезная команда по безопасности — GitHub Security Lab. Наличие таких значительных ресурсов и возможностей для коллаборации должно еще сильнее повысить безопасность экосистемы, ведь теперь Microsoft может полностью отследить и обезопасить путь от исходного кода на GitHub до скомпилированного пакета в npm registry.




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


Сканирование пакетов


Платформа npm автоматически анализирует все пакеты в момент их публикации на наличие потенциальных рисков. Система безопасности не только анализирует код каждого пакета статически, но и применяет методы поведенческого анализа для выявления различных угроз. При этом проверяются скрипты установки, сетевая активность и другие факторы на предмет подозрительного поведения. Также система использует дельта-анализ, сравнивая новую версию пакета с предыдущей для выявления конкретных изменений и их дальнейшего анализа. К факторам, которые влияют на оценку безопасности, относится и то, был ли загружен пакет с использованием двухфакторной аутентификации, или был ли он загружен из сети TOR (которой часто пользуются злоумышленники).


В момент сканирования пакета система сверяется, в том числе, и с базами данных СПАМа для выявления нежелательных пакетов, а также проверяет названия новых пакетов на сходство с названиями уже имеющихся: злоумышленники в прошлом подменяли пакеты, пользуясь невнимательностью пользователей, которые совершали опечатки в названии пакета в момент его установки.


Чтобы повысить эффективность сканера, команде npm удалось собрать самую большую в мире библиотеку вредоносного кода на JavaScript, которая постоянно пополняется. Эта библиотека, в том числе, содержит списки опасных доменных имен, IP-адресов и URL, которые могут использоваться злоумышленниками, а также другие индикаторы заражения. Команда npm планирует открыть доступ к этой библиотеке, которая получила название Security Insight API. Это позволит энтузиастам со стороны разрабатывать собственные решения, которые еще более повысят безопасность экосистемы.


Автоматический отзыв токенов аутентификации


npm поддерживает аутентификацию при помощи специальных токенов вместо логина и пароля. Это необходимо для публикации пакетов в npm registry, для работы с закрытыми (private) пакетами в рамках автоматизированных процессов (например, используя CI/CD-конвейер), а также для интеграции со сторонними решениями.


Однако возникали ситуации, когда разработчики по ошибке выкладывали свои секретные токены в открытый доступ, например, в содержимом npm-пакета или в исходном коде на GitHub. Такая утечка очень существенна, потому что токен может давать полные права на управление аккаунтом npm, а значит, злоумышленник сможет от лица автора опубликовать вредоносную версию пакета или удалить пакеты автора из репозитория.



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


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


Компрометация паролей



Довольно часто пользователи используют один и тот же пароль между различными сервисами и аккаунтами. При этом они могут даже не догадываться, что их данные оказались в публичном доступе из-за утечки с одного из сайтов, где они были зарегистрированы. Сервис Have I Been Pwned содержит огромную базу данных утечек и позволяет по вашему E-mail адресу определить, попали ли именно ваши данные в одну из них. Например, мой адрес на GMail, которым я пользуюсь уже 11 лет, попал аж в 14 утечек. Я уверен, вас тоже ждут интересные новости!


А теперь о хорошем: каждый раз, когда вы вводите ваш пароль при аутентификации в npm, а также при его назначении и замене, npm сверяет пароль с базой данных скомпрометированных паролей (разумеется, безопасным способом), и в случае обнаружения запрещает его использование. Таким образом, если ваш пароль попадет в утечку и злоумышленник решит им воспользоваться, у него ничего не выйдет (конечно, при условии, что npm успеет обновить базу данных утекших паролей до этого момента).


Ручной аудит пакетов


Одним из важнейших способов обнаружения уязвимостей является ручной аудит пакетов. Несмотря на то, что команда безопасности npm работает круглосуточно в режиме 24/7, проверить все публикуемые пакеты в ручном режиме невозможно, но это и не требуется. Сообщество разработчиков JavaScript, а также различные партнеры и третьи стороны каждый день отправляют в npm отчеты о найденных уязвимостях с указанием проблемных пакетов и их версий. В неделю npm насчитывает порядка 25 подобных обращений. Специалисты из команды безопасности тщательно проверяют каждый отчет об уязвимости и стараются подтвердить проблему в лабораторных условиях на специальном исследовательском стенде.


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


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


Ещё нужно понимать, что информация об уязвимости обязательно включается в базу данных npm в качестве так называемой security advisory. А учитывая очень широкий охват аудитории (через npm audit), информация становится доступна всем, включая злоумышленников, которые могут воспользоваться найденной уязвимостью в корыстных целях. По этой причине важно, чтобы автор уязвимого пакета узнал об этом первым и мог оперативно принять необходимые меры (выпустить исправленную версию). Если уязвимость уже публично известна, то команда npm дает автору пакета 48 часов на её устранение, после этого уязвимость будет добавлена в общую базу. Если же информация об уязвимости была передана в npm в частном порядке и не публиковалась в открытом доступе, то команда безопасности дает автору пакета 45 дней на выпуск обновления и не публикует информацию официально, чтобы она не попала в руки хакеров, которые непременно захотят ей воспользоваться.



По словам специалистов из npm, из всех отчетов об уязвимостях, которые им присылают, только 20 % в итоге подтверждаются и доходят до публикации. На момент написания этого поста в базе npm было 1427 рекомендаций по безопасности (security advisories). Полный список рекомендаций можно посмотреть на официальном сайте в специальном разделе. Также доступен список рекомендаций со стороны GitHub.


К счастью, чтобы пользоваться базой данных рекомендаций, вам не нужно читать их все, или даже заходить на эти страницы: npm CLI автоматически обращается к этой базе при установке зависимостей и сообщает вам об уязвимостях в пакетах, которые используются в вашем проекте. Подробнее об этом я расскажу в следующем посте.


Продолжение следует


Хотя команда безопасности npm самостоятельно выполняет огромную работу и позволяет существенно сократить риски использования стороннего кода, это не означает, что нам, разработчикам, не нужно ничего делать.


npm предоставляет много полезных инструментов, которые требуют внедрения с нашей стороны. Сюда относится двухфакторная аутентификация/авторизация, механизмы ограничения возможностей токенов аутентификации и команда npm audit. Обо всём этом и о том, какие дополнительные меры вы можете применить, мы подробнее поговорим в следующем посте.


Если вам понравился материал, то, пожалуйста, ставьте лайки, подписывайтесь на наш блог и делитесь ссылками с коллегами. Так мы будем понимать, что наша работа востребована, и будем продолжать радовать вас новыми полезными материалами.


Если у вас есть вопросы или желание что-то добавить по теме, то не бойтесь оставлять комментарии, я с радостью приму участие в обсуждении и учту ваши пожелания в следующих постах.