Один клик по ссылке — и у атакующего твой GitHub-токен на чтение и запись всех репозиториев, включая приватные
Ammar Askar разобрал цепочку, которая складывается из вполне безобидных по отдельности фич. Началось всё с github.dev — это лёгкий VSCode прямо в браузере, который открывается, если в адресе репозитория поменять github.com на github.dev. Чтобы он мог коммитить и слать pull request от твоего имени, github.com по сети передаёт ему OAuth-токен. И вот ключевая деталь: токен не привязан к конкретному репозиторию. Он даёт доступ ко всему, к чему есть доступ у тебя.
VSCode рендерит превью Markdown и Jupyter-ноутбуки внутри webview — это iframe с отдельным origin, отрезанный от основного окна. Идея правильная: даже если в ноутбуке выполнится произвольный JavaScript, до ядра редактора он не дотянется. Но есть нюанс удобства. Чтобы горячие клавиши работали, когда фокус внутри webview, VSCode вешает там слушатель keydown и пробрасывает нажатия в основное окно сообщением did-keydown. Основное окно принимает их за реальный ввод пользователя. А значит, скрипт из недоверенного webview может сам сгенерировать keydown и «нажать» клавиши за тебя.
Дальше Askar обходит защиты одну за другой, и это самая поучительная часть:
🔘Палитру команд (Ctrl+Shift+P) открыть получается, но напечатать в неё текст нельзя: поле ввода слушает не keydown, а обычный HTML-input, до которого синтетические события не доходят
🔘Тогда в дело идут встроенные хоткеи VSCode, которые висят прямо на keydown. Через .vscode/extensions.json репозиторий рекомендует «своё» расширение, всплывает уведомление, а Ctrl+Shift+A («принять основное действие уведомления») жмёт кнопку установки
🔘Система доверия к издателю (с версии 1.97) показала бы диалог подтверждения, но кнопку в нём синтетическим Enter не нажать. Обход — local workspace extensions: расширение прямо в .vscode/extensions в доверенном workspace ставится без проверки издателя, а github.dev доверенный всегда
🔘Последний барьер, CSP, ломал прямую загрузку. Решение изящное: расширение через package.json регистрирует свой keybinding на runCommands, который вызывает workbench.extensions.installExtension с флагом skipPublisherTrust. Своё нажатие клавиши воспроизводится железно, так что устанавливается уже что угодно
Итоговый payload прячется в Markdown-ячейке ноутбука как картинка с onerror, ждёт всплывающего уведомления, шлёт Ctrl+Shift+A, затем Ctrl+F1, и установленное расширение читает OAuth-токен и дёргает api.github.com за списком приватных репозиториев. CSRF-токенов у github.dev нет, поэтому редиректнуть жертву на атаку может любая ссылка.
Отдельно ценен раздел про то, что VSCode сделал правильно: именно defense-in-depth спас от худшего сценария. На странице расширения скрипты в Markdown-превью отрублены через script-src 'none', иначе это была бы 1-click RCE на десктопе. Microsoft выкатил фикс на следующий день (3 июня): подтверждение при открытии ноутбуков в вебе и запрет пробрасывать keydown из webview ноутбука.
Если защищаешься: очисти cookies и site data для github.dev. Тогда при заходе появится диалог, на котором можно уйти со страницы до запуска цепочки.
Сохранять тем, кто пишет приложения с webview, разбирает модели изоляции iframe или просто любит, когда сложную атаку собирают из десятка «удобных» мелочей.
https://blog.ammaraskar.com/github-token-stealing/
@prog_stuff
Post #2841
584