В новый год с новыми старыми уязвимостями! 25 января командой Qualys был опубликован отчет об уязвимости класса memory corruption в утилите pkexec из компонентов Polkit (бывший PolicyKit). Успешная эксплуатация уязвимости может привести к получению root-привилегий у аутентифицированного локального непривилегированного атакующего (Local Privilege Escalation aka LPE). При этом совсем не важно, запущен демон polkit или нет — для эксплуатации важно наличие уязвимого компонента в системе. Центр мониторинга и реагирования на инциденты информационной безопасности Jet CSIRT компании «Инфосистемы Джет» проанализировал доступную информацию об уязвимости и вывел рекомендации по ее обнаружению и устранению. Добро пожаловать под кат!

Polkit (PolicyKit) — это компонент, контролирующий привилегии на уровне системы в Unix-подобных ОС и позволяющий организовать взаимодействие непривилегированных процессов с привилегированными. Иногда его называют «sudo для systemd». Примеры применения polkit: когда пользователь выключает или перезагружает компьютер, управляет беспроводными подключениями, получает доступ к аудио, сканеру и пр.

Следует отметить, что данная уязвимость — CVE-2021-4034 — не первая уязвимость в PolKit. Еще летом прошлого года публиковалась информация о CVE-2021-3560, 7-летнем баге, который позволял обойти проверку учетных данных при D-Bus запросе, предоставляя атакующему root-привилегии. Текущая уязвимость существует с момента создания pkexec (комит c8c3d83 от 2009 г., добавляющий команду pkexec) — SUID root-программы, предоставляющей интерфейс к Polkit и позволяющей исполнять команды от имени другого пользователя или администратора. 

Суть уязвимости

Уязвимость возникает из-за ошибки в коде pkexec, связанной с неправильной обработкой числа аргументов, когда при отсутствии аргументов (т. е. список аргументов argv, который передается системному вызову execve(), пуст) возможно передать и выполнить «небезопасную» переменную в окружение pkexec. Обычно такие «небезопасные» переменные удаляются из окружения SUID-программ с помощью ld.so до выполнения main()-функции, однако данная уязвимость позволяет вновь ввести подобную переменную. При этом, т. к. у pkexec установлен SUID-бит от root, код выполняется от УЗ root.

Влияние уязвимости

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

Как понять, подвержены ли ваши дистрибутивы уязвимости

Т. к. pkexec уязвим с момента своего появления, для выявления уязвимых систем рекомендуется проверять их на наличие pkexec с помощью одной из следующих команд:

whereis pkexec

which pkexec

ls -la /usr/bin/pkexec

find / -type f -name pkexec

Уязвимы актуальные версии дистрибутивов Debian, RedHat, Centos, Ubuntu, SUSE и др., вероятно, подвержены *BSD- и Solaris-системы. Стоит отметить, что OpenBSD не подвержена уязвимости, т. к. она не пропускает execve-вызов, если число аргументов argc равно 0.

PoC эксплойты

Для уязвимости уже доступен как минимум один PoC в связи с чрезвычайной простотой ее эксплуатации — https://github.com/berdav/CVE-2021-4034.

Как понять, что были попытки эксплуатации уязвимости

В системных журналах (auth.log) могут присутствовать строки вида:

The value for the SHELL variable was not found the /etc/shells file

The value for environment variable […] contains suspicious content.

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

Инструкции по устранению

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

В случае, если нет возможности установить исправления или же производитель их еще не выпустил, то в качестве workaround можно удалить SUID-бит у pkexec, выполнив следующую команду от имени привилегированного пользователя:

chmod 0755 /usr/bin/pkexec

(для восстановления chmod 4755 /usr/bin/pkexec)

Вместо заключения

В Unix-подобных ОС используется довольно много программ с выставленным SUID-битом для root. Потенциальное наличие уязвимостей в подобном ПО открывает широкие возможности для атакующих, и мы, вероятно, еще увидим новые уязвимости, подобные PwnKit.

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


  1. Gordon01
    26.01.2022 16:10
    +2

    Ссылка на чинящий коммит: https://gitlab.freedesktop.org/polkit/polkit/-/commit/a2bf5c9c83b6ae46cbd5c779d3055bff81ded683

    Эксплоит прекрасно работает))


    1. Revertis
      26.01.2022 16:39
      +1

      Эксплоит прекрасно работает))

      Уже после патча? O_o


      1. mammuthus
        28.01.2022 14:50

        Это уже традиция после log4j


    1. NickViz
      26.01.2022 18:26

      А там разве не if (argc < 2) должно быть? первым параметром обычно имя исполняемого файла... argc < 1 ничего не поправит.


      1. sebres
        27.01.2022 22:36

        argc < 1 ничего не поправит.

        Поправит (хотя фикс действительно так себе, но всё же фиксит как и написано "just bail out")...
        Ибо (ударение на сейчас) оно только неправильно работает в случае argc = 0, т.к. он начинает обрабатывать параметры (argv[n]) начиная с n = 1, т.е. "перепрыгивает" NULL и попадает на первую строчку из envp.

        Схематично как это должно быть:

                     n = 1
        |---------+---------+-----+------------|---------+---------+-----+------------|
        | argv[0] | argv[1] | ... | argv[argc] | envp[0] | envp[1] | ... | envp[envc] |
        |----|----+----|----+-----+-----|------|----|----+----|----+-----+-----|------|
             V         V                V           V         V                V
         "program" "-option"           NULL      "value" "PATH=name"          NULL

        Как оно в случае argc = 0:

                     n = 1
        |---------|---------+---------+-----+------------|
        | argv[0] | envp[0] | envp[1] | ... | envp[envc] |
        |----|----|----|----+----|----+-----+-----|------|
             V         V         V                V
            NULL    "value" "PATH=name"          NULL

        В результате вот это вот - path = g_strdup (argv[n]); - очень нехорошая штука (была до фикса)...

        Ну а дальше думаю и так всё понятно.

        А "так себе" собственно, поскольку оно сейчас действительно работает, а завтра кто-нибудь поправит что-нибудь и сломает его для argc = 1, что бы чуть позже кто-то сделал новую CVE.


  1. Maxim_Q
    26.01.2022 23:49
    +1

    в качестве workaround можно удалить SUID-бит у pkexec

    Но по умолчанию этот бит и так не установлен был. Скажите у кого-то он стоял по умолчанию?


    1. Alx1m1K
      27.01.2022 09:57
      +2

      SUID бит (s флаг в user части) должен присутствовать, иначе утилита бы не работала как задумано, для примера из находившегося под рукой:

      не обновлявшийся какое-то время дистрибутив kali (PoC там работает)

      user@kali64:~$ ls -lash /usr/bin/pkexec
      24K -rwsr-xr-x 1 root root 23K Jun 25 2021 /usr/bin/pkexec

      свежий debian 11 с последним патчем на polkit (PoC там ожидаемо не работает)

      user@deb11:~$ ls -lash /usr/bin/pkexec
      24K -rwsr-xr-x 1 root root 23K Jan 13 22:32 /usr/bin/pkexec

      Возможно, на вашей инсталляции уже были выполнены какие-то действия с разрешениями?


    1. SergeyMax
      27.01.2022 15:46

      Но по умолчанию этот бит и так не установлен был.

      CentOS 7.9, бит установлен.


  1. zorn_v
    27.01.2022 18:51
    -1

    Дел, а то скрипткидисы набегут )


  1. JerleShannara
    28.01.2022 15:28

    [arxont@TF307Test CVE-2021-4034]$ ls -la /usr/bin/pkexec
    -r-s--x--x 1 root root 26872 янв 25 20:21 /usr/bin/pkexec
    [arxont@TF307Test CVE-2021-4034]$ pkexec --version
    pkexec version 0.120
    [arxont@TF307Test CVE-2021-4034]$ ./cve-2021-4034
    [arxont@TF307Test CVE-2021-4034]$ whoami
    arxont

    То ли оно не работает на aarch64, то ли оно в Альте исправлено, но вывод PoC не сходится ни с дырявой ни с исправленной версией.


    1. zorn_v
      28.01.2022 19:35

      Какая то больно новая версия у вас )

      Как предположение сначала починили потому что "жопа горит", а потом более грамотно


      1. JerleShannara
        28.01.2022 21:38

        0.120 тоже числится как дырявая по редхату/федоре/генту.