Зна­ешь ли ты, сколь­ко интер­пре­тато­ров Node.js работа­ет на тво­ем ком­пе? А сколь­ко в них дыр? С веб‑стра­ниц JavaScript при­шел на сер­веры, а с сер­веров — на дес­кто­пы, и вот ста­рые баги заиг­рали новыми крас­ками. В этой статье я покажу, как работа­ет NPM Hijacking (Planting) — уяз­вимость Node.js, которая наш­лась во мно­гих популяр­ных при­ложе­ниях, сре­ди которых Discord и VS Code.

В осно­ве этой статьи — мой док­лад, который я читал на ZeroNights 2018, но по раз­ным при­чинам выход матери­ала затянул­ся. Одной из при­чин были намеки Nvidia, что хорошо бы подож­дать до сле­дующе­го пат­ча, где най­ден­ную мной проб­лему хотели решить, выкинув Node.js целиком. В резуль­тате я мог вооб­ще забыть об этой теме, если бы анти­вирус­ные ком­пании не ста­ли находить вре­донос­ное ПО, которое исполь­зует схо­жую с опи­сан­ной в моем док­ладе тех­нику.

Ес­ли хочешь быс­тро про­бежать­ся по моим наход­кам, пос­мотри слай­ды пре­зен­тации, а в статье я рас­смот­рю проб­лему более деталь­но. Почему так выш­ло, что соз­датели мал­вари отнеслись к моей наход­ке с боль­шим инте­ресом, чем раз­работ­чики соф­та?

info

Сло­восо­чета­ние NPM Package Hijacking уже мог­ло тебе встре­чать­ся в ис­сле­дова­нии, которое было опуб­ликова­но Ней­таном Джон­соном в 2016 году. Одна­ко я рас­ска­жу об иной тех­нике, и сов­падение здесь в основном в наз­вании.

 

Node.js everywhere

На­чалась эта исто­рия, ког­да я еще вел в «Хакере» еже­месяч­ные обзо­ры экс­пло­итов. Что­бы поль­зовать­ся все­ми пре­лес­тями фор­мата Markdown, я писал статьи в одном мод­ном тог­да редак­торе и слу­чай­но обна­ружил уяз­вимость типа XSS в модуле пред­прос­мотра статьи. Я все­го‑то забыл добавить кавыч­ки, что­бы обра­мить код оче­ред­ного экс­пло­ита, и вско­ре докопал­ся до RCE!

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

Это вдох­новило меня про­дол­жать иссле­дова­ние и поис­кать похожие прог­раммы. Ведь Node.js в целом и дви­жок Electron в час­тнос­ти все боль­ше набира­ют популяр­ность и исполь­зуют­ся во мно­гих рас­простра­нен­ных при­ложе­ниях. Тут тебе и про­дук­ты Adobe, и апдей­теры раз­ных игр, редак­торы кода и тек­ста, мес­сен­дже­ры (в том чис­ле «защищен­ные») и про­чий софт. Node.js час­то исполь­зует­ся для соз­дания уста­нов­щиков и апдей­теров — Adobe попала в мой спи­сок имен­но так. Или мож­но вспом­нить Nvidia GeForce Experience — ути­литу, которая сле­дит за обновле­ниями дру­гого ПО Nvidia. Она тоже написа­на на мод­ном нын­че Node.js.

При­ложе­ния на Electron вклю­чают в себя бра­узер, осно­ван­ный на Chromium, а к нему обыч­но идет локаль­ный веб‑сер­вер — он тоже вхо­дит в прог­рамму и запус­кает­ся вмес­те с ней. Так и получа­ется, что на тво­ем рабочем ком­пе вне­зап­но кру­тит­ся куча сер­верно­го соф­та. Вот толь­ко сисад­минов у это­го соф­та нет, а уяз­вимос­ти или сла­бые мес­та в защите по‑преж­нему могут быть проб­лемой. Об экс­плу­ата­ции одной из таких сла­бос­тей мы и погово­рим.

В презентации я проиллюстрировал разницу между серверным и десктопным софтом картинками из одной известной игры
В пре­зен­тации я про­иллюс­три­ровал раз­ницу меж­ду сер­верным и дес­ктоп­ным соф­том кар­тинка­ми из одной извес­тной игры
 

NPM Hijacking (Planting)

В «Хакере» уже не раз писали о DLL Hijacking, он же DLL/Binary Planting или Preloading. Эта тех­ника работа­ет так. Если раз­работ­чик не ука­зал явным обра­зом пути для заг­рузки биб­лиотек DLL в сво­ем исполня­емом фай­ле, то опе­раци­онная сис­тема будет искать эти биб­лиоте­ки по путям, перечис­ленным в перемен­ной PATH (в том чис­ле в Windows, под­робнее — в офи­циаль­ной докумен­тации). Под­ложив в какую‑то из этих папок вре­донос­ный клон биб­лиоте­ки, ата­кующий может исполнить про­изволь­ный код.

При заг­рузке модулей Node.js ищет пап­ку node_modules по всем путям выше родитель­ской дирек­тории вызыва­емо­го скрип­та, про­веряя их, пока не най­дет нуж­ный модуль. Получа­ется что‑то вро­де ../node_modules, где ука­зате­лей на родитель­скую пап­ку может быть про­изволь­ное количес­тво. Более наг­лядно это пред­став­лено на кар­тинке ниже.

Загрузка модулей Node.js
Заг­рузка модулей Node.js

Ду­маю, ты уже догадал­ся, почему я окрестил эту ата­ку NPM Hijacking по ана­логии с DLL Hijacking. На иссле­дуемых машинах я заметил мно­гочис­ленные попыт­ки заг­рузить скрип­ты из катало­гов, перечис­ленных в перемен­ной PATH, или домаш­него катало­га текуще­го поль­зовате­ля. Уж эта‑то пап­ка дос­тупна без вся­ких повышен­ных прав, чем и могут вос­поль­зовать­ся вре­доно­сы. Собс­твен­но, такие фокусы уже вов­сю прак­тику­ются при ата­ках на веб‑сер­веры с «Нодой», но там защита в целом на более высоком уров­не, чем на дес­кто­пе, поэто­му такая проб­лема менее опас­на.

 

Уязвимости

Да­вай теперь пос­мотрим, как эта осо­бен­ность экс­плу­ати­рует­ся в раз­ных при­ложе­ниях, внут­ри которых кру­тят­ся сер­ваки с Node.js. Мы рас­смот­рим три при­мера:

 

Discord

Чат Discord зна­менит воз­можностью общать­ся голосом, а сде­лан он на Electron. Неуди­витель­но, что он уяз­вим перед NPM Hijacking, — проб­лему я обна­ружил во вре­мена вер­сии 0.0.300, о чем и опо­вес­тил раз­работ­чиков. При запус­ке Discord ищет сле­дующие скрип­ты, идя вверх по катало­гам:

  • discord_utils.js;
  • discord_overlay2.js;
  • discord_game_utils.js;
  • discord_spellcheck.js;
  • discord_contact_import.js;
  • discord_voice.js.

Сам поиск и заг­рузка скрип­та с точ­ки зре­ния ОС выг­лядят как пос­ледова­тель­ный перебор сле­дующих папок:

  1. C:\Users\User\AppData\Roaming\discord\0.0.300\modules\discord_desktop_core\node_modules
  2. C:\Users\User\AppData\Roaming\discord\0.0.300\modules\node_modules
  3. C:\Users\User\AppData\Roaming\discord\0.0.300\node_modules
  4. C:\Users\User\AppData\Roaming\discord\node_modules
  5. C:\Users\User\AppData\Roaming\node_modules
  6. C:\Users\User\AppData\node_modules
  7. C:\Users\User\node_modules
  8. C:\Users\node_modules
  9. C:\node_modules
  10. C:\Users\User\AppData\Roaming\discord\0.0.300\modules\discord_voice.js

По умол­чанию с пер­вого по девятый пункт опе­раци­онная сис­тема ничего не обна­ружит, если у тебя нет таких папок, и толь­ко потом (на пун­кте 10) Node.js нач­нет поиск скрип­та, лежаще­го не в node_modules, а отдель­но, как и сде­лано в Discord. Если нам дос­тупна для записи пап­ка поль­зовате­ля, то мы можем под­ложить свою биб­лиоте­ку так, что­бы она заг­рузилась, нап­ример, на пун­кте 7.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

1 комментарий

  1. Аватар

    Laglag

    26.10.2020 в 15:15

    Буду повторять спасибо

Оставить мнение