Advisory

Yorick Koster, June 2013

Cisco RV Series multiple vulnerabilities

Abstract

Multiple vulnerabilities have been found in Cisco RV Series devices that allows an attacker to overwrite/create arbitrary files, execute arbitrary commands, and execute Cross-Site Request Forgery attacks.

Affected versions

These following Cisco RV Series devices are affected by these issues:

- Cisco RV120W Wireless-N VPN Firewall running firmware prior to 1.0.5.9
- Cisco RV180 VPN Router and Cisco RV180W Wireless-N Multifunction VPN Router running firmware versions prior to 1.0.4.14
- Cisco RV220W Wireless Network Security Firewall running any currently available release

See also

- CVE-2014-2177
- CVE-2014-2178
- CVE-2014-2179
- cisco-sa-20141105-rv: Multiple Vulnerabilities in Cisco Small Business RV Series Routers

Fix

Please consult Cisco advisory cisco-sa-20141105-rv for fix information.

Introduction

Multiple vulnerabilities have been found in Cisco RV Series devices that allows an attacker to overwrite/create arbitrary files, execute arbitrary commands, and execute CSRF attacks.

Insecure handling of file uploads

The admin pages of the affected devices are created using LUA scripts. It has been discovered that the affected devices use a cookie named TeamF1Login in an insecure manner. The cookie value is used as a path name for storing the uploaded file. No input validation is done on the cookie value. Consequently, an attacker can set this to any value and thus create files in arbitrary locations.

It should be noted that:

- the web server (thttpd) runs as root;
- existing files will be overwritten;
- this issue can be exploited by unauthenticated users.

/pfrm2.0/share/lua/5.1/cgilua/post.lua: local function fileupload (filename)
   -- create a temporary file for uploading the file field
   --local file, err = tmpfile()
   
   -- Adarsh 7/16/07
   local filename = mycookieget("TeamF1Login")
   local file, err = myopen("/tmp/" .. filename, "wb")

   
   if file == nil then
      discardinput(bytesleft)
      error("Cannot create a temporary file.\n"..err)
   end
   local bytesread = 0
   local boundaryline = "\r\n"..boundary
   local out = function (str)
      local sl = strlen (str)
      if bytesread + sl > maxfilesize then
         discardinput (bytesleft)
         error (format ("Maximum file size (%d kbytes) exceeded while uploading `%s'", maxfilesize / 1024, filename))
      end
      file:write (str)
      bytesread = bytesread + sl
   end
   if readuntil (boundaryline, out) then
      file:seek ("set", 0)
      return file, bytesread
   else
      error (format ("Error processing multipart/form-data.\nUnexpected end of input while uploading %s", filename))
   end
end

Command injection in diagnostics tools

The admin pages contain a couple of network diagnostic tools, such as the ability to perform an ICMP ping. Entering special characters in the different forms renders the following error message:

Invalid IP Address/Domain name:Domain/WAN (Internet) must contain only alphanumeric letters, '.' and '-'.

It appears that this check is not enforced server side. Sending the request directly can be used to submit & execute arbitrary commands, which will be executed with root privileges. A valid session is required to access the diagnostics tools.

/pfrm2.0/var/www/diagnostics.htm: if (ButtonType and ButtonType == "ping") then
   local inputTable = web.cgiToLuaTable(cgi)

   local throughVpn = false
   local ipToPing = string.sub(inputTable["ping.ip"], string.find(inputTable["ping.ip"], '[%a%d\.:]+'))
   local pingfile = db.getAttribute("environment", "name", "PING_FILE_NAME", "value")
   local pingprog = ""
   if (inputTable["ping.throughVpn"] ~= nil and inputTable["ping.throughVpn"] == "1") then
      throughVpn = true
   end

   -- ping
[...]
      else
         pingprog = db.getAttribute("environment", "name", "PING_PROGRAM", "value")
         options1 = " 2>&1 "
         local cmd_ping = pingprog .. " " .. ipToPing
         globalCmdOutput = util.runShellCmd(cmd_ping, pingfile, "/tmp/pingErr.txt", options1)
         STATUS_CLASS = INFO_CLASS
         statusMessage = (trStrings["11307"] or 'i18nHTMLMissing') .. " " .. ipToPing
      end
   end
   web.goToPage(NextPage, true, true)

GET requests can be used to bypass Referer check

Whenever a POST request is send to the application, a check is performed on the Referer header. If the Referer is empty or contains an external page, an error message is displayed (401 Unauthorized). It appears that this check is not performed for GET requests. GET & POST parameters are interchangeable and since the Referer check is the only measure against Cross-Site Request Forgery (CSRF) attacks, it is possible to execute CSRF attacks using specially crafted URLs. For example the following URL adds an admin account to the user database:

https://192.168.2.1/platform.cgi?thispage=diagnosticsAP.htm&button.ping.diagDisplayAP=Ping&ping.ip=-h+
2%3e%2fdev%2fnull%3b%2fpfrm2.0%2fbin%2fsqlite3+%2ftmp%2fsystem.db+%22INSERT+INTO+%5c%22users%5c%22+VALUES%28%5c%22
admin%5c%22%2c%5c%22admin%5c%22%2c0%2c%5c%22admin%5c%22%2c10%29%3b%22

Latest News & Research

Work with us →