Concurrent Vulnerability scanning with Erlang

Background

Following the recent series of major vulnerabilities, a trend that’s become popular has been the online scanner. It was far easier to test a service using and online Shellshock scanner, or an online Heartbleed scanner, or in this case, the MShttp.sys vulnerability. This scanner was inspired by this particular scanner.

Scanning larger amounts of machines has however, been historically quite slow. If any of the listed scanners simply iterated across a list of machines, it could take quite some time to run across reasonably large networks.

Concurrent scanning

That introduction is a perfect place to introduce the concurrency capabilities of Erlang. Concurrency has been a huge trend lately, mostly in relation to the (stupid) argument that argues Node.JS has concurrency and therefore it’s the ony platform that can scale to handle a personal blog.

A much more powerful use of concurrency exists in this snippet of code, which I see myself using regularly.

{% highlight erlang %} Pid = spawn(fun() -> receive {From, execute} -> From ! {N, function(N)) } end end), Pid ! {self(), execute}, {% endhighlight %}

Which, in short, tells Erlang to run a particular function concurrently, and send the results back to the parent. In this example, I’ve written a scanner for CVE-2015-1635. By utilising this loop, I’ve found you can perform such a scan incredibly fast.

The time I’ve quoted is 200ms, which accounts for a certain amount of network latency, in scanning an entire /24 of network hosts. Without that, let’s see the below:

{% highlight bash %} $ time wget http://erlvulnscan.lolware.net:8080/?network=127.0.0.0 -O -

2015-06-12 10:15:48 (152 MB/s) - written to stdout [12593/12593]

real 0m0.062s user 0m0.003s sys 0m0.007s

{% endhighlight %}

Yes, that’s less than one second to:

  • Make an HTTP connection to each server from 127.0.0.1 to 127.0.0.254
  • Run the vulnerability check
  • Format the results nicely in JSON and render to the user

That’s an impressive time. I look forward to being told it should be done in JS.

Implementation

Source code for a complete implementation can be found here:

erlvulnscan on Github

A key design goal is to allow the project to easily forked and run new types of vulnerability scans, which I am likely to do at some point. A functional implementation can be seen here:

erlvulnscan demonstration

Although the project is scheduled for aesthetic improvements, the backend is now stable.

Design

erlvulnscan is an Erlang OTP application built using Cowboy and Jiffy, and managed by rebar.

Rather than play with Cowboy routes for static data, assets such as the front page are intended to be served using nginx, with a routing rule to forward the API.

Code is intended to be dialyzer and edoc friendly.

The frontend uses ReactJS, although at this stage it is largely a copy of the React tutorial. Starting using this base will allow it to be rapidly improved however.

TODO

In the coming weeks, the project should see the following. Hopefully in time for a new major issue to scan for. This roadmap exists here both to serve as my own roadmap, and avoid the inevitable situation where the only contact someone makes about my this page is point me in the direction of something like Grunt.

  • Properly modularise the scanner, so replacement of a single file can facilitate management of a new vulnerability
  • Fully dialyze and tidy up all warnings
  • Frontend aesthetic overhaul and implementation
  • Route changes, entire project should be able to be served on one port!!
  • Frontend code overhaul. Many function names are straight out of ReactJS tutorial. JSX should be converted and minified on the backend.
  • Learn and implement EUnit
  • Implement Elvis
  • Implement Grunt for the frontend
  • Hot code load implement and test