É possível que um administrador de sistema espione os terminais de seus usuários?

17

Quando conectado a uma máquina, posso descobrir o (s) dispositivo (s) de pseudo-terminais de cada usuário na saída de w . Sendo um administrador de sistema, é possível para eu espionar este terminal sem que o usuário esteja ciente? Em outras palavras, gostaria de ver tudo sendo feito neste terminal como saída em meu próprio terminal.

Por favor, observe o seguinte:

  • Não se trata de um caso de uso prático de monitoramento das atividades do usuário: tenho conhecimento de que existem ferramentas de auditoria do sistema para isso. Eu só estou curioso para saber se isso pode ser feito.
  • Estou ciente de esta questão e não parece para cobrir o que estou perguntando, já que todas as soluções sugeridas são invasivas (o usuário estaria ciente do que estou fazendo) ou produziria muito ruído (a solução strace ). A única solução que chega perto é a que sugere usar gdb . Mas isso só me permite ver o stdout do outro terminal.

O que tentei

Eu tentei isso no meu terminal:

tee /dev/pts/user_pts </dev/pts/user_pts

Isso permite que eu veja cada caractere que o usuário digita no outro pseudo-terminal à medida que o digita. O problema é que, a cada poucos caracteres, seria "pulado": ele mostraria um caractere trapaceiro em um dispositivo terminal, mas não no outro. Também impede a execução de qualquer comando do dispositivo pseudo-terminal do usuário. Eu não tenho certeza porque isso está acontecendo e se há uma maneira de melhorar isso.

O que eu gostaria de ver

USER TERMINAL        |    MY TERMINAL
$ echo "Test"        |    # slick_command_here
Test                 |    echo "Test"
$                    |    Test
    
por Joseph R. 03.08.2013 / 21:39

4 respostas

11

É o fd para o lado mestre do pseudo-terminal no emulador de terminal que você deseja monitorar se quiser ver o que é exibido nele. Aquele mestre fd é o que simula o fio que vai para um terminal real. O que xterm escreve nele são os caracteres gerados a partir da tecla que você pressiona. O que ele lê é o que é exibido.

Por exemplo, no Linux:

$ lsof -ac xterm /dev/ptmx
COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
xterm   15173 chazelas    4u   CHR    5,2      0t0 2131 /dev/ptmx

E, em seguida, execute por exemplo:

stty -echo -opost
strace -e read -e read=4 -p15173 2>&1 | stdbuf -o0 sh -c '
  grep "^ |" | cut -b11-60 | tr -d " " | xxd -r -p'

Claro, funciona melhor se você executar isso em um terminal do mesmo tipo e tamanho que você está tentando monitorar. Você pode obter o tamanho com:

stty size < /dev/pts/that-terminal

Isso despeja o que é lido por xterm do lado mestre do terminal, então o que é exibido lá, incluindo o local echo do que está sendo digitado.

O -e read=4 acima é para strace para gerar um hexdump do que xterm lê em seu fd 4. O restante do comando é convertê-lo nos caracteres reais. Eu tentei peekfd -n -8 15173 4 , mas por algum motivo que apenas deu o que estava sendo escrito.

Estamos usando -opost para desabilitar qualquer pós-processamento em nosso terminal de monitoramento, para que tudo que xxd grava no lado escravo torne-o inalterado para o nosso mestre, para que nosso monitoramento xterm obtenha o mesmo coisa como o monitorado. -echo é para que, se a aplicação no terminal monitorado enviar uma sequência de escape que solicite uma resposta do terminal (como aquelas que solicitam a posição do cursor ou o tipo de terminal ou título da janela), ele será encaminhado para o nosso monitoramento xterm e nosso xterm também responderão. Nós não queremos um eco local disso.

Você também pode monitorar o que está sendo digitado, rastreando as chamadas do sistema write para o mesmo fd (substitua read por write acima). Note que ao pressionar Enter , o emulador de terminal envia um caractere CR, não LF. Além disso, como estamos rastreando no lado mestre, se o usuário digitar a<Backspace>b , veremos todos os três pressionamentos de tecla mesmo se o dispositivo terminal estiver no modo canônico.

Por que o seu não funciona:

tee /dev/pts/user_pts </dev/pts/user_pts

A leitura do dispositivo terminal está lendo a entrada do usuário e a gravação é para exibi-lo ao usuário.

Você está dizendo tee para ler o dispositivo terminal. Então, o que ele lê (a entrada do usuário) não será read pelo (s) aplicativo (s) em execução no terminal (e vice-versa, tee e que application lutará pela entrada do terminal). Escrevendo para o dispositivo terminal, é para exibição lá, não é para colocá-lo de volta lá como entrada. Quando você faz

echo test

(com o stdout de echo sendo o terminal), não é a mesma coisa que se você tivesse digitado test .

Existe um ioctl ( TIOCSTI ) para colocar os caracteres de volta como entrada, mas mesmo isso não funcionaria realmente porque você poderia colocá-lo de volta após o aplicativo, como já leu um pouco mais então isso mudaria a ordem em que o aplicativo está lendo entrada, e de qualquer forma, isso significaria que você o leria repetidas vezes.

    
por 04.08.2013 / 00:17
5

Se o seu sistema operacional está suportando o dtrace, que um script simples, shellsnoop , deve permitir monitorar tudo o que for digitado / impresso em um dado tty.

Se você estiver executando o Linux, o ttysnoop costumava fazer algo semelhante, mas precisava de uma configuração intrusiva como pré-requisito. e não é mais suportado pelo AFAIK com os kernels atuais, então não ajudará no seu caso. Existem tentativas mais ou menos avançadas de fornecer rastreio dinâmico com Linux, systemtap, ktap e até mesmo dtrace, para que você possa investigá-las.

Editar: Cuidado com peekfd , a sua página de manual indica:

Bugs:

Provavelmente muitos. Não fique surpreso se o processo que você está monitorando morrer.

    
por 03.08.2013 / 23:01
3

Essa abordagem envolve um pouco de gdb e tee. Ah, e também usa socat para emular um pseudo-terminal. Poderia funcionar sem ele, mas o usuário notará que sua saída não é mais um terminal (programas como o vi irá reclamar).

Ele faz o seguinte:

  1. Crie um interceptor, usando socat, que se expõe como um arquivo.
  2. O interceptador é conectado ao tee, que duplica os fluxos no terminal $ sys e no terminal $ usr.
  3. O Gdb é usado para substituir os descritores de arquivo stdout / stderr para apontar para o interceptor em vez do terminal $ usr.

Eu notei que o bash parece escrever o que você digita como stderr, não tenho certeza se outros programas fazem o mesmo. Se for esse o caso, o stdin não precisa ser interceptado.

Chame assim: chmod +x /path/to/script; sudo /path/to/script <usr> <sys-adm> . usr e sys-adm são os nomes dos terminais, por exemplo, /dev/pts/1 . Portanto, uma chamada de amostra ficaria assim: sudo /path/to/script /dev/pts/1 /dev/pts/2 . Você pode descobrir seu terminal com o comando tty . E o terminal de usuário com w ou ps .

#!/bin/sh

[ "$1" ] || exit 1
[ "$2" ] || exit 1

usr=$1
sys=$2
utty=${1#/dev/}

ps -e -o tty= -o pid= -o user= | { 
    found_it=

    while read -r tty pid_sh owner; do
        if [ "$utty" = "$tty" ]; then
            found_it=y
            break;
        fi
    done

    [ "$found_it" ] || exit 1

    tmp=$(mktemp)
    tmp_gdb=$(mktemp)

    trap 'rm "$tmp" "$tmp_gdb"' EXIT

    socat PTY,link="$tmp",echo=0,raw,openpty,user="$owner",mode=0600 SYSTEM:"tee $sys > $usr"      &

    printf 'call dup2(open("%s", 1), 1)\ncall dup2(open("%s", 1), 2)
            detach\nquit\n' "$tmp" "$tmp" > "$tmp_gdb"
    gdb -p "$pid_sh" -x "$tmp_gdb" >/dev/null 2>&1 &

    wait
}
    
por 04.08.2013 / 21:03
2

Existe um programa C simples chamado xkey.c para mostrar as explorações do X11. Eu vou deixar você google isso. Você pode capturar os pressionamentos de tecla em um xterm usando isso sem que o usuário esteja ciente disso.

    
por 04.08.2013 / 19:15