network/test_mikrotik_api_auth.py
2026-05-08 17:47:42 -05:00

184 lines
No EOL
6.1 KiB
Python

#!/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()