Может ли системный администратор подслушивать терминалы своих пользователей?

17

При входе в систему я могу узнать псевдо-терминальное устройство (я) каждого пользователя по выходным данным 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
Вы хотите ttysnoopили , возможно peekfd.
нет. местоимения м.

Ответы:

11

Это 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Выше для straceвыводить шестнадцатеричного того , что xtermчитает на его дескриптором 4. Остальная часть команды заключается в преобразовании , что в реальных персонажей. Я пытался, peekfd -n -8 15173 4но по какой-то причине это дало только то, что было написано.

Мы используем, -opostчтобы отключить любую постобработку в нашем терминале мониторинга, чтобы все, что xxdпишет на ведомую сторону, делало ее неизменной на нашей ведущей стороне, так что наш мониторинг xtermполучает то же самое, что и отслеживаемый. -echoЭто так, что если приложение в контролируемом терминале отправляет управляющую последовательность, которая запрашивает ответ от терминала (например, те, которые запрашивают позицию курсора или тип терминала или заголовок окна), то это доберется до нашего мониторинга xtermи нашей xtermволи ответь также. Мы не хотим местного эха этого.

Вы также можете следить за тем, что набирается, отслеживая writeсистемные вызовы того же самого fd (замените readна writeвыше). Обратите внимание, что после нажатия Enterэмулятор терминала отправляет символ CR, а не LF. Кроме того, поскольку мы выполняем трассировку на стороне мастера, если пользователь печатает a<Backspace>b, мы увидим все 3 нажатия клавиш, даже если оконечное устройство находится в каноническом режиме.

Что касается того, почему ваш не работает:

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

Чтение с оконечного устройства - это чтение пользовательского ввода, а запись в него - для отображения его пользователю.

Вы говорите, teeчтобы читать с терминального устройства. Поэтому то, что он читает (пользовательский ввод), не будет выполняться readприложениями, запущенными в терминале (и наоборот, teeи это applicationбудет бороться за ввод с терминала). Запись в терминальное устройство предназначена для отображения там, а не для помещения его обратно в качестве ввода. Когда вы делаете

echo test

echo'stdout, являющимся терминалом), это не то же самое, что если бы вы набрали test.

Существует ioctl( TIOCSTI) для возврата символов в качестве входных данных, но даже это не сработает, потому что вы можете вернуть его после того, как приложение уже прочитало еще, так что это изменило бы порядок, в котором приложение читает ввод, и в любом случае это означало бы, что вы будете читать это снова и снова.

Стефан Шазелас
источник
1
+1 За объяснение и за то, что не использовали внешние инструменты. Мне нужно немного почитать, чтобы понять многие части вашего ответа, но я чувствую, что он соответствует тому, что я хочу.
Джозеф Р.
5

Если ваша ОС поддерживает dtrace, то простой скрипт shellsnoop должен позволить вам отслеживать все, что напечатано / напечатано на данном tty.

Если вы работаете в Linux, ttysnoop делал то же самое, но в качестве предварительного условия требовалась навязчивая конфигурация, и AFAIK больше не поддерживается текущими ядрами, так что в вашем случае это не поможет. Существуют более или менее продвинутые попытки обеспечить динамическую трассировку в Linux, systemtap, ktap и даже dtrace, чтобы вы могли их исследовать.

Редактировать: Остерегайтесь peekfd , его страница руководства гласит:

ошибки:

Наверное, много. Не удивляйтесь, если процесс, который вы отслеживаете, умирает.

jlliagre
источник
3

Этот подход включает в себя немного GDB и ти. Ах, и он также использует 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>. usrи sys-admявляются названиями терминалов, например /dev/pts/1,. Таким образом, пример вызова будет выглядеть следующим образом : sudo /path/to/script /dev/pts/1 /dev/pts/2. Вы можете узнать свой терминал с помощью ttyкоманды. И пользовательский терминал или с wили 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
}
Эдуардо А. Бустаманте Лопес
источник
2

Существует простая C-программа под названием xkey.c, которая демонстрирует эксплойты X11. Я позволю тебе погуглить. Вы можете зафиксировать нажатия клавиш на компьютере xterm, не обращая на это внимания пользователя.

unxnut
источник
Я надеялся на решение, не зависящее от терминала-эмулятора.
Джозеф Р.
xkey даст вам нажатия клавиш на дисплее X. Это будут все xterms и любая другая утилита, которая требует ввода с клавиатуры.
unxnut
Правильно. Я думал, что вы имели в виду xtermконкретно.
Джозеф Р.