Главная » Хабрахабр » [Из песочницы] 12 странных вещей, которые могут произойти после установки npm пакета

[Из песочницы] 12 странных вещей, которые могут произойти после установки npm пакета

Он следит за обновлениями в npm репозитории, скачивает все новые модули, а затем проверяет их на вшивость — ищет сетевую активность, подозрительные операции с файловой системой и т.д. Пару месяцев назад я начал заниматься проектом под названием malicious-packages (ака "вредоносные пакеты"). Это даёт злоумышленникам огромный простор для манёвра, и возникает вопрос — сколько же всякой гадости прячется по тёмным углам npm registry? Даже маленькие проекты на node.js часто имеют большое дерево зависимостей, и у разработчиков физически нет возможности проверить их все. 180000 проверенных пакетов спустя я получил примерный ответ.

image

И этот ответ — пожалуй, не так уж и много.
[прим.: на medium есть англоязычная версия этой статьи, также за моим авторством]

Что npm пакет может сделать c вашей системой?

Давайте рассмотрим оба варианта на примерах. У пакета есть два основных пути навредить вам — при установке / удалении и в момент запуска вашего приложения.

К ним относятся preinstall, install, postinstall, preuninstall и postuninstall, которые автоматически выполняются npm в соответствующий момент жизненного цикла пакета. NPM скрипты позволяют пакетам выполнять произвольные команды в момент установки и удаления. Всё то же самое, что может сделать ваш текущий пользователь — например удалить все ваши фотографии с последнего отпуска, или слить историю вашего браузера в ФБР (хотя, скорее всего, она и так у них есть). Что они могут сделать? Именно через скрипты была осуществлена нашумевшая атака на ESLint, которая затронула пользователей eslint-scope (6 миллионов установок в неделю) и eslint-config-eslint (2 тысячи установок в неделю). Это поведение можно отключить передав флаг --ignore-scripts, но, во-первых, это никто не делает, а во-вторых — таким образом можно сломать кучу вполне себе благонадёжных пакетов.

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

image

Сколько вредоносных пакетов было обнаружено?

Давайте пройдёмся по нему: Что ж, список нельзя назвать впечатляющим, всего было найдено 3 пакета, которые к настоящему моменту удалены из npm репозитория стараниями npm security team.

  • commander-js пытается маскироваться под настоящий commander.js (который https://www.npmjs.com/package/commander), но содержит одну необычную деталь, а именно postinstall скрипт, скачивающий и выполняющий содержимое http://23.94.46.191/update.json (на момент публикации не содержит ничего криминального). Security advisory: https://www.npmjs.com/advisories/763.
  • rrgod через всё те же скрипты загружает и выполняет скрипт из http://static.ricterz.me, который, в свою очередь, пытается загрузить ещё один скрипт, в настоящее время недоступный. Security advisory: https://www.npmjs.com/advisories/764.
  • portionfatty12 нельзя назвать полностью вредоносным, однако способ, которым автор собирает статистику об установках своего детища весьма сомнителен — это отправка вашего публичного ssh-ключа (~/.ssh/id_rsa.pub) на сервер, который в настоящий момент уже недоступен. Security advisory: https://www.npmjs.com/advisories/765.

Итак, давайте представим, что вы случайно выбрали один из множества пакетов из репозитория и устанавливаете его. Несмотря на весьма скромные результаты, в процессе анализа всех подозрительных пакетов (а я просмотрел более 3000 отчётов, чтобы найти эти три жемчужины) обнаружилось немало забавных и не очень вещей, о которых вы обычно не задумываетесь (или тщательно стараетесь не думать) набирая npm install. Что может пойти не так?

Пакет может переопределять методы в других пакетах (в том числе и из стандартной поставки Node.js) 1.

А вот масштабы этой катастрофы вполне могли от вас ускользнуть. Впрочем, если вы прочитали пару предыдущих абзацев или работаете с экосистемой javascript больше недели, то вряд ли для вас это будет являться новостью. Огромное количество пакетов модифицирует чужое API, но лишь немногие из них имеют хоть сколько-нибудь вескую причину для этого. Так, если в вашем проекте есть хотя бы несколько зависимостей, то скорее всего метод fs.closeSync у вас уже переопределён (и, может быть, не один раз). Так же стоит отметить async-listener, переопределяющий 46 различных методов, включая злополучный crypto.randomBytes, что меня несколько напрягло, когда я впервые это обнаружил. Среди "рекордсменов" — graceful-fs с 12 миллионами установок в неделю, который переопределяет десяток методов из fs.

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

Пакет может определять изменённое API вносить в него дополнительные исправления 2.

image

Так что, если вы вдруг столкнулись с непонятными проблемами в стандартной библиотеке, попробуйте просто установить парочку случайных npm пакетов. Да, некоторые пакеты так и поступают (чаще всего в отношении того же graceful-fs) используя чудеса акробатики вроде /graceful-fs/.test(fs.closeSync.toString()). Или просто выключите компьютер и прогуляйтесь по ближайшему парку, жизнь слишком коротка, чтобы разбираться во всём этом.

Он может отправлять аналитику 3.

Некоторые отправляют самую базовую информацию, как, например, ecdsa-csr: Adblock вас не защитит, если дело происходит в консоли, и авторы некоторых пакетов успешно этим пользуются.

// POST https://api.therootcompany.com/api/therootcompany.com/public/ping
{ "package":"ecdsa-csr", "version":"1.1.1", "node":"v10.14.2", "arch":"x64", "platform":"linux", "release":"4.9.125-linuxkit", "action":"install", "ppid":"eDSeYr9XUNRi9WhWli5smBNAvdw="
}

Вот, например часть отчёта serverless (оригинал раза в 2 больше): Некоторые не так стесняются.

// POST https://tracking.serverlessteam.com/v1/track
}
}

До поры до времени. К счастью, jquery никакой статистики не отправляет, так что его по-прежнему можно устанавливать в тайне ото всех.

Ваш компьютер может использоваться вместо CI/CD сервера 4.

Можно получить дополнительную ачивку, если указать только мажорную версию требуемого компилятора, например typescript@3. Зачем вам компилировать ваш пакет, если это могут сделать ваши пользователи при установке? Одна надежда на грамотных ребят из Microsoft, которые умеют делать правильный semver.

Конечно! Можно ли зайти ещё дальше?

"postinstall": "eslint --ext .js,.vue --fix src"

Теперь можно спать спокойно — все пользователи получат идеально отформатированные исходники вашего пакета.

Он может попытаться напугать вас 5.

image

Robot, но всё ещё недостаточно замотивированы, чтобы прочитать Computer Networks и сделать что-нибудь действительно впечатляющее, то есть простое решение — продемонстрируйте миру свои умения посредством пары строчек в postinstall скрипте. Если вы посмотрели все серии Mr. Именно так и поступил автор pizza-pasta (а заодно подарил мне КДПВ).

{ "name": "pizza-pasta", "author": "Zeavo", "scripts": { "install": "mkdir -p ~/Desktop/hacked && touch ~/Desktop/hacked/pwnddddd && wget https://imgur.com/download/KTDNt5I -P ~/Desktop/hacked/", "postinstall": "find ~/.ssh | xargs cat || true && printf '\n\n\n\n\n\nOH HEY LOOK SSH KEYS\n\n\n\nHappy Birthday! Youve been h4ck0red\n\n\n'" }
}

Пакет может загружать и исполнять bash-скрипты 6.

Если нет, то вы вполне можете оказаться сотрудником ORESoftware, у которых есть целая куча пакетов с подобными строчками в postinstall скрипте: Слышали ли вы, что делать curl|bash не очень хорошая идея?

curl --silent -o- https://raw.githubusercontent.com/oresoftware/realpath/master/assets/install.sh | bash

Надеюсь, что все, у кого есть доступ к master в oresoftware/realpath, исключительно честные и порядочные люди. Пока что в этом скрипте нет ничего криминального… Пока.

У вас могут попросить пароль 7.

Его проект состоит из зашифрованного архива и утилит для его расшифровки — но только если вы поместите правильный ключ в переменную окружения MAGICLEAP: Автор magicleap придумал достаточно необычный способ распространять приватный пакет через публичный репозиторий.

// Оригинал: https://github.com/modulesio/magicleap/blob/master/decrypt.js
var key = process.env['MAGICLEAP'];
console.warn('Decrypting magicleap module with MAGICLEAP environment variable');
const ws = fs.createReadStream(path.join(__dirname, 'lib.zip.enc')) .pipe(crypto.createDecipher('aes-256-cbc', Buffer.from(key, 'base64'))) .pipe(fs.createWriteStream(path.join(__dirname, 'lib.zip')));

Пакет может пропатчить сам себя во время установки 8.

У автора fake-template нет времени, чтобы отделять тесты от непосредственного кода, тем более, что это легко сделать, добавив в конец тестовых строк специальный комментарий:

// Оригинал: https://github.com/framp/fake-template/blob/master/index.js
const template = (string, tag=defaultTag) => { if (mode !== 'literal') throw new Error('Invalid template') return (context={}) => tag(literals, ...expressions.map(evalInContext(context)))
} assert.equal(template('')(), ``) // TEST
assert.equal(template('abc')(), `abc`) // TEST
const dog = 'Orlando' // TEST
assert.equal(template('abc ${dog} lol ${cat}')({dog}), `abc ${dog} lol ${cat}`) // TEST

А затем удалить их через sed:

"postinstall": "sed -i '/\\/\\/ TEST/d' index.js"

Просто и элегантно!

Пакет может изменить настройки npm 9.

Впрочем, у некоторых оппонентов этой идеи есть достаточно веские доводы против: На мой скромный взгляд, package-json.lock — отличная штука, которая может спасти от целой кучи проблем, вызванных халатностью других разработчиков.

"preinstall": "npm config set package-lock false"

Он может изменить фон вашего рабочего стола на фото Николаса Кейджа 10.

image

Возможно, стоило и этот пакет зарепортить, как вредоносный. Вот ссылка, просто на всякий случай — https://www.npmjs.com/package/cage-js.

Пакет может вас зарикроллить 11.

К сожалению, никаких данных из Ember в React с его помощью перенести не удастся — в нем нет ни строчки javascript кода. Именно этим занимается ember-data-react, открывая знаменитое видео во время установки.

Он может просто не установиться 12.

6% всех пакетов из npm репозитория. image
Несуществующие зависимости, неправильно указанные версии, приватные репозитории, канувшие в лету — вы не сможете установить около 0.

Вместо заключения

Используйте package-lock.json, чтобы избежать внезапных обновлений (и следите, чтобы никто его не отключил без вашего ведома), настройте CSP на фронтенде, чтобы бэкдор в стороннем модуле хотя бы не смог слить данные своему автору. NPM пакеты могут делать странные вещи с вашей системой, и у вас не так много вариантов защиты от этого. И сделайте бэкап ваших фотографий, на всякий случай.

Утилита полна хаков и неоптимальных решений, но она вполне справляется со своей задачей. Если вы чувствуете в себе достаточно сил для погружения в чудесный мир npm пакетов — вы можете найти все исходники здесь: https://github.com/malicious-packages/core. Я не планирую больше развивать этот проект из-за недостатка времени, но постараюсь помочь со всеми вопросами и проблемами, если таковые будут. Так же в репозитории есть MongoDB дамп с результатами анализа более 180 000 пакетов, главное, не забудьте добавить фильтр {'reports.status': 'unverified'}.

Берегите себя и свои приложения!


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Как изучение критической уязвимости DHCP в Windows 10 привело к обнаружению еще двух ошибок безопасности

Изображение: Unsplash А в некоторых случаях таких новых уязвимостей оказывается больше одной. Как было описано в предыдущей статье про CVE-2019-0726, иногда поиск деталей об уже известной уязвимости приводит к обнаружению новой уязвимости. Как всегда происходит при поиске уязвимостей, даже если ...

Быстрорастворимое проектирование

Люди учатся архитектуре по старым книжкам, которые писались для Java. Книжки хорошие, но дают решение задач того времени инструментами того времени. Время поменялось, C# уже больше похож на лайтовую Scala, чем Java, а новых хороших книжек мало. Увидим обзор типовых ...