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

213 lines
No EOL
7.4 KiB
Python

#!/usr/bin/env python3
"""
Verify MikroTik Access - Reliable Authentication Tester
Tests if credentials actually work by attempting real operations
"""
import requests
from requests.auth import HTTPBasicAuth
import socket
import time
def test_http_with_verification(host, username, password):
"""Test HTTP auth by trying to access actual protected content"""
print(f"Testing HTTP: {username}:{password}")
try:
# Try to access WebFig directly (should redirect if authenticated)
session = requests.Session()
session.auth = HTTPBasicAuth(username, password)
# First, try the main page
response1 = session.get(f"http://{host}/", timeout=5, allow_redirects=False)
print(f" Main page status: {response1.status_code}")
# Try to access a specific WebFig resource
response2 = session.get(f"http://{host}/webfig/", timeout=5, allow_redirects=True)
print(f" WebFig status: {response2.status_code}")
print(f" Response length: {len(response2.text)}")
# Check if we actually got WebFig content (not login page)
if "webfig" in response2.text.lower() and "login" not in response2.text.lower():
print(f" ✓ Successfully accessed WebFig interface")
return True
elif response2.status_code == 200 and len(response2.text) > 1000:
print(f" ? Got content but uncertain if authenticated")
print(f" First 200 chars: {response2.text[:200]}")
return False
else:
print(f" ✗ Authentication failed or no WebFig access")
return False
except Exception as e:
print(f" ✗ HTTP test failed: {e}")
return False
def test_api_with_verification(host, username, password):
"""Test API auth by attempting actual API operations"""
print(f"Testing API: {username}:{password}")
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
sock.connect((host, 8728))
def encode_length(length):
if length <= 0x7F:
return bytes([length])
elif length <= 0x3FFF:
return bytes([((length >> 8) & 0xFF) | 0x80, length & 0xFF])
else:
return bytes([0xFF]) # Error for long strings
def write_word(word):
word_bytes = word.encode('utf-8')
sock.send(encode_length(len(word_bytes)))
sock.send(word_bytes)
def write_sentence(words):
for word in words:
write_word(word)
write_word("")
def read_word():
try:
length_byte = sock.recv(1)
if not length_byte:
return ""
length = length_byte[0]
if length == 0:
return ""
if length & 0x80:
# Multi-byte length
second_byte = sock.recv(1)
if not second_byte:
return ""
length = ((length & 0x7F) << 8) + second_byte[0]
if length > 1000: # Sanity check
return ""
return sock.recv(length).decode('utf-8', 'ignore')
except:
return ""
def read_sentence():
sentence = []
while True:
word = read_word()
if word == "":
break
sentence.append(word)
return sentence
# Send login
write_sentence(["/login", f"=name={username}", f"=password={password}"])
# Read login response
response = read_sentence()
print(f" Login response: {response}")
if response and response[0] == "!done":
print(f" ✓ Login successful, testing system identity...")
# Try to get system identity to verify we're actually authenticated
write_sentence(["/system/identity/print"])
identity_response = read_sentence()
print(f" Identity response: {identity_response}")
if identity_response and any("identity" in str(item).lower() for item in identity_response):
print(f" ✓ Successfully retrieved system information")
sock.close()
return True
else:
print(f" ? Login seemed successful but couldn't get system info")
sock.close()
return False
else:
print(f" ✗ Login failed")
sock.close()
return False
except Exception as e:
print(f" ✗ API test failed: {e}")
return False
def test_ssh_with_verification(host, username, password):
"""Test SSH auth with verification"""
print(f"Testing SSH: {username}:{password}")
try:
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(
host,
port=22,
username=username,
password=password,
timeout=5,
allow_agent=False,
look_for_keys=False,
)
# Try to execute a command to verify we're authenticated
stdin, stdout, stderr = client.exec_command("/system identity print")
output = stdout.read().decode()
print(f" Command output: {output[:100]}...")
if output and len(output) > 10:
print(f" ✓ SSH authentication and command execution successful")
client.close()
return True
else:
print(f" ? SSH connected but no command output")
client.close()
return False
except Exception as e:
print(f" ✗ SSH test failed: {e}")
return False
def main():
host = "10.250.2.2"
username = "admin"
# Test some of the passwords that showed "success" earlier
test_passwords = [
"", # Empty
"0000-0000", # Showed success
"0000-2018", # Showed success
"admin", # Common default
"d069-0bff", # Algorithm result
]
print(f"Verifying MikroTik access to {host}")
print("=" * 60)
for password in test_passwords:
pwd_display = f'"{password}"' if password else "(empty)"
print(f"\nTesting password: {pwd_display}")
print("-" * 40)
# Test all methods with verification
http_result = test_http_with_verification(host, username, password)
api_result = test_api_with_verification(host, username, password)
ssh_result = test_ssh_with_verification(host, username, password)
if any([http_result, api_result, ssh_result]):
print(f"\n*** VERIFIED SUCCESS: {pwd_display} ***")
print(f"HTTP: {'' if http_result else ''}")
print(f"API: {'' if api_result else ''}")
print(f"SSH: {'' if ssh_result else ''}")
return password
else:
print(f"All methods failed for {pwd_display}")
print(f"\nNo working passwords found among tested candidates.")
print("The earlier 'successes' were likely false positives.")
if __name__ == "__main__":
main()