This is an agent less solution to scan complete network and build an asset report. All you need is a Linux host with python3 and pythonping, nmap and ipaddress python modules along with nmap Linux package. Since we are not authenticating to hosts and just doing a predictive scan using underline nmap tool, so report may not be 100% accurate. But still it gives fair enough idea of what all you have on your network.
This works as following
- Explode network into IP addresses.
- Ping 5 packets to IP, and see the result of 3rd ping.
- If 3rd ping is successful then run nmap scan with “-O” option to scan operating system on remote host.
- if return result is not “None”, then parse the returned json data to extract fields of interest.
- We are extracting OS type, vendor, OS family, OS version, accuracy of prediction, cpe, hardware vendor and MAC address.
- Out put will be displayed on screen and will get written in CSV file like <network.csv>, for eg 192.168.0.0.csv.
Depending upon firewall rules, this will try to extract max information it can.
Here is the code
#!/usr/local/bin/python3
from pythonping import ping
from multiprocessing import Pool
import sys
import ipaddress
import nmap
import socket
import os
network = sys.argv[1]
ipList = [str(ip) for ip in ipaddress.IPv4Network(network)][1:-1]
path = os.getcwd()+"/"
fname = network.split('/')[0]+".csv"
if os.path.exists(path+fname):
os.remove(path+fname)
def CommitData(LogMessage):
try:
fopen = open(path+fname, "a")
try:
fopen.write(LogMessage)
fopen.close()
except IOError as e:
print("Failed to write ",e)
except IOError as e:
print("failed to open file", e)
def nmapcheck(host):
pingErr = ping(host, count=5)._responses[3].error_message
if pingErr is None:
# print(pingErr, iphost)
hostscan = nmap.PortScanner()
results = hostscan.scan(hosts=host, arguments='-O')
return(results)
else:
return
#ipList = [str(ip) for ip in ipaddress.IPv4Network(network)][1:-1]
#for iphost in ipList:
def ScanHost(iphost):
results = nmapcheck(iphost)
if results is not None:
if 'mac' in results['scan'][iphost]['addresses']:
macaddr = str(results['scan'][iphost]['addresses']['mac'])
else:
macaddr = "None"
try:
DNSname = socket.gethostbyaddr(iphost)[0]
except:
DNSname = "NotFound"
# print("HWVendor", results['scan'][iphost])
if str(results['scan'][iphost]['vendor']):
hwvendor = str(results['scan'][iphost]['vendor'])
else:
hwvendor = "None"
if results['scan'][iphost]['osmatch'] != []:
results = results['scan'][iphost]['osmatch'][0]['osclass'][0]
keys, values = zip(*results.items())
type, vendor, osfamily, osgen, accuracy, cpe = values[0], values[1], values[2], values[3], values[4], values[5]
LogMessage = str(iphost)+";"+DNSname+";"+str(type)+";"+str(vendor)+";"+str(osfamily)+";"+str(osgen)+";"+str(accuracy)+";"+str(cpe)+";"+hwvendor+";"+macaddr+"\n"
CommitData(LogMessage)
print(LogMessage)
else:
type, vendor, osfamily, osgen, accuracy, cpe = "", "", "", "", "", ""
LogMessage = str(iphost)+";"+DNSname+";"+str(type)+";"+str(vendor)+";"+str(osfamily)+";"+str(osgen)+";"+str(accuracy)+";"+str(cpe)+";"+hwvendor+";"+macaddr+"\n"
CommitData(LogMessage)
print(LogMessage)
else:
LogMessage = iphost+";"+"ping or nmap failed"+"\n"
CommitData(LogMessage)
print(LogMessage)
with Pool(5) as p:
p.map(ScanHost, ipList)
Save above code as scanAsset.py and give execution permission. Remember this has to executed as “root” user. Lets give a try….
root@scorpio:~#./scanAssets.py 192.168.0.0/24
root@scorpio:~#cat 192.168.0.0.csv
192.168.0.1;host1;general purpose;Linux;Linux;3.X;100;['cpe:/o:linux:linux_kernel:3'];{};EC:xxxxxxxxx
192.168.0.2;general purpose;Linux;Linux;2.6.X;100;['cpe:/o:linux:linux_kernel:2.6'];{'84:xxxxxxxxx': 'Tp-link Technologies'};84:xxxxxxxxxx
192.168.0.3;NotFound;general purpose;Linux;Linux;2.6.X;100;['cpe:/o:linux:linux_kernel:2.6'];{'BC:xxxxxxxxxx': 'Hangzhou Hikvision Digital Technology'};BC:xxxxxxxx
192.168.0.4;ping or nmap failed
192.168.0.5;ping or nmap failed
......
......
192.168.0.17;host17;general purpose;Linux;Linux;3.X;100;['cpe:/o:linux:linux_kernel:3'];{};None
192.168.0.23;general purpose;Linux;Linux;3.X;100;['cpe:/o:linux:linux_kernel:3'];{'B8:xxxxxxxxxxx': 'Raspberry Pi Foundation'};B8:xxxxxxxxxx
192.168.0.24;host24;general purpose;Linux;Linux;3.X;100;['cpe:/o:linux:linux_kernel:3'];{'B8:xxxxxxxxx': 'Raspberry Pi Foundation'};B8:xxxxxxxx
192.168.0.101;host101;specialized;Philips;embedded;None;100;['cpe:/h:philips:hue_bridge'];{};CC:xxxxxxxxxx
192.168.0.102;NotFound;;;;;;;;{'38:xxxxxxxxxxx': 'Xiaomi Communications'};38:xxxxxxxxxxx
192.168.0.111;host111;general purpose;Linux;Linux;2.6.X;100;['cpe:/o:linux:linux_kernel:2.6'];{'54:xxxxxxxxxx': 'Google'};54:xxxxxxxxxxxx
192.168.0.116;NotFound;general purpose;Microsoft;Windows;XP;85;['cpe:/o:microsoft:windows_xp::sp2'];{'E4:xxxxxxxxxxx': 'Intel Corporate'};E4:xxxxxxxxxxxxx