Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/gprs/gtp_echo.rb
19851 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Auxiliary::Report
8
include Msf::Auxiliary::UDPScanner
9
10
def initialize
11
super(
12
'Name' => 'GTP Echo Scanner',
13
'Description' => %q{
14
This module sends UDP GTP (GTP-U) echo requests to the target RHOSTS and
15
reports on which ones respond, thus identifying General Packet Radio
16
Service (GPRS) servers. This module does not support scanning with SCTP.
17
},
18
'References' => [
19
['URL', 'https://insinuator.net/tag/gtp/'],
20
['URL', 'https://www.etsi.org/deliver/etsi_ts/129200_129299/129281/08.00.00_60/ts_129281v080000p.pdf']
21
],
22
'Author' => [
23
'Daniel Mende', # original gtp-scan.py script
24
'Spencer McIntyre' # metasploit module
25
],
26
'License' => MSF_LICENSE
27
)
28
29
register_options([
30
OptEnum.new('VERSION', [ true, 'The GTP version to use', '1', ['1', '2'] ]),
31
Opt::RPORT(2152)
32
])
33
end
34
35
class GTPv1 < BinData::Record
36
endian :big
37
38
default_parameter version: 1
39
default_parameter protocol_type: 1
40
default_parameter has_next_extension_header: 0
41
default_parameter has_sequence_number: 0
42
default_parameter has_n_pdu_number: 0
43
default_parameter message_type: 0
44
default_parameter data: ""
45
46
# header
47
bit3 :version, :initial_value => :version
48
bit1 :protocol_type, :initial_value => :protocol_type
49
bit1 :reserved
50
bit1 :has_next_extension_header, :initial_value => :has_next_extension_header
51
bit1 :has_sequence_number, :initial_value => :has_sequence_number
52
bit1 :has_n_pdu_number, :initial_value => :has_n_pdu_number
53
uint8 :message_type, :initial_value => :message_type
54
uint16 :len, :value => :calc_length
55
uint32 :teid
56
57
# body
58
uint16 :sequence_number, onlyif: -> { has_sequence_number.nonzero? }
59
uint8 :n_pdu_number, onlyif: -> { has_n_pdu_number.nonzero? }
60
uint8 :next_extension_header_type, onlyif: -> { has_next_extension_header.nonzero? }
61
string :data, :initial_value => :data, :read_length => :calc_length_read
62
63
def calc_length
64
length = data.length
65
length += 2 if has_sequence_number.nonzero?
66
length += 1 if has_n_pdu_number.nonzero?
67
length += 1 if has_next_extension_header.nonzero?
68
length
69
end
70
71
def calc_length_read
72
length = len
73
length -= 2 if has_sequence_number.nonzero?
74
length -= 1 if has_n_pdu_number.nonzero?
75
length -= 1 if has_next_extension_header.nonzero?
76
length
77
end
78
end
79
80
class GTPv1EchoRequest < GTPv1
81
default_parameter has_sequence_number: 1
82
default_parameter message_type: 1
83
end
84
85
class GTPv2 < BinData::Record
86
endian :big
87
88
default_parameter version: 2
89
default_parameter piggybacking: 0
90
default_parameter message_priority: 0
91
default_parameter message_type: 0
92
default_parameter data: ""
93
94
# header
95
bit3 :version, :initial_value => :version
96
bit1 :piggybacking, :initial_value => :piggybacking
97
bit1 :has_teid
98
bit1 :message_priority, :initial_value => :message_priority
99
uint8 :message_type, :initial_value => :message_type
100
uint16 :len, :value => :calc_length
101
102
# body
103
uint32 :teid, onlyif: -> { has_teid.nonzero? }
104
uint24 :sequence_number
105
uint8 :spare
106
string :data, :initial_value => :data, :read_length => :calc_length_read
107
108
def calc_length
109
length = data.length + 4
110
length += 4 if has_teid.nonzero?
111
length
112
end
113
114
def calc_length_read
115
length = len - 4
116
length -= 4 if has_teid.nonzero?
117
length
118
end
119
end
120
121
class GTPv2EchoRequest < GTPv2
122
default_parameter message_type: 1
123
end
124
125
def build_probe
126
# the tunnel endpoint identifier (TEID) field must be 0 for echo requests
127
# per the specification
128
if datastore['VERSION'] == '1'
129
@probe = GTPv1EchoRequest.new.to_binary_s
130
else
131
@probe = GTPv2EchoRequest.new.to_binary_s
132
end
133
end
134
135
def scanner_postscan(batch)
136
@results.each do |rhost, data|
137
next unless data.length == 1
138
139
data = data[0]
140
141
if datastore['VERSION'] == '1'
142
gtp = GTPv1
143
else
144
gtp = GTPv2
145
end
146
begin
147
response = gtp.read(data)
148
rescue EOFError
149
next
150
end
151
152
if datastore['VERSION'] == '1'
153
next unless response.version == 1
154
next unless response.teid == 0
155
else
156
next unless response.version == 2
157
next unless response.sequence_number == 0
158
end
159
160
peer = "#{rhost}:#{rport}"
161
print_good("GTP v#{datastore['VERSION']} echo response received from: #{peer}")
162
163
report_service(
164
:host => rhost,
165
:proto => 'udp',
166
:port => rport,
167
:name => 'gtp'
168
)
169
end
170
end
171
end
172
173