CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

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