¿Es posible que un administrador de sistemas escuche a escondidas las terminales de sus usuarios?

17

Cuando inicie sesión en una máquina, puedo averiguar los dispositivos pseudo-terminales de cada usuario a partir de la salida de w. Siendo un administrador de sistemas, ¿es posible que escuche a escondidas este terminal sin que el usuario lo sepa? En otras palabras, me gustaría ver todo lo que se hace en este terminal como salida en mi propio terminal.

Tenga en cuenta lo siguiente:

  • Este no es un caso de uso práctico para monitorear las actividades de los usuarios: soy consciente de que existen herramientas de auditoría del sistema para eso. Tengo curiosidad por saber si se puede hacer.
  • Soy consciente de esta pregunta y no parece cubrir lo que estoy preguntando, ya que todas las soluciones sugeridas son invasivas (el usuario estaría al tanto de lo que estoy haciendo) o producen demasiado ruido (el stracesolución). La única solución que se acerca es la que sugiere usar gdb. Pero esto solo me permite ver stdout de la otra terminal.

Lo que he intentado

Intenté esto desde mi terminal:

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

Esto me permite ver cada carácter que el usuario escribe en el otro pseudo-terminal a medida que lo escribe. El problema es que, cada pocos caracteres, se "saltaría": mostraría un carácter falso en un dispositivo terminal pero no en el otro. También evita la ejecución de cualquier comando desde el dispositivo pseudo terminal del usuario. No estoy muy seguro de por qué sucede esto y si hay una manera de mejorarlo.

Lo que me gustaria ver

USER TERMINAL        |    MY TERMINAL
$ echo "Test"        |    # slick_command_here
Test                 |    echo "Test"
$                    |    Test
Joseph R.
fuente
1
Quieres ttysnoopo probablemente peekfd.
n. 'pronombres' m.

Respuestas:

11

Es el fd al lado maestro del pseudo-terminal en el emulador de terminal que desea monitorear si desea ver lo que se muestra en él. Ese maestro fd es lo que simula el cable que va a un terminal real. Lo que xtermescribe en él son los caracteres generados a partir de la tecla que presiona. Lo que lee de él es lo que muestra.

Por ejemplo, en 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

Y luego ejecuta por ejemplo:

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'

Por supuesto, funciona mejor si lo ejecuta en un terminal del mismo tipo y tamaño que el que está tratando de monitorear. Puedes obtener el tamaño con:

stty size < /dev/pts/that-terminal

Que vuelca lo que se leen por xtermel lado del maestro de la terminal, así que lo que se muestra allí, incluyendo los locales echode lo que se está tecleando.

Lo -e read=4anterior es para stracegenerar un volcado hexadecimal de lo que se xtermlee en su fd 4. El resto del comando es convertir eso a los caracteres reales. Lo intenté peekfd -n -8 15173 4pero por alguna razón eso solo dio lo que se estaba escribiendo.

Estamos utilizando -opostpara deshabilitar cualquier procesamiento posterior en nuestro terminal de monitoreo, de modo que todo lo que se xxdescribe en el lado esclavo no cambie a nuestro lado maestro, de modo que nuestro monitoreo xtermobtenga lo mismo que el monitoreado. -echoes para que si la aplicación en el terminal monitoreado envía una secuencia de escape que solicita una respuesta del terminal (como las que solicitan la posición del cursor o el tipo de terminal o título de la ventana), que se abrirá paso a nuestro monitoreo xtermy nuestra xtermvoluntad responde también. No queremos un eco local de eso.

También puede monitorear lo que se está escribiendo al rastrear las writellamadas del sistema a ese mismo fd (reemplace readcon el writeanterior). Tenga en cuenta que al presionar Enter, el emulador de terminal envía un carácter CR, no LF. Además, dado que estamos rastreando en el lado maestro, si el usuario escribe a<Backspace>b, veremos las 3 pulsaciones de teclas incluso si el dispositivo terminal está en modo canónico.

En cuanto a por qué el tuyo no funciona:

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

Leer desde el dispositivo terminal es leer la entrada del usuario, y escribir en ella es mostrarla al usuario.

Estás diciendo teeque leas desde el dispositivo terminal. Entonces, lo que lee (la entrada del usuario) no será readpor las aplicaciones que se ejecutan en el terminal (y viceversa, teey eso applicationluchará por la entrada del terminal). Escribir en el dispositivo terminal es para mostrarlo allí, no para volverlo a poner como entrada. Cuando tu lo hagas

echo test

(con echostdout como terminal), no es lo mismo que si hubiera escrito test.

Hay un ioctl( TIOCSTI) para volver a colocar los caracteres como entrada, pero incluso eso no funcionaría realmente porque podría volver a ponerlo después de la aplicación, ya que ya se leyó un poco más, por lo que cambiaría el orden en que la aplicación está leyendo la entrada, y de cualquier manera, eso significaría que lo leerías una y otra vez.

Stéphane Chazelas
fuente
1
+1 Para la explicación y para no usar herramientas externas. Necesitaré leer un poco para comprender muchas partes de su respuesta, pero siento que está en la línea de lo que quiero.
Joseph R.
5

Si su sistema operativo es compatible con dtrace, ese simple script, shellsnoop , debería permitirle monitorear todo lo escrito / impreso en un tty dado.

Si está ejecutando Linux, ttysnoop solía hacer algo similar, pero necesitaba una configuración intrusiva como requisito previo y AFAIK ya no es compatible con los núcleos actuales de todos modos, por lo que no ayudará en su caso. Hay intentos más o menos avanzados para proporcionar un seguimiento dinámico con Linux, systemtap, ktap e incluso dtrace para que pueda investigarlos.

Editar: Cuidado con peekfd , su página de manual dice:

Loco:

Probablemente muchos. No se sorprenda si el proceso que está monitoreando muere.

jlliagre
fuente
3

Este enfoque implica un poco de gdb y tee. Ah, y también usa socat para emular un pseudo-terminal. Podría funcionar sin él, pero el usuario notará que su salida ya no es una terminal (los programas como vi se quejarán).

Hace lo siguiente:

  1. Cree un interceptor, usando socat, que se exponga como una empanada.
  2. El interceptor está conectado a tee, que duplica las transmisiones tanto en el terminal $ sys como en el terminal $ usr.
  3. Gdb se usa para reemplazar los descriptores de archivo stdout / stderr para apuntar al interceptor en lugar del terminal $ usr.

Me di cuenta de que bash parece escribir lo que escribes en stderr, no estoy seguro de si otros programas hacen lo mismo. Si ese es el caso, stdin no tiene que ser interceptado.

Llamarlo así: chmod +x /path/to/script; sudo /path/to/script <usr> <sys-adm>. usry sys-admson los nombres de los terminales, por ejemplo /dev/pts/1,. Por lo que una llamada de ejemplo sería el siguiente: sudo /path/to/script /dev/pts/1 /dev/pts/2. Puedes encontrar tu terminal con el ttycomando. Y el terminal de usuario con wo 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
fuente
2

Hay un programa simple en C llamado xkey.c para mostrar los exploits de X11. Te dejaré googlearlo. Puede capturar las pulsaciones de teclas en un xterm usando esto sin que el usuario lo sepa.

unxnut
fuente
En realidad esperaba una solución independiente de emulador de terminal.
Joseph R.
xkey le dará pulsaciones de teclas en una pantalla X. Esa será todas las xterms y cualquier otra utilidad que necesite entrada de teclado.
unxnut
Correcto. Pensé que te referías xtermespecíficamente.
Joseph R.