Skip to content

Commit 3619623

Browse files
committed
Merge pull request #1 from jvazquez-r7/sap_router_scan_clean
Clean sap_router_portscanner
2 parents d318c1c + 6fbb782 commit 3619623

File tree

1 file changed

+78
-50
lines changed

1 file changed

+78
-50
lines changed
Lines changed: 78 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
##
2+
# This file is part of the Metasploit Framework and may be subject to
3+
# redistribution and commercial restrictions. Please see the Metasploit
4+
# web site for more information on licensing and terms of use.
5+
# http://metasploit.com/
6+
##
7+
18
require 'msf/core'
29

310
class Metasploit3 < Msf::Auxiliary
@@ -6,35 +13,38 @@ class Metasploit3 < Msf::Auxiliary
613
include Msf::Auxiliary::Report
714
include Msf::Auxiliary::Scanner
815

9-
1016
def initialize
1117
super(
12-
'Name' => 'SAPRouter Port Scanner',
13-
'Description' => %q{
14-
This module allows for mapping ACLs and identify open/closed ports
15-
accessible on hosts through a saprouter},
16-
'Author' => ['Bruno Morisson <bm[at]integrity.pt>', # metasploit module
17-
'nmonkee'], # saprouter packet building code from sapcat.rb
18-
'References' =>
19-
[
20-
# General
21-
['URL', 'http://help.sap.com/saphelp_nw70/helpdata/EN/4f/992dfe446d11d189700000e8322d00/frameset.htm'],
22-
['URL', 'http://help.sap.com/saphelp_dimp50/helpdata/En/f8/bb960899d743378ccb8372215bb767/content.htm'],
23-
['URL', 'http://labs.mwrinfosecurity.com/blog/2012/09/13/sap-smashing-internet-windows/'],
24-
['URL', 'http://scn.sap.com/docs/DOC-17124'] # SAP default ports
25-
],
26-
'License' => MSF_LICENSE
18+
'Name' => 'SAPRouter Port Scanner',
19+
'Description' => %q{
20+
This module allows for mapping ACLs and identify open/closed ports accessible
21+
on hosts through a saprouter.
22+
},
23+
'Author' => [
24+
'Bruno Morisson <bm[at]integrity.pt>', # metasploit module
25+
'nmonkee' # saprouter packet building code from sapcat.rb
26+
],
27+
'References' =>
28+
[
29+
# General
30+
['URL', 'http://help.sap.com/saphelp_nw70/helpdata/EN/4f/992dfe446d11d189700000e8322d00/frameset.htm'],
31+
['URL', 'http://help.sap.com/saphelp_dimp50/helpdata/En/f8/bb960899d743378ccb8372215bb767/content.htm'],
32+
['URL', 'http://labs.mwrinfosecurity.com/blog/2012/09/13/sap-smashing-internet-windows/'],
33+
['URL', 'http://conference.hitb.org/hitbsecconf2010ams/materials/D2T2%20-%20Mariano%20Nunez%20Di%20Croce%20-%20SAProuter%20.pdf'],
34+
['URL', 'http://scn.sap.com/docs/DOC-17124'] # SAP default ports
35+
],
36+
'License' => MSF_LICENSE
2737
)
2838

2939
register_options(
30-
[
31-
OptAddress.new('SAPROUTER_HOST', [true, 'SAPRouter address', '']),
32-
OptPort.new('SAPROUTER_PORT', [true, 'SAPRouter TCP port', '3299']),
33-
OptEnum.new('MODE', [true, 'Connection Mode: 0 for NI_MSG_IO (SAP), 1 for NI_RAW_IO (TCP), 2 for NI_ROUT_IO (ROUTER) ', 0, [0, 1, 2]]),
34-
OptString.new('PORTS', [true, 'Ports to scan (e.g. 22-25,80,110-900)', '3200-3299']),
35-
OptInt.new('TIMEOUT', [true, 'The socket connect timeout in milliseconds', 1000]),
36-
OptInt.new('CONCURRENCY', [true, 'The number of concurrent ports to check per host', 10]),
37-
], self.class)
40+
[
41+
OptAddress.new('SAPROUTER_HOST', [true, 'SAPRouter address', '']),
42+
OptPort.new('SAPROUTER_PORT', [true, 'SAPRouter TCP port', '3299']),
43+
OptEnum.new('MODE', [true, 'Connection Mode: 0 for NI_MSG_IO (SAP), 1 for NI_RAW_IO (TCP), 2 for NI_ROUT_IO (ROUTER) ', 0, [0, 1, 2]]),
44+
OptString.new('PORTS', [true, 'Ports to scan (e.g. 22-25,80,110-900)', '3200-3299']),
45+
OptInt.new('TIMEOUT', [true, 'The socket connect timeout in milliseconds', 1000]),
46+
OptInt.new('CONCURRENCY', [true, 'The number of concurrent ports to check per host', 10]),
47+
], self.class)
3848

3949
deregister_options('RPORT')
4050

@@ -43,19 +53,25 @@ def initialize
4353
def build_ni_packet(routes)
4454

4555
mode = datastore['MODE'].to_i
46-
4756
route_data=''
48-
49-
ni_packet = 'NI_ROUTE' + [0, 2, 39, 2, mode, 0, 0, 1].pack('c*') # create ni_packet header
57+
ni_packet = [
58+
'NI_ROUTE',
59+
0,
60+
2,
61+
39,
62+
2,
63+
mode,
64+
0,
65+
0,
66+
1
67+
].pack("A8c8")
5068

5169
first = false
5270

5371
routes.each do |host, port| # create routes
54-
55-
route_item = host.to_s.dup << [0].pack('c*') << port.to_s.dup << [0].pack('c*') << [0].pack('c*')
56-
72+
route_item = [host, 0, port.to_s, 0, 0].pack("A*CA*cc")
5773
if !first
58-
route_data = route_data << [route_item.length].pack('N') << route_item
74+
route_data = [route_data, route_item.length, route_item].pack("A*NA*")
5975
first = true
6076
else
6177
route_data = route_data << route_item
@@ -68,32 +84,33 @@ def build_ni_packet(routes)
6884

6985
def parse_response_packet(response, ip, port)
7086

71-
vprint_error("#{ip}:#{port} - response packet: #{response}")
87+
#vprint_error("#{ip}:#{port} - response packet: #{response}")
7288

7389
case response
7490
when /NI_RTERR/
7591
case response
7692
when /timed out/
77-
print_error ("#{ip}:#{port} - connection timed out")
93+
vprint_error ("#{ip}:#{port} - connection timed out")
7894
when /refused/
79-
print_error("#{ip}:#{port} - TCP closed")
80-
report_service(:host => ip, :port => port, :state => 'closed')
95+
vprint_error("#{ip}:#{port} - TCP closed")
96+
return [ip, port, "closed"]
8197
when /denied/
82-
print_error("#{ip}:#{port} - blocked by ACL")
98+
vprint_error("#{ip}:#{port} - blocked by ACL")
8399
when /invalid/
84-
print_error("#{ip}:#{port} - invalid route")
100+
vprint_error("#{ip}:#{port} - invalid route")
85101
when /reacheable/
86-
print_error("#{ip}:#{port} - unreachable")
102+
vprint_error("#{ip}:#{port} - unreachable")
87103
else
88-
print_error("#{ip}:#{port} - unknown error message")
104+
vprint_error("#{ip}:#{port} - unknown error message")
89105
end
90106
when /NI_PONG/
91107
print_good("#{ip}:#{port} - TCP OPEN")
92-
report_service(:host => ip, :port => port, :state => 'open')
108+
return [ip, port, "open"]
93109
else
94-
print_error("#{ip}:#{port} - unknown response")
110+
vprint_error("#{ip}:#{port} - unknown response")
95111
end
96112

113+
return nil
97114
end
98115

99116
def run_host(ip)
@@ -111,8 +128,10 @@ def run_host(ip)
111128

112129
print_status("Scanning #{ip}")
113130
thread = []
114-
ports.each do |port|
131+
r = []
115132

133+
begin
134+
ports.each do |port|
116135

117136
if thread.length >= datastore['CONCURRENCY']
118137
# Assume the first thread will be among the earliest to finish
@@ -121,6 +140,10 @@ def run_host(ip)
121140
thread << framework.threads.spawn("Module(#{self.refname})-#{ip}:#{port}", false) do
122141

123142
begin
143+
# create ni_packet to send to saprouter
144+
routes = {sap_host => sap_port, ip => port}
145+
ni_packet = build_ni_packet(routes)
146+
124147
s = connect(false,
125148
{
126149
'RPORT' => sap_port,
@@ -129,14 +152,13 @@ def run_host(ip)
129152
}
130153
)
131154

132-
# create ni_packet to send to saprouter
133-
routes = {sap_host => sap_port, ip => port}
134-
ni_packet = build_ni_packet(routes)
135-
136155
s.write(ni_packet, ni_packet.length)
137156
response = s.get()
138157

139-
parse_response_packet(response, ip, port)
158+
res = parse_response_packet(response, ip, port)
159+
if res
160+
r << res
161+
end
140162

141163
rescue ::Rex::ConnectionRefused
142164
print_error("#{ip}:#{port} - Unable to connect to SAPRouter #{sap_host}:#{sap_port} - Connection Refused")
@@ -152,9 +174,15 @@ def run_host(ip)
152174
end
153175
thread.each { |x| x.join }
154176

155-
rescue ::Timeout::Error
156-
ensure
157-
thread.each { |x| x.kill rescue nil }
177+
rescue ::Timeout::Error
178+
ensure
179+
thread.each { |x| x.kill rescue nil }
180+
end
181+
182+
r.each do |res|
183+
report_service(:host => res[0], :port => res[1], :state => res[2])
184+
end
185+
158186
end
159187

160188
end

0 commit comments

Comments
 (0)