GNU/Linux >> Linux Esercitazione >  >> Linux

Linux:come annullare la condivisione della rete per il processo corrente?

È possibile eseguire un nuovo comando senza accesso alla rete come non root utilizzando unshare -r -n , ad esempio:

$ unshare -r -n ls
a.txt  b.txt

Un comando che richiede l'accesso alla rete fallirà in modo prevedibile.

$ unshare -r -n curl unix.stackexchange.com
curl: (6) Could not resolve host: unix.stackexchange.com

Mi chiedo se sia possibile rimuovere l'accesso alla rete per il processo corrente, potenzialmente scrivendo in un file magico in /sys o qualcosa di simile.

Mi piacerebbe essere in grado di fare qualcosa come

$ /bin/sh -c 'echo 1 > /sys/unsharethis; curl unix.stackexchange.com'

Un estratto da strace -ing unshare -r -n ls mostra il unshare chiamata di sistema

open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=4759040, ...}) = 0
mmap(NULL, 4759040, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7ec6968000
close(3)                                = 0
unshare(CLONE_NEWUSER|CLONE_NEWNET)     = 0
open("/proc/self/setgroups", O_WRONLY)  = 3
write(3, "deny", 4)                     = 4

Il che mi suggerisce che annullare la condivisione dell'accesso alla rete dal processo corrente è in effetti l'unico modo per ottenere l'annullamento della condivisione (cioè non può essere passato come argomento per spawn o un suo equivalente). Suggerisce inoltre che l'annullamento della condivisione da uno script di shell non funzionerebbe a meno che la shell non sia stata specificamente estesa per esporre un wrapper attorno a unshare .

Risposta accettata:

Questo può essere fatto, più o meno, con il gdb debugger e se è possibile allegare il processo in esecuzione (i programmi che alterano il loro stato di dumping, o sono setgid ecc. non possono essere collegati, a meno che non siano root).

Alcuni file opzionali possono aiutare a usare gdb come i simboli di debug per libc6, e alcuni file include relativi a Linux per ottenere i valori effettivi di alcuni simboli in un secondo momento (ad esempio su Debian:(possibilmente) libc6-dbg , libc6-dev e linux-libc-dev pacchetti), ma in realtà una volta preparata la “ricetta”, probabilmente non servono più.

Innanzitutto cosa più di unshare() unshare -r sta facendo? Senza questo, il nuovo utente rimane su nobody e non può nemmeno scrivere come utente iniziale:

$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ strace unshare -r -n /bin/sleep 1 2>&1 |sed -n '/^unshare/,/^execve/p'
unshare(CLONE_NEWNET|CLONE_NEWUSER)     = 0
open("/proc/self/setgroups", O_WRONLY)  = 3
write(3, "deny", 4)                     = 4
close(3)                                = 0
open("/proc/self/uid_map", O_WRONLY)    = 3
write(3, "0 1000 1", 8)                 = 8
close(3)                                = 0
open("/proc/self/gid_map", O_WRONLY)    = 3
write(3, "0 1000 1", 8)                 = 8
close(3)                                = 0
execve("/bin/sleep", ["/bin/sleep", "1"], [/* 18 vars */]) = 0

Verrà utilizzato in seguito.

$ ip -4 -br a
lo               UNKNOWN        127.0.0.1/8 
[email protected]        UP             10.0.3.66/24 
$ ping -c1 10.0.3.1
PING 10.0.3.1 (10.0.3.1) 56(84) bytes of data.
64 bytes from 10.0.3.1: icmp_seq=1 ttl=64 time=0.167 ms

--- 10.0.3.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms

rtt min/avg/max/mdev = 0.167/0.167/0.167/0.000 ms
$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ echo $$
338
$

Su un altro terminale:

$ gdb --pid=338
Reading symbols from /bin/bash...(no debugging symbols found)...done.
Reading symbols from /lib/x86_64-linux-gnu/libtinfo.so.5...(no debugging symbols found)...done.
Reading symbols from /lib/x86_64-linux-gnu/libdl.so.2...Reading symbols from /usr/lib/debug/.build-id/b8/95f0831f623c5f23603401d4069f9f94c24761.debug...done.
done.
Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...Reading symbols from /usr/lib/debug/.build-id/aa/889e26a70f98fa8d230d088f7cc5bf43573163.debug...done.
done.

[…]

(gdb)

Ora chiamiamo la prima funzione:

(gdb) call unshare(CLONE_NEWNET|CLONE_NEWUSER)
No symbol "CLONE_NEWNET" in current context.

Ok, potrebbe esserci un metodo per farlo conoscere a gdb, ma non sono un guru:

(gdb) !
$ grep CLONE_NEW /usr/include/linux/sched.h # man 2 unshare
#define CLONE_NEWNS 0x00020000  /* New mount namespace group */
#define CLONE_NEWCGROUP     0x02000000  /* New cgroup namespace */
#define CLONE_NEWUTS        0x04000000  /* New utsname namespace */
#define CLONE_NEWIPC        0x08000000  /* New ipc namespace */
#define CLONE_NEWUSER       0x10000000  /* New user namespace */
#define CLONE_NEWPID        0x20000000  /* New pid namespace */
#define CLONE_NEWNET        0x40000000  /* New network namespace */
$ find /usr/include/ -name fcntl.h |xargs grep O_WRONLY # man 2 open
/usr/include/asm-generic/fcntl.h:#define O_WRONLY   00000001
$ exit
exit
(gdb) call unshare(0x50000000)
$1 = 0
(gdb) call open("/proc/self/setgroups", 1)
$2 = 3
(gdb) call write($2,"deny",4)
$3 = 4
(gdb) call close($2)
$4 = 0
(gdb) call open("/proc/self/uid_map", 1)
$5 = 3
(gdb) call write($5, "0 1000 1", 8)
$6 = 8
(gdb) call close($5)
$7 = 0
(gdb) call open("/proc/self/gid_map", 1)
$8 = 3
(gdb) call write($8, "0 1000 1", 8)
$9 = 8
(gdb) call close($8)
$10 = 0
(gdb) quit
A debugging session is active.

    Inferior 1 [process 338] will be detached.

Quit anyway? (y or n) y
Detaching from program: /bin/bash, process 338

Sul processo modificato, è possibile verificare eth0 interfaccia scomparsa:

$ ip -br a
lo               DOWN           127.0.0.1/8 
$ echo $$
338
$ id
uid=0(root) gid=0(root) groupes=0(root)
$ touch /
touch: setting times of '/': Permission denied
$ touch ~/test1
$ ls ~/test1
/home/user/test1
$ ping 10.0.3.1
connect: Network is unreachable

Non si torna indietro:il nuovo spazio dei nomi utente non può tornare al suo spazio dei nomi iniziale. Se il processo è in esecuzione con privilegi sufficienti (ad es. root senza capacità perse né SELinux), allora sarebbe possibile (usando solo unshare(CLONE_NEWNET) / setns(savedopenedfd) ).

Correlati:come impostare le impostazioni predefinite del desktop per i nuovi utenti??

Ovviamente è possibile scriverlo in un file e modificare qualsiasi processo in esecuzione consentito, oppure fare in modo che la shell si modifichi da un sottoprocesso gdb. Contenuto di removenetwork.gdb , qui valido solo per modificare un processo con pid:gid ==1000:1000 :

AGGIORNAMENTO:aggiunto il tipo restituito (approssimativo) per le syscall di seguito, questo dovrebbe evitare che alcune versioni di gdb si lamentino in ambienti non di sviluppo:

call (int)unshare(0x50000000)
call (int)open("/proc/self/setgroups", 1)
call (long)write($2,"deny",4)
call (int)close($2)
call (int)open("/proc/self/uid_map", 1)
call (long)write($5, "0 1000 1", 8)
call (int)close($5)
call (int)open("/proc/self/gid_map", 1)
call (long)write($8, "0 1000 1", 8)
call (int)close($8)
quit

Esempio:

$ sh -c 'id; gdb --pid=$$ < removenetwork.gdb >/dev/null 2>&1; id; curl unix.stackexchange.com'
uid=1000(user) gid=1000(user) groups=1000(user)
uid=0(root) gid=0(root) groups=0(root)
curl: (6) Could not resolve host: unix.stackexchange.com

AGGIORNAMENTO :se root non è affatto necessario, come appare per questa domanda, non è affatto necessario eseguire il mapping a root. Sostituisci semplicemente le occorrenze di write($XX, "0 1000 1", 8) con write($XX, "1000 1000 1", 11) (per il uid:gid ==1000:1000 Astuccio). I gruppi supplementari sono ancora inevitabilmente persi, ma l'uid/gid non cambia (è mappato su se stesso).


Linux
  1. 8 comandi Linux per una gestione efficace dei processi

  2. 10 comandi Linux per la diagnostica di rete

  3. Come installare vtop su Linux

  4. Linux:bloccare l'accesso alla rete di un processo?

  5. Come installare e configurare Monit su Linux per il monitoraggio dei processi

Come uccidere i processi Zombie in Linux

Come condividere la stampante in rete in Linux

Come trovare le interfacce di rete disponibili su Linux

Come KILL un processo su Linux

Come aggiungere route su Linux

Come impostare la rete esterna per i container nei container Linux (LXC)