LINUX.ORG.RU

Вроде просто пометь пользователя как user_u и ему по умолчанию будет запрещён вызов setuid()

[root@0x61s ~]# useradd -m test1
[root@0x61s ~]# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
root                 unconfined_u         s0-s0:c0.c1023       *
[root@0x61s ~]# semanage login -a -s user_u test1
[root@0x61s ~]# semanage login -l

Login Name           SELinux User         MLS/MCS Range        Service

__default__          unconfined_u         s0-s0:c0.c1023       *
root                 unconfined_u         s0-s0:c0.c1023       *
test1                user_u               s0                   *
[root@0x61s ~]# su - test1
[test1@0x61s ~]$ su -
Password: 
su: Authentication failure
[test1@0x61s ~]$ exit
logout
[root@0x61s ~]# grep test1 /var/log/audit/audit.log
...
type=USER_AUTH msg=audit(1710274096.627:305): pid=1303 uid=1001 auid=1000 ses=4 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:authentication grantors=? acct="root" exe="/usr/bin/su" hostname=? addr=? terminal=/dev/pts/0 res=failed'UID="test1" AUID="sparks"
...
sparks ★★★★
()
Последнее исправление: sparks (всего исправлений: 1)

Смена UID, GID это capcbilities процесса. Если у процесса есть такие capabilities, то он cможет менять UID, GID вне зависимости от пользователя, который его запустил. Capabilities это свойства программ и от пользователя они не зависят.

Соотв. тебе нужно как-то ловить процессы, которые запускает пользователь и отбирать у них соотв. capabilities. Единственное, что приходит в голову, это запускать пользователя в chroot окружении, в котором ты убрал у всех программ CAP_SETUID, CAP_CHOWN и пр… Будет ли такая система работать с нужным тебе функционалом – вопрос.

soomrack ★★★★★
()
Ответ на: комментарий от sparks
type=USER_AUTH msg=audit(1710274096.627:305): pid=1303 uid=1001 auid=1000 ses=4 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 msg='op=PAM:authentication grantors=? acct="root" exe="/usr/bin/su" hostname=? addr=? terminal=/dev/pts/0 res=failed'UID="test1" AUID="sparks"

во-первых, тут видно, что auid=sparks, поэтому это не аргумент. во-вторых, тут видно, что failure случилось на USER_AUTH на не на системном вызове, скорее всего, где-то внутри PAM с поддержкой SE Linux.

Но да, можно, вероятно, написать (или найти в существующей) полиси, где setuid() запрещён. Возможно, это так для user_u, просто, но судя по https://github.com/fedora-selinux/selinux-policy/pull/625/commits/e967b31972e6e52d3d2694e64f60742c893ff920 полиси просто запрещает запускать su и sudo, а не setuid() если он где-то ещё возьмётся.

Альтернативно можно попробовать запретить setuid() через seccomp.

ivlad ★★★★★
()

Тут все почему-то про setuid() пишут, но дело не совсем не в нём. setuid() обычно и так, кроме рута, никому не доступен. У тебя ж пользователь - не рут?

Уточни что ты имеешь ввиду. «Опасная» смена пользоватиеля в su происходит вовсе не в момент вызова setuid(), а в момент запуска самого su - на нём стоит setuid-бит, и программа эта запускается от рута. Так что смотреть надо, видимо, запрет обработки setuid-битов для конкретного контекста. Но учти, setuid-биты есть не только у программ, меняющих в итоге пользователя, а и, например, у программы passwd, которая это использует чтобы уметь записывать в /etc/shadow, и даже более того - какие-то функции glibc внутри используют запуск setuid-бинарника-помощника, всё это тоже сломается.

firkax ★★★★★
()
Ответ на: комментарий от ivlad

во-первых, тут видно, что поле auid

auid - Records the Audit user ID. This ID is assigned to a user upon login and is inherited by every process even when the user’s identity changes (for example, by switching user accounts with su - john).

т.е. тот кто изначально залогинился в систему, а поле type

USER_AUTH - Triggered when a user-space authentication attempt is detected.

это «общий» эвент попытки аутентификации пользователя

sparks ★★★★
()
Ответ на: комментарий от firkax

У тебя ж пользователь - не рут?

Уточни что ты имеешь ввиду.

Пользователь не рут.
Хочу реализовать следущую модель безопасности: пользователи не имеют пароля, в том числе рут (я один пользователь компьютера, не хочу вводить пароли, считаю это неудобным); обычные пользователи никак не должны иметь возможность делать смену пользователей, даже основной пользователь, под которым сижу в GUI (важно); чтобы иметь рутовый терминал, предпологаю запуск отдельного терминала с автоматическим рутовым логином, где-то из init-скриптов (пока не знаю как запускать такой терминал, подскажите), доступ к которому осуществляется по хоткею (хардварно с клавиатуры, пока не знаю, нужно ли как-то дополнительно ограничивать другие гуёвые программы от возможности эмулировать нажатие хоткея). Т.е. будет система, в которой обычные пользователи никак не могут повышать привилегии (в моей системе также нет sudo), будет работать гуёвый рутовый терминал, на который основной пользователь может переключаться по хоткею.

«Опасная» смена пользоватиеля в su происходит вовсе не в момент вызова setuid(), а в момент запуска самого su - на нём стоит setuid-бит, и программа эта запускается от рута.

Т.е. достаточно всего лишь запретить запуск su, и моя модель будет работать? Какие-то другие программы не смогут выполнять системные вызовы setuid()?

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

обычные пользователи никак не должны иметь возможность делать смену пользователей

чтобы иметь рутовый терминал, предпологаю запуск отдельного терминала с автоматическим рутовым логином

Здравствуйте, хочу запретить огнестрел в стране, но чтобы у каждого была кнопка запуска ядерных ракет

PPP328 ★★★★★
()
Ответ на: комментарий от teod0r

Если предполагать, что в софте нет багов, и что у тебя там не спрятался ещё какой-то клон su (sudo, doas, pkexec, их полно) - то да. Программы, которые переключаются на рута (с помощью бита setuid), всё равно будут, но они будут это делать для своих внутренних нужд и запустить с помощью них что-то ещё (если не найдётся баг) невозможно.

Собственно, то, что один юзер не может сам собой превратиться в другого - это дефолт. su и подобные проги создают исключения в этом дефолте. Наличие или отсутствие паролей вызову setuid() опять же не важно, пароль проверяет всё то же su, или другие «проги для логина» юзерспейсным кодом.

Насчёт эмуляции хоткеев - я не знаю, возможно ли это на уровне ядра, но вот перехватить их точно можно. То есть злонамеренная прога может нарисовать на экране что хочет, перехватить твой хоткей, нарисовать фейкокую рут-консоль (если она знает как она должна выглядеть) и украсть то что ты в эту рут-консоль планировал ввести. А так же вроде проги без всяких хоткеев можгут переключать эти консоли в любой момент времени (но тут не уверен).

firkax ★★★★★
()
Ответ на: комментарий от PPP328

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

firkax ★★★★★
()
Ответ на: комментарий от PPP328

Здравствуйте, хочу запретить огнестрел в стране, но чтобы у каждого была кнопка запуска ядерных ракет

Не у каждого, а только у основного юзера, и только переключением хоткеем на УЖЕ запущенный при старте терминал с рутом (запуск новых копий терминала с рутом будет невозможен).
Чем это менее безопасно всеми любимого sudo без пароля?

teod0r ★★★★★
() автор топика
Ответ на: комментарий от firkax

юзеру с доступом к физической клаве выдать беспарольный доступ везде, а у софта его полностью забрать

да, никакие юзеры впринципе никак не смогут повышать привелегии )))

teod0r ★★★★★
() автор топика
Ответ на: комментарий от sparks

это «общий» эвент попытки аутентификации пользователя

который где-то внутри PAM. а опу нужен системный вызов.

Правда, оказалось, что оп какую-то фигню хочет, так что это не имеет смысла обсуждать.

ivlad ★★★★★
()
Последнее исправление: ivlad (всего исправлений: 1)
Ответ на: комментарий от firkax

запуска самого su - на нём стоит setuid-бит

такой вопрос. вот я убрал setuid-бит с /usr/bin/su и теперь обычные пользователи не могут переключаться на других пользователей. что если всё же иногда нужно менять пользователя, например для понижения привелегий — запуск firefox от другого, ещё более ограниченного пользователя? или выпонение выключения/перезагрузки компьютера пользователем из GUI или по кнопке. Как реальзовать? Через suid-ные скрипты, запускающие нужную функцию от другого пользователя? а если надо poweroff запускать, то вешеть рутовый suid на скрипт? на сколько это безопасно?

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

Самый нормальный вариант, на мой взгляд - это написать программу на Си (и сделать её setuid-root), которая реализует ровно то, что ты хочешь разрешить и проверяя что оно действительно разрешено именно текущему юзеру. И никаких тупых пробрасываний аргументов куда-то - что-нить забудешь и получишь дыру, всё строго сначала парсим, потом выполняем действия. Узнать uid пользователя, её запустившего, можно через getuid(), а полученный из setuid-а root возвращается в geteuid().

запуск firefox от другого, ещё более ограниченного пользователя

Тут надо не забыть доступ к иксам пробросить ещё будет скорее всего - что очередная задача для кастомной проги с контролями доступа.

suid-ные скрипты

Скрипты нельзя suid. Можно си-обёртки, которые внутри запускают скрипты через system() или execve(), но как я уже выше написал, лучше по возможности вообще обойтись без скриптов и всё написать на Си.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от teod0r

Первый способ - вызов статической команды шелла

#include <stdlib.h>
int main(int argc, char **argv) {
  system("echo 123");
  reutrn 0;
}

Второй способ - вызов команды шелла с меняющимися аргументами

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
  char buf[10000];
  snprintf(buf, sizeof(buf), "echo %d", atoi(argv[1]));
  if(strlen(buf)>=sizeof(buf)-1) { fprintf(stderr, "cmd too long\n"); return -1; }
  system(buf);
  reutrn 0;
}
тут надо обратить внимание на две вещи:

1) делать тупо printf всего подряд нельзя, если хочешь передать строку, предоставленную юзером - её надо экранировать (это отдельная возня), иначе юзер может передать строку типа " ; echo qwe > /etc/passwd" которую шелл (функция system вызывает его) распарсит как команду

2) надо следить чтобы не переполнился буфер

Вобщем, не рекомендую этот способ, он чреват дырами, поэтому см. третий.

Третий способ - вызов нужной программы или скрипта без шелла

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
extern char **environ;
int main(int argc, char **argv) {
  argv[0] = "/usr/local/sbin/wrapped_script.sh";
  execve("/usr/local/sbin/wrapped_script.sh", argv, environ);
  fprintf(stderr, "execve(/usr/local/sbin/wrapped_script.sh) error %d (%s)\n", errno, strerror(errno));
  return -1;
}

Тут программа просто запускает скрипт и передаёт ему все свои аргументы как есть. Опасности того, что на этом этапе что-то не так распарсится, нет - никакого парсинга тут не происходит. Вся ответственность за парсинг будет лежать на скрипте. На такую программу уже можно поставить setuid-root, в отличие от шелл-скрипта.

Но как скрипту в такой схеме узнать какой юзер его запустил я не знаю. Возможно там есть какой-нить аналог getuid().

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

а если проще? если для каждого скрипта своя обёртка? Т.е. есть скрипт, запускающий telinit 0, и есть обёртка, которая только это и запускает, без парсинга. ??? т.е. из обёртки только запускать /my_scripts/power_off или сразу /sbin/telinit 0 ??

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

Можно и свою для каждого, тогда можно даже убрать проверку прав из обёрток или скриптов и сделать её с помощью unix-прав доступа к запуску обёртки через группы.

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

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от anonymous

достаточно им не быть в группе wheel и тогда никуда они не переключатся

нет. пользователь не в группе wheel может вызывая su переключаться на других пользователей

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

Использовать пароли, но для актуального пользователя установить автологин. При этом вся ХХ-летняя история развития Линука будет работать на то, чтобы было невозможно сменить пользователя, не зная пароля

Jurik_Phys ★★★★★
()
Ответ на: комментарий от firkax

запуск firefox от другого, ещё более ограниченного пользователя

Тут надо не забыть доступ к иксам пробросить ещё будет скорее всего - что очередная задача для кастомной проги с контролями доступа.

можно с этого места по-подробнее?

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

У иксов есть авторизация по uid и она часто используется. Сменишь юзера - может перестать работать. Если нет uid то нужен пароль от сессии - он обычно хранится в файле, имя которого указано в $XAUTHORITY. Если у проги и uid неподходящий и этот файл ты ей не подсунешь (чтоб смогла его прочесть) - подключение скорее всего не состоится. Можно настроить иксы чтобы пускали с локалхоста всех подряд без проверок, но это не очень хороший способ, лучше прокидывать Xauthority куда надо.

firkax ★★★★★
()
Ответ на: комментарий от teod0r

Симлинк права доступа не даст, он может быть полезен только если юзер тот же но $HOME переназначено. Скорее копировать этот файл перед запуском проги.

firkax ★★★★★
()
Ответ на: комментарий от PeachBlossoms

setpriv

Поддерживаю: https://www.man7.org/linux/man-pages/man1/setpriv.1.html

Посмотреть доступные привилегии:

setpriv --list-caps

Запрещаем всё:

setpriv --groups `id -g groupname`,audio,input,video --no-new-privs --securebits +noroot,+noroot_locked,+no_setuid_fixup,+no_setuid_fixup_locked,+keep_caps_locked --pdeathsig clear --reset-env --ambient-caps -all --inh-caps -all --bounding-set -all /bin/bash

прописать в /etc/passwd или ещё жеще в /etc/inittab для agetty.

Играюсь с capability в Linux: https://www.opennet.ru/openforum/vsluhforumID10/5622.html

pscap у меня выводит необходимые и достаточные CAP для процессов. Сделал костылём-скриптом с помощью setpriv. Пользователю root привилегии с помощью CAP можно порезать сильно. Но буддте готовы, что если вы перезапустите какой-то сервис, то у него может не хватить привилегий для работы. init имеет больше привилегий чем пользователь root.

Реализация CAP в Linux мне не нравится. Хочу обработку filecapabilities для пользователя root как для всех, чтобы можно было xattr, setfcap отбирать привилегии у рутовых процессов, а не только раздавать обычным пользователям. Но Линус Торвальдс лично против. Он считает что админ не может знать какие привилегии необходимы процессу и дал возможность только программистам сбрасывать привилегии самому процессу. Но практически никто с разрабов ПО этим не пользуется. Правильное решение заметил только в smartd.

А давайте патч для ядра Linux напишем чтобы необходимые и достаточные CAP для root процесса можно было выставить filecapabilities.

anonymous
()
Ответ на: комментарий от anonymous

Важное дополнение, вышеописанное даст гарантии для дистров без systemd, dbus, polkitd+JS понятно почему?

Потеринг проделал дырище в классической модели безопасности Linux - всё для удобства пользователей. Чтобы обычные пользователи имели возможность запускать процессы с рутовыми привилегиями. И права в этом случае контролируются polkitd, а правила контроля доступа пишутся на джава скрыпт. Это не шутка.

anonymous
()
Ответ на: комментарий от teod0r

Просмотри весь этот топик: Обновление Fedora в KDE Plasma 5 (комментарий)

Дырявый polkitd: https://www.opennet.ru/openforum/vsluhforumID3/124435.html#131

Polkitd - не корректно работает с памятью, использует JIT и требует выделения память для исполнения и изменения одновременно.

Формат правил контроля доступа нечетабелен - джаваскрипт.

Для компиляции требуется монстр sidermonkey который непонятно что делает.

А заем пользователю вообще выполнять какие либо команды в привилегированном режиме?

Выключить или перезагрузить комп может init, перехватив и обработав нажатие кнопки выключения на корпусе или ctrl+alt+del.

А если вдруг утилите ping требуется открыть net raw сокет, то не надо на нее s-bit ставить, хватит добавить файловые CAP: cap_net_raw. И их можно добавлять как наследуемые, только «+i» и по пользователям в /etc/security/capabilities.conf прописать пользователей имеющих привелегию наследовать cap_net_raw. Можно к файлам с установленными CAP зарезать доступ DAC.

Есть классические реализации контроля доступа в *NIX с конца 1960-тых годов: DAC и MAC. Потом в 1983 решили привилегии root порезать и ввели ещё CAP. Вредитель Леонард Потеринг делает целенаправленно дыру в безопасности GNU/Linux, чтобы обычные пользователи, минуя классические системы контроля доступа могли получить привилегии.

anonymous
()
Ответ на: комментарий от intelfx

Анон правду грит?

Не, неправду.

Лгут все те, кто хвалит: systemd, dbus, polkitd+JS.

systemd вредит безопасности, умышленно, монтируя разделы с возможностью исполнения и изменения одновременно: rw,exec.

для тестирования вашей системы следующая комманда ничего не должна выводить:

mount |grep -v -E '(noexec|ro)'

anonymous
()
Ответ на: комментарий от anonymous

Выключить или перезагрузить комп может init, перехватив и обработав нажатие кнопки выключения на корпусе или ctrl+alt+del.

как это настроить для sysvinit? у меня в /etc/inittab прописано

ca::ctrlaltdel:/sbin/shutdown -r now
pf::powerfail:/sbin/shutdown -h now
на кнопку питания на ноуте система никак не реагирует. при нажатии ctrl+alt+del тоже ничего, только непонятные символы в консоли появляются...

teod0r ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Лгут все те, кто хвалит: systemd, dbus, polkitd+JS.
dbus

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

teod0r ★★★★★
() автор топика
Ответ на: комментарий от teod0r

ca:12345:ctrlaltdel:/sbin/shutdown -r -t5 now

init ловит ctrl+alt+del 100% только в консоли. Даже в консоли, init ещё обрабатывает файл /etc/shutdown.allow и принимает решение о перезагрузке в зависимости от залогиненых пользователей. Если запущен X11 то он может перехватывать все нажатия на клавиатуру, зависит от настроек конкретного X11.

anonymous
()

Есть проще вариант: залочить root, и поставить пустой пароль. Убрать всех пользователей из wheel и удалить polkit. Ну и сделать автовход в root. Должно сработать. Но с nosuid надежнее =)

realbarmaley ★★
()
Ответ на: комментарий от teod0r

И да, лучше в таком случае и от systemd избавиться. Потому что комбайн, а ещё потому что он очень сложен в такой необычной настройке, что то обязательно упустите и… дыра.

realbarmaley ★★
()
Ответ на: комментарий от Gonzo

Мне хочется плакать, но это правда. Я не как юзверь говорю, а как человек, который читал исходники polkitd, писал конфигурации для polkit.

Никак кроме диверсии назвать ЭТО язык не поворачивается. Мне хочется верить, что это не злой умысел, а просто человеческая глупость.

Сам dbus вряд ли сам по себе несёт опасность, скорее демоны, которые вывешивают в него опасные штуки. А в dbus, напомню, модель безопасности Unix слабо работает, это ж шина.

realbarmaley ★★
()
Ответ на: комментарий от teod0r

а от dbus какая угроза?

В мире NIX считают, что не привилегированные процессы не должны общаться с привилигированными. По этому init не принимает от пользователя команды, а перехватывает нажатие клавиш, кнопок и руководствуется настройками в /etc/

Процесы могут создавать сокеты, пайпы. На эти спец файлы распространяются классические средства контроля доступа: DAC, MAC. И другие процессы могут работать с этими файлами. Так взаимодействуют два процесса, даже разных пользователей, в *NIX.

dbus разрешает взаимодействовать непривилигированному и привилегированному процессу, контролируя доступ посредством polkitd, который принимает решение на основе скомпиленых правил написанных на Java script.

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

Это не в dbus, а udev правила надо писать, чтобы обеспечить целостность железа: https://wiki.gentoo.org/wiki/Allow_only_known_usb_devices

anonymous
()