Narzędzia do pokazywania plików, do których program ma dostęp?

12

Nie zamierzam korzystać ze skomplikowanych narzędzi, takich jak tryb skarg AppArmor, potrzebuję łatwych narzędzi, aby powiedzieć mi, do których plików dostęp ma dany program.

Boll19
źródło
7
Pod jakim systemem operacyjnym?
Jeff Schaller
Może być również przydatne, aby wyjaśnić, że spodziewasz się, że program będzie uzyskiwał dostęp do plików w jaki sposób - czytanie, pisanie, dołączanie, tylko uzyskiwanie fstat()lub lstat()informacje itp.
Sergiy Kolodyazhnyy
Zarówno Suse, jak i Ubuntu
Boll19
Nie ma znaczenia, w jaki sposób muszę wiedzieć, czy programuje się fstat () lub lstat ()?
Boll19
Innymi słowy, komentarz Siergieja Kolodyazhnyya: jeśli program sprawdza długość pliku, datę modyfikacji, uprawnienia lub inne właściwości, ale nie uzyskuje dostępu do danych pliku, czy liczyłbyś to jako „dostęp do pliku”, czy nie?
telcoM

Odpowiedzi:

12

Według Chrisa Down możesz użyć strace -pdo zbadania już uruchomionego procesu, aby zobaczyć, jakie pliki otwiera od teraz, aż do momentu zakończenia śledzenia lub samego procesu.

Jeśli chcesz, aby pliki były otwarte przez cały czas trwania procesu, od samego początku użyj stracenazwy pliku wykonywalnego. Dodanie -fgwarantuje, że raportowane będą również wszelkie rozwidlone podprocesy. Przykład

# strace -e open -f /bin/id
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/proc/thread-self/attr/current", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/proc/self/task/1581/attr/current", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
open("/etc/group", O_RDONLY|O_CLOEXEC)  = 3
open("/etc/group", O_RDONLY|O_CLOEXEC)  = 3
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
+++ exited with 0 +++
#

Używanie lsofdo sprawdzania, jakie pliki aktualnie otwiera proces

# lsof -p $(pidof NetworkManager)
COMMAND   PID USER   FD      TYPE             DEVICE  SIZE/OFF     NODE NAME
NetworkMa 722 root  cwd       DIR              253,0       224       64 /
NetworkMa 722 root  rtd       DIR              253,0       224       64 /
NetworkMa 722 root  txt       REG              253,0   2618520   288243 /usr/sbin/NetworkManager
NetworkMa 722 root  mem       REG              253,0     27776    34560 /usr/lib64/libnss_dns-2.17.so
[...]
#

Jeśli masz SystemTap, możesz monitorować cały host pod kątem otwierania plików.

[root@localhost tmp]# cat mon
#!/usr/bin/env stap
probe syscall.open { printf ("pid %d program %s opened %s\n", pid(), execname(), filename) }
# ./mon
pid 14813 program touch opened "/etc/ld.so.cache"
pid 14813 program touch opened "/lib64/libc.so.6"
pid 14813 program touch opened 0x7f7a8c6ec8d0
pid 14813 program touch opened "foo2"
[...]
#
Steve
źródło
2
opento nie jedyne odpowiednie wywołanie systemowe. Na przykład możliwe jest przekazywanie deskryptorów plików między procesami przez gniazdo unix, i istnieje openatwywołanie systemowe, które może również otworzyć plik.
kasperd
---- SIGUSR1 {si_signo = SIGUSR1, si_code = SI_TKILL, si_pid = 6026, si_uid = 1002} ---- co to jest
Boll19 28.01.2018
kaspers, czy muszę tylko szukać „openat” w poleceniu wyjścia strace?
Boll19
Próbujesz otworzyć plik (ale plik może nie istnieć) jest również wyświetlany w wynikach „strace”?
Boll19
Boll19, pliki, które nie otwierają się z powodu ich nieistnienia, są szczęśliwie zgłaszane wewnątrz strace, patrz wiersze ENOENT w przykładzie.
steve
5

Możesz skorzystać opensnoopz BCC, który korzysta z eBPF pod maską:

# ./opensnoop -p 1576
PID    COMM      FD ERR PATH
1576   snmpd     11   0 /proc/sys/net/ipv6/conf/lo/forwarding
1576   snmpd     11   0 /proc/sys/net/ipv6/neigh/lo/base_reachable_time_ms
1576   snmpd      9   0 /proc/diskstats
1576   snmpd      9   0 /proc/stat
1576   snmpd      9   0 /proc/vmstat
[...]

Jest to dość wydajne, ponieważ używa kprobes zamiast restartować syscalls, podobnie jak stracerobi.

Możesz to również zrobić za pomocą strace(potencjalnie z -fpodążaniem za potomkami śledzonego procesu), ale jego sposób działania, polegający na ponownym uruchomieniu wywołań systemowych w ramach ptrace , nieco spowolni twoją aplikację:

# strace -e open -p 15735
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/gconv/gconv-modules.cache", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/gconv/gconv-modules", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/python2.7/site-packages", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/etc/localtime", O_RDONLY|O_CLOEXEC) = 8
[...]

Możesz również uruchomić aplikację w ten sposób, jeśli chcesz, używając strace [executable]lub strace -f [executable].

Chris Down
źródło
5

Moim ulubionym narzędziem do monitorowania, które pliki otwiera aplikacja, jest potężne środowisko monitorowania sysdig.

Do monitorowania wszystkich otwartych plików otwartych przez program o nazwie exe_file:

sudo sysdig -p "proc.name=exe_file %12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open

Monitorowanie wszystkich plików otwartych na serwerze:

sudo sysdig -p "%12user.name %6proc.pid %12proc.name %3fd.num %fd.typechar %fd.name" evt.type=open

Tworzenie pliku śledzenia, który będzie zawierał tylko zdarzenia zapisu w katalogach domowych (które możemy później sprawdzić sysdig -r writetrace.scap.gz):

sudo sysdig -p "%user.name %proc.name %fd.name" "evt.type=write and fd.name contains /home/" -z -w writetrace.scap.gz

Widząc wszystko na poziomie syscall, proces o nazwie exe_filewykonuje:

sudo sysdig proc.name=exe_file

Sysdig ma wiele dłut, sprawdź ciekawsze rzeczy, które może zrobić:

Masz również to, dtraceże nie jest zbyt często używane w Linuksie, ale nadal jest dużo używane w systemach operacyjnych * BSD:

# Files opened by process,
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'

Poza tym sysdig, stracei dtrace, również mam ltrace, które rekordy / przechwytuje sygnały / biblioteki dynamiczne / wywołania systemowe, które są nazywane / otrzymane w procesie:

ltraceto program, który po prostu uruchamia określone polecenie, dopóki nie zakończy działania. Przechwytuje i rejestruje dynamiczne wywołania biblioteki, które są wywoływane przez wykonywany proces oraz sygnały odbierane przez ten proces. Może także przechwytywać i drukować wywołania systemowe wykonywane przez program.

$ltrace exe_file
_libc_start_main(0x400624, 1, 0x7ffcb7b6d7c8, 0x400710 <unfinished ...>  
time(0)                                                                              = 1508018406  
srand(0x59e288e6, 0x7ffcb7b6d7c8, 0x7ffcb7b6d7d8, 0)                                 = 0  
sprintf("mkdir -p -- '/opt/sms/AU/mo'", "mkdir -p -- '%s'", "/opt/sms/AU/mo")        = 28  
system("mkdir -p -- '/opt/sms/AU/mo'" <no return ...>  
--- SIGCHLD (Child exited) ---  
<... system resumed> )                                                               = 0  
rand(2, 0x7ffcb7b6d480, 0, 0x7f9d6d4622b0)                                           = 0x2d8ddbe1  
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo")      = 29  
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1)                              = 3  
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo")      = 29  
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1)                              = 4  
+++ exited (status 0) +++  

Jeśli program jest mały, możesz również rozważyć jego dezasemblację objdump -d exe_filelub deasemblację / dekompilację Hopper, aby zobaczyć wszystkie pliki , z którymi ma do czynienia.

Aby uzyskać więcej informacji, zobacz: Zrozumienie, co robi plik binarny systemu Linux

Jako pierwsze podejście zrobiłbym również:

strings exe_file

Jest to podejście tanie, a przy odrobinie szczęścia niektóre nazwy plików mogą po prostu być obecne w trybie ASCII w pliku binarnym przy odrobinie szczęścia.

Zobacz także pokrewną odpowiedź Dlaczego prawda i fałsz są tak duże?

Jeśli pliki binarne / pliki dostarczane z dystrybucją można również pobrać źródła ze źródłowych repozytoriów dystrybucji lub oficjalnych repozytoriów rzeczywistego narzędzia.

Jako ostatni zasób możesz zawsze używać narzędzi takich jak gdb lub rr do debugowania pliku binarnego w czasie rzeczywistym.

Rui F. Ribeiro
źródło
aaa43bb66: ~ # sudo proc.name = exe_file sysdig -p "% 12user.name% 6proc.pid% 12proc.name% 3fd.num% fd.typechar% fd.name" evt.type = otwórz Nie można załadować błędu sterownika urządzenie otwierające / dev / sysdig0. Upewnij się, że masz poświadczenia root i że moduł sysdig-probe jest załadowany.
Boll19
/ * <pre> aaa43bb66: ~ # sudo proc.name = exe_file sysdig -p "% 12user.name% 6proc.pid% 12proc.name% 3fd.num% fd.typechar% fd.name" evt.type = open Nie można załadować sterownik błędu urządzenia otwierającego / dev / sysdig0. Upewnij się, że masz poświadczenia root i że moduł sysdig-probe jest załadowany. <kod> * /
Boll19
@ Boll19 Wystąpił błąd, poprawiono go. Ta wiadomość dotyczy sysdigbłędu (czy używasz ARM?), Proszę o nowe pytanie.
Rui F Ribeiro