Est-il possible pour un administrateur système d'écouter les terminaux de ses utilisateurs?

17

Une fois connecté à une machine, je peux trouver le ou les périphériques pseudo-terminaux de chaque utilisateur à partir de la sortie de w. Étant un administrateur système, est-il possible pour moi d'écouter ce terminal à l'insu de l'utilisateur? En d'autres termes, je voudrais voir tout ce qui se fait sur ce terminal comme sortie sur mon propre terminal.

Veuillez noter ce qui suit:

  • Il ne s'agit pas d'un cas d'utilisation pratique de la surveillance des activités des utilisateurs: je sais qu'il existe des outils d'audit système pour cela. Je suis simplement curieux de savoir si cela peut être fait.
  • Je suis conscient de cette question et elle ne semble pas couvrir ce que je demande, car toutes les solutions suggérées sont invasives (l'utilisateur serait conscient de ce que je fais) ou produisent trop de bruit (le straceSolution). La seule solution qui se rapproche est celle qui suggère d'utiliser gdb. Mais cela ne me permet que de voir la sortie standard de l'autre terminal.

Ce que j'ai essayé

J'ai essayé cela depuis mon terminal:

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

Cela me permet de voir chaque caractère que l'utilisateur tape dans l'autre pseudo-terminal pendant qu'il le tape. Le problème est que, sur quelques caractères, il "sauterait": il montrerait un caractère escroc sur un terminal mais pas sur l'autre. Il empêche également l'exécution de toute commande à partir du pseudo-terminal de l'utilisateur. Je ne sais pas vraiment pourquoi cela se produit et s'il existe un moyen de l'améliorer.

Ce que j'aimerais voir

USER TERMINAL        |    MY TERMINAL
$ echo "Test"        |    # slick_command_here
Test                 |    echo "Test"
$                    |    Test
Joseph R.
la source
1
Vous voulez ttysnoopou probablement peekfd.
n. «pronoms» m.

Réponses:

11

C'est le fd du côté maître du pseudo-terminal dans l'émulateur de terminal que vous souhaitez surveiller si vous voulez voir ce qui y est affiché. Ce maître fd est ce qui simule le fil qui va à une vraie borne. Ce qui y est xtermécrit, ce sont les caractères générés à partir de la touche sur laquelle vous appuyez. Ce qu'il en lit, c'est ce qu'il affiche.

Par exemple, sous 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

Et puis exécutez par exemple:

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'

Bien sûr, cela fonctionne mieux si vous l'exécutez dans un terminal de même type et de même taille que celui que vous essayez de surveiller. Vous pouvez obtenir la taille avec:

stty size < /dev/pts/that-terminal

Cela supprime ce qui est lu par xtermle côté maître du terminal, donc ce qui y est affiché, y compris le local echode ce qui est tapé.

Ce qui -e read=4précède est pour stracesortir un hexdump de ce qui se xtermlit sur son fd 4. Le reste de la commande consiste à convertir cela en caractères réels. J'ai essayé, peekfd -n -8 15173 4mais pour une raison quelconque, cela ne donnait que ce qui était écrit.

Nous utilisons -opostpour désactiver tout post-traitement dans notre terminal de surveillance, de sorte que tout ce qui est xxdécrit sur le côté esclave le rend inchangé sur notre côté maître, de sorte que notre surveillance xtermobtienne la même chose que celle surveillée. -echoest de sorte que si l'application dans le terminal surveillé envoie une séquence d'échappement qui demande une réponse du terminal (comme celles qui demandent la position du curseur ou le type de terminal ou le titre de la fenêtre), cela fera son chemin vers notre surveillance xtermet notre xtermvolonté répondez aussi. Nous ne voulons pas d'un écho local de cela.

Vous pouvez également surveiller ce qui est tapé en traçant les writeappels système vers ce même fd (remplacer readpar writeci-dessus). Notez qu'en appuyant sur Enter, l'émulateur de terminal envoie un caractère CR, pas LF. De plus, puisque nous traçons du côté maître, si l'utilisateur tape a<Backspace>b, nous verrons les 3 frappes même si le terminal est en mode canonique.

Quant à savoir pourquoi le vôtre ne fonctionne pas:

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

Lire à partir du terminal, c'est lire l'entrée utilisateur, et y écrire, c'est l'afficher pour l'utilisateur.

Vous dites teede lire depuis le terminal. Donc, ce qu'il lit (l'entrée utilisateur) ne sera pas readpar les applications exécutées dans le terminal (et vice versa, teeet cela applicationse battra pour l'entrée du terminal). L'écriture sur le terminal est destinée à être affichée là-bas, elle ne sert pas à la replacer en entrée. Quand tu fais

echo test

(avec echostdout étant le terminal), ce n'est pas la même chose que si vous aviez tapé test.

Il y a un ioctl( TIOCSTI) pour remettre les caractères en entrée, mais même cela ne fonctionnerait pas vraiment parce que vous pourriez le remettre après l'application comme déjà lu, donc cela changerait l'ordre dans lequel l'application lit l'entrée, et de toute façon, cela signifierait que vous le liriez encore et encore.

Stéphane Chazelas
la source
1
+1 Pour l'explication et pour ne pas utiliser d'outils externes. Je devrai faire un peu de lecture pour comprendre de nombreuses parties de votre réponse, mais je pense que c'est dans le sens de ce que je veux.
Joseph R.
5

Si votre système d'exploitation prend en charge dtrace, qu'un simple script, shellsnoop , devrait vous permettre de surveiller tout ce qui est tapé / imprimé sur un tty donné.

Si vous utilisez Linux, ttysnoop avait l' habitude de faire une chose similaire mais avait besoin d'une configuration intrusive en tant que pré-requis et l'AFAIK n'est plus pris en charge avec les noyaux actuels de toute façon, cela ne vous aidera pas dans votre cas. Il existe des tentatives plus ou moins avancées pour fournir un suivi dynamique avec Linux, systemtap, ktap et même dtrace afin que vous puissiez les étudier.

Edit: Méfiez - vous de peekfd , sa page de manuel indique:

Bugs:

Probablement beaucoup. Ne soyez pas surpris si le processus que vous surveillez meurt.

jlliagre
la source
3

Cette approche implique un peu de gdb et tee. Ah, et il utilise également socat pour émuler un pseudo-terminal. Cela pourrait fonctionner sans, mais l'utilisateur remarquera que sa sortie n'est plus un terminal (des programmes comme vi s'en plaindront).

Il fait ce qui suit:

  1. Créez un intercepteur, en utilisant socat, qui s'expose comme un pty.
  2. L'intercepteur est connecté à tee, qui duplique les flux à la fois dans le terminal $ sys et dans le terminal $ usr.
  3. Gdb est utilisé pour remplacer les descripteurs de fichier stdout / stderr pour pointer vers l'intercepteur au lieu du terminal $ usr.

J'ai remarqué que bash semble écrire ce que vous tapez sur stderr, je ne sais pas si d'autres programmes font de même. Si tel est le cas, stdin n'a pas à être intercepté.

Appelez cela comme ceci: chmod +x /path/to/script; sudo /path/to/script <usr> <sys-adm>. usret sys-admsont les noms des terminaux, par exemple /dev/pts/1,. Donc , un appel échantillon ressemblerait à ceci: sudo /path/to/script /dev/pts/1 /dev/pts/2. Vous pouvez découvrir votre terminal avec la ttycommande. Et le terminal utilisateur avec 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
la source
2

Il existe un simple programme C appelé xkey.c pour montrer les exploits de X11. Je vous laisse google. Vous pouvez capturer les frappes sur un xterm en utilisant ceci sans que l'utilisateur en soit conscient.

unnut
la source
J'espérais en fait une solution agnostique de terminal-émulateur.
Joseph R.
xkey vous donnera des touches sur un écran X. Ce sera tous les xterms et tout autre utilitaire qui nécessite une entrée au clavier.
unxnut
Droite. Je pensais que tu voulais dire xtermspécifiquement.
Joseph R.