Modo pratico (più vicino a quello classico di Linux) di usare (automatizzare) SUDO per CygWin


11

Essere in grado di usare i sudocomandi in CygWin è utile e più veloce dell'apertura di una shell elevata:

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.

Come mostrato sopra, puoi anche eseguire comandi / script di Windows, proprio come Linux. Per me è pulito; funziona su console remote (SSH) e consente di combinare comandi Windows / Linux . Quindi essere in grado di eseguire compiti amministrativi è quasi un must.

Ma il progetto SUDO per CygWin ha un comportamento che potrebbe essere pericoloso : funziona come un'architettura server / client , infatti un client (sudo) invia richieste di comandi a un server (sudoserver.py) all'interno (non in ascolto al di fuori del computer locale) porta 7070TCP, senza controllo utente o autorizzazioni , quindi chiunque (anche utenti non privilegiati) che ha effettuato l'accesso al computer potrebbe eseguire comandi o script della shell degli amministratori (CygWin o Windows) (anche CygWin o Windows).
Il problema peggiora se si mantiene il metodo suggerito dall'autore: registrando "sudoserver.py" come servizio, quindi continuerà a funzionare permanentemente.

Quindi, per mantenere le cose un po ' più sicure (non del tutto), lo faccio:
1. Eseguo "sudoserver.py" su una shell di amministrazione.
2.- Esegui i miei comandi "sudo" su un'altra shell CygWin.
3.- Chiudi (Ctrl + C) "sudoserver.py" e la shell di amministrazione.

Un po ' fastidioso . Lo sto risolvendo usando un .cmdfile con tasto di scelta rapida assegnato che esegue "sudoserver.py" e lo sto chiudendo (manualmente) dopo i miei lavori amministrativi, ma ancora lontano dalla classica usabilità "sudo" su Linux.

Il modo migliore e pratico sarebbe un metodo che:

  1. ** Apre automaticamente "sudoserver.py" richiedendo il prompt di elevazione UAC (o utente / password).
  2. Chiude dopo un po ', quindi la richiesta UAC non continuerà a disturbare in caso di più sudocomandi eseguiti in sequenza.

C'è un modo per automatizzare questo , almeno in parte?

Risposte:


10

NOTA: Questo è principalmente un programma (shell script) che ho creato e so che questo forum è più un sito di domande e risposte che di introduzione di programmi. Ma non ho alcun account GitHub (o simile), né ho avuto il tempo di fare ricerche sul metodo di pubblicazione di un programma Open Source nella comunità. Quindi, fintanto che esiste il rischio che un programma funzionante e utile rimanga inosservato (anche per mesi) a coloro che potrebbero apprezzarlo, e sarebbe triste non condividere un programma già realizzato, lo pubblicherò qui per adesso. Nessun problema per me se gli amministratori decidessero di rimuovere questa discussione, capirò. Spero di aver formulato la questione in una domanda-risposta modo abbastanza per renderlo utile a questo forum. Se ce ne sono abbastanzautenti interessati , farò del mio meglio per dedicare un po 'di tempo per continuare il progetto (dopo tutte le mie ricerche, non ho trovato nulla di più vicino a questo su Internet, ma, beh ... non so se il mio script è prezioso o è stata una perdita di tempo).

Ho programmato un semplice script shell Linux che funziona (fino ad ora) su CygWin e aiuta (spero) a ridurre il SUDO per l'intervallo di attacco temporale di CygWin. Il programma si chiama TOUACExt (acronimo di " TimeOut and UAC Extension ") e funge da wrapper per SUDO per CygWin (richiesto installato) ed è realmente composto da un set di quattro .shprogrammi.

Esempio di esecuzione TOUACExt

Caratteristiche :

  • Comodo utilizzo : simulando il sudo originale dal comportamento di Linux, il prompt della richiesta di conferma UAC appare solo una volta (più sudocomandi consecutivi genereranno una sola richiesta UAC). Finché sudoserver.py continua a funzionare (impostazione predefinita per 15 minuti), non ci saranno più richieste di controllo dell'account utente .
  • Gli utenti con privilegi (Admin) ricevono solo la richiesta di conferma UAC ( Sì / No ) sullo schermo.
  • Gli utenti non privilegiati (non amministratori) ottengono una schermata di immissione dell'account / password dell'amministratore .
  • sudoserver.py continua a funzionare, quindi si chiude automaticamente dopo un tempo predefinito (15 minuti) dall'ultima esecuzione del comando sudo.
  • sudoserver.py non si chiude (continua a funzionare e controllerà di nuovo in 5 minuti) in caso di qualsiasi istanza di sudo in esecuzione.
  • Funziona in remoto (testato tramite SSH):
    • Gli utenti non privilegiati non possono avviare sudoserver.py in remoto.
  • Crea un registro (ancora semplice e non molto leggibile) su /var/log/SUDOForCygWin/.

Requisiti (in CygWin):

  • SUDO per CygWin .
  • pgrep (al procpspacchetto).
  • gregge (al util-linuxpacchetto).
  • nohup (penso che sia installato di default su CygWin, ma non ne sono sicuro).

Supponendo : - I due programmi del progetto SUDO per CygWin sul percorso suggerito dall'autore:

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

TOUACExt è stato testato lavorando su Windows 7 SP1 e Windows XP SP3, ma non so se abbia senso usarlo su quest'ultimo.

Istruzioni di installazione :

  • Metti questo script (nome suggerito:) SUDOServer.cmde crea un collegamento (puoi personalizzare la sua icona se vuoi) con il nome SUDOServer.lnk(devi abilitare su questo collegamento Advanced Options --> Execute as Administrator) in qualsiasi punto del tuo percorso di Windows , quindi sudoserver.pypuò essere richiesto direttamente da Windows:

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

  • Inserisci i quattro script .sh di TOUACExt sul percorso, ad esempio:

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

  • Rinomina lo script Python originale da sudoa sudo.py:

    mv /usr/local/bin/sudo /usr/local/bin/sudo.py
    ATTENZIONE: lo script Python "sudo" originale non deve rimanere in alcun punto del percorso, altrimenti potrebbe essere eseguito.

  • Crea questo alias (ad esempio, manualmente o modificando il tuo ~/.bashrc):

    alias sudo='SUDO.sh'

Codice per 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.

Codice per 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). 

Codice per 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 

Codice per 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 

Testare il programma da una shell 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

NOTA 2: questi script sono in versione pre-beta , quindi sono ancora difettosi e il codice non è molto pulito. Ad ogni modo, nei miei test con tre diversi computer Windows 7 sembrano funzionare (principalmente) OK.

Breve spiegazione del programma:

  1. A causa dell'alias , quando si esegue un comando sudo viene invocato lo script SUDO.sh.
  2. SUDO.sh chiama SUDOServer.sh , aprendo (via SUDOServer.lnk) "sudoserver.py" se necessario.
  3. Il comando originale sudo richiamato dall'utente viene eseguita.
  4. Quindi SUDO.sh chiama SUDOServerWatchDogScheduler.sh , che pianifica SUDOServerWatchDog.sh per l'esecuzione dopo il tempo specificato (impostazione predefinita di 15 minuti) per la chiusura sudoserver.py.
  5. Dopo il tempo predefinito, SUDOServerWatchDog.sh chiude sudoserver.py . Se ci sono istanze di sudo in esecuzione , si programma per la nuova esecuzione dopo 5 minuti.

Da fare :

  • Installatore sé che crea tutte le .sh, .cmd e file .lnk automaticamente.
  • Stabilisci il file di blocco su un altro (è in $ TMP / lockfile.lck).
  • Aggiungi uno script di configurazione o un file .config (per impostazione predefinita in timeout, posizioni dei file ... ecc.).
  • Aggiungi comportamento dell'account di sistema (grazie, @ Wyatt8740).
  • ¿Cambiare "flock" (modalità SUDO con blocco interno) con "fuser" dove appropriato?
  • Suggerimenti accettati.

Bug segnalati :

  • La shell bash rimane aperta anche dopo l'input exitse sudoserver.pyè in esecuzione fino alla chiusura. Soluzioni alternative provvisorie sono benvenute.

Spero che qualcuno userà le lunghe ore di programmazione che ho dedicato a TOUACExt.
Miglioramenti e correzioni accettati.
Sono accettati anche suggerimenti su dove devo andare a pubblicare il codice per smettere di tormentare questo forum ;-).

Ci scusiamo per il lungo post. Non ho molto tempo libero e questo progetto stava per scomparire nel mio armadio (forse per anni, chi lo sa?).


2
Se vuoi feedback sul tuo codice, pubblicalo su codereview.stackexchange.com. (Le note e gli esempi di utilizzo sono utili qui)
Ben Voigt

Grazie, @BenVoigt, non lo sapevo. Per favore una domanda: se lo faccio, penso che la maggior parte del post dovrebbe essere un duplicato di questa risposta. Sarà considerato il cross-posting?
Sopalajo de Arrierez,

1
Assicurati di collegarli tra loro. Il danno nel crossposting è che le persone duplicano lo sforzo. Se sono collegati, non è un problema del genere
Ben Voigt

Questa è un'ottima soluzione. Se non richiedesse Python, lo userei. Ho un profondo disprezzo personale per il pitone. È un bel linguaggio, ma per motivi personali più che altro, non mi piace. Tuttavia, poiché quasi nessun altro odia il pitone e il mio odio è irrazionale, ho votato a favore della tua soluzione, poiché è più vicina alla cosa reale della mia.
Wyatt8740,

1
Grazie, @CharlesRobertoCanato. Forse potresti darmi i dettagli nella chat, al fine di risolverlo? Chat room "TOUACExt - SuDo per Windows": chat.stackexchange.com/rooms/56716/touacext-sudo-for-windows
Sopalajo de Arrierez

1

SEMPLICE sudo.bat (usa nircmd)

Nircmd può essere scaricato qui:
http://www.nirsoft.net/utils/nircmd.html

Ho scaricato nircmd e rinominato nircmdc.exein nircmd.exe, sostituendo l'originale nircmd.exe. L'ho quindi spostato in C:\windows\system32.

Ho anche creato il seguente file batch per consentire la trasmissione degli argomenti allo script.

Va detto che ho disabilitato UAC sul mio computer, quindi non ho più bisogno di questo script, ma funziona come da Windows 8. Funziona anche in Cygwin.

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

Una soluzione elegante. Breve e facile Ma perché mi manca in modo semplice sudo.bat dir? Un errore di Windows indica "Impossibile trovare il file denominato dir". Sembra funzionare sudo echo Hello, ma non c'è l'output della console.
Sopalajo de Arrierez,

Un piccolo inconveniente con questo metodo è la richiesta continua di prompt UAC in comandi consecutivi. TOUACExt risolve questo, proprio come nelle classiche esecuzioni sudo Linux. Ho modificato l'elenco delle funzionalità per mostrarlo.
Sopalajo de Arrierez,

dirnon funziona perché dirtecnicamente non è un programma, ma un comando DOS incorporato. mentre in linux, lsè un programma binario, in DOS / windows, dirè gestito dall'interprete stesso (es. COMMAND.COM o cmd.exe). Non esiste un dir.exeposto dove eseguire il mio programma. Ma per Cygwin, sudo lsdovrebbe essere sufficiente. Anche se non lo fai, fare sudo cmdo sudo bashqualsiasi altra cosa dovrebbe ricevere un prompt di livello 'Amministratore'. Anche "Amministratore" è sotto "SISTEMA", tuttavia - per "SISTEMA", utilizzare nircmd.exe elevatecmd runassystem <program.exe>. Inoltre, disabilito UAC sui miei
computer

Inoltre, non penso echosia un programma in Windows. Fa parte di COMMAND.COM/cmd.exe. Per me, però, un utente cygwin con ls.exee echo.exefunziona benissimo. E in realtà l'ho usato oggi per la prima volta in mesi per gestire i file sull'account di mio fratello senza accedere come lui (è riuscito a mettere ogni singolo programma sul suo computer nella directory "avvio" del suo menu di avvio: P). Appena entrato in un altro e usato sudo.bat cmdper ottenere un prompt a livello di amministratore che mi avrebbe permesso di gestire i file di altri utenti.
Wyatt8740,

La tua idea dell'account di sistema è buona. Lo aggiungerò a TOUCExt come opzione.
Sopalajo de Arrierez,

0

Non essendo soddisfatto della soluzione disponibile, ho adottato lo script di nu774 per aggiungere sicurezza e semplificare l'installazione e l'uso. Il progetto è disponibile su Github

Per usarlo, basta scaricarlo cygwin-sudo.pyed eseguirlo tramite python3 cygwin-sudo.py **yourcommand**.

Puoi impostare un alias per comodità:

alias sudo="python3 /path-to-cygwin-sudo/cygwin-sudo.py"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.