Czy administrator systemu może podsłuchiwać terminale swoich użytkowników?

17

Po zalogowaniu się na maszynie mogę znaleźć pseudo-terminale każdego użytkownika na podstawie danych wyjściowych w. Będąc sysadminem, czy mogę podsłuchiwać ten terminal bez wiedzy użytkownika? Innymi słowy, chciałbym, aby wszystko robiono na tym terminalu jako wyjście na moim własnym terminalu.

Uwaga:

  • Nie jest to praktyczny przypadek użycia do monitorowania działań użytkownika: wiem, że istnieją do tego narzędzia do kontroli systemu. Jestem tylko ciekawy, czy da się to zrobić.
  • Zdaję sobie sprawę z tego pytania i wydaje się, że nie obejmuje ono tego, o co pytam, ponieważ wszystkie rozwiązania sugerują, że są albo inwazyjne (użytkownik byłby świadomy tego, co robię), albo wytwarzają zbyt dużo hałasu ( stracerozwiązanie). Jedynym zbliżającym się rozwiązaniem jest to, które sugeruje użycie gdb. Ale to pozwala mi tylko zobaczyć stdout drugiego terminala.

Co próbowałem

Próbowałem tego z mojego terminalu:

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

To pozwala mi zobaczyć każdy znak, który użytkownik wpisuje w drugim pseudo-terminalu podczas jego wpisywania. Problem polega na tym, że co kilka znaków „przeskakuje”: pokazywałby jeden nieuczciwy znak na jednym urządzeniu końcowym, ale nie na drugim. Zapobiega również wykonywaniu jakichkolwiek poleceń z pseudo terminala użytkownika. Nie jestem do końca pewien, dlaczego tak się dzieje i czy istnieje sposób, aby to poprawić.

Co chciałbym zobaczyć

USER TERMINAL        |    MY TERMINAL
$ echo "Test"        |    # slick_command_here
Test                 |    echo "Test"
$                    |    Test
Joseph R.
źródło
1
Chcesz ttysnooplub prawdopodobnie peekfd.
n. „zaimki” m.

Odpowiedzi:

11

Jest to fd po stronie master pseudo-terminala w emulatorze terminali, który chcesz monitorować, jeśli chcesz zobaczyć, co się na nim wyświetla. Ten master fd jest tym, co symuluje drut prowadzący do prawdziwego terminala. Co xtermpisze na nim jest postacie wygenerowane z klucza naciśnięcia. Odczytuje z niego to, co wyświetla.

Na przykład w systemie 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

A następnie uruchom na przykład:

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'

Oczywiście działa lepiej, jeśli uruchamiasz go w terminalu tego samego typu i wielkości, co ten, który próbujesz monitorować. Rozmiar można uzyskać za pomocą:

stty size < /dev/pts/that-terminal

Że wysypisk co jest czytane przez xtermod strony głównego terminala, więc to, co jest wyświetlane tam, w tym lokalnej echo, co jest wpisane.

-e read=4Powyżej jest stracedo wyjścia hexdump co xtermczyta na jego fd 4. spoczynku polecenia jest konwersja że do rzeczywistych postaci. Próbowałem, peekfd -n -8 15173 4ale z jakiegoś powodu podałem tylko to, co zostało napisane.

Używamy -opostdo wyłączania przetwarzania końcowego w naszym terminalu monitorującym, aby wszystko xxdzapisywało po stronie podrzędnej, co czyni go niezmienionym po stronie nadrzędnej, dzięki czemu nasze monitorowanie xtermjest takie samo jak monitorowane. -echojest tak, że jeśli aplikacja w monitorowanym terminalu wysyła sekwencję ucieczki, która żąda odpowiedzi z terminala (na przykład tych, które żądają pozycji kursora lub typu terminala lub tytułu okna), to przejdzie do naszego monitorowania xtermi naszej xtermwoli odpowiedz również. Nie chcemy lokalnego echa tego.

Można także monitorować to, co jest wpisane przez śledzenie writewywołań systemowych do tego samego fd (zamiast readz writewyżej). Zauważ, że po naciśnięciu Enteremulator terminala wysyła znak CR, a nie LF. Ponadto, ponieważ śledzimy po stronie wzorcowej, jeśli użytkownik wpisze a<Backspace>b, zobaczymy wszystkie 3 naciśnięcia klawiszy, nawet jeśli urządzenie końcowe jest w trybie kanonicznym.

Dlaczego twój nie działa:

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

Odczytywanie z urządzenia końcowego odczytuje dane wejściowe użytkownika, a zapisywanie na nim ma na celu wyświetlenie go użytkownikowi.

Mówisz teeczytać z urządzenia końcowego. Więc to, co odczytuje (dane wejściowe użytkownika), nie będzie readprzez aplikacje działające w terminalu (i odwrotnie, teei to applicationbędzie walczyć o dane wejściowe na terminalu). Zapis do urządzenia końcowego służy do wyświetlania, nie służy do umieszczania go z powrotem jako danych wejściowych. Kiedy to zrobisz

echo test

(ze echostdout jest terminalem), to nie to samo, co gdybyś pisał test.

Istnieje funkcja ioctl( TIOCSTI), aby wstawić znaki z powrotem jako dane wejściowe, ale nawet to nie zadziałałoby, ponieważ można je było umieścić z powrotem po aplikacji, ponieważ już przeczytało trochę więcej, więc zmieniłoby kolejność, w której aplikacja odczytuje dane wejściowe, i w dowolny sposób, oznaczałoby to, że czytałbyś go w kółko.

Stéphane Chazelas
źródło
1
+1 Za wyjaśnienie i nieużywanie narzędzi zewnętrznych. Będę musiał trochę przeczytać, aby zrozumieć wiele części twojej odpowiedzi, ale czuję, że jest to zgodne z tym, czego chcę.
Joseph R.
5

Jeśli twój system operacyjny obsługuje dtrace, to prosty skrypt shellsnoop powinien umożliwiać monitorowanie wszystkiego , co napisano / wydrukowano na danym tty.

Jeśli używasz Linuksa, ttysnoop robił to samo, ale wymagał uciążliwej konfiguracji jako warunku wstępnego i nie jest już obsługiwany przez AFAIK z obecnymi jądrami, więc nie pomoże w twoim przypadku. Istnieją mniej lub bardziej zaawansowane próby zapewnienia dynamicznego śledzenia w systemie Linux, systemtap, ktap, a nawet dtrace, abyś mógł je zbadać.

Edycja: Uważaj na peekfd , jego strona podręcznika stanowi:

Błędy:

Prawdopodobnie dużo. Nie zdziw się, jeśli proces, który monitorujesz, umrze.

jlliagre
źródło
3

To podejście wymaga trochę gdb i tee. Ach, a także używa socat do emulacji pseudoterminalu. Bez niego może działać, ale użytkownik zauważy, że jego wyjście nie jest już terminalem (programy takie jak vi będą narzekać).

Wykonuje następujące czynności:

  1. Utwórz przechwytywacz za pomocą socat, który ujawnia się jako pty.
  2. Przechwytywacz jest podłączony do tee, który duplikuje strumienie zarówno w terminalu $ sys, jak i terminalu usr.
  3. Gdb służy do zastępowania deskryptorów plików stdout / stderr w celu wskazania przechwytywacza zamiast terminala $ usr.

Zauważyłem, że bash wydaje się pisać to, co piszesz na stderr, nie jestem pewien, czy inne programy robią to samo. W takim przypadku stdin nie musi być przechwytywany.

Nazwijmy to tak: chmod +x /path/to/script; sudo /path/to/script <usr> <sys-adm>. usri sys-admsą to nazwy terminali, na przykład /dev/pts/1. Tak więc próba połączenia będzie wyglądać następująco: sudo /path/to/script /dev/pts/1 /dev/pts/2. Możesz znaleźć swój terminal za pomocą ttypolecenia. I terminal użytkownika z wlub 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
źródło
2

Istnieje prosty program C o nazwie xkey.c, który pokazuje exploity X11. Pozwolę ci google. Możesz przechwytywać naciśnięcia klawiszy na xtermie, używając tego, bez wiedzy użytkownika.

unxnut
źródło
Miałem nadzieję na rozwiązanie agnostyczne terminal-emulator.
Joseph R.
xkey daje naciśnięcia klawiszy na ekranie X. To będą wszystkie xtermy i wszelkie inne narzędzia wymagające klawiatury.
unxnut
Dobrze. Myślałem, że masz na myśli xtermkonkretnie.
Joseph R.