Manière pratique (plus proche de celle classique de Linux) d'utiliser (automatiser) SUDO pour CygWin

11

Pouvoir utiliser des sudocommandes dans CygWin est utile et plus rapide que d'ouvrir un shell élevé:

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.

Comme indiqué ci-dessus, vous pouvez également exécuter des commandes / scripts Windows, tout comme Linux. Pour moi, c'est bien; fonctionne sur des consoles distantes (SSH) et permet de combiner des commandes Windows / Linux . Il est donc presque indispensable de pouvoir exécuter des tâches administratives.

Mais le projet SUDO pour CygWin a un comportement qui pourrait être dangereux : il fonctionne comme une architecture serveur / client , en fait, un client (sudo) envoie des requêtes de commandes à un serveur (sudoserver.py) en interne (sans écouter en dehors du ordinateur local) port 7070TCP, sans vérification des utilisateurs ou des autorisations , de sorte que toute personne (même les utilisateurs non privilégiés) connecté à l'ordinateur puisse exécuter des commandes ou des scripts shell admins (CygWin ou Windows) (CygWin ou Windows, également).
Le problème s'aggrave si vous conservez la méthode suggérée par l'auteur: enregistrer "sudoserver.py" en tant que service, afin qu'il continue de fonctionner en permanence.

Donc, pour maintenir les choses un peu plus sécurisées (pas totalement), je fais:
1.- Exécutez "sudoserver.py" sur un shell administrateur.
2.- Exécutez mes commandes "sudo" sur un autre shell CygWin.
3.- Fermez (Ctrl + C) "sudoserver.py" et le shell d'administration.

Un peu ennuyeux . Je le contourne en utilisant un .cmdfichier avec un raccourci clavier assigné qui exécute "sudoserver.py", et je le ferme (manuellement) après mes travaux administratifs, mais toujours loin de l' utilisabilité "sudo" classique sur Linux.

La grande et pratique façon serait une méthode qui:

  1. ** Ouverture automatique de "sudoserver.py" demandant l'invite d'élévation UAC (ou utilisateur / mot de passe).
  2. Le ferme après un certain temps, donc la requête UAC ne continuera pas de déranger en cas de plusieurs sudocommandes exécutées séquentiellement.

Existe-t-il un moyen d' automatiser cela , au moins partiellement?

Sopalajo de Arrierez
la source

Réponses:

10

REMARQUE: Il s'agit principalement d'un programme (script shell) que j'ai créé, et je sais que ce forum est plus un site de questions-réponses qu'un programme d'introduction de programmes. Mais je n'ai pas de compte GitHub (ou similaire), et je n'ai pas eu le temps de rechercher la méthode de publication d'un programme Open Source dans la communauté. Donc, tant qu'il y a un risque qu'un programme fonctionnel et utile passe inaperçu (même pendant des mois) à ceux qui pourraient en profiter, et il serait triste de ne pas partager un programme déjà fait, je vais le publier ici pour maintenant. Aucun problème pour moi si les administrateurs décident de supprimer ce fil, je comprendrai. J'espère avoir formulé la question sous forme de questions-réponses suffisamment pour la rendre utile à ce forum. S'il y en a assezutilisateurs intéressés , je ferai de mon mieux pour consacrer un peu de temps à la poursuite du projet (après toutes mes recherches, je n'ai rien trouvé de plus proche de celui-ci sur Internet, mais bon ... je ne sais pas si mon script est valable ou cela a été une perte de temps).

J'ai programmé un script shell Linux simple qui fonctionne (jusqu'à présent) sur CygWin et aide (j'espère) à réduire l'intervalle de temps d'attaque SUDO pour CygWin. Le programme est nommé TOUACExt (acronyme de " TimeOut and UAC Extension ") et agit comme un wrapper pour SUDO pour CygWin (requis installé), et est vraiment composé d'un ensemble de quatre .shprogrammes.

Exemple d'exécution TOUACExt

Caractéristiques :

  • Utilisation confortable : en simulant le sudo d'origine à partir du comportement de Linux, l' invite de demande de confirmation UAC n'apparaît qu'une seule fois (plusieurs sudocommandes consécutives ne généreront qu'une seule demande UAC). Tant que sudoserver.py continue de fonctionner (15 minutes par défaut), il n'y aura plus de requêtes UAC .
  • Les utilisateurs privilégiés (Admin) reçoivent uniquement la demande de confirmation UAC ( Oui / Non ) à l'écran.
  • Les utilisateurs non privilégiés (non administrateurs) obtiennent un écran de saisie de compte / mot de passe administrateur .
  • sudoserver.py continue de fonctionner, puis se ferme automatiquement après un temps prédéfini (15 minutes) à partir de la dernière exécution de la commande sudo.
  • sudoserver.py ne se ferme pas (continue de fonctionner et vérifiera à nouveau dans 5 minutes) en cas de toute exécution de sudo .
  • Fonctionne à distance (testé via SSH):
    • Les utilisateurs non privilégiés ne peuvent pas démarrer sudoserver.py à distance.
  • Crée un journal (pourtant simple et peu lisible) sur /var/log/SUDOForCygWin/.

Exigences (dans CygWin):

  • SUDO pour CygWin .
  • pgrep (au procpspaquet).
  • troupeau (à l' util-linuxemballage).
  • nohup (je pense installé par défaut sur CygWin, mais pas sûr).

En supposant : - Les deux programmes du projet SUDO pour CygWin sur le chemin suggéré par l'auteur:

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

TOUACExt a été testé sur Windows 7 SP1 et Windows XP SP3, mais je ne sais pas s'il est logique de l'utiliser sur ce dernier.

Instructions d'installation :

  • Mettez ce script (nom suggéré:) SUDOServer.cmdet créez un raccourci (vous pouvez personnaliser son icône si vous le souhaitez) à lui nommé SUDOServer.lnk(vous devez activer sur ce raccourci Advanced Options --> Execute as Administrator) n'importe où sur votre chemin Windows , donc sudoserver.pypeut être directement demandé à Windows:

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

  • Mettez les quatre scripts .sh de TOUACExt sur le chemin, par exemple:

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

  • Renommer l'original script Python à partir sudode sudo.py:

    mv /usr/local/bin/sudo /usr/local/bin/sudo.py
    AVERTISSEMENT: le script Python "sudo" d'origine ne doit pas rester n'importe où dans votre chemin, sinon il pourrait être exécuté à la place.

  • Créez cet alias (par exemple, manuellement ou en modifiant votre ~/.bashrc):

    alias sudo='SUDO.sh'

Code pour 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.

Code pour 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). 

Code pour 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 

Code pour 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 

Testez le programme à partir d'un 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

REMARQUE 2: Ces scripts sont en version pré-bêta , ils sont donc toujours bogués et le code n'est pas très propre. Quoi qu'il en soit, dans mes tests avec trois ordinateurs Windows 7 différents, ils semblent fonctionner (principalement) OK.

Brève explication du programme:

  1. En raison de l'alias, lors de l'exécution d'une commande sudo, le script SUDO.sh est appelé .
  2. SUDO.sh appelle SUDOServer.sh , ouvrant (via SUDOServer.lnk) "sudoserver.py" si nécessaire.
  3. La commande sudo d'origine invoquée par l'utilisateur est exécutée.
  4. SUDO.sh appelle ensuite SUDOServerWatchDogScheduler.sh , qui planifie SUDOServerWatchDog.sh pour une exécution après l'heure donnée (15 minutes par défaut) pour la fermeture sudoserver.py.
  5. Après l'heure prédéfinie, SUDOServerWatchDog.sh ferme sudoserver.py . S'il y a une instance de sudo en cours d'exécution , il se programme pour une nouvelle exécution après 5 minutes.

À faire :

  • Auto-installateur qui crée automatiquement tous les fichiers .sh, .cmd et .lnk.
  • Établissez le fichier de verrouillage sur un autre (il s'agit de $ TMP / lockfile.lck).
  • Ajoutez un script de configuration ou un fichier .config (pour les valeurs par défaut dans les délais d'expiration, les emplacements des fichiers, etc.).
  • Ajouter le comportement du compte système (merci, @ Wyatt8740).
  • ¿Changer "flock" (mode SUDO à verrouillage interne) avec "fuser" le cas échéant?
  • Suggestions acceptées.

Bogues signalés :

  • Le shell bash reste ouvert même après avoir entré exitif sudoserver.pyest en cours d'exécution jusqu'à sa fermeture. Les solutions provisoires sont les bienvenues.

J'espère que quelqu'un utilisera la programmation de longues heures que j'ai dédiée à TOUACExt.
Améliorations et corrections acceptées.
Des suggestions sur où devrais-je aller publier le code pour arrêter de harceler ce forum sont également acceptées ;-).

Désolé pour le long post. Je n'ai pas beaucoup de temps libre, et ce projet était sur le point de disparaître dans mon placard (peut-être pendant des années, qui sait?).

Sopalajo de Arrierez
la source
2
Si vous souhaitez des commentaires sur votre code, postez-le sur codereview.stackexchange.com. (Les notes d'utilisation et les exemples sont bons à avoir ici)
Ben Voigt
Merci, @BenVoigt, je ne savais pas. S'il vous plaît une question: si je le fais, je pense que la plupart des messages devraient être un double de cette réponse. Cela sera-t-il considéré comme un affichage croisé?
Sopalajo de Arrierez
1
Assurez-vous de les lier les uns aux autres. Le mal du crossposting est que les gens redoublent d'efforts. S'ils sont liés, ce n'est pas un problème
Ben Voigt
C'est une très bonne solution. S'il ne nécessitait pas de python, je l'utiliserais. J'ai une haine profonde et personnelle du python. C'est une belle langue, mais pour des raisons personnelles plus que tout, je ne l'aime pas. Pourtant, comme presque personne d'autre ne déteste le python et que ma haine est irrationnelle, j'ai voté pour votre solution, car elle est plus proche de la réalité que la mienne.
Wyatt8740
1
Merci, @CharlesRobertoCanato. Peut-être pourriez-vous me donner les détails lors du chat, afin de le résoudre? Salon de discussion "TOUACExt - SuDo pour Windows": chat.stackexchange.com/rooms/56716/touacext-sudo-for-windows
Sopalajo de Arrierez
1

SIMPLE sudo.bat (utilise nircmd)

Nircmd peut être téléchargé ici:
http://www.nirsoft.net/utils/nircmd.html

J'ai téléchargé nircmd et renommé nircmdc.exeen nircmd.exeremplaçant l'original nircmd.exe. Je l'ai ensuite déplacé vers C:\windows\system32.

J'ai également créé le fichier de commandes suivant pour permettre aux arguments d'être transmis au script.

Il faut dire que j'ai désactivé l'UAC sur ma machine, donc je n'ai plus besoin de ce script, mais il FONCTIONNE à partir de Windows 8. Il fonctionne tout aussi bien dans cygwin.

@echo off
if "%*" == "" goto error
nircmd elevate %*
goto thisiseof
:error
echo No arguments were given. Exiting.
:thisiseof
Wyatt8740
la source
Une solution sophistiquée. Court et facile. Mais pourquoi me manque-t-il d'une manière simple sudo.bat dir? Une fenêtre d'erreur indique "Windows ne peut pas trouver le fichier nommé dir". Il semble fonctionner avec sudo echo Hello, mais il n'y a pas de sortie console.
Sopalajo de Arrierez
Un petit inconvénient de cette méthode est la demande continue d'invite UAC dans les commandes consécutives. TOUACExt résout ce problème , un peu comme dans les exécutions classiques de sudo Linux. J'ai modifié la liste des fonctionnalités pour l'afficher.
Sopalajo de Arrierez
dirne fonctionne pas car dirn'est pas techniquement un programme, mais une commande DOS intégrée. tandis que sous Linux, lsest un programme binaire, sous DOS / windows, direst géré par l'interpréteur lui-même (c'est-à-dire COMMAND.COM ou cmd.exe). Il n'y a aucun dir.exeendroit où exécuter mon programme. Mais pour cygwin, cela sudo lsdevrait suffire. Même si vous ne le faites pas, faire sudo cmdou sudo bashquoi que ce soit devrait vous obtenir une invite de niveau «Administrateur». Même «Administrateur» est en dessous de «SYSTÈME», cependant - pour «SYSTÈME», utilisez nircmd.exe elevatecmd runassystem <program.exe>. De plus, je désactive l'UAC sur mes machines :)
Wyatt8740
De plus, je ne pense pas que ce echosoit un programme sous Windows. Cela fait partie de COMMAND.COM/cmd.exe. Pour moi cependant, un utilisateur de cygwin avec ls.exeet echo.execela fonctionne très bien. Et je l'ai utilisé aujourd'hui pour la première fois depuis des mois pour gérer les fichiers sur le compte de mon frère sans me connecter en tant que lui (il a réussi à mettre chaque programme sur son ordinateur dans le répertoire "démarrage" de son menu Démarrer: P). Juste connecté à un autre et utilisé sudo.bat cmdpour obtenir une invite de niveau administrateur qui me permettrait de gérer les fichiers des autres utilisateurs.
Wyatt8740
Votre idée du compte système est bonne. Je vais l'ajouter à TOUCExt en option.
Sopalajo de Arrierez
0

N'étant pas satisfait de la solution disponible, j'ai adopté le script de nu774 pour ajouter de la sécurité et faciliter sa configuration et son utilisation. Le projet est disponible sur Github

Pour l'utiliser, il suffit de le télécharger cygwin-sudo.pyet de l'exécuter via python3 cygwin-sudo.py **yourcommand**.

Vous pouvez configurer un alias pour plus de commodité:

alias sudo="python3 /path-to-cygwin-sudo/cygwin-sudo.py"
Chronial
la source