РАЗБОР Статья

Уязвимость drag-and-drop в терминалах: путь к RCE

Сергей Попов
Сергей Попов Red Team · 6,7 тыс. сообщений
Подписаться
815
[ обложка статьи ]
Режим чтения
Макросъёмка фрагмента клавиатуры ноутбука на чёрном антистатическом коврике: три клавиши сняты, мембрана под ними со следом ожога вдоль клавиши Return. На экране терминал выводит повреждённый монош...


CVE-2023-46300 - CVSS 9.8 CRITICAL, automatable, публичный PoC. Для RCE на рабочей станции с iTerm2 хватает одного: заставить терминал обработать строку с escape-последовательностями. Никакого эксплойта под ядро, никакого вредоносного бинарника на диске. Жертва запускает cat, curl, перетаскивает файл в окно терминала - и shell выполняет произвольную команду. Уязвимость drag-and-drop в терминальных эмуляторах - класс атак, где терминальный эмулятор сам становится вектором initial access, а escape-последовательности работают как payload.

Русскоязычных разборов этого направления почти нет, хотя механизм бьёт далеко за пределы iTerm2. Ниже - пошаговый разбор цепочки эксплуатации, привязка к MITRE ATT&CK и приёмы detection.

Как ANSI escape sequence атака приводит к command execution​

Терминалы живут по стандарту VT100 1978 года. Архитектурное решение - in-band signaling: управляющие команды и пользовательские данные идут в одном потоке. \x1b[32m меняет цвет текста, \x1b[H перемещает курсор - ANSI escape codes встроены прямо в вывод программы. Решение сорокашестилетней давности, от которого до сих пор никто не отказался.

Критично обратное направление: терминал тоже отвечает через тот же канал. Его ответы попадают в stdin оболочки - shell интерпретирует их как пользовательский ввод. Вот какие запросы порождают ответ в stdin:
  • Device Status Report - \x1b[5n возвращает \x1b[0n
  • Cursor Position Report - \x1b[6n возвращает \x1b[{row};{col}R
  • Color Query - \x1b]4;N;?\007 возвращает rgb-значения со слэшами
  • DECRQSS - \x1bP$q$|\x1b\\ возвращает строку с текущими настройками терминала
Shell поглощает часть ответа как escape-комбинации (аналог Alt+P, PgUp). Остальные символы попадают прямо в командную строку. Атакующий конструирует цепочку запросов так, чтобы из "мусора" ответов сложилась исполняемая команда. По сути - терминал сам набирает команду за пользователя. Неконтролируемый ввод, прошедший через escape-обработчик, превращается в shell injection - escape sequence injection атака в чистом виде.

Маппинг на MITRE ATT&CK:

CVE-2023-46300 и CVE-2023-46301: iTerm2 уязвимость с CVSS 9.8​

1793950618744.webp

iTerm2 - один из самых популярных терминальных эмуляторов на macOS (я бы сказал, дефолтный выбор каждого второго разработчика). В версиях до 3.4.20 обнаружены две CRITICAL-уязвимости, обе с CWE-116 (Improper Encoding or Escaping of Output):

ПараметрCVE-2023-46300CVE-2023-46301
ОписаниеRCE через tmux integrationRCE через функцию upload
CVSS 3.19.8 (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)9.8 (аналогичный вектор)
CISA SSVCTrack* - PoC публичный, automatable: yes, technical impact: totalTrack* - аналогично
EPSS0.0132, percentile 0.70940.0132, percentile 0.7094
Затронутоiterm2:iterm2 до версии 3.4.20iterm2:iterm2 до версии 3.4.20

Обе уязвимости строятся на одном примитиве: нестандартные escape-последовательности для tmux-интеграции и загрузки файлов инъецируют linefeed в stdin. Linefeed - это нажатие Enter, которое заставляет shell выполнить всё, что накопилось в командной строке. По данным исследования solidsnail, именно инъекция linefeed - ключевое звено цепочки.

CVSS-вектор говорит сам за себя: AV:N - атака по сети, AC:L - сложных условий нет, PR:N и UI:N - ни привилегий, ни действий пользователя. Для пентестера это значит: если на цели стоит уязвимый iTerm2 - command injection в terminal emulator достигается через контроль вывода любой программы.

Бизнес-логика атаки. RCE на рабочей станции разработчика - это lateral movement к CI/CD, SSH-ключам, токенам API, репозиториям. Монетизация - supply chain compromise или прямой доступ к продовой инфраструктуре. Один скомпрометированный макбук девелопера может стоить компании дороже, чем взлом периметра.

Цепочка эксплуатации терминального эмулятора: пошаговый разбор​

📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
- CUP (Cursor Position), перемещает курсор терминала на строку 14. Подготовка к запросу координат.

\x1b[6n - DSR координат курсора. Ответ \x1b[14;{col}R, из которого в строку попадает 4;{col}R.

Промежуточный результат: в командной строке - newcmd arg1$r{...}$|m4;{col}R. Shell отбрасывает $r{...}$ как пустые переменные окружения. Всё после ; - отдельная команда. Эффективный вызов: newcmd arg1|m4.

m4 - макропроцессор, штатно установленный на macOS. Получая через pipe вывод (содержащий syscmd(open -a Calculator)), m4 интерпретирует макрос и выполняет системную команду. Это Indirect Command Execution (T1202) - arbitrary code execution через terminal проходит три уровня: escape-обработчик, shell, m4. Три рикошета - и калькулятор открывается.

\x1bP1000p%session-changed $9 s\n - имитация вывода tmux в control mode. iTerm2 обрабатывает эту последовательность (CVE-2023-46300) и инъецирует linefeed в stdin. Shell выполняет накопленную команду.

Предусловия​

УсловиеЗначение
ТерминалiTerm2 < 3.4.20
Shellzsh (для этого PoC; вариант для bash требует доставки исполняемого файла)
ОСmacOS
Доставка файлаНе требуется
UI-взаимодействиеНет (CVSS UI:N)
Привилегии атакующегоНет (CVSS PR:N)

Command execution через drag-and-drop и вставку текста в терминал​

1793950589842.webp

Описанный PoC использует программный вывод, но escape sequence injection работает при любом способе доставки неконтролируемого ввода в терминал. Три вектора - одна точка входа.

Drag-and-drop. Перетаскивание файла в окно терминала вставляет путь к нему. Если имя файла содержит escape-последовательности - терминал обработает их точно так же, как вывод программы. Атакующий размещает файл с payload в имени (через общую папку, архив, загрузку) и рассчитывает на привычку разработчиков перетаскивать файлы для быстрого ввода пути. Прямое соответствие T1204.004 Malicious Copy and Paste. По данным исследования solidsnail, терминалы не фильтруют escape-последовательности при обработке drop-событий - drag-and-drop работает как полноценный вектор для command execution.

Clipboard paste. Веб-страница скрывает escape-последовательности через CSS (display:none, font-size:0) или Unicode-обфускацию - Command Obfuscation (T1027.010). Пользователь копирует "безобидную" команду со Stack Overflow или GitHub и вставляет в терминал. Clipboard injection attack - один из самых распространённых подклассов этой атаки. Порог входа для атакующего минимален: хватит контролируемой веб-страницы.

Программный вывод. cat, curl, git log, docker logs - любая утилита, выводящая данные из недоверенного источника. Основной вектор в исследовании solidsnail и самый опасный: жертва может даже не осознавать, что запустила обработку вредоносного контента. Просто cat README.md - и всё.

Все три вектора сходятся в одной точке: escape-последовательности достигают обработчика терминала. Если эмулятор отвечает через stdin - цепочка RCE в терминальных эмуляторах запускается.

Детект и митигация: RCE в терминальных эмуляторах​

Проверка версии. Для iTerm2: меню About iTerm2. Уязвимы все версии до 3.4.20. Обновление закрывает CVE-2023-46300 и CVE-2023-46301. Первый и самый очевидный шаг.

Тест на stdin-инъекцию. Проверить, отвечает ли ваш терминал через stdin:
Bash:
printf '\x1b[5n' ; sleep 0.1 ; cat -v
Появление ^[[0n в выводе - терминал инъецирует ответ в stdin. Это необходимое предусловие для этого класса атак. Нет ответа - эмулятор либо не поддерживает DSR, либо фильтрует ответы. Попробуйте на своём рабочем терминале прямо сейчас - результат может удивить.

Bracketed paste mode. Современные терминалы оборачивают вставленный текст маркерами \x1b[200~ / \x1b[201~. Shell распознаёт маркеры и не выполняет вставку автоматически. Закрывает вектор drag-and-drop и clipboard paste, но не программный вывод. Проверить в zsh: bindkey | grep bracketed.

Фильтрация вывода. При работе с недоверенными данными - пропускать через cat -v (заменяет непечатные символы видимыми) или strings. Ограничение очевидное: ломает легитимное форматирование - цвета, прогресс-бары, TUI-приложения. Выбор между безопасностью и удобством, как обычно.

Отключение лишних функций. В iTerm2: Preferences -> General -> tmux -> отключить tmux integration; Preferences -> General -> Magic -> отключить upload. Каждая нестандартная escape-последовательность - потенциальный примитив для shell injection. Не используете функцию - выключайте.

Мониторинг на хосте. Аномальные вызовы m4, python -c, perl -e из pipe-цепочек, которые пользователь не инициировал. На Linux - правило auditd на execve по имени m4. На macOS - eslogger exec с фильтром по процессу. Arbitrary code execution через terminal оставляет характерный след: родителем подозрительного процесса будет shell-сессия терминала, а не приложение пользователя.

Разработчики терминалов воспринимают обработку escape-последовательностей как фичу, а не как security boundary. Tmux integration, запросы цвета, DSR - всё добавляется ради удобства, а аудит безопасности случается постфактум, уже после публикации CVE. Две уязвимости в iTerm2 с CVSS 9.8 просуществовали в кодовой базе до 2023 года - при том что механизм stdin-инъекции через ответы терминала был документирован задолго до этого. Знали, но не чинили.

Проблема глубже конкретных CVE. Стандарт VT100 архитектурно не разделяет управляющий и data-канал - решение 1978 года, от которого не отказался ни один современный эмулятор. Bracketed paste закрывает вектор вставки, но не программный вывод. cat -v ломает форматирование. Полноценного решения - sandbox для escape-обработчика с whitelist допустимых ответов в stdin - нет ни в одном массовом терминале. Каждая новая функция (inline images, AI-ассистент, облачная IDE-интеграция) расширяет attack surface ПО, которое запускается с полными правами пользователя и имеет прямой доступ к shell. Пока уязвимость drag-and-drop в терминальных эмуляторах остаётся архитектурно неизлечимой - этот вектор стоит проверять на каждом проекте с macOS или GNU/Linux в scope. На HackerLab (ХакерЛаб) есть лаба, где подобную injection-цепочку нужно собрать end-to-end без подсказок.
Полезно · 1

Комментарии

0