Неожиданное развитие получила история разработчика Азера Кочулу (Azer Koçulu), который на прошлой неделе удалил из менеджера пакетов Node.js (npm) все свои утилиты и модули, чем спровоцировал настоящий коллапс в работе множества других проектов. Инженер Google Сэм Сакконе (Sam Saccone) обнаружил, что не только удаление данных из npm может привести к катастрофическим последствиям. Добавление в экосистему вредоносных пакетов тоже может спровоцировать эффект домино.
Сакконе обнаружил проблему еще прошлой зимой и сообщил об этом разработчикам npm в январе 2016 года. Однако специалисты только развели руками и ответили, что ничего не могут поделать с данной проблемой, у них просто не хватит ресурсов. Затем, еще в феврале 2016 года, Сакконе раскрыл подробности о своей находке, и 25 марта уязвимость получила собственный идентификатор в CERT. После этого на проблему по-настоящему обратили внимание. Не последнюю роль в этом сыграл недавний импульсивный поступок Кочулу, а также коллапс, который вызвало неожиданное исчезновение функции left-pad.
Проблема заключается в следующем. Во время исполнения команды npm install (которая приведет к загрузке и установке нужного пакета для вашего проекта), npm позволит свежескачанному пакету загрузить и выполнить так называемые lifecycle scripts — вспомогательные скрипты, которые выполняются с привилегиями текущего пользователя системы. Однако этот нюанс известен давно.
Сакконе фактически создал эксплоит, использующий сразу три функции npm. Первая проблема касается системы SemVer, отвечающей за определение версий. SemVer не заставляет разработчиков пользоваться определенными версиями модулей, даже если их авторы зафиксировали какую-то определенную версию в качестве основной. Дело в том, что многие проекты и модули тесно зависят друг от друга, и модуль, от которого зависят другие проекты, сам имеет такие же зависимости от других. Одним словом, ограничение по версиям здесь реализовать сложно.
Вторая составляющая проблемы – тот факт, что разработчики, залогиненные в npm, остаются залогиненными до тех пор, пока не осуществят выход из аккаунта вручную. При этом залогиненный разработчик может публиковать пакеты непосредственно в реестр npm.
Третьей частью проблемы Сакконе считает сам реестр npm в принципе, а точнее его централизованность. Код, который публикуется в npm, не проходит никаких проверок и доступен любому.
На базе этих данных Сакконе сумел создать самого настоящего червя, которому дал имя npm hydra worm. Распространение вредоноса начинается невинно – он публикуется под видом обычного работающего пакета, но помимо заявленных легитимных функций содержит вредоносный код. Как только какой-либо разработчик сочтет этот пакет удобным и включит его в состав собственного проекта командой npm install, запустится эффект домино. Вредоносный пакет загрузится, установится, и вышеупомянутые lifecycle scripts смогут доставить малварь на машину жертвы.
Если жертва подобной атаки будет разработчиком, заголиненным в npm, малварь может с легкостью обыскать репозиторий пострадавшего, прописаться в код его проектов или добавить к ним новые пакеты, выдав всё это за обновление или патч. Другие проекты, полагающиеся в работе на модули пострадавшего разработчика, автоматически подгрузят эти «обновления» к себе. Начнется цепная реакция, в ходе которой червь может распространиться со скоростью лесного пожара.
Инженеры npm не видят способов решения этой проблемы. У компании просто нет ресурсов, чтобы проверять весь код, который загружают разработчики. В официальном блоге в минувшую пятницу, 25 марта, появилось следующее заявление:
«К сожалению, если большое количество пользователей объединят усилия для публикации в npm вредоносных пакетов, вредоносные пакеты будут доступны в npm. [Но] сообщество npm в основном состоит из доброжелательных, готовых прийти на помощь людей, так что в подавляющем большинстве ПО в реестре безопасно и используется очень широко.
Мы надеемся, что сообщество npm продолжит помогать нам поддерживать всё в текущем виде, а мы сделаем всё возможное, чтобы и далее улучшать надежность и безопасность реестра».
Всё, что смогли порекомендовать официальные представители npm: ограничивать работу lifecycle scripts или отключить их вовсе.
Подробный отчет Сакконе о npm hydra worm можно прочесть здесь (PDF).