Manera práctica (más cercana a la clásica de Linux) de usar (automatizar) SUDO para CygWin

11

Poder utilizar sudocomandos en CygWin es útil y más rápido que abrir un shell elevado:

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.

Como se muestra arriba, también puede ejecutar comandos / scripts de Windows, al igual que Linux. Para mí está ordenado; funciona en consolas remotas (SSH) y permite combinar comandos de Windows / Linux . Por lo tanto, poder ejecutar tareas administrativas es casi imprescindible.

Pero el proyecto SUDO for CygWin tiene un comportamiento que podría ser peligroso : funciona como una arquitectura de servidor / cliente , de hecho, un cliente (sudo) envía solicitudes de comandos a un servidor (sudoserver.py) a nivel interno (no escucha fuera del computadora local) puerto 7070TCP, sin verificación de usuarios o permisos , por lo que cualquier persona (incluso usuarios no privilegiados) que inicie sesión en la computadora podría ejecutar comandos o scripts de administrador (CygWin o Windows) (CygWin o Windows también).
El problema empeora si mantiene el método sugerido del autor: registrar "sudoserver.py" como un servicio, por lo que seguirá ejecutándose permanentemente.

Entonces, para mantener las cosas un poco más seguras (no totalmente), hago:
1.- Ejecuto "sudoserver.py" en un shell de administración.
2.- Ejecute mis comandos "sudo" en otro shell CygWin.
3.- Cierre (Ctrl + C) "sudoserver.py" y el shell del administrador.

Un poco molesto . Lo estoy solucionando usando un .cmdarchivo con tecla de acceso rápido asignada que ejecuta "sudoserver.py", y lo estoy cerrando (manualmente) después de mis trabajos administrativos, pero aún lejos de la usabilidad clásica de "sudo" en Linux.

La mejor y práctica forma sería algún método que:

  1. ** Abre automáticamente "sudoserver.py" solicitando un aviso de elevación de UAC (o usuario / contraseña).
  2. Cierra después de un tiempo, por lo que la solicitud de UAC no seguirá siendo molesta en caso de que varios sudocomandos se ejecuten secuencialmente.

¿Hay alguna forma de automatizar esto , al menos parcialmente?

Sopalajo de Arrierez
fuente

Respuestas:

10

NOTA: Este es principalmente un programa (script de shell) que hice, y sé que este foro es más un sitio de preguntas y respuestas que uno de introducción de programas. Pero no tengo ninguna cuenta de GitHub (o similar), ni he tenido tiempo para investigar sobre el método de publicación de un programa Open Source en la comunidad. Por lo tanto, mientras exista el riesgo de que un programa funcional y útil pase desapercibido (incluso durante meses) para aquellos que puedan disfrutarlo, y sería triste no compartir un programa ya realizado, lo publicaré aquí para ahora. No hay problemas para mí si los administradores deciden eliminar este hilo, lo entenderé. Espero haber redactado el asunto lo suficiente como para responder preguntas lo suficiente como para que sea útil para este foro. Si hay suficientesusuarios interesados , haré todo lo posible para dedicar algo de tiempo a continuar el proyecto (después de todas mis investigaciones, no he encontrado nada más cercano a esto en Internet, pero, bueno ... no sé si mi script es valioso o no ha sido una pérdida de tiempo).

He programado un simple script de shell de Linux que funciona (hasta ahora) en CygWin y ayuda (espero) a reducir el SUDO para el intervalo de tiempo de ataque de CygWin. El programa se llama TOUACExt (acrónimo de " TimeOut and UAC Extension ") y actúa como un contenedor para SUDO para CygWin (requerido instalado), y está realmente compuesto por un conjunto de cuatro .shprogramas.

Ejemplo de ejecución de TOUACExt

Caracteristicas :

  • Uso cómodo : al simular el sudo original del comportamiento de Linux, el mensaje de solicitud de confirmación de UAC solo aparece una vez (varios sudocomandos consecutivos solo generarán una solicitud de UAC). Mientras sudoserver.py siga ejecutándose (15 minutos por defecto), no habrá más solicitudes de UAC .
  • Los usuarios privilegiados (administradores) solo reciben la solicitud de confirmación de UAC ( Sí / No ) en la pantalla.
  • Los usuarios no privilegiados (no administradores) obtienen una pantalla de ingreso de cuenta / contraseña de administrador .
  • sudoserver.py sigue ejecutándose, luego se cierra automáticamente después de un tiempo predefinido (15 minutos) desde la última ejecución del comando sudo.
  • sudoserver.py no se cierra (sigue ejecutándose y volverá a comprobarlo en 5 minutos) en caso de que se ejecute sudo .
  • Funciona de forma remota (probado a través de SSH):
    • Los usuarios sin privilegios no pueden iniciar sudoserver.py de forma remota.
  • Crea un registro (aunque simple y no muy legible) en /var/log/SUDOForCygWin/.

Requisitos (en CygWin):

  • SUDO para CygWin .
  • pgrep (en el procpspaquete).
  • flock (en util-linuxpaquete).
  • nohup (creo que está instalado por defecto en CygWin, pero no estoy seguro).

Suponiendo : - Los dos programas del proyecto SUDO para CygWin en el camino sugerido por el autor:

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

TOUACExt ha sido probado trabajando en Windows 7 SP1 y Windows XP SP3, pero no sé si tiene sentido usarlo en este último.

Instrucciones de instalación :

  • Ponga este script (nombre sugerido:) SUDOServer.cmdy cree un acceso directo (puede personalizar su icono si lo desea) con el nombre SUDOServer.lnk(debe habilitarlo en este acceso directo Advanced Options --> Execute as Administrator) en cualquier lugar de su ruta de Windows , por lo que sudoserver.pypuede solicitarlo directamente desde Windows:

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

  • Coloque los cuatro scripts .sh de TOUACExt en la ruta, por ejemplo:

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

  • Cambie el nombre del script de Python original de sudoa sudo.py:

    mv /usr/local/bin/sudo /usr/local/bin/sudo.py
    ADVERTENCIA: El script Python original "sudo" no debe permanecer en ninguna parte de su ruta, o podría ejecutarse en su lugar.

  • Cree este alias (por ejemplo, manualmente o editando su ~/.bashrc):

    alias sudo='SUDO.sh'

Código para 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.

Código para 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). 

Código para 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 

Código para 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 

Pruebe el programa desde 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

NOTA2: estos scripts están en versión pre-beta , por lo que todavía tienen errores y el código no está muy limpio. De todos modos, en mis pruebas con tres computadoras con Windows 7 diferentes, parecen estar funcionando (en su mayoría) bien.

Breve explicación del programa:

  1. Debido al alias, al ejecutar un comando sudo se invoca el script SUDO.sh.
  2. SUDO.sh llama a SUDOServer.sh , abriendo (mediante SUDOServer.lnk) "sudoserver.py" si es necesario.
  3. Se ejecuta el comando sudo original invocado por el usuario.
  4. Luego, SUDO.sh llama a SUDOServerWatchDogScheduler.sh , que programa SUDOServerWatchDog.sh para que se ejecute después del tiempo dado (15 minutos predeterminado) para cerrar sudoserver.py.
  5. Después del tiempo predefinido, SUDOServerWatchDog.sh cierra sudoserver.py . Si hay alguna instancia de sudo en ejecución , se programa para una nueva ejecución después de 5 minutos.

Para hacer :

  • Auto instalador que crea todos los archivos .sh, .cmd y .lnk automáticamente.
  • Establezca el archivo de bloqueo a otro (está en $ TMP / lockfile.lck).
  • Agregue una secuencia de comandos de configuración o un archivo .config (para valores predeterminados en tiempos de espera, ubicaciones de archivos ... etc.).
  • Agregar el comportamiento de la cuenta del sistema (gracias, @ Wyatt8740).
  • ¿Cambiar "flock" (modo SUDO de bloqueo interno) con "fusor" cuando corresponda?
  • Sugerencias aceptadas.

Reportadas Errores :

  • El shell bash se mantiene abierto incluso después de ingresar exitsi se sudoserver.pyestá ejecutando hasta que se cierra. Las soluciones provisionales son bienvenidas.

Espero que alguien use las largas horas de programación que he dedicado a TOUACExt.
Mejoras y correcciones aceptadas. También se aceptaron
sugerencias sobre dónde debo publicar el código para dejar de molestar a este foro ;-).

Perdón por la larga publicación. No tengo mucho tiempo libre, y este proyecto estuvo a punto de desaparecer en mi armario (tal vez durante años, ¿quién sabe?).

Sopalajo de Arrierez
fuente
2
Si desea comentarios sobre su código, publíquelo en codereview.stackexchange.com. (Las notas de uso y ejemplos son buenos para tener aquí)
Ben Voigt
Gracias, @BenVoigt, no lo sabía. Por favor una pregunta: si lo hago, creo que la mayor parte de la publicación debería ser un duplicado de esta respuesta. ¿Eso se considerará publicación cruzada?
Sopalajo de Arrierez
1
Asegúrese de vincularlos entre sí. El daño en la publicación cruzada es que las personas duplican el esfuerzo. Si están vinculados, eso no es un problema
Ben Voigt
Esta es una muy buena solución. Si no requiriera python, lo usaría. Tengo un odio personal y profundo por Python. Es un lenguaje agradable, pero por razones personales más que nada, no me gusta. Aún así, como casi nadie más odia a Python, y mi odio es irracional, voté por su solución, ya que está más cerca de la realidad que la mía.
Wyatt8740
1
Gracias, @CharlesRobertoCanato. ¿Tal vez podrías darme los detalles en el chat para resolverlo? Sala de chat "TOUACExt - SuDo para Windows": chat.stackexchange.com/rooms/56716/touacext-sudo-for-windows
Sopalajo de Arrierez
1

SIMPLE sudo.bat (usa nircmd)

Nircmd se puede descargar aquí:
http://www.nirsoft.net/utils/nircmd.html

Descargué nircmd y cambié el nombre nircmdc.exea nircmd.exe, reemplazando el original nircmd.exe. Luego lo mudé a C:\windows\system32.

También hice el siguiente archivo por lotes para permitir que los argumentos se pasen al script.

Debe decirse que he desactivado UAC en mi máquina, por lo que ya no necesito este script, pero sí funciona a partir de Windows 8. También funciona en Cygwin.

@echo off
if "%*" == "" goto error
nircmd elevate %*
goto thisiseof
:error
echo No arguments were given. Exiting.
:thisiseof
Wyatt8740
fuente
Una solución elegante. Corto y fácil. Pero, ¿por qué me está fallando de una manera simple sudo.bat dir? Un error de Windows dice "Windows no puede encontrar el archivo llamado dir". Parece funcionar sudo echo Hello, pero no hay salida de consola.
Sopalajo de Arrierez
Un pequeño inconveniente con este método es la solicitud continua de solicitud de UAC en comandos consecutivos. TOUACExt resuelve esto, al igual que en las ejecuciones de sudo de Linux clásico. He editado la lista de características para mostrarla.
Sopalajo de Arrierez
dirno funciona porque dirtécnicamente no es un programa, sino un comando DOS incorporado. mientras que en linux, lses un programa binario, en DOS / windows, dires manejado por el propio intérprete (es decir, COMMAND.COM o cmd.exe). No hay un dir.exelugar para que mi programa se ejecute. Pero para Cygwin, sudo lsdebería ser suficiente. Incluso si no lo hace, hacer sudo cmdo sudo bashlo que sea debería obtener un mensaje de nivel de 'Administrador'. Incluso 'Administrador' está debajo de 'SISTEMA', sin embargo, para 'SISTEMA', use nircmd.exe elevatecmd runassystem <program.exe>. Además, desactivo UAC en mis máquinas :)
Wyatt8740
Además, tampoco creo que echosea ​​un programa en Windows. Es parte de COMMAND.COM/cmd.exe. Sin embargo, para mí, un usuario de cygwin ls.exey echo.exefunciona bien. Y en realidad lo usé hoy por primera vez en meses para administrar archivos en la cuenta de mi hermano sin iniciar sesión como él (logró poner todos los programas en su computadora en el directorio de "inicio" de su menú de inicio: P). Acabo sudo.bat cmdde iniciar sesión en otro y solía obtener un mensaje de nivel de administrador que me permitiría administrar los archivos de otros usuarios.
Wyatt8740
Su idea de la cuenta del sistema es buena. Lo agregaré a TOUCExt como una opción.
Sopalajo de Arrierez
0

Al no estar contento con la solución disponible, adopté el script de nu774 para agregar seguridad y facilitar la configuración y el uso. El proyecto está disponible en Github

Para usarlo, simplemente descárguelo cygwin-sudo.pyy ejecútelo a través de python3 cygwin-sudo.py **yourcommand**.

Puede configurar un alias por conveniencia:

alias sudo="python3 /path-to-cygwin-sudo/cygwin-sudo.py"
Crónica
fuente