While people have created AWS Lambda based scanners, such as AWS-SCAN and Better-AWS-SCAN which make use of “python-nmap“, I wanted to see if I could get the “real” Nmap running in AWS Lambda having recently created a Slack bot that runs PhantomJS in Lambda.
DISCLAIMER: Please ensure you’ve read https://aws.amazon.com/security/penetration-testing/ and have all the permission necessary if you’re going to perform any of the below. Your country of residence might also have laws about port/automated scanning which might make the following steps illegal. The information here is provided for academic reasons only, I will not be held responsible for your actions.
Using the code and steps in my previous PhantomJS blog post, and simply replacing the PhantomJS binary with an Nmap binary resulted in dependency issues, which I was able to resolve by using a statically compiled version of Nmap found here: https://github.com/andrew-d/static-binaries/tree/master/binaries/linux/x86_64.
Next up was an “Unable to find nmap-services! Resorting to /etc/services” error/warning… which makes sense, just because the binary’s static doesn’t make all of its files required for running are included. Using “strace” it was easy to see what it was looking for:
stat("/tmp/../share/nmap/updates/6.49/nmap-services", 0x7ffd54c68650) = -1 ENOENT (No such file or directory)
All I had to do was move the binary (currently in my “/tmp” directory on my local machine) in to a “bin” directory and copy the files in “/usr/share/nmap/” to “/tmp/share” and all worked fine (again, just locally).
Changing a few lines (for the file paths and arguments) in my slack bot / phantomjs code were required:
var target = text; // consider doing a .split(' ') and passing the resulting array in as processArgs for more command line options ;) var binaryPath = path.join(__dirname, 'bin', BINARY); var processArgs = [ target ];
I also had to copy the “bin” and “share” directories in to the code directory (making sure to “chmod +x bin/nmap”) before zipping up the Lambda code – and increasing the Lambda timeout from 3 seconds to a more reasonable duration – giving me Nmap running in Lambda 🙂
START RequestId: 43206f47-01a6-10f4-780d-1a8c9dc83002 Version: $LATEST 2018-01-24T01:03:21.320Z 43206f47-01a6-10f4-780d-1a8c9dc83002 Running nmap... 2018-01-24T01:03:27.520Z 43206f47-01a6-10f4-780d-1a8c9dc83002 Starting Nmap 6.49BETA1 ( http://nmap.org ) at 2018-01-24 01:03 UTC Nmap scan report for hypn.za.net (188.8.131.52) Host is up (0.071s latency). Not shown: 992 filtered ports PORT STATE SERVICE 22/tcp open ssh 25/tcp closed smtp 80/tcp open http 443/tcp closed https Nmap done: 1 IP address (1 host up) scanned in 5.60 seconds END RequestId: 43206f47-01a6-10f4-780d-1a8c9dc83002 REPORT RequestId: 43206f47-01a6-10f4-780d-1a8c9dc83002 Duration: 6163.33 ms Billed Duration: 6200 ms Memory Size: 128 MB Max Memory Used: 35 MB
So that’s 6.2 seconds of execution time, at $0.000000208 per 100ms (ignoring the free tier), makes a cost of $0.0013 for this scan… a lot cheaper than having a VM hanging around for a month to use only occasionally. Remember this could be triggered by an API Gateway endpoint or Slackbot. Now for “Nmap as a service”? 😛