Overview - All GL-MV1000 devices running firmware <= 3.215 are vulnerable to an authenticated arbitrary file write, where an empty file can be created almost anywhere on the filesystem, as long as the filename and path is <= 6 characters long (the working directory is /www). This is due to a blind command injection vulnerability with a short character limit and filter applied. Example request below (note, you will be disconnected temporarily due to invalid MAC address):
1 2 3 4 5 6 7 8
POST /api/router/mac/clone HTTP/1.1 Host: 192.168.8.1 Authorization: 80dafe40822e4a59b6daabd659617963 Content-Type: application/x-www-form-urlencoded Connection: close Content-Length: 24
newmac=2:a:a:a:a:>/tmp/a
Description
The API endpoint /api/router/mac/clone takes a new MAC address in the newmac variable, does some (insufficient) checks on it to see if it’s valid, and then pipes it into a system command. The corresponding API function will check to ensure that the string is in the form ?:?:?:?:?:? (5 semicolons), where the first ? is an even number, and the exact length is 17 characters. While the intended format is 00:00:00:00:00:00, the string 2:a:a:a:a:>/tmp/a is also valid.
The system command being run is iw dev %s station dump | grep %s, with the newmac value in the second %s. Plugging in our malicious value gives us the command iw dev ? station dump | grep 2:a:a:a:a:>/tmp/a, which will pipe no results into the file /tmp/a (which it creates).
Since firmware 3.215, all string parameters are checked to determine if shell injection characters (like ; or | are being used), and any API requests with those special characters are immediately blocked. These characters include ;, |, &, (, ), $, and the backtick char. However, the > and < signs are not, hence allowing us this behavior. If this filter was not in place, then this vulnerability would be command injection, as the payload 2:a:a:a:a:;pwd would be valid, and the pwd command could be executed.
Note that this can also be used to overwrite existing files. For example, the payload 2:a:a:a:a:>api would overwrite the /www/api binary, making the web GUI completely unusable.
Steps to reproduce - run the Proof of Concept below using python3 exploit.py <domain/IP> <authtoken>, such as python3 exploit.py 192.168.8.1 80dafe40822e4a59b6daabd659617963
Fix
This was fixed in 3.216 by filtering out all > characters.