├── README.md └── nmap_scan.py /README.md: -------------------------------------------------------------------------------- 1 | **WAZUH AND NMAP FOR NETWORK SCAN** 2 | ## 3 | 4 | ## Intro 5 | 6 | Wazuh and NMAP integration to scan network subnets for open ports and services. 7 | 8 | In this integration we’ll use python-nmap (https://pypi.org/project/python-nmap/) to scan for open ports/services found in different subnets. 9 | 10 | NMAP port scanners can be installed in different Wazuh agents placed in different network segments. The NMAP output is converted to JSON and appended to each agent’s active responses file. 11 | 12 | The scan can be scheduled via cron jobs to be executed once a week, month, etc. It can also be triggered using Wazu’s wodle command integration. 13 | 14 | 15 | ## Requirements 16 | 17 | 18 | * NMAP installed in every agent to run the network scan. 19 | * python-nmap ([https://pypi.org/project/python-nmap/](https://pypi.org/project/python-nmap/)) installed. 20 | 21 | 22 | ## Python-nmap 23 | 24 | Python-nmap is a python library which helps in using nmap port scanner. It allows to easilly manipulate nmap scan results and will be a perfect tool for systems administrators who want to automate scanning tasks and reports. It also supports nmap script outputs. 25 | 26 | 27 | ## Python script run on agents 28 | 29 | 30 | ``` 31 | ################################ 32 | ### Python Script to Run Network Scans and append results to Wazuh Active Responses Log 33 | ### Requirements: 34 | ### NMAP installed in Agent 35 | ### python-nmap (https://pypi.org/project/python-nmap/) 36 | ### Replace the Array "subnets" with the subnets to scan from this agent. 37 | ### Do NOT include subnets with a network firewall in the path of the agent and the subnet. 38 | ################################ 39 | import nmap 40 | import time 41 | import json 42 | nm = nmap.PortScanner() 43 | #Add subnets to scan to the Subnets Array 44 | subnets=['192.168.252.0/24','192.168.1.0/24'] 45 | for subnet in subnets: 46 | json_output={} 47 | nm.scan(subnet) 48 | for host in nm.all_hosts(): 49 | json_output['nmap_host']=host 50 | for proto in nm[host].all_protocols(): 51 | if proto not in ["tcp", "udp"]: 52 | continue 53 | json_output['nmap_protocol']=proto 54 | lport = list(nm[host][proto].keys()) 55 | lport.sort() 56 | for port in lport: 57 | hostname = "" 58 | json_output['nmap_port']=port 59 | for h in nm[host]["hostnames"]: 60 | hostname = h["name"] 61 | json_output['nmap_hostname']=hostname 62 | hostname_type = h["type"] 63 | json_output['nmap_hostname_type']=hostname_type 64 | json_output['nmap_port_name']=nm[host][proto][port]["name"] 65 | json_output['nmap_port_state']=nm[host][proto][port]["state"] 66 | json_output['nmap_port_product']=nm[host][proto][port]["product"] 67 | json_output['nmap_port_extrainfo']=nm[host][proto][port]["extrainfo"] 68 | json_output['nmap_port_reason']=nm[host][proto][port]["reason"] 69 | json_output['nmap_port_version']=nm[host][proto][port]["version"] 70 | json_output['nmap_port_conf']=nm[host][proto][port]["conf"] 71 | json_output['nmap_port_cpe']=nm[host][proto][port]["cpe"] 72 | with open("/var/ossec/logs/active-responses.log", "a") as active_response_log: 73 | active_response_log.write(json.dumps(json_output)) 74 | active_response_log.write("\n") 75 | time.sleep(2) 76 | ``` 77 | 78 | 79 | This script can be placed in any folder in the agent’s file system and its execution can be scheduled using cron. 80 | 81 | 82 | ## Detection Rules (Wazuh Manager) 83 | 84 | 85 | ``` 86 | 87 | 88 | json 89 | \.+ 90 | \.+ 91 | NMAP: Network Scan Host $(nmap_host) 92 | no_full_log 93 | 94 | 95 | ``` 96 | 97 | 98 | 99 | ## Scan Results - Wazuh Manager Alerts (examples) 100 | 101 | 102 | ``` 103 | { 104 | "timestamp":"2022-02-23T04:37:32.001+0000", 105 | "rule":{ 106 | "level":3, 107 | "description":"NMAP: Network Scan Host 192.168.252.222", 108 | "id":"200400", 109 | "firedtimes":55, 110 | "mail":false, 111 | "groups":[ 112 | "linux", 113 | "nmap", 114 | "netwprk_scan" 115 | ] 116 | }, 117 | "agent":{ 118 | "id":"017", 119 | "name":"ubunutu2004vm", 120 | "ip":"192.168.252.191" 121 | }, 122 | "manager":{ 123 | "name":"ASHWZH01" 124 | }, 125 | "id":"1645591052.115711751", 126 | "decoder":{ 127 | "name":"json" 128 | }, 129 | "data":{ 130 | "nmap_host":"192.168.252.222", 131 | "nmap_protocol":"tcp", 132 | "nmap_port":"443", 133 | "nmap_hostname":"_gateway", 134 | "nmap_hostname_type":"PTR", 135 | "nmap_port_name":"https", 136 | "nmap_port_state":"open", 137 | "nmap_port_product":"OPNsense", 138 | "nmap_port_reason":"syn-ack", 139 | "nmap_port_conf":"10" 140 | }, 141 | "location":"/var/ossec/logs/active-responses.log" 142 | } 143 | ``` 144 | -------------------------------------------------------------------------------- /nmap_scan.py: -------------------------------------------------------------------------------- 1 | ################################ 2 | ### Python Script to Run Network Scans and append results to Wazuh Active Responses Log 3 | ### Requirements: 4 | ### NMAP installed in Agent 5 | ### python-nmap (https://pypi.org/project/python-nmap/) 6 | ### Replace the Array "subnets" with the subnets to scan from this agent. 7 | ### Do NOT include subnets with a network firewall in the path of the agent and the subnet. 8 | ################################ 9 | import nmap 10 | import time 11 | import json 12 | nm = nmap.PortScanner() 13 | #Add subnets to scan to the Subnets Array 14 | subnets=['192.168.252.0/24','192.168.1.0/24'] 15 | for subnet in subnets: 16 | json_output={} 17 | nm.scan(subnet) 18 | for host in nm.all_hosts(): 19 | json_output['nmap_host']=host 20 | for proto in nm[host].all_protocols(): 21 | if proto not in ["tcp", "udp"]: 22 | continue 23 | json_output['nmap_protocol']=proto 24 | lport = list(nm[host][proto].keys()) 25 | lport.sort() 26 | for port in lport: 27 | hostname = "" 28 | json_output['nmap_port']=port 29 | for h in nm[host]["hostnames"]: 30 | hostname = h["name"] 31 | json_output['nmap_hostname']=hostname 32 | hostname_type = h["type"] 33 | json_output['nmap_hostname_type']=hostname_type 34 | json_output['nmap_port_name']=nm[host][proto][port]["name"] 35 | json_output['nmap_port_state']=nm[host][proto][port]["state"] 36 | json_output['nmap_port_product']=nm[host][proto][port]["product"] 37 | json_output['nmap_port_extrainfo']=nm[host][proto][port]["extrainfo"] 38 | json_output['nmap_port_reason']=nm[host][proto][port]["reason"] 39 | json_output['nmap_port_version']=nm[host][proto][port]["version"] 40 | json_output['nmap_port_conf']=nm[host][proto][port]["conf"] 41 | json_output['nmap_port_cpe']=nm[host][proto][port]["cpe"] 42 | with open("/var/ossec/logs/active-responses.log", "a") as active_response_log: 43 | active_response_log.write(json.dumps(json_output)) 44 | active_response_log.write("\n") 45 | time.sleep(2) --------------------------------------------------------------------------------