-
Notifications
You must be signed in to change notification settings - Fork 167
/
mikrotik_jailbreak.py
executable file
·148 lines (137 loc) · 4.94 KB
/
mikrotik_jailbreak.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/python3
import mmap
import os
import sys
import telnetlib
import time
#
# MikroTik Cloud Hosted Router Universal Unpatchable Jailbreak
# By Pedro Ribeiro (@pedrib1337 | [email protected])
# From Agile Information Security
#
# - What it does:
# 1) Uses virsh to save a running MikroTik Cloud Hosted Router (CHR) virtual machine to disk
# 2) Finds a specific reference to /nova/bin/login (MikroTik's restricted shell, which is what you
# get when you login via telnet or SSH) and replaces it with our own binary which invokes /bin/sh
#
# - Tested on (should work on all 6.x and 7.x versions):
# Cloud Hosted Router 6.47.10
# Cloud Hosted Router 7.3.1
# Cloud Hosted Router 7.14beta9
#
# - Prerequisites:
# 1) MikroTik CHR running on KVM/qemu (with virsh command line access)
# 1.1) VM has to be booted, and you have had to go through initial setup
# 2) The following statically built binaries for x86:
# 2.1) "exec" (see below for source code) in /rw/disk/exec
# 2.2) "busybox" in /rw/disk/busybox, with your favourite symlinks (ls, id, etc)
#
# - Before running this script, go through setup in the VM. Then shut it down and upload the static binaries:
# 1) gcc -m32 -o exec -static exec.c
# 2) sudo guestmount -a chr-6.47.10.img -m /dev/sda1 /mnt/misc/
# 2.1) NOTE: on 7.x versions, use /dev/sda2 instead
# 3) cp exec /mnt/misc/rw/disk/exec
# 4) chmod +x /mnt/misc/rw/disk/exec && sudo umount /mnt/misc
# 5) Repeat the steps above for busybox
# 6) Create symlinks for busybox:
# 6.1) cd /mnt/misc/rw/disk
# 6.2) ln -s busybox id
# 6.3) ln -s busybox uname
# (... more symlinks as desired ...)
# 7) sudo umount /mnt/misc
#
# - A few notes:
# Step 4) in the instructions above (making it executable) is the reason the upload cannot be done with the Web UI.
# Web UI uploads do not make the file executable...
# Since we are patching /nova/bin/login in memory, the new executable name cannot have more than 14 characters.
# It can have less, but has to be padded to 14 chars to work.
#
# THIS IS NOT A PERMANENT ROOT JAILBREAK! You have to run it every time you reboot your VM.
#
# - "exec" file:
# #include <unistd.h>
# int main() {
# char* argv[] = { "sh", 0 };
# execve("/rw/disk/busybox", argv, 0);
# }
#
# - Typical run:
# (... Boot the VM first ...)
# mikrotik > ./mikrotik_jailbreak.py MikroTik_CHR 10.9.8.12 PASSWORD
# [*] Logging in 10.9.8.12 via telnet to prep patch
# [*] Saving VM
#
# Domain 'MikroTik_CHR' saved to mikrotik.save
#
# [*] Running sudo to chmod 777 memory file so we can patch it
# [+] Found patch target at location 0x3063847
# [+] Patch successful!
# [*] Restoring VM
# Domain restored from mikrotik.save
#
# [+] Finished, enjoy Shelly!
# [!] Don't forget to set the PATH variable in the shell: `export PATH=$PATH:/rw/disk`
#
# Trying 10.9.8.12...
# Connected to 10.9.8.12.
# Escape character is '^]'.
# / # export PATH=$PATH:/rw/disk/
# / # id
# uid=0 gid=0
# / # uname -a
# Linux MikroTik 5.6.3-64 #1 SMP Thu Feb 1 09:18:34 UTC 2024 x86_64 GNU/Linux
# / #
#
#
# Enjoy your shell!
SAVEFILE = "mikrotik.save"
def telnet_prep(host, admin_pass):
tn = telnetlib.Telnet(host)
tn.read_until(b"Login: ")
tn.write("admin".encode('ascii') + b"\n")
tn.read_until(b"Password: ")
if admin_pass != '':
tn.write(admin_pass.encode('ascii') + b"\n")
else:
tn.write(b"\n")
time.sleep(1)
tn.write("quit".encode('ascii') + b"\n")
def patch_mem():
with open(SAVEFILE, 'r+b') as file, \
mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_WRITE) as mm:
loc = mm.find(b"(/nova/bin/login")
if loc != -1:
print("[+] Found patch target at location %s" % (hex(loc)))
mm.seek(loc)
mm.write(b"(/rw/disk/exec\x00\x00")
print("[+] Patch successful!")
else:
print("[-] Patch failed, couldn't find (/nova/bin/login")
print("MikroTik Cloud Hosted Router Universal Unpatchable Jailbreak")
print(" By Pedro Ribeiro (@pedrib1337 | [email protected]) from Agile Information Security")
print("")
print("Usage: ./mikrotik_jailbreak.py <VIRSH_DOMAIN> <HOST> <ADMIN_PASS>")
print(" Check script code for information on prerequisites")
print("")
if len(sys.argv) < 4:
sys.exit()
else:
domain = sys.argv[1]
host = sys.argv[2]
admin_pass = sys.argv[3]
print("[*] Logging in %s via telnet to prep patch" % (host))
telnet_prep(host, admin_pass)
print("[*] Saving VM")
os.system("virsh save --domain %s %s" % (domain, SAVEFILE))
time.sleep(1)
print("[*] Running sudo to chmod 777 memory file so we can patch it")
os.system("sudo chmod 777 %s" % (SAVEFILE))
patch_mem()
print("[*] Restoring VM")
os.system("virsh restore --file %s" % (SAVEFILE))
time.sleep(1)
os.unlink(SAVEFILE)
time.sleep(5)
print("[+] Finished, enjoy Shelly!")
print("[!] Don't forget to set the PATH variable in the shell: `export PATH=$PATH:/rw/disk`\n")
os.system("telnet %s" % (host))