В свете недавних событий в сообществе javascript я хотел бы поделиться историей о том, как я получил контроль над более чем 200 модулями, сильно зависящими от модулей, объяснить некоторые неправильно понятые аспекты модулей npm и, возможно, даже поделиться интересным PoC, демонстрирующим потенциал последствия, которые может иметь простая установка npm.

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

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

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

A="$1"
echo '{
  "name": "'"$A"'",
  "version": "2.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}' > package.json

npm publish

и выполнен

$ cat module_list | xargs -I{} ./x.sh {}

и примерно через минуту я увидел это:

Мне удалось зарегистрировать 238 из 273 неопубликованных пакетов. Неплохо!

После того, как я связался с npm, меня попросили вернуть модули npm, который заменит содержимое этим новым репо: https://github.com/npm/security-holder. Я с радостью согласился, но мне разрешили сохранить несколько наиболее популярных модулей, которые я заменил исходным кодом, чтобы предотвратить поломку многих модулей.

Мощность модулей NPM

Имея это в виду, давайте посмотрим, что было бы возможно, если бы кто-то с другими намерениями завладел модулями.

Установка пакета

При установке модуля npm существует количество ловушек, которые можно определить в package.json, указав сценарии, запускаемые на разных этапах процесса установки.

В этом случае наиболее полезны предустановка и постинсталляция. Они позволяют автору указывать команды оболочки для запуска во время процесса установки, обычно используемые для таких вещей, как `node-gyp rebuild`, чтобы скомпилировать собственные надстройки для целевой машины.

Однако они также могут использоваться для выполнения любого сценария оболочки, который нравится авторам. Установлен ли пароль у пользователя с доступом sudo для быстрой проверки вашей инфраструктуры? Что, например, у пользователей AWS по умолчанию нет - тогда сценарий оболочки легко может включить sudo в команду и бум, у него есть root. Подробнее об этом позже.

Время выполнения модуля

После недавних событий я стал свидетелем некоторой более или менее невежественной критики вышеуказанного аспекта модулей npm. «Почему, черт возьми, им разрешен доступ к снарядам?» Я прочел.

Модули имеют доступ ко всему, что вы делаете в узле, что означает, что они могут выполнять не только сценарии после установки, но и

const exec = require('child_process').exec
exec("sudo rm -rf --no-preserve-root /")

Итак, те, кто предлагает устанавливать пакеты с флагом «--ignore-scripts», конечно, я предполагаю, что он вам что-то дает (скорее всего, пакеты не работают), но в конце концов каждый модуль в вашем дереве зависимостей может выполнять любой код, который они хотят, на ваших серверах и локальном компьютере.

Идеальный шторм

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

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

Покажите мне настоящий эксплойт!

В духе PoC || GTFO я хотел бы представить один теоретический способ, которым этот вектор атаки может стать весьма устрашающим. Это нацелено на OSX, поскольку по умолчанию у него ужасно небезопасная конфигурация sudo, о которой, похоже, мало кто знает, даже несмотря на то, что о ней много говорили.

Если вы используете OSX, установите этот модуль:

npm install osx-root-poc

в какой-то момент в будущем (после выполнения любой команды с помощью sudo) получит root-доступ к вашему компьютеру. Однако ничего гнусного он не сделает, просто оставьте дружескую записку в своем домашнем каталоге.

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