Разбираемся с уязвимостями безопасности расширений Visual Studio Code

Разбираемся с уязвимостями безопасности расширений Visual Studio Code

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

Автор: Рауль Оница-Клугман, Кирилл Ефимов
Источник: https://snyk.io/blog/visual-studio-code-extension-security-vulnerabilities-deep-dive/

Стремясь всегда опережать злоумышленников, мы постоянно отслеживаем различные угрозы безопасности. Одной из серьезных угроз являются атаки на цепочку поставок, нацеленные на компрометацию организации в процессе разработки программного обеспечения. В последнее время наблюдался взрывной рост числа подобных атак - было обнаружено запутывание зависимостей (dependency confusion) , сообщалось о взломе SolarWinds, отмечалось большее количество вредоносных пакетов . Вот почему данная тема так для нас привлекательна (как и для всего остального мира).

Благодаря нашему исследованию Snyk обнаружил новый вектор атак на цепочку поставок: IDE плагины. В популярных расширениях VS Code были найдены серьезные уязвимости, позволяющие злоумышленникам взломать локальные машины, а также системы сборки и развертывания через IDE разработчика.


Каковы риски?

По данным Microsoft, в настоящее время самой популярной IDE (около 50% рынка) является VS Code, имеющая 14 миллионов активных пользователей. Широкая распространенность представляет огромную поверхность для атак злоумышленников.

Кроме того, IDE практически никогда не остаются в базовой комплектации. Для улучшения процесса разработки постоянно устанавливаются плагины и расширения, включая анализ кода, интеграцию среды развертывания, синтаксический анализ файлов, предварительный просмотр и многое другое. Плагины написаны сторонними разработчиками и хранятся на специализированных торговых площадках. Нет никаких гарантий, что установленное разработчиком расширение не содержит уязвимость, ставящую под угрозу его кодовую базу (codebase) или приложение.

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

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

Вектор атаки

Бреши безопасности, о которых далее пойдет речь, появляются через VS Code расширения, запускающие веб-серверы. Обычно данные серверы доступны локально через браузер или используются для целей IPС. Если веб-сервер уязвим, злоумышленник может этим воспользоваться для организации атаки. Для этого всего лишь требуется, чтобы разработчик установил расширение и активировал его (активация обычно происходит путем простого открытия соответствующего файла).

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

Чтобы продемонстрировать данный вектор атаки, мы создали простой Node.js Express сервер, работающий локально на машине разработчика:

const express = require('express');
const cp = require('child_process');

express()
    .get('/', (req, res) => {
        cp.execSync(req.query.cmd);
        res.send('ok');
    })
    .listen(8765);

Сервер прослушивает 8765 порт и имеет уязвимость внедрения команды в cmd параметре запроса GET-запроса к /конечной точке. Чтобы воспользоваться данной уязвимостью, злоумышленник может обманом заставить разработчика открыть URL-адрес. Представьте, что открытая разработчиком веб-страница содержит простой img тег:


Как только браузер разработчика открывает веб-страницу, он загружает все ресурсы, включая URL-адрес, указанный в src атрибуте img тега. Следовательно, он делает запрос к уязвимому локальному серверу, выполняющему вредоносную полезную нагрузку: echo pwned>~/pwned


Прежде чем перейти к выводам, отметим, что идея взлома службы через локальный веб-сервер совсем не новая. Одним из последних примеров, демонстрирующих данный вектор атаки, является CVE-2019-13567 - удаленное выполнение кода в ZoomOpener, части клиента Zoom для macOS. Дополнительные сведения об уязвимости можно посмотреть на GitHub Gist (с эксплойтом) .

В нашей работе мы исследовали безопасность локальных HTTP и WebSocket серверов с различными расширениями Visual Studio Code, чтобы использовать как указанную выше, так и дополнительные типы уязвимостей.

Поиск уязвимостей безопасности в расширениях VS Code

Мы загрузили и проанализировали основные расширения из Visual Studio Code Marketplace. В результате нами были обнаружены уязвимости в нескольких популярных расширениях. Давайте рассмотрим подробнее каждый случай в отдельности.

LaTeX Workshop

LaTeX Workshop - популярное расширение для VS Code, скачанное около 1 200 000 раз. Когда разработчик открывает .tex файл в редакторе, расширение по умолчанию запускает HTTP-сервер и WebSocket сервер на случайном порте. Сервер предназначен для предварительного просмотра PDF-файла в браузере. Мы обнаружили уязвимость сервера для внедрения команд из-за несанкционированного ввода от WebSocket клиента, поступающего в openExternal VS Code API метод.

Чтобы воспользоваться уязвимостью внедрения команд, вредоносная веб-страница (размещенная на ngrok.io в видео) должна подключиться к локальному WebSocket серверу расширения.

Поскольку сервер прослушивает случайный порт, эксплойт должен перебрать все возможные динамические порты, прежде чем сможет выполнить вредоносную полезную нагрузку. Для macOS потребуется около 30 секунд, чтобы охватить все 13 383 возможных порта(от 49152 до 65535).

В Chrome браузере имеется механизм защиты, который не позволяет злоумышленнику перебрать WebSocket порты - после 10-й попытки начинается троттлинг (throttling). К сожалению, такую защиту легко обойти, поскольку HTTP и WebSocket серверы расширения запускаются на одном и том же порте. Этим можно воспользоваться для перебора всех возможных локальных портов путем проверки наличия изображения на конкретном localhost порту, добавив к img тегу onload обработчик .

Ниже приведен эксплойт, который, как показано на видео, открывает приложение калькулятора в macOS:


 Полезная нагрузка действительна для расширения с версией 8.17.0. 

Open In Default Browser

Open In Default Browser - расширение для VS Code, которое запускает HTTP-сервер для предварительного просмотра HTML-страниц в браузере. Мы обнаружили, что сервер уязвим для обхода пути (path traversal vulnerability). В контексте вектора атаки, описанного в данной публикации, обход пути позволяет злоумышленнику украсть конфиденциальные файлы с машины жертвы.

В следующем демонстрационном видео мы смогли украсть id_rsa.pub файл:

Для данного веб-сервера нам не нужно подбирать порт, потому что он жестко запрограммирован- 52330. Однако, при использовании уязвимости возникает ряд других проблем.

Каждый современный браузер применяет SOP (same-origin policy) защиту - блокирует страницу от выполнения XHR GET запросов с перекрестным происхождением к другому домену. Чтобы обойти данное ограничение, злоумышленник должен использовать XSS-уязвимость на веб-сервере. Пока расширение позволяет просматривать HTML файлы вместе с CSS и JavaScript, злоумышленник может создать XSS полезную нагрузку, загрузить ее как файл и открыть в iframe, как показано на рисунке:


Загрузку файла можно осуществить без взаимодействия с пользователем. Сначала просто создав в DOM a тег с атрибутами href и download, а затем вызвав на нем click() метод. Таким образом можно загрузить XSS полезную нагрузку от имени пользователя.

Поскольку XSS полезная нагрузка выполняется в контексте iframe в домене localhost, появляется возможность получить доступ к ранее недоступным ресурсам.

Еще одна сложность эксплойта заключается в том, что мы должны указать путь как для id_rsa.pub так и для XSS полезной нагрузки относительно текущего рабочего пространства VS Code. Обычно рабочая область находится в домашней папке пользователя, но может быть глубоко вложена в файловую структуру. В эксплойте мы пытались подняться до десяти уровней ( ../) в файловой структуре.

Ниже приведен эксплойт, который, как показано на видео, может украсть id_rsa.pub на macOS:


Эксплойт действителен для версии расширения 2.1.3. Практически такая же уязвимость была обнаружена и в расширении Instant Markdown (версия 1.4.6).

Пердящая радуга (Rainbow Fart)

Rainbow Fart - расширение для VS Code, воспроизводящее звуки, при вводе пользователем в редакторе определенных ключевых слов. Оказывается, данное расширение устанавливалось более 60 000 раз, и оно имеет уязвимость Zip Slip . Уязвимость, в контексте вектора атаки, позволяет злоумышленнику перезаписывать произвольные файлы на машине жертвы.

Сервер, порожденный расширением на 7777 порте, позволяет пользователю импортировать голосовые пакеты - ZIP-архивы, содержащие MP3 файлы.

Злоумышленник может создать специальный ZIP-архив с путями за пределами рабочего каталога расширения, используя несколько ../ сегментов пути. Например, вот файл, payload.zip содержащий pwned файл, находящийся на восемь уровней глубже CWD:

zipinfo payload.zip
Zip file size: 423 bytes, number of entries: 2 
-rw-r--r--  3.0 unx       67 tx defN 21-Mar-30 15:40 manifest.json
-rw-r--r--  3.0 unx        7 tx stor 21-Mar-30 15:37 ../../../../../../../../pwned

Для загрузки и выполнения полезной нагрузки злоумышленник может воспользоваться тем, что /import-voice-package конечная точка не защищена от атаки с подделкой межсайтовых запросов (CSRF). Киберпреступник может сделать неавторизованные POST-запросы к конечной точке со специально созданной веб-страницы.

Эксплойт (размещенный на ngrok.io в видео) отправляет POST-запрос на https://127.0.0.1:7777/import-voice-package конечную точку сервера и отправляет упомянутый выше ZIP-архив. В результате pwned файл появляется в домашнем каталоге пользователя. Данная атака может быть использована для перезаписи файлов вроде .bashrc, чтобы получить возможность удаленного выполнения кода.

Эксплойт действителен для версии расширения 1.4.0.

Совет по исправлению

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

Поскольку расширения VS Code содержат сторонние пакеты, рекомендуем разработчикам использовать знания сообщества для установления наиболее безопасных и популярных зависимостей, чтобы не изобретать колесо заново. Например, расширение Open In Default Browser может использовать send NPM пакет для защиты от уязвимости обхода пути вместо реализации настраиваемого статического сервера. То же самое происходит и с расширением Instant Markdown. В случае с Rainbow Fart мы бы предложили использовать extract-zip NPM пакет для предотвращения уязвимости Zip Slip. Считаем, что разработчики должны использовать последние версии своих зависимостей там, где это возможно, и постоянно отслеживать их с помощью Snyk Open Source, чтобы гарантировать безопасность.

Кроме того, угрозы безопасности могут быть внесены через собственный код, написанный разработчиками расширения. Рекомендуем использовать Snyk Code для выполнения статического тестирования безопасности приложений (SAST) и выявления уязвимостей. Например, Snyk Code легко обнаруживает уязвимость обхода пути в расширении Open In Default Browser:


Показанные нами уязвимости касаются уязвимых реализаций локальных веб-серверов.

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

Чтобы защитить WebSocket сервер от приема соединений от ненадежных доменов, рекомендуем проверить Origin заголовок. Как следует из разбора расширения LaTeX Workshop, простая проверка может полностью исключить возможность атаки.

Кроме того, CSRF уязвимости являются распространенной и опасной угрозой. Они входят в первую десятку уязвимостей веб-приложений по версии сообщества OWASP. Для уменьшения вероятности данной угрозы, рекомендуем следовать инструкциям по профилактике. В случае расширения Rainbow Fart простое добавление токена CSRF в форму загрузки сделает уязвимость Zip Slip неработающей для указанного вектора атаки.

Выводы

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

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


Ваш провайдер знает о вас больше, чем ваша девушка?

Присоединяйтесь и узнайте, как это остановить!