É possível que um administrador de sistemas escute os terminais de seus usuários?

17

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

Por favor observe o seguinte:

  • Este não é um caso de uso prático para monitorar as atividades do usuário: eu sei que existem ferramentas de auditoria do sistema para isso. Só estou curioso se isso pode ser feito.
  • Estou ciente dessa pergunta e parece não cobrir o que estou perguntando, pois todas as soluções sugeridas são invasivas (o usuário está ciente do que estou fazendo) ou produzem muito ruído (o stracesolução). A única solução que se aproxima é a que sugere o uso gdb. Mas isso só me permite ver stdout do outro terminal.

O que eu tentei

Eu tentei isso no meu terminal:

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

Isso me permite ver cada caractere que o usuário digita no outro pseudo-terminal à medida que o digita. O problema é que, a cada poucos caracteres, ele "pulava": mostrava um caractere não autorizado 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. Não sei ao certo por que isso está acontecendo e se há uma maneira de melhorá-lo.

O que eu gostaria de ver

USER TERMINAL        |    MY TERMINAL
$ echo "Test"        |    # slick_command_here
Test                 |    echo "Test"
$                    |    Test
Joseph R.
fonte
1
Você quer ttysnoopou provavelmente peekfd.
n. 'pronomes' m.

Respostas:

11

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

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 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'

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

stty size < /dev/pts/that-terminal

Isso despeja o que é lido pelo xtermlado mestre do terminal, então o que é exibido lá, incluindo o local echodo que está sendo digitado.

O exemplo -e read=4acima é para stracegerar um hexdump do que é xtermlido em seu fd 4. O restante do comando é converter isso nos caracteres reais. Eu tentei, peekfd -n -8 15173 4mas por algum motivo, apenas deu o que estava sendo escrito.

Estamos usando -opostpara desativar qualquer pós-processamento em nosso terminal de monitoramento, para que tudo o que é xxdgravado no lado escravo o mantenha inalterado em nosso lado mestre, para que nosso monitoramento xtermfique com a mesma coisa que o monitorado. -echoé para que, se o aplicativo 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 o título da janela), isso vá para o nosso monitoramento xterme nossa xtermvontade responda também. Não queremos um eco local disso.

Você também pode monitorar o que está sendo digitado, rastreando as writechamadas do sistema para o mesmo fd (substitua readpor writeacima). Observe 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 as três teclas pressionadas, mesmo que o dispositivo terminal esteja no modo canônico.

Por que o seu não funciona:

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

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

Você está dizendo teepara ler no dispositivo terminal. Portanto, o que ele lê (a entrada do usuário) não será readpelo (s) aplicativo (s) em execução no terminal (e vice-versa, teee isso applicationlutará pela entrada do terminal). Escrever no dispositivo do terminal é para exibição lá, não é para colocá-lo lá de volta como entrada. Quando você faz

echo test

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

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

Stéphane Chazelas
fonte
1
+1 Para a explicação e para não usar ferramentas externas. Vou precisar ler um pouco para entender muitas partes da sua resposta, mas acho que está na linha do que eu quero.
Joseph R.
5

Se o seu sistema operacional estiver suportando o dtrace, um script simples, shellsnoop , deve permitir que você monitore tudo o que é digitado / impresso em um determinado tty.

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

Edit: Cuidado com o peekfd , sua página do manual declara:

Insetos:

Provavelmente muitos. Não se surpreenda se o processo que você está monitorando morre.

jlliagre
fonte
3

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

Faz o seguinte:

  1. Crie um interceptador, usando socat, que se expõe como um pty.
  2. O interceptador está 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 interceptador em vez do terminal $ usr.

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

Chamá-lo assim: chmod +x /path/to/script; sudo /path/to/script <usr> <sys-adm>. usre sys-admsão os nomes dos terminais, por exemplo /dev/pts/1,. Assim, uma chamada de exemplo ficaria assim: sudo /path/to/script /dev/pts/1 /dev/pts/2. Você pode descobrir o seu terminal com o ttycomando E o terminal do usuário com wou 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
}
Eduardo A. Bustamante López
fonte
2

Existe um programa C simples chamado xkey.c para mostrar as explorações do X11. Vou deixar você pesquisar no Google. Você pode capturar as teclas digitadas em um xterm usando isso sem que o usuário esteja ciente disso.

unxnut
fonte
Eu esperava uma solução independente de emulador de terminal.
Joseph R.
O xkey fornece pressionamentos de teclas em um display X. Serão todos os xterms e qualquer outro utilitário que precise de entrada do teclado.
Unxnut
Certo. Eu pensei que você quis dizer xtermespecificamente.
Joseph R.