Skip to content

Commit 612eabd

Browse files
committed
added sap_router_portscanner module
1 parent f76a50a commit 612eabd

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
require 'msf/core'
2+
3+
class Metasploit3 < Msf::Auxiliary
4+
5+
include Msf::Exploit::Remote::Tcp
6+
include Msf::Auxiliary::Report
7+
include Msf::Auxiliary::Scanner
8+
9+
10+
def initialize
11+
super(
12+
'Name' => 'SAPRouter Port Scanner',
13+
'Description' => 'This module allows for mapping ACLs and identify open/closed ports accessible on hosts through a saprouter',
14+
'Author' => ['Bruno Morisson <bm[at]integrity.pt>', # metasploit module
15+
'nmonkee'], # saprouter packet building code from sapcat.rb
16+
'References' =>
17+
[
18+
# General
19+
['URL', 'http://help.sap.com/saphelp_nw70/helpdata/EN/4f/992dfe446d11d189700000e8322d00/frameset.htm'],
20+
['URL', 'http://help.sap.com/saphelp_dimp50/helpdata/En/f8/bb960899d743378ccb8372215bb767/content.htm'],
21+
['URL', 'http://labs.mwrinfosecurity.com/blog/2012/09/13/sap-smashing-internet-windows/'],
22+
['URL', 'http://scn.sap.com/docs/DOC-17124'] # SAP default ports
23+
],
24+
'License' => MSF_LICENSE
25+
)
26+
27+
register_options(
28+
[
29+
OptAddress.new('SAPROUTER_HOST', [true, 'SAPRouter address', '']),
30+
OptPort.new('SAPROUTER_PORT', [true, 'SAPRouter TCP port', '3299']),
31+
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]]),
32+
OptString.new('PORTS', [true, 'Ports to scan (e.g. 22-25,80,110-900)', '3200-3299']),
33+
OptInt.new('TIMEOUT', [true, 'The socket connect timeout in milliseconds', 1000]),
34+
OptInt.new('CONCURRENCY', [true, 'The number of concurrent ports to check per host', 10]),
35+
], self.class)
36+
37+
deregister_options('RPORT')
38+
39+
end
40+
41+
def build_ni_packet(routes)
42+
43+
mode = datastore['MODE'].to_i
44+
45+
route_data=''
46+
47+
ni_packet = 'NI_ROUTE' + [0, 2, 39, 2, mode, 0, 0, 1].pack('c*') # create ni_packet header
48+
49+
first = false
50+
51+
routes.each do |host, port| # create routes
52+
53+
route_item = host.to_s.dup << [0].pack('c*') << port.to_s.dup << [0].pack('c*') << [0].pack('c*')
54+
55+
if !first
56+
route_data = route_data << [route_item.length].pack('N') << route_item
57+
first = true
58+
else
59+
route_data = route_data << route_item
60+
end
61+
end
62+
63+
ni_packet << [route_data.length - 4].pack('N') << route_data # add routes to packet
64+
ni_packet = [ni_packet.length].pack('N') << ni_packet # add size
65+
end
66+
67+
def parse_response_packet(response, ip, port)
68+
report=[]
69+
70+
vprint_error("#{ip}:#{port} - response packet: #{response}")
71+
72+
case response
73+
when /NI_RTERR/
74+
case response
75+
when /timed out/
76+
print_error ("#{ip}:#{port} - connection timed out")
77+
when /refused/
78+
print_error("#{ip}:#{port} - TCP closed")
79+
report << [ip, port, 'closed']
80+
when /denied/
81+
print_error("#{ip}:#{port} - blocked by ACL")
82+
when /invalid/
83+
print_error("#{ip}:#{port} - invalid route")
84+
when /reacheable/
85+
print_error("#{ip}:#{port} - unreachable")
86+
else
87+
vprint_error("#{ip}:#{port} - unknown error message")
88+
end
89+
when /NI_PONG/
90+
print_good("#{ip}:#{port} - TCP OPEN")
91+
report << [ip, port, 'open']
92+
else
93+
vprint_error("#{ip}:#{port} - unknown response")
94+
end
95+
report
96+
97+
end
98+
99+
def run_host(ip)
100+
101+
timeout = datastore['TIMEOUT'].to_i
102+
ports = Rex::Socket.portspec_crack(datastore['PORTS'])
103+
104+
sap_host = datastore['SAPROUTER_HOST']
105+
sap_port = datastore['SAPROUTER_PORT']
106+
107+
if ports.empty?
108+
print_error('Error: No valid ports specified')
109+
return
110+
end
111+
112+
print_status("Scanning #{ip}")
113+
114+
while (ports.length > 0)
115+
thread = []
116+
report = []
117+
begin
118+
1.upto(datastore['CONCURRENCY']) do
119+
this_port = ports.shift
120+
break if not this_port
121+
thread << framework.threads.spawn("Module(#{self.refname})-#{ip}:#{this_port}", false, this_port) do |port|
122+
123+
begin
124+
s = connect(false,
125+
{
126+
'RPORT' => sap_port,
127+
'RHOST' => sap_host,
128+
'ConnectTimeout' => (timeout / 1000.0)
129+
}
130+
)
131+
132+
# create ni_packet to send to saprouter
133+
routes = {sap_host => sap_port, ip => port}
134+
ni_packet = build_ni_packet(routes)
135+
136+
s.write(ni_packet, ni_packet.length)
137+
response = s.get()
138+
139+
report = parse_response_packet(response, ip, port)
140+
141+
rescue ::Rex::ConnectionRefused
142+
print_error("#{ip}:#{port} - Unable to connect to SAPRouter #{sap_host}:#{sap_port} - Connection Refused")
143+
144+
rescue ::Rex::ConnectionError, ::IOError, ::Timeout::Error
145+
rescue ::Rex::Post::Meterpreter::RequestError
146+
rescue ::Interrupt
147+
raise $!
148+
rescue ::Exception => e
149+
print_error("#{ip}:#{port} exception #{e.class} #{e} #{e.backtrace}")
150+
ensure
151+
disconnect(s) rescue nil
152+
end
153+
end
154+
end
155+
thread.each { |x| x.join }
156+
157+
rescue ::Timeout::Error
158+
ensure
159+
thread.each { |x| x.kill rescue nil }
160+
end
161+
162+
report.each { |res| report_service(:host => res[0], :port => res[1], :state => res[2]) }
163+
end
164+
end
165+
166+
end

0 commit comments

Comments
 (0)