#!/usr/bin/env python3 """ MikroTik Plain API Authentication Tester Tests credentials using plain (non-SSL) MikroTik API protocol on port 8728 """ import socket import sys class MikrotikPlainAPITester: def __init__(self, host, port=8728): self.host = host self.port = port self.sock = None def connect(self): """Establish plain connection to MikroTik router""" try: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.settimeout(10) self.sock.connect((self.host, self.port)) return True except Exception as e: print(f"Connection failed: {e}") return False def disconnect(self): """Close the connection""" 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.sock.recv(1)[0] if (c & 0x80) == 0x00: return c elif (c & 0xC0) == 0x80: return ((c & ~0xC0) << 8) + self.sock.recv(1)[0] elif (c & 0xE0) == 0xC0: data = self.sock.recv(2) return ((c & ~0xE0) << 16) + (data[0] << 8) + data[1] elif (c & 0xF0) == 0xE0: data = self.sock.recv(3) return ((c & ~0xF0) << 24) + (data[0] << 16) + (data[1] << 8) + data[2] elif (c & 0xF8) == 0xF0: data = self.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.sock.send(self.encode_length(len(word_bytes))) self.sock.send(word_bytes) def read_word(self): """Read a word from the router""" length = self.decode_length() if length == 0: return "" return self.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" port = 8728 # Plain API port # 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 Plain API authentication on {host}:{port}") print("=" * 60) tester = MikrotikPlainAPITester(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} (Plain API)") print(f"Username: {username}") print(f"Password: {pwd_display}") return else: print("✗ Failed") print("\nNo working credentials found with common defaults.") print("\nNext steps:") print("1. Device likely has custom password") print("2. Consider hardware reset if you own the device") print("3. Check device label for default credentials") print("4. Try WinBox which might show more info") if __name__ == "__main__": main()