Skip to content
Permalink
Browse files

Land #11781, add GTP-U echo scanner module

  • Loading branch information...
busterb committed Apr 30, 2019
2 parents efa5fbf + cc62ca5 commit d8432fd8de91f8514910d6d0154d8c1722ea6116
Showing with 200 additions and 0 deletions.
  1. +28 −0 documentation/modules/auxiliary/scanner/gprs/gtp_echo.md
  2. +172 −0 modules/auxiliary/scanner/gprs/gtp_echo.rb
@@ -0,0 +1,28 @@
This module provides a port of Daniel Mende's (released under the BSD license) gtp-scan.py utility. It brings the ability to scan for GPRS servers to Metasploit via sending GTP-U v1 and v2 echo requests.

## Vulnerable Application

Open-source GGSN implementations can be used as a target for this module as well as commercial GPRS gear. For information on one project suitable as a target, see [OsmoGGSN](https://osmocom.org/projects/openggsn/wiki/OsmoGGSN).

## Options

**The RPORT option**

This option can be changed to target GTP-U (2152) or GTP-C (2123), which both use the same packet type for echo probing.

## Scenarios

```
metasploit-framework (S:0 J:1) auxiliary(scanner/gprs/gtp_echo) > set RHOSTS 192.168.28.200-192.168.28.208
RHOSTS => 192.168.28.200-192.168.28.208
metasploit-framework (S:0 J:1) auxiliary(scanner/gprs/gtp_echo) > run
[*] [2019.04.22-16:38:27] Sending probes to 192.168.28.200->192.168.28.208 (9 hosts)
[+] [2019.04.22-16:38:42] GTP v1 echo response received from: 192.168.28.200:2152
[+] [2019.04.22-16:38:43] GTP v1 echo response received from: 192.168.28.201:2152
[+] [2019.04.22-16:38:43] GTP v1 echo response received from: 192.168.28.207:2152
[+] [2019.04.22-16:38:43] GTP v1 echo response received from: 192.168.28.208:2152
[*] [2019.04.22-16:38:43] Scanned 9 of 9 hosts (100% complete)
[*] Auxiliary module execution completed
metasploit-framework (S:0 J:1) auxiliary(scanner/gprs/gtp_echo) >
```
@@ -0,0 +1,172 @@
##
# 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' => 'GTP Echo Scanner',
'Description' => %q{
This module sends UDP GTP (GTP-U) echo requests to the target RHOSTS and
reports on which ones respond, thus identifying General Packet Radio
Service (GPRS) servers. This module does not support scanning with SCTP.
},
'References' =>
[
['URL', 'https://insinuator.net/tag/gtp/'],
['URL', 'https://www.etsi.org/deliver/etsi_ts/129200_129299/129281/08.00.00_60/ts_129281v080000p.pdf']
],
'Author' =>
[
'Daniel Mende', # original gtp-scan.py script
'Spencer McIntyre' # metasploit module
],
'License' => MSF_LICENSE
)

register_options([
OptEnum.new('VERSION', [ true, 'The GTP version to use', '1', ['1', '2'] ]),
Opt::RPORT(2152)
])
end

class GTPv1 < BinData::Record
endian :big

default_parameter version: 1
default_parameter protocol_type: 1
default_parameter has_next_extension_header: 0
default_parameter has_sequence_number: 0
default_parameter has_n_pdu_number: 0
default_parameter message_type: 0
default_parameter data: ""

# header
bit3 :version, :initial_value => :version
bit1 :protocol_type, :initial_value => :protocol_type
bit1 :reserved
bit1 :has_next_extension_header, :initial_value => :has_next_extension_header
bit1 :has_sequence_number, :initial_value => :has_sequence_number
bit1 :has_n_pdu_number, :initial_value => :has_n_pdu_number
uint8 :message_type, :initial_value => :message_type
uint16 :len, :value => :calc_length
uint32 :teid

# body
uint16 :sequence_number, onlyif: -> { has_sequence_number.nonzero? }
uint8 :n_pdu_number, onlyif: -> { has_n_pdu_number.nonzero? }
uint8 :next_extension_header_type, onlyif: -> { has_next_extension_header.nonzero? }
string :data, :initial_value => :data, :read_length => :calc_length_read

def calc_length
length = data.length
length += 2 if has_sequence_number.nonzero?
length += 1 if has_n_pdu_number.nonzero?
length += 1 if has_next_extension_header.nonzero?
length
end

def calc_length_read
length = len
length -= 2 if has_sequence_number.nonzero?
length -= 1 if has_n_pdu_number.nonzero?
length -= 1 if has_next_extension_header.nonzero?
length
end
end

class GTPv1EchoRequest < GTPv1
default_parameter has_sequence_number: 1
default_parameter message_type: 1
end

class GTPv2 < BinData::Record
endian :big

default_parameter version: 2
default_parameter piggybacking: 0
default_parameter message_priority: 0
default_parameter message_type: 0
default_parameter data: ""

# header
bit3 :version, :initial_value => :version
bit1 :piggybacking, :initial_value => :piggybacking
bit1 :has_teid
bit1 :message_priority, :initial_value => :message_priority
uint8 :message_type, :initial_value => :message_type
uint16 :len, :value => :calc_length

# body
uint32 :teid, onlyif: -> { has_teid.nonzero? }
uint24 :sequence_number
uint8 :spare
string :data, :initial_value => :data, :read_length => :calc_length_read

def calc_length
length = data.length + 4
length += 4 if has_teid.nonzero?
length
end

def calc_length_read
length = len - 4
length -= 4 if has_teid.nonzero?
length
end
end

class GTPv2EchoRequest < GTPv2
default_parameter message_type: 1
end

def build_probe
# the tunnel endpoint identifier (TEID) field must be 0 for echo requests
# per the specification
if datastore['VERSION'] == '1'
@probe = GTPv1EchoRequest.new.to_binary_s
else
@probe = GTPv2EchoRequest.new.to_binary_s
end
end

def scanner_postscan(batch)
@results.each do |rhost, data|
next unless data.length == 1
data = data[0]

if datastore['VERSION'] == '1'
gtp = GTPv1
else
gtp = GTPv2
end
begin
response = gtp.read(data)
rescue EOFError
next
end

if datastore['VERSION'] == '1'
next unless response.version == 1
next unless response.teid == 0
else
next unless response.version == 2
next unless response.sequence_number == 0
end

peer = "#{rhost}:#{rport}"
print_good("GTP v#{datastore['VERSION']} echo response received from: #{peer}")

report_service(
:host => rhost,
:proto => 'udp',
:port => rport,
:name => 'gtp'
)
end
end
end

0 comments on commit d8432fd

Please sign in to comment.
You can’t perform that action at this time.