description = [[
Detects vulnerabilities and gathers information (such as version
numbers and hardware support) from VxWorks Wind DeBug agents.
Wind DeBug is a SunRPC-type service that is enabled by default on many devices
that use the popular VxWorks real-time embedded operating system. H.D. Moore
of Metasploit has identified several security vulnerabilities and design flaws
with the service, including weakly-hashed passwords and raw memory dumping.
See also:
http://www.kb.cert.org/vuls/id/362332
]]
---
-- @usage
-- nmap -sU -p 17185 --script wdb-version <target>
-- @output
-- 17185/udp open wdb Wind DeBug Agent 2.0
-- | wdb-version:
-- | VULNERABLE: Wind River Systems VxWorks debug service enabled. See http://www.kb.cert.org/vuls/id/362332
-- | Agent version: 2.0
-- | VxWorks version: VxWorks5.4.2
-- | Board Support Package: PCD ARM940T REV 1
-- | Boot line: host:vxWorks.z
author = "Daniel Miller"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
-- may also be "safe", but need testing to determine
categories = {"default", "version", "discovery"}
require 'shortport'
require 'rpc'
require 'stdnse'
-- WDB protocol information
-- http://www-kryo.desy.de/documents/vxWorks/V5.5/tornado-api/wdbpcl/wdb.html
-- Metasploit scanner module
-- http://www.metasploit.com/redmine/projects/framework/repository/entry/lib/msf/core/exploit/wdbrpc.rb
portrule = shortport.port_or_service(17185, "wdbrpc", {"udp"} )
rpc.RPC_version["wdb"] = { min=1, max=1 }
local WDB_Procedure = {
["WDB_TARGET_CONNECT"] = 1,
}
local function checksum(data)
local sum = 0
local p = 0
p, _ = bin.unpack(">I", data)
while p < data:len() do
local c
p, c = bin.unpack(">S", data, p)
sum = sum + c
end
sum = bit.band(sum, 0xffff) + bit.rshift(sum, 16)
return bit.bnot( sum )
end
local seqnum = 0
local function seqno()
seqnum = seqnum + 1
return seqnum
end
local function request(comm, procedure, data)
local packet = comm:EncodePacket( nil, procedure, {type = rpc.Portmap.AuthType.NULL}, nil )
local wdbwrapper = bin.pack( ">I2", data:len() + packet:len() + 8, seqno() )
local sum = checksum(packet..bin.pack(">I", 0x00000000)..wdbwrapper..data)
return packet .. bin.pack(">S2", 0xffff, sum) .. wdbwrapper .. data
end
local function decode_reply(data, pos)
local wdberr, len
local done = data:len()
local info = {}
pos, _ = rpc.Util.unmarshall_uint32(data, pos)
pos, _ = rpc.Util.unmarshall_uint32(data, pos)
pos, wdberr = rpc.Util.unmarshall_uint32(data, pos)
info["error"] = bit.band(wdberr, 0xc0000000)
if (info["error"] ~= 0x00000000 ) then
stdnse.print_debug(1,"Error from decode_reply: %x", info["error"])
return nil, info
end
pos, len = rpc.Util.unmarshall_uint32(data, pos)
if (len ~= 0) then
pos, info["agent_ver"] = rpc.Util.unmarshall_vopaque(len, data, pos)
end
pos, info["agent_mtu"] = rpc.Util.unmarshall_uint32(data, pos)
pos, info["agent_mod"] = rpc.Util.unmarshall_uint32(data, pos)
pos, info["rt_type"] = rpc.Util.unmarshall_uint32(data, pos)
pos, len = rpc.Util.unmarshall_uint32(data, pos)
if (pos == done) then return pos, info end
if (len ~= 0) then
pos, info["rt_vers"] = rpc.Util.unmarshall_vopaque(len, data, pos)
end
pos, info["rt_cpu_type"] = rpc.Util.unmarshall_uint32(data, pos)
pos, len = rpc.Util.unmarshall_uint32(data, pos)
info["rt_has_fpp"] = ( len ~= 0 )
pos, len = rpc.Util.unmarshall_uint32(data, pos)
info["rt_has_wp"] = ( len ~= 0 )
pos, info["rt_page_size"] = rpc.Util.unmarshall_uint32(data, pos)
pos, info["rt_endian"] = rpc.Util.unmarshall_uint32(data, pos)
pos, len = rpc.Util.unmarshall_uint32(data, pos)
if (len ~= 0) then
pos, info["rt_bsp_name"] = rpc.Util.unmarshall_vopaque(len, data, pos)
end
pos, len = rpc.Util.unmarshall_uint32(data, pos)
if (len ~= 0) then
pos, info["rt_bootline"] = rpc.Util.unmarshall_vopaque(len, data, pos)
end
if (pos == done) then return pos, info end
pos, info["rt_membase"] = rpc.Util.unmarshall_uint32(data, pos)
if (pos == done) then return pos, info end
pos, info["rt_memsize"] = rpc.Util.unmarshall_uint32(data, pos)
if (pos == done) then return pos, info end
pos, info["rt_region_count"] = rpc.Util.unmarshall_uint32(data, pos)
if (pos == done) then return pos, info end
pos, len = rpc.Util.unmarshall_uint32(data, pos)
if (len ~= 0) then
info["rt_regions"] = {}
for i = 1, len do
pos, info["rt_regions"][i] = rpc.Util.unmarshall_uint32(data, pos)
end
end
if (pos == done) then return pos, info end
pos, len = rpc.Util.unmarshall_uint32(data, pos)
if (len == nil) then return pos, info end
if (len ~= 0) then
pos, info["rt_hostpool_base"] = rpc.Util.unmarshall_vopaque(len, data, pos)
end
if (pos == done) then return pos, info end
pos, len = rpc.Util.unmarshall_uint32(data, pos)
if (len ~= 0) then
pos, info["rt_hostpool_size"] = rpc.Util.unmarshall_vopaque(len, data, pos)
end
return pos, info
end
action = function(host, port)
local comm = rpc.Comm:new("wdb", 1)
local status, err, data, pos, header
local info = {}
status, err = comm:Connect(host, port)
if (not(status)) then
return stdnse.format_output(false, err)
end
comm.socket:set_timeout(3000)
local packet = request(comm, WDB_Procedure["WDB_TARGET_CONNECT"], bin.pack(">I3", 0x00000002, 0x00000000, 0x00000000))
if (not(comm:SendPacket(packet))) then
return stdnse.format_output(false, "Failed to send request")
end
status, data = comm:ReceivePacket()
if (not(status)) then
--return stdnse.format_output(false, "Failed to read data")
return nil
end
nmap.set_port_state(host, port, "open")
pos = 0
pos, header = comm:DecodeHeader(data, pos)
if not header then
return stdnse.format_output(false, "Failed to decode header")
end
if ( pos == data:len() ) then
return stdnse.format_output(false, "No WDB data in reply")
end
pos, info = decode_reply(data, pos)
if not pos then
return stdnse.format_output(false, "WDB error: "..info.error)
end
port.version.name = "wdb"
port.version.name_confidence = 10
port.version.product = "Wind DeBug Agent"
port.version.version = info["agent_ver"]
if (port.version.ostype ~= nil) then
port.version.ostype = "VxWorks " .. info["rt_vers"]
end
nmap.set_port_version(host, port, "hardmatched")
local o = {}
table.insert(o, "VULNERABLE: Wind River Systems VxWorks debug service enabled. See http://www.kb.cert.org/vuls/id/362332")
if (info.agent_ver) then
table.insert(o, "Agent version: " .. info.agent_ver)
end
--table.insert(o, "Agent MTU: " .. info.agent_mtu)
if (info.rt_vers) then
table.insert(o, "VxWorks version: " .. info.rt_vers)
end
-- rt_cpu_type is an enum type, but I don't have access to
-- cputypes.h, where it is defined
--table.insert(o, "CPU Type: " .. info.rt_cpu_type)
if (info.rt_bsp_name) then
table.insert(o, "Board Support Package: " .. info.rt_bsp_name)
end
if (info.rt_bootline) then
table.insert(o, "Boot line: " .. info.rt_bootline)
end
return stdnse.format_output(true, o)
end
Copyright 2K16 - 2K18 Indonesian Hacker Rulez