Maneira prática (mais próxima da clássica do Linux) de usar (automatizar) o SUDO para CygWin

11

Ser capaz de usar sudocomandos no CygWin é útil e mais rápido do que abrir um 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 mostrado acima, você também pode executar comandos / scripts do Windows, assim como o Linux. Para mim é legal; funciona em consoles remotos (SSH) e permite combinar comandos do Windows / Linux . Portanto, ser capaz de executar tarefas administrativas é quase uma obrigação.

Mas o projeto SUDO for CygWin tem um comportamento que pode ser perigoso : ele funciona como uma arquitetura servidor / cliente ; de fato, um cliente (sudo) envia solicitações de comandos para um servidor (sudoserver.py) no ambiente interno (não escuta fora do porta local 7070TCP, sem verificação de usuário ou permissão , para que qualquer pessoa (mesmo usuários sem privilégios) conectado ao computador possa executar comandos ou scripts de shell de administrador (CygWin ou Windows) (também CygWin ou Windows).
O problema piora se você mantiver o método sugerido pelo autor: registrando "sudoserver.py" como um serviço, para que ele continue sendo executado permanentemente.

Portanto, para manter as coisas um pouco mais seguras (não totalmente), eu faço:
1.- Execute "sudoserver.py" em um shell de administrador.
2.- Execute meus comandos "sudo" em outro shell CygWin.
3.- Feche (Ctrl + C) "sudoserver.py" e o shell do administrador.

Um pouco chato . Estou contornando-o usando um .cmdarquivo com a tecla de atalho atribuída que executa "sudoserver.py" e estou fechando (manualmente) após meus trabalhos administrativos, mas ainda longe da usabilidade clássica de "sudo" no Linux.

A maneira ótima e prática seria algum método que:

  1. ** Abre automaticamente "sudoserver.py" solicitando o prompt de elevação do UAC (ou usuário / senha).
  2. Fecha-o após um tempo, para que a solicitação do UAC não seja perturbadora no caso de vários sudocomandos executados sequencialmente.

Existe alguma maneira de automatizar isso , pelo menos parcialmente?

Sopalajo de Arrierez
fonte

Respostas:

10

NOTA: Este é principalmente um programa (shell script) que eu criei e sei que este fórum é mais um site de perguntas e respostas do que um site de introdução de programas. Mas eu não tenho nenhuma conta no GitHub (ou similar), nem tive tempo para pesquisar sobre o método de publicação de um programa de código aberto para a comunidade. Portanto, desde que exista o risco de um programa útil e útil passar despercebido (mesmo por meses) para aqueles que possam apreciá-lo, e seria triste não compartilhar um programa já criado, vou publicá-lo aqui para agora. Sem problemas para mim, se os administradores decidirem remover este tópico, eu entenderei. Espero ter redigido o assunto de uma maneira que responda perguntas e respostas, a fim de torná-lo útil para este fórum. Se houver o suficienteusuários interessados , farei o possível para dedicar algum tempo para continuar o projeto (depois de todas as minhas pesquisas, não encontrei nada mais próximo disso na Internet, mas, bem ... não sei se meu script é valioso ou foi uma perda de tempo).

Programei um script de shell simples do Linux que funciona (até agora) no CygWin e ajuda (espero) a reduzir o SUDO para o intervalo de ataque de tempo do CygWin. O programa é nomeado TOUACExt (acrônimo de " TimeOut e extensão UAC ") e atua como um wrapper para SUDO para CygWin (necessário instalado) e é realmente composto por um conjunto de quatro .shprogramas.

Exemplo de execução do TOUACExt

Características :

  • Uso confortável : simulando o sudo original do comportamento do Linux, o prompt de solicitação de confirmação do UAC é exibido apenas uma vez (vários sudocomandos consecutivos geram apenas uma solicitação do UAC). Enquanto o sudoserver.py continuar em execução (padrão de 15 minutos), não haverá mais solicitações de UAC .
  • Usuários privilegiados (Admin) recebem apenas uma solicitação de confirmação do UAC ( Sim / Não ) na tela.
  • Usuários não privilegiados (não administradores) recebem uma tela de entrada de conta / senha de administrador .
  • O sudoserver.py continua em execução e fecha automaticamente após um tempo predefinido (15 minutos) a partir da última execução do comando sudo.
  • O sudoserver.py não fecha (continua em execução e verifica novamente em 5 minutos) no caso de qualquer instância de sudo em execução.
  • Funciona remotamente (testado via SSH):
    • Usuários não privilegiados não podem iniciar o sudoserver.py remotamente.
  • Cria um log (ainda que simples e pouco legível) em /var/log/SUDOForCygWin/.

Requisitos (no CygWin):

  • SUDO para CygWin .
  • pgrep (no procpspacote).
  • rebanho (na util-linuxembalagem).
  • nohup (acho que instalado por padrão no CygWin, mas não tenho certeza).

Assumindo : - Os dois programas do projeto SUDO for CygWin no caminho sugerido pelo autor:

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

O TOUACExt foi testado em Windows 7 SP1 e Windows XP SP3, mas não sei se faz sentido usá-lo neste último.

Instruções de instalação :

  • Coloque esse script (nome sugerido:) SUDOServer.cmde crie um atalho (você pode personalizar seu ícone, se desejar) com o nome SUDOServer.lnk(você deve ativar esse atalho Advanced Options --> Execute as Administrator) em qualquer lugar do caminho do Windows , para que sudoserver.pypossa ser solicitado diretamente no Windows:

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

  • Coloque os quatro scripts .sh do TOUACExt no caminho, por exemplo:

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

  • Renomeie o script Python original de sudopara sudo.py:

    mv /usr/local/bin/sudo /usr/local/bin/sudo.py
    AVISO: O script Python "sudo" original não deve permanecer em nenhum lugar do caminho ou pode ser executado.

  • Crie este alias (por exemplo, manualmente ou editando o seu ~/.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 

Teste o programa a partir de um 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: Esses scripts estão na versão pré-beta , portanto ainda estão com erros e o código não está muito limpo. Enfim, nos meus testes com três computadores com Windows 7 diferentes, eles parecem estar funcionando (principalmente) OK.

Breve explicação do programa:

  1. Devido ao alias, ao executar um comando sudo, o script SUDO.sh é chamado.
  2. SUDO.sh chama SUDOServer.sh , abrindo (via SUDOServer.lnk) "sudoserver.py" se necessário.
  3. O comando sudo original invocado pelo usuário é executado.
  4. Em seguida, SUDO.sh chama SUDOServerWatchDogScheduler.sh , que agenda SUDOServerWatchDog.sh para execução após o tempo determinado (padrão de 15 minutos) para fechar sudoserver.py.
  5. Após o tempo predefinido, SUDOServerWatchDog.sh fecha o sudoserver.py . Se houver alguma instância do sudo em execução , ele se programa para nova execução após 5 minutos.

Para fazer :

  • Auto-instalador que cria todos os arquivos .sh, .cmd e .lnk automaticamente.
  • Estabeleça um arquivo de bloqueio para outro (está em $ TMP / lockfile.lck).
  • Adicione um script de configuração ou arquivo .config (para padrões em tempos limite, localizações de arquivos ... etc).
  • Adicionar comportamento da conta do sistema (obrigado, @ Wyatt8740).
  • ¿Troque "rebanho" (modo SUDO de travamento interno) por "fusor", onde apropriado?
  • Sugestões aceitas.

Erros relatados :

  • O shell bash permanece aberto mesmo após a entrada, exitse sudoserver.pyestiver em execução até fechar. Soluções provisórias são bem-vindas.

Espero que alguém use as longas horas de programação que dediquei ao TOUACExt.
Aprimoramentos e correções aceitos. Também são aceitas
sugestões sobre onde devo publicar o código para deixar de incomodar este fórum ;-).

Desculpe pelo longo post. Não tenho muito tempo livre, e esse projeto estava prestes a desaparecer no meu armário (talvez por anos, quem sabe?).

Sopalajo de Arrierez
fonte
2
Se você deseja feedback sobre o seu código, publique-o em codereview.stackexchange.com. (As notas de uso e exemplos são bons de ter aqui)
Ben Voigt
Obrigado, @BenVoigt, eu não sabia. Por favor, faça uma pergunta: se eu fizer, acho que a maior parte do post deve ser uma duplicata desta resposta. Isso será considerado postagem cruzada?
Sopalajo de Arrierez
1
Certifique-se de vinculá-los um ao outro. O dano no cruzamento é que as pessoas duplicam o esforço. Se eles estão ligados, isso não é problema tão grande um
Ben Voigt
Esta é uma solução muito boa. Se não exigisse python, eu o usaria. Eu tenho um ódio pessoal e profundo por python. É uma linguagem agradável, mas por razões pessoais, mais do que tudo, eu não gosto. Ainda assim, como quase ninguém mais odeia python, e meu ódio é irracional, votei na sua solução, pois ela é mais próxima da realidade do que a minha.
precisa saber é o seguinte
1
Obrigado, @CharlesRobertoCanato. Talvez você possa me dar os detalhes no chat, a fim de resolvê-lo? Chat Room "TOUACExt - Sudo for Windows": chat.stackexchange.com/rooms/56716/touacext-sudo-for-windows
Sopalajo de Arrierez
1

SIMPLE sudo.bat (usa nircmd)

O Nircmd pode ser baixado aqui:
http://www.nirsoft.net/utils/nircmd.html

Eu baixei o nircmd e renomei nircmdc.exepara nircmd.exe, substituindo o original nircmd.exe. Eu então mudei para C:\windows\system32.

Também criei o seguinte arquivo em lotes para permitir que argumentos sejam passados ​​para o script.

Deve-se dizer que desativei o UAC na minha máquina, por isso não preciso mais desse script, mas funciona a partir do Windows 8. Ele também funciona no cygwin.

@echo off
if "%*" == "" goto error
nircmd elevate %*
goto thisiseof
:error
echo No arguments were given. Exiting.
:thisiseof
Wyatt8740
fonte
Uma solução sofisticada. Curto e fácil. Mas por que está me falhando de uma maneira simples sudo.bat dir? Uma janela de erro informa "O Windows não consegue encontrar o arquivo chamado dir". Parece funcionar sudo echo Hello, mas não há saída do console.
Sopalajo de Arrierez
Um pequeno inconveniente com esse método é a solicitação contínua de prompt do UAC em comandos consecutivos. O TOUACExt resolve isso, assim como nas execuções clássicas de sudo do Linux. Eu editei a lista de recursos para mostrá-lo.
Sopalajo de Arrierez
dirnão funciona porque dirtecnicamente não é um programa, mas um comando interno do DOS. enquanto no linux, lsé um programa binário, no DOS / windows, diré tratado pelo próprio interpretador (por exemplo, COMMAND.COM ou cmd.exe). Não há nenhum dir.exelugar para o meu programa ser executado. Mas para cygwin, sudo lsdeve ser suficiente. Mesmo que você não faça isso, faça sudo cmdou sudo basho que for necessário para obter um prompt de nível de 'Administrador'. Mesmo 'Administrador' está abaixo de 'SISTEMA', no entanto - para 'SISTEMA', use nircmd.exe elevatecmd runassystem <program.exe>. Além disso, eu desabilitar o UAC em minhas máquinas :)
Wyatt8740
Além disso, eu não acho que echoseja um programa no Windows. Faz parte do COMMAND.COM/cmd.exe. Para mim, porém, um usuário cygwin ls.exee echo.exefunciona bem. Na verdade, eu o usei hoje pela primeira vez em meses para gerenciar arquivos na conta do meu irmão sem fazer login como ele (ele conseguiu colocar todos os programas em seu computador no diretório "startup" do menu Iniciar: P). Apenas entrei em outro e usei sudo.bat cmdum prompt de administrador que me permitia gerenciar os arquivos de outros usuários.
precisa saber é o seguinte
Sua ideia da conta do sistema é boa. Vou adicioná-lo ao TOUCExt como uma opção.
Sopalajo de Arrierez
0

Insatisfeito com a solução disponível, adotei o script do nu774 para adicionar segurança e facilitar a configuração e o uso. O projeto está disponível no Github

Para usá-lo, basta fazer o download cygwin-sudo.pye executá-lo via python3 cygwin-sudo.py **yourcommand**.

Você pode configurar um alias por conveniência:

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