Using Nmap As a Lightweight Vulnerability Scanner
Yesterday, Bojan wrote a nice diary[1] about the power of the Nmap scripting language (based on LUA). The well-known port scanner can be extended with plenty of scripts that are launched depending on the detected ports. When I read Bojan's diary, it reminded me of an old article[2] that I wrote on my blog a long time ago. The idea was to use Nmap as a lightweight vulnerability scanner. Nmap has a scan type that tries to determine the service/version information running behind an open port (enabled with the '-sV' flag). Based on this information, the script looks for interesting CVE in a flat database. Unfortunately, the script was developed by a third-party developer and was never integrated into the official list of scripts.
However, a second project was kicked off and integrated into Nmap: The vulners[3] script. The principle is the same: You scan the host (with '-sV') and, for each identified service, the script performs a lookup in the CVE database. Example:
root@kali:~# nmap -sV --script=vulners -v x.x.x.x Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-07 17:28 CEST NSE: Loaded 46 scripts for scanning. NSE: Script Pre-scanning. Initiating NSE at 17:28 Completed NSE at 17:28, 0.00s elapsed Initiating NSE at 17:28 Completed NSE at 17:28, 0.00s elapsed Initiating Ping Scan at 17:28 Scanning x.x.x.x [4 ports] Completed Ping Scan at 17:28, 0.19s elapsed (1 total hosts) Initiating Parallel DNS resolution of 1 host. at 17:28 Completed Parallel DNS resolution of 1 host. at 17:28, 2.17s elapsed Initiating SYN Stealth Scan at 17:28 Scanning x.x.x.x [1000 ports] Discovered open port 443/tcp on x.x.x.x Discovered open port 3389/tcp on x.x.x.x Discovered open port 445/tcp on x.x.x.x Discovered open port 21/tcp on x.x.x.x Discovered open port 3306/tcp on x.x.x.x Discovered open port 135/tcp on x.x.x.x Discovered open port 139/tcp on x.x.x.x Discovered open port 80/tcp on x.x.x.x Discovered open port 49158/tcp on x.x.x.x Discovered open port 3800/tcp on x.x.x.x Discovered open port 49160/tcp on x.x.x.x Discovered open port 49154/tcp on x.x.x.x Discovered open port 49152/tcp on x.x.x.x Discovered open port 49153/tcp on x.x.x.x Discovered open port 49155/tcp on x.x.x.x Discovered open port 49157/tcp on x.x.x.x Completed SYN Stealth Scan at 17:28, 5.58s elapsed (1000 total ports) Initiating Service scan at 17:28 Scanning 16 services on x.x.x.x Service scan Timing: About 56.25% done; ETC: 17:30 (0:00:44 remaining) [70/1471] Completed Service scan at 17:30, 84.04s elapsed (16 services on 1 host) NSE: Script scanning x.x.x.x. Initiating NSE at 17:30 Completed NSE at 17:30, 6.91s elapsed Initiating NSE at 17:30 Completed NSE at 17:30, 1.55s elapsed Nmap scan report for x.x.x.x Host is up (0.19s latency). Not shown: 984 closed ports PORT STATE SERVICE VERSION 21/tcp open ftp FileZilla ftpd 0.9.41 beta 80/tcp open http Apache httpd 2.4.17 ((Win32) OpenSSL/1.0.2d PHP/5.6.20) |_http-server-header: Apache/2.4.17 (Win32) OpenSSL/1.0.2d PHP/5.6.20 | vulners: | cpe:/a:apache:http_server:2.4.17: | CVE-2017-7679 7.5 https://vulners.com/cve/CVE-2017-7679 | CVE-2017-7668 7.5 https://vulners.com/cve/CVE-2017-7668 | CVE-2017-3169 7.5 https://vulners.com/cve/CVE-2017-3169 | CVE-2017-3167 7.5 https://vulners.com/cve/CVE-2017-3167 | CVE-2019-0211 7.2 https://vulners.com/cve/CVE-2019-0211 | CVE-2018-1312 6.8 https://vulners.com/cve/CVE-2018-1312 | CVE-2017-15715 6.8 https://vulners.com/cve/CVE-2017-15715 | CVE-2017-9788 6.4 https://vulners.com/cve/CVE-2017-9788 | CVE-2019-0217 6.0 https://vulners.com/cve/CVE-2019-0217 | CVE-2020-1927 5.8 https://vulners.com/cve/CVE-2020-1927 | CVE-2019-10098 5.8 https://vulners.com/cve/CVE-2019-10098 | CVE-2020-1934 5.0 https://vulners.com/cve/CVE-2020-1934 | CVE-2019-0220 5.0 https://vulners.com/cve/CVE-2019-0220 | CVE-2019-0196 5.0 https://vulners.com/cve/CVE-2019-0196 | CVE-2018-17199 5.0 https://vulners.com/cve/CVE-2018-17199 | CVE-2017-9798 5.0 https://vulners.com/cve/CVE-2017-9798 | CVE-2017-15710 5.0 https://vulners.com/cve/CVE-2017-15710 | CVE-2016-8743 5.0 https://vulners.com/cve/CVE-2016-8743 | CVE-2016-8740 5.0 https://vulners.com/cve/CVE-2016-8740 | CVE-2019-0197 4.9 https://vulners.com/cve/CVE-2019-0197 | CVE-2019-10092 4.3 https://vulners.com/cve/CVE-2019-10092 | CVE-2018-11763 4.3 https://vulners.com/cve/CVE-2018-11763 | CVE-2016-4975 4.3 https://vulners.com/cve/CVE-2016-4975 | CVE-2016-1546 4.3 https://vulners.com/cve/CVE-2016-1546 | CVE-2018-1283 3.5 https://vulners.com/cve/CVE-2018-1283 |_ CVE-2016-8612 3.3 https://vulners.com/cve/CVE-2016-8612 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 443/tcp open ssl/http Apache httpd 2.4.17 ((Win32) OpenSSL/1.0.2d PHP/5.6.20) |_http-server-header: Apache/2.4.17 (Win32) OpenSSL/1.0.2d PHP/5.6.20 | vulners: | cpe:/a:apache:http_server:2.4.17: | CVE-2017-7679 7.5 https://vulners.com/cve/CVE-2017-7679 | CVE-2017-7668 7.5 https://vulners.com/cve/CVE-2017-7668 | CVE-2017-3169 7.5 https://vulners.com/cve/CVE-2017-3169 | CVE-2017-3167 7.5 https://vulners.com/cve/CVE-2017-3167 | CVE-2019-0211 7.2 https://vulners.com/cve/CVE-2019-0211 | CVE-2018-1312 6.8 https://vulners.com/cve/CVE-2018-1312 | CVE-2017-15715 6.8 https://vulners.com/cve/CVE-2017-15715 | CVE-2017-9788 6.4 https://vulners.com/cve/CVE-2017-9788 | CVE-2019-0217 6.0 https://vulners.com/cve/CVE-2019-0217 | CVE-2020-1927 5.8 https://vulners.com/cve/CVE-2020-1927 | CVE-2019-10098 5.8 https://vulners.com/cve/CVE-2019-10098 | CVE-2020-1934 5.0 https://vulners.com/cve/CVE-2020-1934 | CVE-2019-0220 5.0 https://vulners.com/cve/CVE-2019-0220 | CVE-2019-0196 5.0 https://vulners.com/cve/CVE-2019-0196 | CVE-2018-17199 5.0 https://vulners.com/cve/CVE-2018-17199 | CVE-2017-9798 5.0 https://vulners.com/cve/CVE-2017-9798 | CVE-2017-15710 5.0 https://vulners.com/cve/CVE-2017-15710 | CVE-2016-8743 5.0 https://vulners.com/cve/CVE-2016-8743 | CVE-2016-8740 5.0 https://vulners.com/cve/CVE-2016-8740 | CVE-2019-0197 4.9 https://vulners.com/cve/CVE-2019-0197 | CVE-2019-10092 4.3 https://vulners.com/cve/CVE-2019-10092 | CVE-2018-11763 4.3 https://vulners.com/cve/CVE-2018-11763 | CVE-2016-4975 4.3 https://vulners.com/cve/CVE-2016-4975 | CVE-2016-1546 4.3 https://vulners.com/cve/CVE-2016-1546 | CVE-2018-1283 3.5 https://vulners.com/cve/CVE-2018-1283 |_ CVE-2016-8612 3.3 https://vulners.com/cve/CVE-2016-8612 445/tcp open microsoft-ds Microsoft Windows Server 2008 R2 - 2012 microsoft-ds 3306/tcp open mysql MariaDB (unauthorized) 3389/tcp open ssl/ms-wbt-server? 3800/tcp open tcpwrapped 49152/tcp open msrpc Microsoft Windows RPC 49153/tcp open msrpc Microsoft Windows RPC 49154/tcp open msrpc Microsoft Windows RPC 49155/tcp open msrpc Microsoft Windows RPC 49157/tcp open msrpc Microsoft Windows RPC 49158/tcp open msrpc Microsoft Windows RPC 49160/tcp open msrpc Microsoft Windows RPC Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows NSE: Script Post-scanning. Initiating NSE at 17:30 Completed NSE at 17:30, 0.00s elapsed Initiating NSE at 17:30 Completed NSE at 17:30, 0.00s elapsed Read data files from: /usr/bin/../share/nmap Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 100.83 seconds Raw packets sent: 1022 (44.944KB) | Rcvd: 1001 (40.108KB)
The difference between the two scripts is the way they search for CVE. In this case, the script requires Internet access to query the Vulners API[4].
Note that the script accepts one parameter: You can specify the minimum CVSS ("Common Vulnerability Scoring System") score to display:
root@kali:~# nmap -sV --script=vulners --script-args mincvss=8 x.x.x.x
Once you get some results, our next goal could be to automatically process the results. Let's use a few lines of Python to parse the Nmap XML output (that is created via the '-oX' flag):
root@kali:~# nmap -sV --script=vulners -oX x.x.x.x.xml x.x.x.x root@kali:~# python3 Python 3.7.7 (default, Mar 10 2020, 13:18:53) [GCC 9.2.1 20200306] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from libnmap.parser import NmapParser >>> p = NmapParser.parse_fromfile("x.x.x.x.xml") >>> for host in p.hosts: ... for svc in host.services: ... for script in svc.scripts_results: ... output = script.get("output") ... print(output) ... cpe:/a:microsoft:sql_server:2014: CVE-2015-1763 8.5 https://vulners.com/cve/CVE-2015-1763 CVE-2015-1762 7.1 https://vulners.com/cve/CVE-2015-1762 CVE-2020-0618 6.5 https://vulners.com/cve/CVE-2020-0618 CVE-2019-1068 6.5 https://vulners.com/cve/CVE-2019-1068 CVE-2016-7253 6.5 https://vulners.com/cve/CVE-2016-7253 CVE-2016-7250 6.5 https://vulners.com/cve/CVE-2016-7250 CVE-2015-1761 6.5 https://vulners.com/cve/CVE-2015-1761 CVE-2017-8516 5.0 https://vulners.com/cve/CVE-2017-8516 CVE-2014-1820 4.3 https://vulners.com/cve/CVE-2014-1820
Nice! So, we have a lightweight vulnerability scanner and we can automate the reporting. Another idea could be to perform a diff of a first scan - used as a baseline - and a second one (performed at regular intervals. Ndiff[5] is a great tool to achieve this.
In conclusion, a tool can be for multiple purposes, offensive VS. defensive security!
[1] https://isc.sans.edu/forums/diary/Scanning+with+nmaps+NSE+scripts/26096/
[2] https://blog.rootshell.be/2010/06/03/vulnerability-scanner-within-nmap/
[3] https://github.com/vulnersCom/nmap-vulners
[4] https://vulners.com/api/v3/
[5] https://nmap.org/ndiff/
Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Reverse-Engineering Malware: Advanced Code Analysis | Online | Greenwich Mean Time | Oct 28th - Nov 1st 2024 |
Comments