Сегодня поговорим об уязвимости в редакторе Vim и его побратиме Neovim. Для ее эксплуатации не нужно никаких привилегий, пользователю достаточно открыть специально сформированный файл, который выполнит произвольный код на целевой системе.
Vim — это бесконечно кастомизируемая среда, которая подходит для решения огромного перечня задач. Кто-то им просто редактирует файлы, а кто-то модифицирует, пока не получится IDE для какого-то из языков программирования. Благодаря такой гибкости Vim остается одним из самых популярных редакторов. Он предустановлен на большей части современных дистрибутивов Linux, поэтому уязвимость в нем потенциально интересна.
Уязвимость обнаружил Армин Размжоу (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 без сохранения результатов редактирования файла, нужно перейти в нормальный режим с помощью Esc
и ввести :q!
. Ура, ты спасен!
Для начала давай разберемся, что такое modeline
. В 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 можно использовать не все настройки.
Например, попробуем поменять кодировку, в которой работает редактор. За это отвечает опция enc
.
/* vim: set enc=foo: */
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).
В ней допускается применение только простейших «безопасных операций».
Обратимся к сорцам. Проверяет, можно ли запустить выражение в песочнице, функция check_secure
.
Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее
1 год7690 р. |
1 месяц720 р. |
Я уже участник «Xakep.ru»
Читайте также
Последние новости