Следующая новость
Предыдущая новость

Убойный текст. Выполняем произвольный код в Vim и Neovim

07.10.2019 12:53
Убойный текст. Выполняем произвольный код в Vim и Neovim

Содержание статьи

  • Стенд
  • Детали уязвимости
  • Демонстрация уязвимости (видео)
  • Вывод

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

Vim — это бесконечно кастомизируемая среда, которая подходит для решения огромного перечня задач. Кто-то им просто редактирует файлы, а кто-то модифицирует, пока не получится IDE для какого-то из языков программирования. Благодаря такой гибкости Vim остается одним из самых популярных редакторов. Он предустановлен на большей части современных дистрибутивов Linux, поэтому уязвимость в нем потенциально интересна.

INFO

Уязвимость обнаружил Армин Размжоу (Armin Razmjou) в середине этого года. Ей присвоен номер CVE-2019-12735: «уязвимость выполнения произвольного кода в Vim и Neovim». Под угрозой оказались версии Vim, которые не содержат патча 8.1.1365, и версии Neovim ниже 0.3.6.

Причина бага в том, что функция source обрабатывает файлы вне защищенного окружения. Это позволяет злоумышленнику выполнить любые команды, которые доступны в Vim.

Стенд

Для начала поднимем стенд с уязвимыми версиями Vim и Neovim. Будем использовать контейнер Docker с Debian.

$ docker run --rm --hostname vimrce --name vimrce --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -it debian /bin/bash 

Устанавливаем все необходимые зависимости.

$ apt update && apt install -y nano build-essential cmake wget unzip pkg-config libtool libtool-bin gettext git gdb libncurses5-dev libncursesw5-dev strace ltrace 

Такая портянка нужна, потому что мы будем компилировать дистрибутивы редакторов из исходников. Скачиваем уязвимые версии: для Vim это все, что ниже версии 8.1.1365, а для Neovim — не выше 0.3.5.

$ cd ~ $ git clone https://github.com/vim/vim.git --depth=1 --branch=v8.1.1364 $ git clone https://github.com/neovim/neovim.git --depth=1 --branch=v0.3.5 

Компилим и устанавливаем Vim. Включаем флаги для добавления отладочной информации.

$ cd ~/vim $ sed -i 's@#STRIP = /@STRIP = /@' src/Makefile $ CFLAGS="-g -DDEBUG" ./configure $ make $ make install 

То же самое проделываем и для Neovim.

$ cd ~/neovim $ make CMAKE_EXTRA_FLAGS="-g" $ make install 

Теперь нам нужно создать конфигурационные файлы, в которых надо активировать modeline. Для Vim это .vimrc в домашней директории, а для Neovim — init.vim.

$ echo "set modeline" > ~/.vimrc $ mkdir -p ~/.config/nvim/ $ echo "set modeline" > ~/.config/nvim/init.vim 

Стенд готов. Можешь запустить редакторы и проверить их работоспособность.

Убойный текст. Выполняем произвольный код в Vim и Neovim
Готовый стенд с уязвимыми версиями Vim и Neovim

Убойный текст. Выполняем произвольный код в Vim и Neovim

INFO

Чтобы выйти из Vim без сохранения результатов редактирования файла, нужно перейти в нормальный режим с помощью Esc и ввести :q!. Ура, ты спасен!

Детали уязвимости

Для начала давай разберемся, что такое modeline. В Vim существует четыре основных режима работы: обычный режим, режим вставки, командный режим и визуальный режим.

Убойный текст. Выполняем произвольный код в Vim и Neovim
Отображение режима работы редактора Vim

Для перехода в обычный режим нужно нажать Esc, а с помощью : можно войти в командный. В нем ты можешь выполнять команды, встроенные в Vim или предоставляемые плагинами. Это могут быть самые разные действия: настройка среды и рабочих файлов, функции, связанные с обработкой текста, команды оболочки и тому подобное.

Не прописывать команды каждый раз вручную и настроить среду Vim под свои нужды помогает файл .vimrc. По аналогии с .bashrc он выполняется каждый раз при запуске Vim. Если такой файл находится в корневом каталоге текущего пользователя, то он будет загружен автоматически.

Это все, конечно, удобно, но что, если нужно переопределить какие-то настройки для конкретного типа файлов или вообще в пределах одного документа? Тут на помощь и приходит modeline. Этот режим позволяет определить в открываемом файле опции его редактирования. Настройки задаются напрямую в файле, по дефолту интерпретируется первая и последняя строка. Если они соответствуют шаблону, то Vim выполняет их.

В некоторых современных дистрибутивах Linux этот режим включен по умолчанию. Если версия твоего редактора в зоне риска, то набери команду :set modeline?. Увидишь в ответ nomodeline — считай, что ты в безопасности и уязвимость на тебя не распространяется.

Существует два формата указания опций в modeline. Первый — короткий.

[любой_текст]{пробел_или_таб}{vi:|vim:|ex:}[пробел_или_таб]{опции} 

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

vim:tw=80 ts=4 et 

Второй формат — расширенный.

[любой_текст]{пробел_или_таб}{vi:|vim:|ex:}[пробел_или_таб]se[t] {опции}:[любой_текст] 

В этом формате те же самые опции будут выглядеть следующим образом:

/* vim: set textwidth=80 tabstop=4 expandtab: */ 

Разумеется, в целях безопасности в modeline можно использовать не все настройки.

Убойный текст. Выполняем произвольный код в Vim и Neovim
Не все опции доступны для изменения через modeline

Например, попробуем поменять кодировку, в которой работает редактор. За это отвечает опция enc.

/* vim: set enc=foo: */ 
Убойный текст. Выполняем произвольный код в Vim и Neovim
Опция enc недоступна для изменения через modeline
/src/option.c
4544:       /* Disallow changing some options from modelines. */ 4545:       if (opt_flags & OPT_MODELINE) 4546:       { 4547:       if (flags & (P_SECURE | P_NO_ML)) 4548:       { 4549:           errmsg = _("E520: Not allowed in a modeline"); 4550:           goto skip; 4551:       } 

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

/* vim: set fdm=expr fde=getline(v:lnum)=~'{'?'>1':'1': */ 

Все выражения выполняются в режиме песочницы (sandbox).

Убойный текст. Выполняем произвольный код в Vim и Neovim
Выражения из modeline выполняются в песочнице

В ней допускается применение только простейших «безопасных операций».

Обратимся к сорцам. Проверяет, можно ли запустить выражение в песочнице, функция check_secure.

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

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

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

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

1 год

7690 р.

1 месяц

720 р.

Я уже участник «Xakep.ru»

Источник

Последние новости