Praktyczny (bliższy klasycznego Linuksa) sposób użycia (automatyzacji) SUDO dla CygWin

11

Możliwość używania sudopoleceń w CygWin jest przydatna i szybsza niż otwieranie podwyższonej powłoki:

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.

Jak pokazano powyżej, możesz także uruchamiać polecenia / skrypty systemu Windows, podobnie jak Linux. Dla mnie jest schludne; działa na zdalnych konsolach (SSH) i pozwala łączyć polecenia Windows / Linux . Możliwość wykonywania zadań administracyjnych jest więc prawie koniecznością.

Ale projekt SUDO dla CygWin ma zachowanie, które może być niebezpieczne : działa jako architektura serwer / klient , w rzeczywistości klient (sudo) wysyła żądania poleceń do serwera (sudoserver.py) wewnętrznie (nie nasłuchuje poza komputer lokalny) port 7070TCP, bez sprawdzania użytkownika lub uprawnień , aby każdy (nawet nieuprzywilejowani użytkownicy) zalogowani na komputerze mogli wykonywać polecenia powłoki lub skrypty administratora (CygWin lub Windows) (również CygWin lub Windows).
Problem pogarsza się, jeśli zachowasz sugerowaną metodę autora: rejestrację „sudoserver.py” jako usługi, dzięki czemu będzie działała na stałe.

Tak więc, aby zachować nieco bezpieczeństwo (nie do końca), robię:
1. - Uruchom „sudoserver.py” na powłoce administracyjnej.
2.- Wykonaj moje polecenia „sudo” na innej powłoce CygWin.
3. - Zamknij (Ctrl + C) „sudoserver.py” i powłokę administratora.

Trochę denerwujące . Obejmuję go za pomocą .cmdpliku z przypisanym klawiszem skrótu, który uruchamia plik „sudoserver.py”, i zamykam go (ręcznie) po moich zadaniach administracyjnych, ale wciąż daleko od klasycznej użyteczności „sudo” w systemie Linux.

Świetnym i praktycznym sposobem byłaby metoda, która:

  1. ** Automatycznie otwiera plik „sudoserver.py” z prośbą o podanie wysokości UAC (lub użytkownika / hasła).
  2. Zamyka go po chwili, aby żądanie UAC nie przeszkadzało w przypadku kilku sudopoleceń wykonywanych sekwencyjnie.

Czy istnieje jakiś sposób na zautomatyzowanie tego , przynajmniej częściowo?

Sopalajo de Arrierez
źródło

Odpowiedzi:

10

UWAGA: Jest to głównie program (skrypt powłoki), który stworzyłem, i wiem, że to forum jest bardziej stroną z pytaniami i odpowiedziami niż stroną z programami. Ale nie mam konta GitHub (lub podobnego), ani nie miałem czasu na badanie metody publikowania społeczności programu Open Source. Więc, jak długo istnieje ryzyko, że pracy i przydatny program zachowuje niezauważone (nawet kilka miesięcy) do tych, którzy mogli cieszyć się nim, a to byłoby smutne nie podzielają już wykonany program mam zamiar opublikować go tutaj dla teraz. Nie ma dla mnie problemów, jeśli administratorzy zdecydują się usunąć ten wątek, zrozumiem. Mam nadzieję, że sformułowałem sprawę w sposób umożliwiający udzielenie odpowiedzi na to pytanie . Jeśli jest wystarczającoZainteresowani użytkownicy dołożę wszelkich starań, aby poświęcić trochę czasu na kontynuację projektu (po wszystkich moich badaniach nie znalazłem niczego najbliższego w Internecie, ale ... no cóż ... nie wiem, czy mój skrypt jest wartościowy czy to strata czasu).

Zaprogramowałem prosty skrypt powłoki Linuksa, który działa (do tej pory) na CygWin i pomaga (mam nadzieję) zmniejszyć SUDO dla interwału czasowego ataku CygWin. Program nosi nazwę TOUACExt (akronim „ TimeOut and UAC Extension ”) i działa jako opakowanie dla SUDO dla CygWin (wymagana instalacja) i jest naprawdę złożony z zestawu czterech .shprogramów.

Przykład wykonania TOUACExt

Funkcje :

  • Wygodne użytkowanie : poprzez symulację oryginalnego sudo z zachowania Linux, monit o potwierdzenie UAC pojawia się tylko raz (wiele kolejnych sudopoleceń wygeneruje tylko jedno żądanie UAC). Tak długo, jak sudoserver.py działa (domyślnie 15 minut), nie będzie więcej żądań UAC .
  • Użytkownicy uprzywilejowani (administratorzy) otrzymują tylko prośbę o potwierdzenie UAC ( tak / nie ) na ekranie.
  • Użytkownicy nieuprzywilejowani (niebędący administratorami) otrzymują ekran wprowadzania konta administratora / hasła .
  • sudoserver.py nadal działa, a następnie zamyka się automatycznie po określonym czasie (15 minut) od ostatniego wykonania polecenia sudo.
  • sudoserver.py nie zamyka się (kontynuuje działanie i sprawdzi ponownie za 5 minut) w przypadku jakiegokolwiek wystąpienia sudo .
  • Działa zdalnie (testowane przez SSH):
    • Nieuprzywilejowani użytkownicy nie mogą zdalnie uruchomić sudoserver.py.
  • Tworzy (ale prosty i niezbyt czytelny) dziennik w /var/log/SUDOForCygWin/.

Wymagania (w CygWin):

  • SUDO dla CygWin .
  • pgrep (w procpspakiecie).
  • flock (na util-linuxopakowaniu).
  • nohup (myślę, że domyślnie zainstalowany na CygWin, ale nie jestem pewien).

Zakładając : - Dwa programy projektu SUDO dla CygWin na ścieżce sugerowanej przez autora:

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

TOUACExt zostały przetestowane na systemach Windows 7 z dodatkiem SP1 i Windows XP z dodatkiem SP3, ale nie wiem, czy ma sens używanie go w tym ostatnim.

Instrukcje instalacji :

  • Umieść ten skrypt (sugerowana nazwa:) SUDOServer.cmdi utwórz skrót (możesz spersonalizować jego ikonę, jeśli chcesz) do niego o nazwie SUDOServer.lnk(musisz włączyć ten skrót Advanced Options --> Execute as Administrator) w dowolnym miejscu na ścieżce systemu Windows , więc sudoserver.pymożna go bezpośrednio zażądać od systemu Windows:

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

  • Umieść cztery skrypty .sh TOUACExt na ścieżce, na przykład:

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

  • Zmień nazwę oryginalnego skryptu Python z sudona sudo.py:

    mv /usr/local/bin/sudo /usr/local/bin/sudo.py
    OSTRZEŻENIE: Oryginalny skrypt „sudo” w języku Python nie może pozostać nigdzie na ścieżce, w przeciwnym razie można go wykonać.

  • Utwórz ten alias (na przykład ręcznie lub edytując swój ~/.bashrc):

    alias sudo='SUDO.sh'

Kod dla 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.

Kod dla 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). 

Kod dla 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 

Kod dla 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 

Przetestuj program z powłoki 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

UWAGA 2: Te skrypty są w wersji wcześniejszej niż beta , więc nadal są wadliwe, a kod nie jest bardzo czysty. W każdym razie, w moich testach z trzema różnymi komputerami z systemem Windows 7 wydają się działać (głównie) OK.

Krótkie wyjaśnienie programu:

  1. Z powodu aliasu podczas wykonywania polecenia sudo wywoływany jest skrypt SUDO.sh.
  2. SUDO.sh wywołuje SUDOServer.sh , otwierając (przez SUDOServer.lnk) „sudoserver.py” w razie potrzeby.
  3. Pierwotne polecenie sudo wywoływane przez użytkownika jest wykonywany.
  4. Następnie SUDO.sh wywołuje SUDOServerWatchDogScheduler.sh , który planuje wykonanie SUDOServerWatchDog.sh po upływie określonego czasu (domyślnie 15 minut) do zamknięcia sudoserver.py.
  5. Po określonym czasie SUDOServerWatchDog.sh zamyka plik sudoserver.py . Jeśli jest uruchomione jakieś wystąpienie sudo , programuje się do nowego wykonania po 5 minutach.

Do zrobienia :

  • Własna instalator , który tworzy cały .sh, cmd i pliki .lnk automatycznie.
  • Ustanowić plik blokady na innym (znajduje się w $ TMP / lockfile.lck).
  • Dodaj skrypt konfiguracyjny lub plik .config (domyślne ustawienia limitów czasu, lokalizacji plików ... itd.).
  • Dodaj zachowanie konta systemowego (dzięki, @ Wyatt8740).
  • ¿Zmienić „flock” (tryb SUDO z wewnętrznym ryglowaniem) na „utrwalacz”, gdzie to stosowne?
  • Sugestie zaakceptowane.

Zgłoszone błędy :

  • Powłoka bash pozostaje otwarta nawet po wprowadzeniu, exitjeśli sudoserver.pydziała, dopóki się nie zamknie. Tymczasowe obejścia są mile widziane.

Mam nadzieję, że ktoś wykorzysta długie godziny programowania, które poświęciłem TOUACExt.
Ulepszenia i poprawki są akceptowane. Zaakceptowano również
sugestie, gdzie powinienem opublikować kod, aby przestać dokuczać temu forum ;-).

Przepraszam za długi post. Nie mam dużo wolnego czasu, a ten projekt miał zniknąć w mojej szafie (może na lata, kto wie?).

Sopalajo de Arrierez
źródło
2
Jeśli chcesz uzyskać opinię na temat swojego kodu, opublikuj go na codereview.stackexchange.com. (Warto zapoznać się z uwagami i przykładami użycia)
Ben Voigt
Dzięki, @BenVoigt, nie wiedziałem. Pytanie: jeśli tak, myślę, że większość postów powinna być duplikatem tej odpowiedzi. Czy będzie to uważane za delegowanie?
Sopalajo de Arrierez
1
Pamiętaj, aby połączyć je ze sobą. Szkoda w crossspostingu polega na tym, że ludzie duplikują wysiłek. Jeśli są ze sobą powiązane, nie jest to taki problem
Ben Voigt
To bardzo dobre rozwiązanie. Gdyby nie wymagał Pythona, użyłbym go. Mam osobistą, głęboką wstręt do pytona. To fajny język, ale z powodów osobistych bardziej mi się nie podoba. Mimo to, ponieważ prawie nikt inny nie nienawidzi Pythona, a moja nienawiść jest irracjonalna, głosowałem za twoim rozwiązaniem, ponieważ jest ono bliższe rzeczywistemu niż mojemu.
Wyatt8740
1
Dzięki, @CharlesRobertoCanato. Może mógłbyś podać mi szczegóły na czacie, aby je rozwiązać? Pokój czatu „TOUACExt - SuDo dla Windows”: chat.stackexchange.com/rooms/56716/touacext-sudo-for-windows
Sopalajo de Arrierez
1

SIMPLE sudo.bat (używa nircmd)

Nircmd można pobrać tutaj:
http://www.nirsoft.net/utils/nircmd.html

Pobrałem nircmd i zmieniłem nazwę nircmdc.exena nircmd.exe, zastępując oryginał nircmd.exe. Następnie przeniosłem go do C:\windows\system32.

Zrobiłem również następujący plik wsadowy, aby umożliwić przekazywanie argumentów do skryptu.

Należy powiedzieć, że wyłączyłem UAC na moim komputerze, więc nie potrzebuję już tego skryptu, ale DZIAŁA on od systemu Windows 8. Działa również w cygwin.

@echo off
if "%*" == "" goto error
nircmd elevate %*
goto thisiseof
:error
echo No arguments were given. Exiting.
:thisiseof
Wyatt8740
źródło
Fantazyjne rozwiązanie. Krótko i łatwo. Ale dlaczego zawodzi mnie to w prosty sposób sudo.bat dir? Windows błędu mówi „Windows nie może znaleźć pliku o nazwie katalog”. Wygląda na to, że działa sudo echo Hello, ale nie ma wyjścia konsoli.
Sopalajo de Arrierez
Małe niedogodności tej metody jest ciągła zapytanie UAC w kolejnych poleceń. TOUACExt rozwiązuje to, podobnie jak w klasycznych wykonaniach sudo w Linuksie. Zredagowałem listę funkcji, aby ją pokazać.
Sopalajo de Arrierez
dirnie działa, ponieważ dirtechnicznie nie jest programem, ale wbudowanym poleceniem DOS. w Linuksie lsjest programem binarnym, w DOS / Windows dirobsługiwanym przez samego interpretera (tj. COMMAND.COM lub cmd.exe). Nigdzie nie ma dir.exemojego programu do uruchomienia. Ale dla cygwina sudo lspowinno wystarczyć. Nawet jeśli nie, robi sudo cmdlub sudo bashczy cokolwiek powinno Ci poziom „Administrator” szybka. Jednak nawet „Administrator” jest poniżej „SYSTEM” - użyj „SYSTEM” nircmd.exe elevatecmd runassystem <program.exe>. Ponadto wyłączam UAC na moich komputerach :)
Wyatt8740
Ponadto nie sądzę, że echojest to program w systemie Windows. Jest częścią COMMAND.COM/cmd.exe. Dla mnie jednak użytkownik cygwin z ls.exei echo.exedziała dobrze. I faktycznie użyłem go dzisiaj po raz pierwszy od miesięcy do zarządzania plikami na koncie mojego brata bez logowania się jako on (udało mu się umieścić każdy program na swoim komputerze w katalogu „startowym” swojego menu startowego: P). Właśnie zalogowałem się na innym i sudo.bat cmdotrzymałem monit na poziomie administratora, który pozwoliłby mi zarządzać plikami innych użytkowników.
Wyatt8740
Twój pomysł na konto systemowe jest dobry. Dodam go do TOUCExt jako opcję.
Sopalajo de Arrierez
0

Będąc niezadowolonym z dostępnego rozwiązania, zaadaptowałem skrypt nu774, aby zwiększyć bezpieczeństwo i ułatwić konfigurację i obsługę. Projekt jest dostępny na Github

Aby go użyć, wystarczy go pobrać cygwin-sudo.pyi uruchomić python3 cygwin-sudo.py **yourcommand**.

Dla wygody możesz ustawić alias:

alias sudo="python3 /path-to-cygwin-sudo/cygwin-sudo.py"
Chronial
źródło