1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
local bin = require "bin"
local bit = require "bit"
local nmap = require "nmap"
local rpc = require "rpc"
local shortport = require "shortport"
local stdnse = require "stdnse"
local table = require "table"
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
--@xmloutput
-- <elem>VULNERABLE: Wind River Systems VxWorks debug service enabled. See http://www.kb.cert.org/vuls/id/362332</elem>
-- <elem key="Agent version">2.0</elem>
-- <elem key="VxWorks version">5.4</elem>
-- <elem key="Board Support Package">Alcatel CMM MPC8245/100</elem>
-- <elem key="Boot line">lanswitchCmm:</elem>
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", "vuln"}
-- WDB protocol information
-- http://www.vxdev.com/docs/vx55man/tornado-api/wdbpcl/wdb.html
-- http://www.verysource.com/code/2817990_1/wdb.h.html
-- Metasploit scanner module
-- http://www.metasploit.com/redmine/projects/framework/repository/entry/lib/msf/core/exploit/wdbrpc.rb
portrule = shortport.version_port_or_service(17185, "wdbrpc", {"udp"} )
rpc.RPC_version["wdb"] = { min=1, max=1 }
local WDB_Procedure = {
["WDB_TARGET_PING"] = 0,
["WDB_TARGET_CONNECT"] = 1,
["WDB_TARGET_DISCONNECT"] = 2,
["WDB_TARGET_MODE_SET"] = 3,
["WDB_TARGET_MODE_GET"] = 4,
}
local function checksum(data)
local sum = 0
local p = 0
local _
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 stripnull(str)
local e = -1
while str:byte(e) == 0 do
e = e - 1
end
return str:sub(1,e)
end
local function decode_reply(data, pos)
local wdberr, len
local done = data:len()
local info = {}
local _
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 = stripnull(info["agent_ver"])
if (port.version.ostype ~= nil) then
port.version.ostype = "VxWorks " .. stripnull(info["rt_vers"])
end
nmap.set_port_version(host, port)
-- Clean up (some agents will continue to send data until we disconnect)
packet = request(comm, WDB_Procedure["WDB_TARGET_DISCONNECT"], bin.pack(">I3", 0x00000002, 0x00000000, 0x00000000))
if (not(comm:SendPacket(packet))) then
return stdnse.format_output(false, "Failed to send request")
end
local o = stdnse.output_table()
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
o["Agent version"] = stripnull(info.agent_ver)
end
--table.insert(o, "Agent MTU: " .. info.agent_mtu)
if (info.rt_vers) then
o["VxWorks version"] = stripnull(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
o["Board Support Package"] = stripnull(info.rt_bsp_name)
end
if (info.rt_bootline) then
o["Boot line"] = stripnull(info.rt_bootline)
end
return o
end
|