#!/usr/bin/env python3 """ MikroTik API Authentication Tester Tests credentials using the MikroTik API protocol on port 8728/8729 """ import ssl import socket import sys class MikrotikAPITester: def __init__(self, host, port=8729): self.host = host self.port = port self.sock = None self.ssl_sock = None def connect(self): """Establish SSL connection to MikroTik router""" try: # Create socket and SSL context context = ssl.create_default_context() context.check_hostname = False context.verify_mode = ssl.CERT_NONE # Allow older SSL/TLS versions for compatibility context.set_ciphers('DEFAULT:@SECLEVEL=0') # Connect to router self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.settimeout(10) self.sock.connect((self.host, self.port)) self.ssl_sock = context.wrap_socket(self.sock) return True except Exception as e: print(f"Connection failed: {e}") return False def disconnect(self): """Close the connection""" if self.ssl_sock: self.ssl_sock.close() if self.sock: self.sock.close() def encode_length(self, length): """Encode length for MikroTik API protocol""" if length <= 0x7F: return bytes([length]) elif length <= 0x3FFF: return bytes([((length >> 8) & 0xFF) | 0x80, length & 0xFF]) elif length <= 0x1FFFFF: return bytes([((length >> 16) & 0xFF) | 0xC0, (length >> 8) & 0xFF, length & 0xFF]) elif length <= 0xFFFFFFF: return bytes([((length >> 24) & 0xFF) | 0xE0, (length >> 16) & 0xFF, (length >> 8) & 0xFF, length & 0xFF]) else: return bytes([0xF0, (length >> 24) & 0xFF, (length >> 16) & 0xFF, (length >> 8) & 0xFF, length & 0xFF]) def decode_length(self): """Decode length from MikroTik API protocol""" c = self.ssl_sock.recv(1)[0] if (c & 0x80) == 0x00: return c elif (c & 0xC0) == 0x80: return ((c & ~0xC0) << 8) + self.ssl_sock.recv(1)[0] elif (c & 0xE0) == 0xC0: data = self.ssl_sock.recv(2) return ((c & ~0xE0) << 16) + (data[0] << 8) + data[1] elif (c & 0xF0) == 0xE0: data = self.ssl_sock.recv(3) return ((c & ~0xF0) << 24) + (data[0] << 16) + (data[1] << 8) + data[2] elif (c & 0xF8) == 0xF0: data = self.ssl_sock.recv(4) return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3] def write_word(self, word): """Send a word to the router""" word_bytes = word.encode('utf-8') self.ssl_sock.send(self.encode_length(len(word_bytes))) self.ssl_sock.send(word_bytes) def read_word(self): """Read a word from the router""" length = self.decode_length() if length == 0: return "" return self.ssl_sock.recv(length).decode('utf-8', 'ignore') def write_sentence(self, words): """Send a sentence (list of words) to the router""" for word in words: self.write_word(word) self.write_word("") def read_sentence(self): """Read a sentence from the router""" sentence = [] while True: word = self.read_word() if word == "": break sentence.append(word) return sentence def test_login(self, username, password): """Test login credentials""" if not self.connect(): return False try: # Send login command self.write_sentence(["/login", f"=name={username}", f"=password={password}"]) # Read response response = self.read_sentence() if response and response[0] == "!done": return True else: return False except Exception as e: print(f"Login test error: {e}") return False finally: self.disconnect() def main(): host = "10.250.2.2" # Test both SSL and non-SSL ports ports = [8729, 8728] # SSL and non-SSL # Common MikroTik default passwords credentials = [ ("admin", ""), # Empty password ("admin", "admin"), # admin/admin ("admin", "password"), # admin/password ("admin", "123456"), # admin/123456 ("admin", "mikrotik"), # admin/mikrotik ("admin", "router"), # admin/router ("admin", "default"), # admin/default ] print(f"Testing MikroTik API authentication on {host}") print("=" * 60) for port in ports: port_type = "SSL" if port == 8729 else "Non-SSL" print(f"\nTesting port {port} ({port_type}):") tester = MikrotikAPITester(host, port) for username, password in credentials: pwd_display = f'"{password}"' if password else "(empty)" print(f" Testing {username}:{pwd_display}...", end=" ") if tester.test_login(username, password): print(f"✓ SUCCESS!") print(f"\n*** WORKING CREDENTIALS FOUND ***") print(f"Host: {host}") print(f"Port: {port} ({port_type})") print(f"Username: {username}") print(f"Password: {pwd_display}") return else: print("✗ Failed") print("\nNo working credentials found with common defaults.") print("\nSuggestions:") print("1. Device may have custom password") print("2. Try hardware reset if you own the device") print("3. Check if WinBox shows any additional information") if __name__ == "__main__": main()