Чи можливо, щоб sysadmin підслухав термінали своїх користувачів?


17

Після входу в машину я можу дізнатися псевдо-кінцеві пристрої кожного користувача з виходу w. Чи можу я бути підслуховувачем цього терміналу, не знаючи користувача? Іншими словами, я хотів би бачити все, що робиться на цьому терміналі, як вихід на мій власний термінал.

Зверніть увагу на таке:

  • Це не для практичного використання для моніторингу діяльності користувачів: я знаю, що для цього є інструменти аудиту системи. Мені просто цікаво, чи можна це зробити.
  • Мені відомо про це питання, і воно, схоже, не охоплює те, про що я питаю, оскільки всі запропоновані рішення є або інвазивними (користувач буде в курсі, що я роблю), або випускають занадто багато шуму ( straceрішення). Єдине рішення, яке наближається, - це рішення, яке пропонує використовувати gdb. Але це дозволяє лише мені бачити stdout іншого терміналу.

Що я спробував

Я спробував це з мого терміналу:

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системних викликів в тому ж дескриптор (замінити readз writeвище). Зауважте, що після натискання Enterемулятор терміналу надсилає символ CR, а не LF. Крім того, оскільки ми відстежуємо на головній стороні, якщо користувач вводить a<Backspace>b, ми побачимо всі 3 натискання клавіш, навіть якщо термінальний пристрій знаходиться в канонічному режимі.

Щодо того, чому ваша не працює:

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

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

Ви говорите teeчитати з термінального пристрою. Отже, те, що він читає (введення користувача), не відбуватиметься readза допомогою додатків, що працюють у терміналі (і навпаки, teeі це applicationбуде боротися за термінальний вхід). Запис на термінальний пристрій призначений для відображення там, це не для того, щоб повернути його туди як вхід. Коли ви робите

echo test

(якщо echostdout є терміналом), це не те саме, що якби ви ввели test.

Існує ioctl( TIOCSTI) повернення символів як вхідних даних, але навіть це не справді спрацювало, тому що ви можете повернути його після програми, як уже прочитали, і це змінило б порядок, коли програма читає введення, і будь-яким способом, це означатиме, що ви будете читати це знову і знову.


1
+1 Для пояснення та невикористання зовнішніх інструментів. Мені потрібно буде трохи прочитати, щоб зрозуміти багато частин вашої відповіді, але я відчуваю, що це узгоджується з тим, що я хочу.
Джозеф Р.

5

Якщо ваша ОС підтримує dtrace, простий скрипт, shellsnoop , повинен дозволяти вам контролювати все, набране / надруковане на заданій tty.

Якщо ви працюєте з Linux, ttysnoop робив подібні речі, але потрібна нав'язлива конфігурація як попередній запит, і AFAIK більше не підтримується поточними ядрами, тому не допоможе у вашому випадку. Існують більш-менш розширені спроби надати динамічне відстеження за допомогою Linux, systemtap, ktap і навіть dtrace, щоб ви могли їх дослідити.

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

Помилки:

Напевно, багато. Не дивуйтеся, якщо процес, за яким ви стежите, загине.


3

Цей підхід передбачає трохи gdb та tee. Так, і він також використовує socat для емуляції псевдотерміналу. Це може працювати і без цього, але користувач помітить, що його / її вихід більше не є терміналом (такі програми, як vi, скаржаться).

Він робить наступне:

  1. Створіть перехоплювач, використовуючи socat, який виставляє себе як шкода.
  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, використовуючи це, не знаючи про це користувача.


Я справді сподівався на термінально-емуляторно-агностичне рішення.
Джозеф Р.

xkey подасть вам натискання клавіш на X-дисплеї. Це будуть всі xterms та будь-яка інша утиліта, яка потребує введення з клавіатури.
unxnut

Правильно. Я думав, ти xtermконкретно мав на увазі .
Джозеф Р.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.