Что будет, если переименовать суперпользователя? Экспериментируем, удивляемся и расстраиваемся…

в 14:28, , рубрики: linux, root, selectel, суперпользователь
Что будет, если переименовать суперпользователя? Экспериментируем, удивляемся и расстраиваемся… - 1

В интернете много желающих перебирать пароли к SSH, чтобы получить мощности вашего сервера безвозмездно. Как это можно предотвратить? Отключить вход по паролю? Лениво. Использовать нестандартный порт? Не поможет. Поставить fail2ban? Скучно. Переименовать root? Вот это хорошая идея!

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

Примечание: для понимания статьи требуются минимальные познания в операционных системах семейств Linux или UNIX.

Для операционных систем семейства *NIX написано много программ. Протестировать их все не получится. Что можно сделать? Разобраться как операционная система (ОС) работает в многопользовательском режиме. Начнем с логического начала — загрузим ОС. Этот процесс можно разбить на следующие этапы:

  • загрузка ядра (Kernel),
  • инициализация служб,
  • вход в систему.

Получилось кратко. Рассмотрим каждый из этапов.

Используйте навигацию, если не хотите читать текст полностью:

Пользователи в пространстве ядра
Пространство пользователя
Интерактивный уровень
Рубрика «Эксперименты»
Где суперпользователь не root?

Пользователи в пространстве ядра


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

Где применяется разграничение прав доступа? В файловой системе:

# ls -la
total 645
drwxrwxrwx 9 root      256 Sep 22 05:49 .
drwxrwxrwx 9 root      256 Sep 22 05:49 ..
drwxrwxr-x 2 bin      2512 Sep 22 05:32 bin
-rwxr-xr-x 1 bin      8986 Jun  8  1979 boot
drwxrwxr-x 2 bin       160 Sep 22 05:47 dev
drwxrwxr-x 2 bin       336 Sep 22 05:47 etc
-rwxr-xr-x 1 sys     53302 Jun  8  1979 hphtunix
-rwxr-xr-x 1 sys     52850 Jun  8  1979 hptmunix
drwxrwxr-x 2 bin       320 Sep 22 05:33 lib
drwxrwxr-x 2 root       96 Sep 22 05:46 mdec
-rwxr-xr-x 1 root    50990 Jun  8  1979 rkunix
-rwxr-xr-x 1 root    51982 Jun  8  1979 rl2unix
-rwxr-xr-x 1 sys     51790 Jun  8  1979 rphtunix
-rwxr-xr-x 1 sys     51274 Jun  8  1979 rptmunix
drwxrwxr-x 2 root      112 Sep 22 06:52 tmp
drwxrwxr-x11 root      176 Sep 22 05:46 usr

Что ограничивают в правах? Программы:

firemoon@DESKTOP-7S33FAN:~$ ps u
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
firemoon    12  0.0  0.0   9172  5244 pts/0    Ss   13:56   0:00 -bash
firemoon    82  0.0  0.0  10456  3308 pts/0    R+   14:04   0:00 ps u

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

В ядре Linux метаинформация процесса хранится в структуре task_struct. Описание этой структуры занимает более 700 строк кода, поэтому вот краткая выжимка:

struct task_struct {
        /* Тут много пропущено */
        /* Process credentials: */
        /* Tracer's credentials at attach: */
        const struct cred __rcu                *ptracer_cred;
        /* Objective and real subjective task credentials (COW): */
        const struct cred __rcu                *real_cred;
        /* Effective (overridable) subjective task credentials (COW): */
        const struct cred __rcu                *cred;
        /* Тут пропущено больше */
};

Сама структура cred описана в другом файле и выглядит не менее солидно:

struct cred {
        atomic_long_t        usage;
        kuid_t                uid;                /* real UID of the task */
        kgid_t                gid;                /* real GID of the task */
        kuid_t                suid;                /* saved UID of the task */
        kgid_t                sgid;                /* saved GID of the task */
        kuid_t                euid;                /* effective UID of the task */
        kgid_t                egid;                /* effective GID of the task */
        kuid_t                fsuid;                /* UID for VFS ops */
        kgid_t                fsgid;                /* GID for VFS ops */
        /* Тут много пропущено */
} __randomize_layout;

Смотрим на структуры данных kuid_t и kgid_t:

typedef struct {
        uid_t val;
} kuid_t;
typedef struct {
        gid_t val;
} kgid_t;

Так, теперь разбираем uid_t и gid_t:

typedef __kernel_uid32_t        uid_t;
typedef __kernel_gid32_t        gid_t;

Ну и в конце выбираем одно из платформозависимых определений:

#ifndef __kernel_uid32_t
typedef unsigned int        __kernel_uid32_t;
typedef unsigned int        __kernel_gid32_t;
#endif

Аналогично: информация о владельце и группе-владельце хранится в структуре inode. Она описывает файл на файловой системе:

struct inode {
        umode_t                        i_mode;
        unsigned short                i_opflags;
        kuid_t                        i_uid;
        kgid_t                        i_gid;
        unsigned int                i_flags;
        /* Тут много пропущено */
} __randomize_layout;

Ядро резервирует два идентификатора.

  • 0 — идентификатор суперпользователя. Пользователь с этим идентификатором игнорирует все (или почти) проверки прав доступа.
  • (uid_t)-1 (в беззнаковом — это максимальное значение типа данных) — обозначение ошибки.

Что из этого следует? Ядро операционной системы не использует имена пользователей и наша шалость с переименованием никак не повлияет на ранние этапы загрузки ОС.

Ядро по готовности запускает главный процесс в пространстве пользователя — init.

Что будет, если переименовать суперпользователя? Экспериментируем, удивляемся и расстраиваемся… - 2

Пространство пользователя

Что будет, если переименовать суперпользователя? Экспериментируем, удивляемся и расстраиваемся… - 3

Отвлеченная шутка к началу раздела.

Процесс init (сокращенно от initialization) обычно имеет идентификатор процесса (pid) равный единице и запускается ядром. В каноническом UNIX инициализация состояла из следующих шагов:

  • запуск скрипта /etc/rc,
  • подключение к физическим или виртуальным терминалам (getty),
  • запуск скрипта /etc/rc.local (специфично для BSD).

В современных операционных системах семейства Linux вместо классического init используется монструозный systemd. Тем не менее, нет значения, какая подсистема инициализации используется, если сервисы не смогут запуститься. Давайте разбираться, что и где может пойти не так.

Есть старая админская хитрость: вместо init «подставить» /bin/sh. Это позволит получить интерактивный доступ к ОС без аутентификации. Это известное решение для сброса забытого пароля суперпользователя.

Ядро «волшебным» образом создает первый процесс от имени суперпользователя. Все остальные процессы — его дети. «Размножение» процессов в *NIX происходит в два системных вызова:

  • fork(2) — клонирование текущего процесса,
  • execve(2) — выполнение указанного исполняемого файла.

Вот так выглядит полный пример:

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[], char *envp[]) {
    int pid = fork();
    switch(pid) {
        case -1:
            /* Ошибка */
            perror("fork");
            return -1;
        case 0:
            /* Ветка, доступная ребенку */
            char* child_argv[] = {"/bin/echo", "Hello, World!", NULL};
            /* Вызываем /bin/echo с указанными аргументами */
            execve("/bin/echo", child_argv, envp);
            /* Вообще-то дальше код недостижим. Но если достижим, то это ошибка */
            perror("execve");
            return -2;
        default:
            /* Ветка, доступная родителю. pid - идентификатор ребенка */
            printf("Child pid = %dn", pid);
    }
    /* Хорошим тоном будет дождаться выполнения дочернего процесса */
    int status;
    waitpid(pid, &status, 0);
    printf("Child process exited with exit code: %dn", WEXITSTATUS(status));
    return 0;
}

В этом примере нет ничего про пользователей, потому что это происходит неявно. Системный вызов fork(2) занимается копированием, поэтому дочерний процесс имеет ту же информацию о пользователе, что и родительский. Системный вызов execve(2) находит исполняемый файл и проверяет его права доступа.

Если у программы в правах есть бит SUID, то execve(2) всегда запускает программу от имени владельца файла. Но эту особенность рассмотрим позже.

Итак, init запускает служебные процессы, но не каждому процессу полагаются максимальные права в системе. Ядро позволяет переключиться на любого пользователя. Этим занимается системный вызов setuid(2):

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[], char *envp[]) {
    if(setuid(747) < 0) {
        perror("setuid");
        return -1;
    }
    char* child_argv[] = {"id", NULL};
    execve("/usr/bin/id", child_argv, envp);
    return 0;
}

Как говорилось ранее, ядро оперирует только идентификаторами, поэтому setuid(2) принимает числа. Этот системный вызов позволяет изменить пользователя, от имени которого выполняется программа. В случае суперпользователя — добровольно отказаться от своих прав.

Системный вызов setuid(2) позволяет представляться разными пользователями, поэтому он доступен только для суперпользователя:

firemoon@ubuntu:/tmp$ ./a.out
setuid: Operation not permitted
root@ubuntu:/tmp$ ./a.out
uid=747 gid=0(root) groups=0(root)

У Linux есть отступления от традиционной для UNIX системы разграничения прав. В частности, существует система возможностей, capabilities(7), которая позволяет более тонко настраивать права и функции пользователей. В терминах этой системы setuid(2) доступен при наличии атрибута CAP_SETUID.

Опытный администратор наверняка отметит, что в systemd-юнитах указывается имя пользователя, а не его числовой идентификатор. Как имя превращается в число?

Управление пользователями вне ядра берет на себя стандартная библиотека С, libc или glibc (в зависимости от используемой ОС). Функции getpwnam(3) и getpwuid(3) позволяют получить запись о пользователе по имени (логину) или числовому идентификатору.

По умолчанию все пользователи ОС хранятся в локальной базе данных, файле /etc/passwd, однако современные операционные системы позволяют сконфигурировать обращение к удаленным БД, например через LDAP.

Из-за соображений безопасности хэши паролей пользователей вынесли из общедоступного /etc/passwd в /etc/shadow с ограничением на чтение не суперпользователю.

Это первая потенциальная точка отказа. Если при запуске демона явно указано имя суперпользователя root, то система не найдет его, а демон не будет запущен. Можно предположить оптимистичный вариант. Допустим, что в реализации init есть микро оптимизация — игнорировать явное указание на пользователя root. Тогда, может, ничего не сломается.

Резюмируем. При загрузке ОС могут сломаться сервисы, в которых явно прописан пользователь root. Понадеемся, что этого не случится, и перейдем к интерактивному взаимодействию с системой.

Интерактивный уровень


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

Самое время рассказать про SUID-бит и почему он нужен. Аутентификацией и созданием сессии пользователя занимается программа login(1). Она запускается от имени суперпользователя, принимает данные для входа и проверяет их. Если пара логин-пароль существует в системе, login(1) переключается в указанного пользователя через setuid(2) и запускает интерпретатор командной строки.

Как было сказано ранее, все дочерние процессы, созданные в командной строке, будут запущены от имени того же пользователя. Также мы уже знаем, что setuid(2) в классическом *NIX может запускать только суперпользователь. Безвыходная ситуация? Нет. Бит SUID — это особый механизм, который позволяет запускать программу с правами владельца файла.

$ ls -l /usr/bin/su*
-rwsr-xr-x 1 root root 55672 Feb 21  2022 /usr/bin/su
-rwsr-xr-x 1 root root 232416 Apr  3  2023 /usr/bin/sudo
-rwxr-xr-x 1 root root  35232 Feb  7  2022 /usr/bin/sum

Обратите внимание на право s вместо x для программ su и sudo. Это и есть бит SUID. Это значит, что execve(2) всегда будет запускать эти программы от имени владельца файла, в данном случае — от root. Этот механизм позволяет запускать программы «от администратора». Вот показательный, но вредный пример:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char *argv[], char *envp[]) {
    uid_t uid = getuid();
    if(uid == 0) {
        printf("We are root! pid = %dn", getpid());
        return 0;
    }
    printf("Let's request root access! pid = %dn", getpid());
    char* child_argv[] = {"su", "-c", argv[0], NULL};
    execve("/usr/bin/su", child_argv, envp);
    return 0;
}

На выходе получаем это:

ubuntu@ubuntu-2204:/tmp$ ./a.out
Let's request root access! pid = 3354
Password:
We are root! pid = 3355

В своем канале я писал про повышение через перерождение. Если хотите читать краткие познавательные заметки раньше, чем выходят полноценные тексты на Хабр, — подписывайтесь.

Пример использует программу su, которая по умолчанию переключает в пользователя root, если имени пользователя нет в аргументах. Аналогично имя суперпользователя жестко прописано в программе sudo. Это создает угрозу для shell-скриптов, которые хотят выполнить что-либо от имени администратора. Пример:

# Было
sudo apt update
# Стало
sudo -u <новое имя суперпользователя> apt update

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

root@ubuntu-2204:~# echo $USER
root

Это не мотивирует делать корректную проверку по числовому идентификатору пользователя. Никто ведь не будет переименовывать root, правда? Но если вы об этом задумались, то вот команды, которые работают с UID, а не с именем:

# Узнать UID текущего пользователя, для проверок на суперпользователя
id -u
# Переключение на пользователя с uid=0
sudo -u '#0' -i
# Переключение на пользователя с uid=0 при помощи su:
su - $(id -un 0)

Я взял первый попавшийся скрипт, установщик Docker Engine, и он собрал джекпот: проверил суперпользователя по имени и su/sudo без аргументов.

if [ "$user" != 'root' ]; then
    if command_exists sudo; then
        sh_c='sudo -E sh -c'
    elif command_exists su; then
        sh_c='su -c'
    else
        cat >&2 <<-'EOF'
        Error: this installer needs the ability to run commands as root.
        We are unable to find either "sudo" or "su" available to make this happen.
        EOF
        exit 1
    fi
fi

Резюмируем. Скорее всего, сломаются shell-скрипты, которые используют программы для повышения привилегий su, sudo или аналогичные. Это, конечно, решается редактированием скриптов или созданием псевдонима, но универсального решения может не быть.

alias sudo='sudo -u <новое имя суперпользователя>'

Что-то сломается, что-то — нет. Пора переходить к практике.

Рубрика «Эксперименты»

Ubuntu 22.04

Ubuntu — это моя рабочая операционная система, поэтому практическую часть решил начать с нее. Сперва я начал с версии на базе графической оболочки. Переименовать суперпользователя достаточно просто — я выбрал имя void.

  1. Переименовываем root в void в файле /etc/passwd.
  2. Переименовываем root в void в файле /etc/shadow.
  3. Перезагружаем ОС, чтобы все компоненты системы гарантированно узнали об изменениях.

Операционная система никак не препятствует изменениям:

Что будет, если переименовать суперпользователя? Экспериментируем, удивляемся и расстраиваемся… - 4

Вот что вас ждет.

После перезагрузки система теряет работоспособность для конечного пользователя.

  • Login Manager отказывается запускаться. Графический интерфейс входа на tty1 не загружается.
  • Не запускаются виртуальные терминалы tty2 и прочие. Ctrl+Alt+F2 не поможет зайти в систему.
  • Если у вас случайно оказался установлен SSH-сервер на ОС с графическим интерфейсом, это тоже не поможет. NetworkManager откажется запускаться и подключения к сети не произойдет.

Единственная возможность зайти в систему — загрузиться в режим восстановления. Отладка в таком режиме показалась совершенно бесперспективным занятием, поэтому я попытал счастья в серверной редакции Ubuntu 22.04. И она запустилась после перезагрузки! Но, как и ожидалось, не полностью.

Служба User Login Management (systemd-logind) по-прежнему отказывается запускаться, поэтому доступен только один виртуальный терминал, tty1. При этом в логах есть таймаут, но нет явной ошибки:

Feb 04 19:43:05 ubuntu-2204 systemd[1]: Starting User Login Management...
Feb 04 19:43:05 ubuntu-2204 systemd-logind[1205]: New seat seat0.
Feb 04 19:43:05 ubuntu-2204 systemd-logind[1205]: Watching system buttons on /dev/input/event0 (Power Button)
Feb 04 19:43:05 ubuntu-2204 systemd-logind[1205]: Watching system buttons on /dev/input/event1 (Sleep Button)
Feb 04 19:43:05 ubuntu-2204 systemd-logind[1205]: Watching system buttons on /dev/input/event2 (AT Translated Set 2 keyboard)
Feb 04 19:44:36 ubuntu-2204 systemd[1]: systemd-logind.service: start operation timed out. Terminating.
Feb 04 19:44:36 ubuntu-2204 systemd[1]: systemd-logind.service: Failed with result 'timeout'.
Feb 04 19:44:36 ubuntu-2204 systemd[1]: Failed to start User Login Management.
Feb 04 19:44:36 ubuntu-2204 systemd[1]: systemd-logind.service: Scheduled restart job, restart counter is at 7.
Feb 04 19:44:36 ubuntu-2204 systemd[1]: Stopped User Login Management.

Ошибка связана с D-Bus, системой межпроцессного взаимодействия, которая активно используется с systemd и графической оболочкой GNOME. В описании systemd-logind.service можно найти декларацию для D-Bus:

[Service]
BusName=org.freedesktop.login1

Похоже, что какие-то механизмы D-Bus завязаны на имя суперпользователя, из-за чего программа не может подключиться к шине, а systemd не видит процесса по указанному имени и перезапускает службу. Сломанный D-Bus также влияет на обращения к systemctl из-под обычного пользователя:

ubuntu@ubuntu-2204:~$ reboot
Failed to set wall message, ignoring: Connection timed out
Failed to reboot system via logind: Connection timed out
Failed to open initctl fifo: Permission denied
Failed to talk to init daemon.

Дополнительный артефакт — это бесправный пользователь root. Я переименовал пользователя root, значит после перезагрузки его не должно существовать. Но он существует и его идентификатор отличен от нуля. Пользователь появляется даже при загрузке в режим восстановления:

ubuntu@ubuntu-2204:~$ getent passwd root
root:x:998:0::/root:/bin/bash

Это выглядит как интересный троллинг молодых системных администраторов, который принуждает думать. Смотрите сами:

ubuntu@ubuntu-2204:~$ sudo apt update
[sudo] password for ubuntu:
Reading package lists... Done
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
W: Problem unlinking the file /var/cache/apt/pkgcache.bin - RemoveCaches (13: Permission denied)
W: Problem unlinking the file /var/cache/apt/srcpkgcache.bin - RemoveCaches (13: Permission denied)

Таким образом, команды su и sudo будут корректно работать, то есть переключать в пользователя root, но результат выполнения команды будет неожиданным.

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

Processing triggers for man-db (2.10.2-1) ...
Error: Timeout was reached
Scanning processes...

В итоге простое переименование суперпользователя хорошо ломает Ubuntu, даже серверную. Ошибка явно связана с D-Bus и systemctl, которые сейчас, кажется, в каждом первом дистрибутиве Linux. Чего же ждать дальше?

Debian 9

Что будет, если переименовать суперпользователя? Экспериментируем, удивляемся и расстраиваемся… - 5

ОС Debain — это основа для Ubuntu. Может, проблема с D-Bus связана с каким-то особенностями Ubuntu? Нет. Несколько служб «упали», виртуальных терминалов нет. Симптомы точь-в-точь такие же. Тогда следующий шаг — другое семейство дистрибутивов.

Manjaro Linux (Arch Linux)

Методом «научного тыка» следующей для проверки я выбрал Arch Linux. Этот дистрибутив отличается подходом rolling release, который обещает самые свежие версии ПО. Для теста я взял дистрибутив Manjaro Linux с графической оболочкой xfce. Далее — переименование root по уже известной схеме. Система вновь не препятствует деструктивным действиям.

Что будет, если переименовать суперпользователя? Экспериментируем, удивляемся и расстраиваемся… - 6

Момент истины.

И здесь я немного удивился. Не упал ни один из systemd-юнитов. Коммуникация с systemd от имени обычного пользователя через утилиты reboot и shutdown работает как раньше. Пакетный менеджер работает тоже в норме. Хотя некоторые сообщения об ошибке оказывают психологическое давление.

[arch@arch-virtualbox ~]$ sudo pacman -S clang
[sudo] пароль для arch: 
ошибка: для выполнения этой операции требуются права root.

Окей, двигаемся дальше, в сторону CentOS.

CentOS 9 Stream

Основной проблемный компонент — D-Bus. Но systemd может ограниченно работать без D-Bus, а вот оболочка GNOME — нет. Посмотрим на еще одно семейство ОС — CentOS. Для эксперимента выберем CentOS 9 Stream с графической оболочкой GNOME.

CentOS активно сопротивляется: файл /etc/shadow имеет права 000 и доступ ограничен через SELinux.

centos@localhost:~$ ls -l /etc/shadow
----------. 1 root root 1122 фев  4 22:51 /etc/shadow

Но проблема легко решается командой chmod. Назначаем права 600, редактируем файл, возвращаем права 000 и перезапускаем систему. Система успешно загружается, в systemd все юниты в работе. Проверяем пакетный менеджер:

[centos@localhost ~]$ sudo yum install clang
[sudo] пароль для centos:
Последняя проверка окончания срока действия метаданных: 0:25:37 назад, Пн 05 фев 2024 12:41:33.
Зависимости разрешены.
…

Подождите. А почему sudo смог? Проверяем.

[centos@localhost ~]$ sudo id
[sudo] пароль для centos:
uid=0(void) gid=0(root) группы=0(root) контекст=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[centos@localhost ~]$ getent passwd 0
void:x:0:0:root:/root:/bin/bash
[centos@localhost ~]$ getent passwd root
root:x:0:0:Super User:/root:/bin/bash
[centos@localhost ~]$ getent passwd | grep ^root
[centos@localhost ~]$

При обращении к пользователю root по имени системы всегда находит этого пользователя! Даже если в общей базе его нет. Потрясающий ход. Ну тогда продолжим установку:

  Установка        : gcc-toolset-13-runtime-13.0-2.el9.x86_64                                                      9/16
  Запуск скриптлета: gcc-toolset-13-runtime-13.0-2.el9.x86_64                                                      9/16
Error writing to log: Ошибка ввода/вывода
Error in POSTIN scriptlet in rpm package gcc-toolset-13-runtime
Error: Cannot open file /var/cache/dnf/appstream-831abc7e9d6a1a72/packages/gcc-toolset-13-binutils-2.40-17.el9.x86_64.rpm: [Errno 5] Ошибка ввода/вывода: '/var/cache/dnf/appstream-831abc7e9d6a1a72/packages/gcc-toolset-13-binutils-2.40-17.el9.x86_64.rpm'
TypeError: an integer is required (got type NoneType)
FATAL ERROR: python callback ??? failed, aborting!

Странная ошибка. Но подробностей выяснить не удалось.

[centos@localhost ~]$ ls
-bash: /usr/libexec/pk-command-not-found: Input/output error
[centos@localhost ~]$ reboot
-bash: /usr/libexec/pk-command-not-found: Input/output error
[centos@localhost ~]$ getent passwd
-bash: /usr/bin/getent: Input/output error

После принудительной перезагрузке система отказалась «просыпаться» даже в режиме восстановления:

Что будет, если переименовать суперпользователя? Экспериментируем, удивляемся и расстраиваемся… - 7

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

RedOS

RedOS построена на базе CentOS, поэтому, ожидаемо, наблюдается сходное поведение:

  • файл /etc/shadow защищен правами 000,
  • после переименования система использует «фантомного» суперпользователя.

RedOS не «развалилась» как оригинальная CentOS при установке пакетов. Возможно, это какой-то редкий сбой ОС, либо не менее редкий сбой VirtualBox. В любом случае, это был неприятный прецедент, который повышает риски и для RedOS.

FreeBSD 14

Чтобы разбавить концентрацию Linux-ов, последним в списке будет FreeBSD. Начнем с того, что FreeBSD имеет туз в рукаве — суперпользователя с именем toor.

root@freebsd:~ # getent passwd | grep '^[^:]*:[^:]*:0'
root:*:0:0:Charlie &:/root:/bin/sh
toor:*:0:0:Bourne-again Superuser:/root:

Пользователь toor — это наследие истории. Пользователь root — это главный и единственный пользователь, который может восстановить систему после сбоя. При этом в корне чаще всего находился только минимально необходимый для работы набор программ, а дополнительные программы выносились на другие разделы. Так было и с командным интерпретатором. Для пользователя root это минимальный sh.

Для повышения комфорта повседневной работы завели пользователя toor, который имеет идентификатор 0, но использует более современный и функциональный интерпретатор — Bourne-Again SHell (bash).

В FreeBSD есть файл /etc/passwd, а есть его бинарные «братья». Для переименования суперпользователя нужно запустить специальный редактор vipw. В отличие от Linux, дистрибутив FreeBSD принял потерю пользователя root как должное. Пользователь не был создан с ограниченными правами, не появилось и «фантомной» записи. Пользователь toor намекает, что другим именем суперпользователя систему не удивить, хотя su определенно сломается.

freebsd@freebsd:~ $ su -c whoami
su: Sorry

Возможно, эти тексты тоже вас заинтересуют:

«Двигай телом»: обзор новой игровой консоли Nex Playground
Dell, IBM и Google заставили сотрудников вернуться в офисы: что в итоге?
Базовая настройка коммутатора Cisco 2960: особенности и фишки

Где суперпользователь не root?


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

Имя суперпользователя root — это особенность семейств *NIX. И большинство систем следует этому правилу. Маленькие исключения — BSD-системы и Ubuntu. В первой есть «запасной» пользователь toor, о котором говорилось ранее. А Ubuntu абстрагирует пользователя от суперпользователя, предлагая выполнять административные действия через sudo:

Что будет, если переименовать суперпользователя? Экспериментируем, удивляемся и расстраиваемся… - 8

Пришлось поставить BeOS 5.

Впрочем, мне удалось найти старинную BeOS, которая развивалась до 2001 года. Она не является ответвлением семейства UNIX, но частично соблюдает интерфейс POSIX и имеет множество утилит, портированных из UNIX. BeOS не предлагает создать пользователя при установке, но при этом имеет ряд утилит для работы с пользователями.

  • Есть утилита whoami, которая раскрывает имя текущего пользователя.
  • Есть утилита id, которая позволяет убедиться, что пользователь baron — это действительно суперпользователь.
  • Есть утилита su, которая по умолчанию хочет переключиться в несуществующего пользователя system.
  • Утилит для создания пользователей мне найти не удалось, в том числе в графическом интерфейсе.

Переименовать суперпользователя — это простое действие, очень похожее на «лутбоксы» или «русскую рулетку». Нет никакой уверенности, что это действие добавит безопасности, зато определенно что-нибудь сломает. В лучшем случае, система адаптируется, как это произошло с CentOS и RedOS, в худшем случае — не запустится, как показала нам Ubuntu с графической оболочкой.

Автор: Владимир

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js