Практичний (ближчий до класичного Linux) спосіб використання (автоматизації) SUDO для CygWin


11

Вміння використовувати sudoкоманди в CygWin корисно і швидше, ніж відкривати підвищену оболонку:

Luis@Kenobi /cygdrive/c/Users/Luis
$ net user /add TestUser
System error 5.
Access denied.

Luis@Kenobi /cygdrive/c/Users/Luis
$ sudo net user /add TestUser
Command completed successfully.

Як показано вище, ви також можете запускати команди / скрипти Windows, як і Linux. Для мене акуратно; працює на віддалених (SSH) консолях і дозволяє комбінувати команди Windows / Linux . Отже, можливість виконувати адміністративні завдання майже не обов'язкова.

Але проект SUDO для CygWin має поведінку, яка може бути небезпечною : він працює як архітектура сервера / клієнта , насправді клієнт (sudo) надсилає запити команд на сервер (sudoserver.py) на внутрішній (не слухає зовні порт 7070TCP на локальному комп'ютері, без перевірки користувачем або дозволів , тому будь-хто (навіть непривілейовані користувачі) увійшов на комп'ютер, міг би виконувати команди або сценарії оболонок адміністраторів (CygWin або Windows) (CygWin або Windows).
Проблема загострюється, якщо ви дотримуєтесь запропонованого автором методу: зареєструвавши "sudoserver.py" як сервіс, тому він буде постійно працювати.

Отже, щоб підтримувати речі трохи безпечніше (не повністю), я виконую:
1.- Виконати "sudoserver.py" на оболонці адміністратора.
2.- Виконайте мої команди "sudo" на іншій оболонці CygWin.
3.- Закрийте (Ctrl + C) "sudoserver.py" та оболонку адміністратора.

Трохи прикро . Я workarounding його з допомогою .cmdфайлу з призначеної гарячою клавішею , яка працює «sudoserver.py», і я закриваю (вручну) це після моїх адміністративних робочих місць, але все ще далека від класичної «SUDO» юзабіліті на Linux.

Чудовим і практичним способом був би такий метод, який:

  1. ** Автоматично відкриває "sudoserver.py" із запитом на підказку UAC Elevation (або користувач / пароль).
  2. Через деякий час він закривається , тому запит UAC не буде тривожним у разі sudoпослідовного виконання декількох команд.

Чи є спосіб автоматизувати це , принаймні частково?

Відповіді:


10

ПРИМІТКА. Це, здебільшого, програма (скрипт оболонки), яку я створив, і я знаю, що цей форум - це скоріше сайт із запитаннями, ніж відповідь на впровадження програм. Але я не маю жодного облікового запису GitHub (або подібного), а також не мав часу досліджувати спосіб публікації програми з відкритим кодом для громади. Таким чином, до тих пір , поки існує ризик того, що робоча і корисна програма зберігає непомітно (навіть в протягом декількох місяців) для тих , хто міг би насолоджуватися цим, і було б сумно не розділяти вже зробив програму, я збираюся опублікувати його тут для зараз. Немає проблем для мене, якщо адміністратори вирішать видалити цю тему, я зрозумію. Я сподіваюсь, що я сформулював це питання достатньо, щоб зробити його корисним для цього форуму. Якщо їх достатньозацікавлені користувачі , я зроблю все можливе, щоб приділити деякий час для продовження проекту (після всіх моїх досліджень я не знайшов нічого найбільш близького до цього в Інтернеті, але, ну ... я не знаю, чи мій сценарій цінний чи це було марною тратою часу).

Я запрограмував простий скрипт оболонки Linux, який працює (до цих пір) на CygWin і допомагає (сподіваюся) скорочуючи інтервал часу атаки SUDO для CygWin. Програма має назву TOUACExt (абревіатура " TimeOut та UAC Extension ") і виступає в якості обгортки для SUDO для CygWin (потрібно встановити), і справді складається з набору з чотирьох .shпрограм.

Приклад виконання TOUACExt

Особливості :

  • Зручне використання : імітуючи оригінальний sudo з поведінки Linux, запит на підтвердження UAC з'являється лише один раз (кілька послідовних sudoкоманд генерують лише один запит UAC). Поки sudoserver.py не працює (за замовчуванням 15 хвилин), більше не буде запитів UAC .
  • Привілейовані користувачі (Адміністратор) отримують на екрані лише запит на підтвердження UAC ( Так / Ні ).
  • Непривілейовані (не-адміністратори) користувачі отримують екран введення облікового запису адміністратора / пароля .
  • sudoserver.py продовжує працювати, а потім автоматично закривається через попередньо визначений час (15 хвилин) від останнього виконання команди sudo.
  • sudoserver.py не закривається (продовжує працювати і знову перевіриться через 5 хвилин) у разі будь-якого екземпляра запуску sudo .
  • Працює віддалено (тестується через SSH):
    • Непривілейовані користувачі не можуть запускати sudoserver.py віддалено.
  • Створює (але простий і не дуже читабельний) журнал у /var/log/SUDOForCygWin/.

Вимоги (у CygWin):

  • SUDO для CygWin .
  • pgrep (на procpsупаковці).
  • зграя (на util-linuxупаковці).
  • nohup (я думаю, встановлений за замовчуванням на CygWin, але не впевнений).

Припустимо : - Дві програми проекту SUDO для CygWin на шляху, запропонованому автором:

/usr/local/bin/sudoserver.py
/usr/local/bin/sudo

TOUACExt пройшли тестування на Windows 7 SP1 та Windows XP SP3, але я не знаю, чи є сенс використовувати його на останньому.

Інструкція з установки :

  • Помістіть цей скрипт (запропоноване ім'я SUDOServer.cmd:) та створіть ярлик (ви можете персоналізувати його значок, якщо хочете) до його імені SUDOServer.lnk(потрібно ввімкнути цей ярлик Advanced Options --> Execute as Administrator) в будь-якому місці вашого шляху Windows , щоб його sudoserver.pyможна було запитувати безпосередньо в Windows:

    c:\CygWin\bin\python2.7.exe /usr/local/bin/sudoserver.py

  • Покладіть на шлях чотири .sh- сценарії TOUACExt , наприклад:

    /usr/local/bin/SUDO.sh /usr/local/bin/SUDOServer.sh /usr/local/bin/SUDOServerWatchDog.sh /usr/local/bin/SUDOServerWatchDogScheduler.sh

  • Перейменуйте вихідний сценарій Python від sudoдо sudo.py:

    mv /usr/local/bin/sudo /usr/local/bin/sudo.py
    ПОПЕРЕДЖЕННЯ: Оригінальний скрипт "sudo" Python не повинен залишатися ніде на вашому шляху, інакше він може бути виконаний натомість.

  • Створіть цей псевдонім (наприклад, вручну або відредагувавши свій ~/.bashrc):

    alias sudo='SUDO.sh'

Код для SUDO.sh :

#!/bin/bash

# ********** SUDO.sh v0.04a **********

# Variables:
# LockFile (will use a temporal one for now):
#lockfile=sudoserver-running.lck
LockFile=lockfile.lck

# Creating LogFile (if it does not exist):
mkdir /var/log/SUDOForCygWin 2>/dev/null
chmod 777 /var/log/SUDOForCygWin 2>/dev/null
LogFile=/var/log/SUDOForCygWin/$(date +%Y%m%d).log
exec 5>>$LogFile    # Redirector 5 will be the log file.
chmod 777 $LogFile >&5 2>&5 # Writable to anyone (for now).

# Start of the program
echo "========== Starting SUDO Server for CygWin ==========" >&5
echo $(date) >&5

# does the lock file exists as locked?
if [ $(flock -n $TMP/$LockFile echo>/dev/null;echo $?) -eq 0 ]
   then
    # The lock file is not locked.
    echo "LockFile not locked. Testing sudo access..." >&5
    if [ $(sudo.py vartemp=0>/dev/null 2>/dev/null;printf $?) -eq 0 ]
       then
        # Wooops. sudoserver.py is running without the lockfile. Better to correct this.
        echo "LockFile not locked, but sudoserver.py seems to be running." >&5
        printf "Killing sudoserver.py...\n" >&5
        sudo.py kill $(sudo.py pgrep.exe -f -l sudoserver.p[y] | grep "pgrep" -v | awk '{print $1}') >&5 2>&5
    fi
    # Starting SUDOServer.sh
    printf "Requesting SUDOServer start...\n" >&5
    nohup SUDOServer.sh >&5 2>&1&
    # Wait some time delay for UAC Prompt to start
    sleep 2
    timeout=$((SECONDS+10))
    # Has sudoserver.py already started?
    while [ $(flock -w 1 $TMP/$LockFile echo>/dev/null;printf $?) -eq 0 ] || [ $(tasklist | grep "consent.exe" -i>/dev/null;printf $?) -eq 0 ]
    do
        # No. We have to wait.
        # Waiting for SUDOServer.py to be running.
        printf "."
        if [ $SECONDS -ge $timeout ]
           then
            # sudoserver.py not responding. Aborting with errorlevel=3.
            printf "sudoserver.py not responding. Aborting.\n"
            exit 3
        fi
    done
    # Yes. sudoserver.py is up and running.
fi

printf "\n"
# Schedule (add) SUDOServer Watch Dog to Task Scheduler:
SUDOServerWatchDogScheduler.sh

# Invoke requested sudo command
sudo.py $@

#printf "ErrorLevel was: "$?


# ErrorLevel Codes:
# 3 --> timeout waiting for sudoserver.py to respond.

Код для SUDOServer.sh :

#!/bin/bash

# ********** SUDOServer.sh v0.04a **********

# Variables:
# LockFile (a temporal one for now):
#lockfile=sudoserver-running.lck
LockFile=lockfile.lck

# Check for other instances of sudoserver.py running
if [ $(flock -n $TMP/$LockFile echo>/dev/null;printf $?) -eq 0 ]
   then
    printf "Creating lockfile: "$TMP/$LockFile"\n"
    flock $TMP/$LockFile -c 'cmd /c SUDOServer'
    # The file has been unlocked. Send error level=2.
    exit 2
   else
    printf "The lockfile: "$TMP/$LockFile" is locked by another process.\n"
    printf "Exiting SUDOServer.sh"
fi

printf "SUDOServer.sh execution finished. Exiting."

# Exiting with no problems.
exit 0

# ErrorLevel Codes:
# 2 --> SUDOServer.lnk (maybe denial of UAC). 

Код для SUDOServerWatchDog.sh :

#!/bin/bash

# ********** SUDOServerWatchDog.sh v0.04a **********

# Variables:
# LockFile (a temporal one for now):
#lockfile=sudoserver-running.lck
LockFile=lockfile.lck

# Redirecting to LogFile:
LogFile=/var/log/SUDOForCygWin/$(date +%Y%m%d).log
exec 5>>$LogFile
if [ $(stat $LogFile -c %a) -ne 777 ]
   then
    echo "Logfile "$LogFile" has incorrect permissions." >&5
    echo "Attemping to change permissions of "$LogFile >&5
    chmod 777 $LogFile >&5 2>&5
fi

# Remove Task Scheduler entry, if exists.
if [ $(schtasks.exe /query | grep "SUDOServerWatchDog" -i>/dev/null 2>&5;printf $?) -eq 0 ]
   then
    sudo.py schtasks.exe /delete /tn "SUDOServerWatchDog" /f >&5 2>&5
fi

# Is sudoserver.py running?
if [ $(flock -n $TMP/$LockFile echo>/dev/null;printf $?) -eq 1 ] || [ $(sudo.py vartemp=0>/dev/null 2>/dev/null;printf $?) -eq 0 ]
   then
    # Yes. sudoserver.py is running. So...
    printf "sudoserver.py detected running...\n" >&5
    # Is any instance of sudo running right now?
    if [ $(sudo.py pgrep -f -l "/usr/local/bin/sudo.py " | grep -v grep>/dev/null 2>&5;printf $?) -eq 0 ]
       then
        # Yes. sudo is running right now. So...
        printf "There are instances of sudo running.\n" >&5
        sudo.py schtasks /create /tn "SUDOServerWatchDog" /tr "SUDOServerWatchDog" /sc minute /mo 5 /sd 10/10/2010 /ru "SYSTEM" >&5 2>&5
        printf "Will check again in 5 minutes. Adding Task.\n" >&5
       else
        # No. sudo is not running right now. So...
        # Kill sudoserver.py.
        printf "Closing sudoserver.py\n" >&5
        sudo.py kill $(sudo.py pgrep.exe -f -l sudoserver.p[y] | grep "pgrep" -v | awk '{print $1}')
    fi
   else
    printf "sudoserver.py not running. Nothing to be done.\n" >&5
fi 

Код для SUDOServerWatchDogScheduler.sh :

#!/bin/bash

# ********** SUDOWatchDogScheduler.sh v0.04a **********

# Check if WatchDog is already scheduled
if [ $(schtasks.exe /query | grep "SUDOServerWatchDog">/dev/null 2>&5;printf $?) -eq 0 ]
   then
    # Yes. Remove it in order to create a new one.
        echo "Task SUDOServerWatchDog already existing." >&5
    echo "Removing task SUDOServerWatchDog..." >&5
    sudo.py schtasks.exe /delete /tn "SUDOServerWatchDog" /f >&5 2>&5
    if [ $? -eq 0 ]
       then
        # Task correctly deleted.
        echo "Task correctly removed." >&5
       else
        # Something failed in task creation. Report.
        echo "ERROR on deleting the SUDOServerWatchDog programmed task." >&5
    fi
fi
# Schedule new task for deletion.
echo "Adding new SUDOServerWatchDog task to trigger in 15 minutes." >&5
sudo.py schtasks /create /tn "SUDOServerWatchDog" /tr "SUDOServerWatchDog" /sc minute /mo 15 /sd 10/10/2010 /ru "SYSTEM" >&5 2>&5
if [ $? -eq 0 ]
   then
    # Task correctly scheduled.
    echo "Task SUDOServerWatchDog correctly scheduled." >&5
   else
    # Something failed in task scheduling. Report.
    echo "ERROR on scheduling programmed task SUDOServerWatchDog." >&5
fi 

Перевірте програму на оболонці CygWin Bash:

Luis@Kenobi ~
$ sudo ls -la
<UAC ELEVATION PROMPT APPEARS>
total 49
drwxr-xr-x+ 1 Luis  None     0 abr  7 02:23 .
drwxrwxrwt+ 1 Luis- None     0 abr  4 03:27 ..
-rw-------  1 Luis  None 13798 abr 14 00:31 .bash_history
-rwxr-xr-x  1 Luis  None  1494 mar  3 11:36 .bash_profile
-rwxr-xr-x  1 Luis  None  6260 abr  6 05:19 .bashrc
-rwxr-xr-x  1 Luis  None  1919 mar  3 11:36 .inputrc
-rw-------  1 Luis  None    35 abr  2 01:43 .lesshst
-rwxr-xr-x  1 Luis  None  1236 mar  3 11:36 .profile
drwx------+ 1 Luis  None     0 mar  8 01:49 .ssh
-rw-r--r--  1 Luis  None     7 mar  4 18:01 d:ppp.txt
-rw-r--r--  1 Luis  None    37 abr  7 02:23 my.log

ПРИМІТКА2. Ці сценарії знаходяться в попередній бета-версії , тому вони все ще баггі і код не дуже чистий. У будь-якому випадку, на моїх тестах з трьома різними комп'ютерами Windows 7 вони, здається, працюють (здебільшого) гаразд.

Коротке пояснення програми:

  1. У зв'язку з псевдонімом, при виконанні команди SUDO SUDO.sh скрипт викликається.
  2. SUDO.sh називає SUDOServer.sh , відкриваючи (через SUDOServer.lnk) "sudoserver.py", якщо потрібно.
  3. Вихідна команда Sudo викликається користувачем виконується.
  4. Потім SUDO.sh викликає SUDOServerWatchDogScheduler.sh , який планує завершити виконання SUDOServerWatchDog.sh після заданого часу (15 хвилин за замовчуванням), щоб закрити sudoserver.py.
  5. Після визначеного часу SUDOServerWatchDog.sh закриває sudoserver.py . Якщо є якийсь екземпляр запуску sudo , він програмує себе на нове виконання через 5 хвилин.

Щоб зробити :

  • Самостійний інсталятор, який автоматично створює всі .sh, .cmd та .lnk файли.
  • Встановіть файл блокування для іншого (це на $ TMP / lockfile.lck).
  • Додайте сценарій конфігурації або файл .config (для замовчувань у режимі очікування, розташування файлів ... тощо).
  • Додайте поведінку системного облікового запису (спасибі, @ Wyatt8740).
  • Змініть "стадо" (режим внутрішнього блокування SUDO) на "термоядер", де це доречно?
  • Пропозиції прийняті.

Повідомлення про помилки :

  • Оболонка bash залишається відкритою навіть після введення, exitякщо sudoserver.pyвона працює, поки вона не закриється. Тимчасові шляхи вирішення вітаються.

Я сподіваюся, що хтось використає довгі години програмування, яке я присвятив TOUACExt.
Покращення та виправлення прийняті.
Пропозиції щодо того, куди мені слід надрукувати код, щоб перестати нудити на цьому форумі, також прийняті ;-).

Вибачте за довгий пост. У мене мало багато вільного часу, і цей проект був про те, щоб зникнути в моїй шафі (можливо, роками, хто знає?).


2
Якщо ви хочете отримати відгук про свій код, опублікуйте його на codereview.stackexchange.com. (Примітки щодо використання та приклади тут добре мати)
Ben Voigt

Дякую, @BenVoigt, я не знав. Будь ласка, запитання: якщо я це зробити, я думаю, що більшість публікацій мають бути дублікатами цієї відповіді. Чи буде це вважатися перехресним дописом?
Sopalajo de Arrierez

1
Обов’язково зв’яжіть їх один з одним. Шкода в перехресному посту полягає в тому, що люди повторюють зусилля. Якщо вони пов'язані, це не така проблема
Бен Войгт

Це дуже хороше рішення. Якби для цього не потрібен python, я б використовував його. У мене є особиста, глибока ненависть до пітона. Це гарна мова, але з особистих міркувань я більше не люблю її. Але, оскільки майже ніхто більше не ненавидить пітона, а моя ненависть ірраціональна, я підтримав ваше рішення, оскільки воно ближче до справжньої речі, ніж моя.
Wyatt8740

1
Дякую, @CharlesRobertoCanato Можливо, ви могли б дати мені деталі в чаті, щоб вирішити це? Чат "TOUACExt - SuDo для Windows": chat.stackexchange.com/rooms/56716/touacext-sudo-for-windows
Sopalajo de Arrierez

1

ПРОСТИЙ sudo.bat (використовує nircmd)

Nircmd можна завантажити тут:
http://www.nirsoft.net/utils/nircmd.html

Я завантажив nircmd і перейменував його nircmdc.exeна nircmd.exe, замінивши оригінал nircmd.exe. Потім я перемістив його C:\windows\system32.

Я також зробив наступний пакетний файл, щоб дозволити передавати аргументи до сценарію.

Слід сказати, що я відключив UAC на своїй машині, тому мені більше не потрібен цей скрипт, але він працює як у Windows 8. Він також працює в cygwin.

@echo off
if "%*" == "" goto error
nircmd elevate %*
goto thisiseof
:error
echo No arguments were given. Exiting.
:thisiseof

Вигадливе рішення. Короткий і легкий. Але чому це мені не в простому sudo.bat dir? Вікно про помилку повідомляє "Windows не може знайти файл з назвою dir". Здається, це працює sudo echo Hello, але консольного виходу немає.
Sopalajo de Arrierez

Невелика незручність , з допомогою цього методу є безперервним запит UAC в рядку послідовних команд. TOUACExt вирішує це, як і в класичних Linux-версіях. Я відредагував список функцій, щоб показати його.
Sopalajo de Arrierez

dirне працює, оскільки dirтехнічно це не програма, а вбудована команда DOS. тоді як у Linux ls- це двійкова програма, в DOS / windows dirобробляє сам інтерпретатор (тобто COMMAND.COM або cmd.exe). Для dir.exeмоєї програми ніде не працює. Але для cygwin, sudo lsповинно вистачити. Навіть якщо ви цього не зробите sudo cmdабо зробите, sudo bashчи що завгодно, вам слід отримати запит на рівні адміністратора. Навіть "Administrator" знаходиться нижче "SYSTEM", хоча - для "SYSTEM", використовуйте nircmd.exe elevatecmd runassystem <program.exe>. Також я відключаю UAC на своїх машинах :)
Wyatt8740

Крім того, я не думаю echo, що це програма ні в Windows. Це частина COMMAND.COM/cmd.exe. Для мене, однак, користувач cygwin, ls.exeі echo.exeвін працює чудово. І я фактично використовував його сьогодні вперше за кілька місяців, щоб керувати файлами в акаунті мого брата, не входячи в систему як він (йому вдалося помістити кожну програму на своєму комп’ютері в каталог запуску меню «Пуск»: P). Просто увійшов до іншого і використовував sudo.bat cmdдля отримання запиту на рівні адміністратора, який дозволив би мені керувати файлами інших користувачів.
Wyatt8740

Ваше уявлення про обліковий запис системи добре. Я додам його до TOUCExt як варіант.
Sopalajo de Arrierez

0

Будучи незадоволений наявним рішенням, я прийняв сценарій nu774, щоб додати безпеку та полегшити налаштування та використання. Проект доступний на Github

Щоб використовувати його, просто завантажте cygwin-sudo.pyта запустіть його через python3 cygwin-sudo.py **yourcommand**.

Ви можете налаштувати псевдонім для зручності:

alias sudo="python3 /path-to-cygwin-sudo/cygwin-sudo.py"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.