Land #9256, Add aux module to discover WSDD enabled devices

Land #9256
MS-2855/keylogger-mettle-extension
Wei Chen 2017-12-12 11:55:42 -06:00
commit 6149f51273
No known key found for this signature in database
GPG Key ID: 6E162ED2C01D9AAC
2 changed files with 176 additions and 0 deletions

View File

@ -0,0 +1,34 @@
## Vulnerable Application
[Web Services Dynamic Discovery (WS-Discovery)](https://en.wikipedia.org/wiki/WS-Discovery) is a multicast discovery protocol utilising SOAP over UDP to locate web services on a local network.
Web service enabled devices typically include printers, scanners and file shares.
The reply from some devices may include optional vendor extensions. This data may include network information such as the device MAC address and hostname, or hardware information such as the serial number, make, and model.
## Verification Steps
1. Start `msfconsole`
2. Do: `use auxiliary/scanner/wsdd/wsdd_query`
3. Do: `set RHOSTS [IP]` (Default: `239.255.255.250`)
4. Do: `run`
## Scenarios
```
msf > use auxiliary/scanner/wsdd/wsdd_query
msf auxiliary(wsdd_query) > set rhosts 239.255.255.250
rhosts => 239.255.255.250
msf auxiliary(wsdd_query) > run
[*] Sending WS-Discovery probe to 1 hosts
[+] 10.1.1.184 responded with:
Address: http://10.1.1.184:3911/
Types: wsdp:Device, wprt:PrintDeviceType, wscn:ScanDeviceType, hpd:hpDevice
Vendor Extensions: {"HardwareAddress"=>"123456789ABC", "UUID"=>"12345678-1234-1234-abcd-123456789abc", "IPv4Address"=>"10.1.1.123", "Hostname"=>"HP09AAFB", "DeviceId"=>"MFG:HP;MDL:Photosmart 5520 series;DES:CX042A;", "DeviceIdentification"=>{"MakeAndModel"=>"Photosmart 5520 series", "MakeAndModelBase"=>"Photosmart 5520 series"}, "SerialNumber"=>"123456", "Services"=>" Print9100 SclScan RESTScan CIFS DOT4 LEDM", "AdapterType"=>"WifiEmbedded"}
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
```

View File

@ -0,0 +1,142 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Auxiliary::Report
include Msf::Auxiliary::UDPScanner
def initialize
super(
'Name' => 'WS-Discovery Information Discovery',
'Description' => %q{
Discover information from Web Services Dynamic Discovery (WS-Discovery)
enabled systems.
},
'Author' => 'Brendan Coles <bcoles[at]gmail.com>',
'License' => MSF_LICENSE,
'References' =>
[
['URL', 'https://msdn.microsoft.com/en-us/library/windows/desktop/bb513684(v=vs.85).aspx'],
['URL', 'http://specs.xmlsoap.org/ws/2005/04/discovery/ws-discovery.pd'],
['URL', 'https://en.wikipedia.org/wiki/Web_Services_for_Devices'],
['URL', 'https://en.wikipedia.org/wiki/WS-Discovery'],
['URL', 'https://en.wikipedia.org/wiki/Zero-configuration_networking#WS-Discovery']
]
)
register_options [
Opt::RPORT(3702),
OptAddressRange.new('RHOSTS', [true, 'The multicast address or CIDR range of targets to query', '239.255.255.250'])
]
end
def rport
datastore['RPORT']
end
def wsdd_probe
probe = '<?xml version="1.0" encoding="utf-8" ?>'
probe << '<soap:Envelope'
probe << ' xmlns:soap="http://www.w3.org/2003/05/soap-envelope"'
probe << ' xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"'
probe << ' xmlns:wsd="http://schemas.xmlsoap.org/ws/2005/04/discovery"'
probe << ' xmlns:wsdp="http://schemas.xmlsoap.org/ws/2006/02/devprof">'
probe << '<soap:Header>'
# WS-Discovery
probe << '<wsa:To>urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To>'
# Action (Probe)
probe << "<wsa:Action>http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action>"
# Message identifier (unique GUID)
probe << "<wsa:MessageID>urn:uuid:#{SecureRandom.uuid}</wsa:MessageID>"
probe << '</soap:Header>'
probe << '<soap:Body>'
probe << '<wsd:Probe/>' # WS-Discovery type (blank)
probe << '</soap:Body>'
probe << '</env:Envelope>'
probe
end
def scanner_prescan(batch)
print_status "Sending WS-Discovery probe to #{batch.length} hosts"
@results = {}
end
def scan_host(ip)
vprint_status "#{ip}:#{rport} - Sending WS-Discovery probe"
scanner_send wsdd_probe, ip, datastore['RPORT']
end
def scanner_postscan(_batch)
if @results.empty?
print_status 'No WS-Discovery endpoints found.'
return
end
found = {}
@results.each_pair do |ip, responses|
responses.uniq.each do |res|
found[ip] ||= {}
next if found[ip][res]
response_info = parse_wsdd_response res
if response_info.nil?
print_error "#{ip} responded with malformed data"
next
end
msg = []
msg << "Address: #{response_info['Address']}"
msg << "Types: #{response_info['Types'].to_s.split(/\s+/).join(', ')}"
msg << "Vendor Extensions: #{response_info['VendorExtension']}" unless response_info['VendorExtension'].nil?
print_good "#{ip} responded with:\n#{msg.join("\n")}"
report_service(host: ip, port: rport, proto: 'udp', name: 'wsdd', info: response_info)
found[ip][res] = true
end
end
end
def parse_wsdd_response(wsdd_res)
info = {}
# Validate ProbeMatches SOAP response contains a ProbeMatch
begin
soap = ::Nokogiri::XML wsdd_res
return nil if soap.xpath('//soap:Body//wsd:ProbeMatches//wsd:ProbeMatch').empty?
rescue
return nil
end
# Convert SOAP response to Hash
begin
res = Hash.from_xml wsdd_res
rescue REXML::ParseException
return nil
end
# Use the first ProbeMatch
probe_match = res['Envelope']['Body']['ProbeMatches'].first
return nil unless probe_match[0].eql? 'ProbeMatch'
return nil if probe_match[1].nil? || probe_match[1].empty?
match = probe_match[1]
# Device Address
info['Address'] = match['XAddrs'] || ''
# Device Types
info['Types'] = match['Types'] || ''
# Optional vendor extensions
unless match['VendorExtension'].nil? || match['VendorExtension'].empty?
info['VendorExtension'] = match['VendorExtension']
end
info
end
end