mgeeky-Penetration-Testing-.../networks/dtpscan.py

156 lines
4.7 KiB
Python
Raw Normal View History

2018-02-02 22:22:43 +01:00
#!/usr/bin/python
#
# Simple script showing configuration of the DTP protocol on
# the switch's port. This reconessaince will be helpful for performing
# VLAN Hopping attacks.
#
2021-10-24 23:11:42 +02:00
# Mariusz Banach / mgeeky, '18
2018-02-02 22:22:43 +01:00
#
import os
import sys
from scapy.all import *
config = {
'count' : 10,
'timeout' : 90
}
ciscoConfigMaps = {
2: '''
ACCESS/OFF/ACCESS
Administrative Mode: static access
Operational Mode: static access
Administrative Trunking Encapsulation: dot1q
Operational Trunking Encapsulation: native
Negotiation of Trunking: Off''',
3: '''
ACCESS/DESIRABLE/ACCESS
Administrative Mode: dynamic desirable
Operational Mode: static access
Administrative Trunking Encapsulation: dot1q
Operational Trunking Encapsulation: native
Negotiation of Trunking: On''',
4: '''
ACCESS/AUTO/ACCESS
Administrative Mode: dynamic auto
Operational Mode: static access
Administrative Trunking Encapsulation: dot1q
Operational Trunking Encapsulation: native
Negotiation of Trunking: On''',
0x81: '''
TRUNK/ON/TRUNK
Administrative Mode: trunk
Operational Mode: trunk
Administrative Trunking Encapsulation: dot1q
Operational Trunking Encapsulation: dot1q
Negotiation of Trunking: On''',
}
def showConfig(stat):
if stat in ciscoConfigMaps.keys():
print(ciscoConfigMaps[stat])
def inspectPacket(dtp):
tlvs = dtp['DTP'].tlvlist
stat = -1
for tlv in tlvs:
if tlv.type == 2:
# TLV: DTPStatus
stat = ord(tlv.status)
break
print(' ' + '=' * 60)
if stat == -1:
print('[!] Something went wrong: Got invalid DTP packet.')
print(' ' + '=' * 60)
return False
elif stat == 2:
print('[-] DTP disabled, Switchport in Access mode configuration')
print('[-] VLAN Hopping via Switch Spoofing/trunking IS NOT possible.')
print('\n\tSWITCH(config-if)# switchport mode access')
elif stat == 3:
print('[+] DTP enabled, Switchport in default configuration')
print('[+] VLAN Hopping via Switch Spoofing/trunking IS POSSIBLE.')
print('\n\tSWITCH(config-if)# switchport dynamic desirable (or none)')
elif stat == 4 or stat == 0x84:
print('[+] DTP enabled, Switchport in Dynamic Auto configuration')
print('[+] VLAN Hopping via Switch Spoofing/trunking IS POSSIBLE.')
print('\n\tSWITCH(config-if)# switchport mode dynamic auto')
elif stat == 0x81:
print('[+] DTP enabled, Switchport in Trunk configuration')
print('[+] VLAN Hopping via Switch Spoofing/trunking IS POSSIBLE.')
print('\n\tSWITCH(config-if)# switchport mode trunk')
elif stat == 0xa5:
print('[?] DTP enabled, Switchport in Trunk with 802.1Q encapsulation forced configuration')
print('[?] VLAN Hopping via Switch Spoofing/trunking may be possible.')
print('\n\tSWITCH(config-if)# switchport mode trunk 802.1Q')
elif stat == 0x42:
print('[?] DTP enabled, Switchport in Trunk with ISL encapsulation forced configuration')
print('[?] VLAN Hopping via Switch Spoofing/trunking may be possible.')
print('\n\tSWITCH(config-if)# switchport mode trunk ISL')
showConfig(stat)
print(' ' + '=' * 60)
return True
def packetCallback(pkt):
print('[>] Packet: ' + pkt.summary())
def main(argv):
if os.getuid() != 0:
print('[!] This program must be run as root.')
return False
load_contrib('dtp')
print('[*] Sniffing for DTP frames (Max count: {}, Max timeout: {} seconds)...'.format(
config['count'], config['timeout']
))
dtps = sniff(
count = config['count'],
filter = 'ether[20:2] == 0x2004',
timeout = config['timeout'],
prn = packetCallback,
stop_filter = lambda x: x.haslayer(DTP)
)
if len(dtps) == 0:
print('[-] It seems like there was no DTP frames transmitted.')
print('[-] VLAN Hopping may not be possible (unless Switch is in Non-negotiate state):')
print('\n\tSWITCH(config-if)# switchport nonnegotiate\t/ or / ')
print('\tSWITCH(config-if)# switchport mode access')
return False
print('[*] Got {} DTP frames.\n'.format(
len(dtps)
))
success = False
for dtp in dtps:
if dtp.haslayer(DTP):
if inspectPacket(dtp):
success = True
break
if not success:
print('[-] Received possibly corrupted DTP frames! General failure.')
print('')
return success
if __name__ == '__main__':
main(sys.argv)