系统管理员是否可以窃听他/她的用户终端?

系统管理员是否可以窃听他/她的用户终端?

当登录到计算机时,我可以从 的输出中找到每个用户的伪终端设备w。作为系统管理员,我是否可以在用户不知情的情况下窃听该终端?换句话说,我希望看到该终端上所做的一切都作为我自己终端上的输出。

请注意以下事项:

  • 这不适用于监视用户活动的实际用例:我知道有用于此目的的系统审核工具。我只是好奇是否可以做到。
  • 我知道这个问题它似乎没有涵盖我要问的内容,因为所有解决方案都表明要么具有侵入性(用户会意识到我在做什么),要么产生太多噪音(解决方案strace)。一种接近的解决方案是建议使用gdb.但这只能让我看到另一个终端的标准输出。

我尝试过的

我从我的终端尝试了这个:

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

这使我可以看到用户在另一个伪终端中键入的每个字符。问题是,每隔几个字符,它就会“跳过”:它会在一台终端设备上显示一个流氓字符,但在另一台终端设备上则不会。它还可以防止从用户的伪终端设备执行任何命令。我不太确定为什么会发生这种情况以及是否有办法改进它。

我想看到什么

USER TERMINAL        |    MY TERMINAL
$ echo "Test"        |    # slick_command_here
Test                 |    echo "Test"
$                    |    Test

答案1

如果您想查看终端仿真器上显示的内容,则需要监视该终端仿真器中伪终端的主端的 fd。那掌握fd 模拟连接到真实终端的线路。上面写的xterm是您按下的按键生成的字符。它从中读取的内容就是它显示的内容。

例如,在 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

然后运行例如:

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'

当然,如果您在与您要监视的终端类型和大小相同的终端中运行它,效果会更好。您可以通过以下方式获取尺寸:

stty size < /dev/pts/that-terminal

这会转储什么xterm终端的主端,所以那里显示的内容,包括echo正在键入的本地内容。

上面的命令-e read=4用于输出在其 fd 4 上读取的strace内容的十六进制转储xterm。该命令的其余部分是将其转换为实际字符。我尝试过peekfd -n -8 15173 4,但由于某种原因,只给出了所写的内容。

我们用来-opost禁用监控终端中的任何后处理,以便xxd写入从属端的所有内容使其在我们的主端保持不变,以便我们的监控xterm获得与受监控的相同的东西。-echo是这样的,如果受监控终端中的应用程序发送一个转义序列来请求终端的答复(例如那些请求光标位置或终端类型或窗口标题的转义序列),它将进入我们的监控xterm和我们的xterm意愿也回复一下。我们不希望在当地出现这样的情况。

您还可以通过跟踪write对同一 fd 的系统调用来监视正在键入的内容(替换readwrite上面的内容)。请注意,按 后Enter,终端仿真器会发送 CR 字符,而不是 LF。另外,由于我们在主端进行跟踪,因此如果用户键入a<Backspace>b,即使终端设备处于规范模式,我们也会看到所有 3 个击键。

至于为什么你的不起作用:

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

从终端设备读取就是读取用户输入,写入就是将其显示给用户。

您告诉我们tee从终端设备读取。因此,它读取的内容(用户输入)不会read由终端中运行的应用程序读取(反之亦然,teeapplication将争夺终端输入)。写入终端设备,是为了在那里显示,而不是为了把它放回那里作为输入。当你这样做时

echo test

echo的 stdout 是终端),它与您输入的不同test

有一个ioctl( TIOCSTI) 可以将字符放回输入,但即使这样也不起作用,因为您可以将其放回应用程序已经读取了更多内容,因此它会更改应用程序读取输入的顺序,无论如何,这意味着您将一遍又一遍地读取它。

答案2

如果您的操作系统支持 dtrace,这是一个简单的脚本,贝壳窥探,应该允许您监视在给定 tty 上键入/打印的所有内容。

如果您运行的是 Linux,蒂斯努普曾经做过类似的事情,但需要一个侵入性配置作为先决条件,而且据我所知,当前内核不再支持无论如何,所以对您的情况没有帮助。有或多或少的高级尝试使用 Linux、systemtap、ktap 甚至 dtrace 提供动态跟踪,因此您可以研究它们。

编辑:提防窥视FD,其手册页指出:

错误:

可能很多。如果您监控的进程死掉,请不要感到惊讶。

答案3

这种方法涉及一些 gdb 和 tee。啊,它还使用 socat 来模拟伪终端。它可以在没有它的情况下工作,但用户会注意到他/她的输出不再是终端(像 vi 这样的程序会抱怨)。

它执行以下操作:

  1. 使用 socat 创建一个拦截器,它将自身公开为 pty。
  2. 拦截器连接到 tee,它在 $sys 终端和 $usr 终端中复制流。
  3. Gdb 用于替换 stdout/stderr 文件描述符以指向拦截器而不是 $usr 终端。

我注意到 bash 似乎将您输入的内容写入 stderr,我不确定其他程序是否也这样做。如果是这种情况,则不必拦截 stdin。

像这样称呼它:chmod +x /path/to/script; sudo /path/to/script <usr> <sys-adm>usrsys-adm是终端的名称,例如/dev/pts/1。因此,示例调用如下所示sudo /path/to/script /dev/pts/1 /dev/pts/2:您可以使用命令找到您的终端tty。用户终端用wps

#!/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
}

答案4

有一个名为 xkey.c 的简单 C 程序来展示 X11 的漏洞。我会让你谷歌一下。您可以使用它捕获 xterm 上的击键,而用户不会意识到。

相关内容