Разрешить запуск сценария bash от имени пользователя root, но не sudo

Я изменил свой код на:

function gp() { grep -rnIi --exclude-dir='.svn' $1 $2;}

и это работает

25
30.12.2020, 05:33
7 ответов

Единственный способ, который я мог придумать, это проверить одну из SUDO_*сред. переменные, установленные sudo:

#!/usr/bin/env sh

if [ "$(id -u)" -eq 0 ]
then
    if [ -n "$SUDO_USER" ]
    then
        printf "This script has to run as root (not sudo)\n" >&2
        exit 1
    fi
    printf "OK, script run as root (not sudo)\n"
else
    printf "This script has to run as root\n" >&2
    exit 1
fi

Обратите внимание, что это решение, конечно, не рассчитано на будущее, поскольку вы не можете кто-либо из установки переменной перед запуском скрипта:

$ su
Password:
# SUDO_USER=whatever./root.sh
This script has to run as root (not sudo)
#./root.sh
OK, script run as root (not sudo)
23
18.03.2021, 22:40

Я предлагаю проверить строки списка процессов и посмотреть, запускает ли пользователь программу, используяsudo

contype=`tty | cut -d '/' -f 3`
tty="$contype/`tty | cut -d '/' -f 4`"

if [ "$(id -u)" -eq 0 ]
then
    res=`ps ax | grep "$tty" | grep "$0" | grep "sudo"`
    if [ $? == 0 ]
    then
        echo "You should not run the script using sudo!"
        exit 2
    else
        echo "Done."
    fi
else
    echo "You are not root. Run this script as root."
    exit 2
fi

Эта переменная resпросто для вас, если вы хотите снова отфильтровать результаты.

Код Arkadusz хорош, но, к сожалению, его можно очень легко обойти...

4
18.03.2021, 22:40

Информация о том, какой пользователь вошел в систему, доступна в /proc/self/loginuid. РЕДАКТИРОВАТЬиз-за комментариев :Похоже, что этот файл существует не во всех системах. Я тестировал, и он доступен на Centos 6, Fedora 32, Fedora 33 и Ubuntu 20.04, все в стандартных настройках x86 _64. Если мы войдем в систему как наш пользователь, а затем используем sudoили su, чтобы стать root, это не изменит /proc/self/loginuid, и это будет некоторое ненулевое значение -. Если мы напрямую войдем в систему как root, то cat /proc/self/loginuidвернет 0. Обратите внимание, что этот файл НЕЛЬЗЯ изменять, даже root не может этого сделать.РЕДАКТИРОВАТЬиз-за комментария Stéphane Chazelas :Root может перезаписать этот файл, используя echo 0 > /proc/self/loginuid. Однако этого можно избежать, установив auditctl --loginuid-immutable.

Сценарий для проверки реального корня (, если auditctl --loginuid-immutableустановлен ), может выглядеть так

#!/bin/bash
loginuid=$(cat /proc/self/loginuid)
echo $loginuid
if [[ $loginuid -ne 0 ]]; then
    echo "You did not log in as root."
    exit
fi
13
18.03.2021, 22:40

Избегать sudoв скриптеrootbash?

Преамбула:Корневая учетная запись Care Sharing !!

К сожалению, стойкого пути нет... Пожалуйста, дочитайте внимательно до последнего абзаца

Как только вы даете root-доступ кому-то, они могут делать что угодно, включая редактирование вашего скрипта!!

Например, если пользователь нажал sudo su -, то переменные SUDO_*больше не существуют...

Первый быстрый способ с помощьюpstree

Таким образом, более простой способ поиска sudoприсутствия во всем текущем дереве, похоже, используетpstree:

die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
pstree -s $$ | grep -q '\bsudo\b' && die "Can't be run under sudo"

Только с psвы можете зацикливаться наps ho ppid:

die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
pid=$$
while read pid name foo < <(ps ho ppid,cmd $pid) && ((pid>1));do
    [ "$name" = "sudo" ] && die "Can't be run under sudo"
done

По поводу комментария к переименованномуsudo

Если команда sudo переименована или скопирована, то вместо поиска имени команды ищите UID во всем родительском дереве. Итак, сценарий такой же, как и предыдущий,но поиск UID >= 1000в родительском дереве:

die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
pid=$$
while read pid uid < <(ps ho ppid,uid $pid) && ((pid>1));do
    ((uid>999)) && die "Can't be run under sudo"
done

Поскольку мы говорим о Un *x

Чтобы быть правильным, избегайте использования фиксированных статических данных, используйте UID_MINиз /etc/login.defs:

.
die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
while read fld val;do
    case $fld in UID_MIN ) UIDMIN=$val ;break ;; esac
done </etc/login.defs
((UIDMIN)) || die Getting UID_MIN.
pid=$$
while read pid uid < <(ps ho ppid,uid $pid) && ((pid>1));do
    (( uid >= UIDMIN )) && die "Can't be run under sudo"
done

Обходной путь для выполнения этого с помощью sudoв любом случае

Но все это как-то хрупко:

$ sudo su -
# screen -D -R  # apt install screen if not installed

Теперь нажмите Ctrl + a , затем d , чтобы отсоединиться . Введите exitили нажмите Ctrl + d , чтобы вернуться в пользовательский режим ...

Тогда просто:

$ sudo screen -x

Теперь вы войдете в сеанс корневого входа . Никаких следов sudo.

# ps $PPID
 PID TTY      STAT   TIME COMMAND
 26367 ?        Ss     0:00 SCREEN -D -R
# ps ho ppid $PPID
 1
# set | grep SUDO
                                         # <-- nothing here!

Заключение

Как chepner правильно прокомментировал:sudo предназначен для предоставления доступа к конкретным инструментам:

Nothing about sudo requires it to give you root access; that's just the default behavior everyone is familiar with. sudo can be configured to allow you to do only very specific things, including not gain root access at all – chepner

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

См.:

apropos sudo

И читайте внимательно

man sudo.conf
man sudoers

Относительноlogname

Посмотрите на правильный ответ Стефана Шазела ! Это может быть лучшим ответом на домашнее задание !!

Опять же, множество обходных путей , таких как:echo 0 > /proc/self/loginuid...

О /proc/self/loginuidподLinux

Пожалуйста, прочтите интересный ответ laolux по этому поводу!

die() { echo >&2 ${0##*/} Error: "$@"; exit 1;}
read lUid </proc/self/loginuid || die "Can't access procfile"
((lUid)) && die "You must be logged as root."

(Этот синтаксис избегает разветвлений!)

Но тем не менее

  • скрипт можно было копировать и редактировать
  • В зависимости от конфигурации/ядра эта запись ядра может быть подделана
  • Sudoer может создать cronзапись для инициации специального screenсеанса какroot.(cronи screen— не единственный способ делать подобные вещи! Просто первое, что пришло мне в голову.)
6
18.03.2021, 22:40
man sudoers 

(детали могут различаться от системы к системе)

«Подключаемый модуль политики sudoers определяет привилегии пользователя sudo. Это подключаемый модуль политики sudo по умолчанию. Политика управляется файлом /etc/sudoers...»

«Файл sudoers состоит из двух типов записей :псевдонимов (, в основном переменных )и пользовательских спецификаций (, которые определяют, кто и что может запускать )».

Удалите всех пользователей из /etc/sudoers (детали опущены ), и команда sudo не будет работать ни для кого. После этого только root может запускать команды, требующие привилегий root.

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

Обратите внимание, что мы делаем за вас домашнее задание, и мы не должны делать это снова.

-2
18.03.2021, 22:40
if [ "$(id -u)" -ne 0 ] || [ "$(logname)" != root ]; then
  echo >&2 "You either don't have superuser privilege or didn't login as root"
  exit 1
fi

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

4
18.03.2021, 22:40

Просто чтобы опубликовать что-то совершенно другое:

if ! tty -s 2>&0
then    echo "Need to run with standard error on a terminal"
        exit 1
fi

if [ x"`stat --printf=%u $(tty)`" != x"0" ]
then    echo "Must be logged in as root. Can't use sudo or su here."
        exit 1
fi

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

2
18.03.2021, 22:40

Теги

Похожие вопросы