Nmap results are a semigroup. Contribute to t94j0/haskell-nmap development by creating an account on GitHub.
Haskellers are known for sitting in their ivory tower and laughing at the plebians using inferior languages. If that’s true, then I’m a Robin Hood delivering this knowledge to the unwashed masses¹.
One reason people like Haskell so much is because it forces you to think about types according to the algebraic structures (and categories, more broadly) they implement. In the context of programming, an algebraic structure is just a fancy word for a type with operations that can be preformed on that type. For example, in C, the
int type can have addition, subtraction, multiplication, division, and the modulo operations applied to it. People who program in Haskell are obsessed with the operations that can be applied to a type. Sometimes they even like to make their own operations (this is why most Haskell code looks like garbage).
One of those operations is an algebraic structure called a Semigroup which uses the operator
<> in Haskell. A semigroup is just a binary operation that has associativity which means it takes two arguments, produces a single output (of the same type), and that operation must satisfy
(A <> B) <> C == A <> (B <> C) . If you think about it, addition satisfies the requirement of a semigroup. This means that you’ve used a semigroup before even if you didn’t know it.
On a different note, I’m taking the OSCP in February, so I’ve been looking at more nmap scans than I want to admit. My goal has been to root two machines a day. That wouldn’t be so bad if every machine only needed one nmap scan, but during the reconnaissance phase, you may need to run many scans to find vulnerabilities with NSE scripts or even using another scan type if the scan says the port is closed. Those scans are output in different files and a bit too cumbersome to read through when the OSCP is all about hacking quickly. There’s probably a tool for managing nmap scans already, but with the power of the semigroup, an nmap management tool should be easy to implement.
If we define the semigroup for an nmap scan to be concatenating the scan results, then we could fold scan results down to a single nmap structure and output the result. This is even easier in Haskell with the
sconcat function which “Reduce[s] a non-empty list with
<>.” For a useful semigroup, we need to think of some good merging rules. If we are given two nmap results, one where port 80 is closed and one where port 80 is open, which one should we pick? The one where port 80 is opened, of course, because we would rather know that a port is open rather than closed. The same goes for selecting the service that nmap believes is listening on that port. If we are given a service probe on port 80 and the table method says it’s HTTP while the probe method says it’s OpenSSH, which one should we choose to display to the user? The probe output because that’s more reliable. When the values are the same, we can just select one of them arbitrarily. Although these rules hide some through combination, the goal of this tool is hacking quickly. I’d prefer to read the current status of a machine’s open ports no matter the scan type used rather than reading a diff of different scans.
I ended up running with this idea and building a nmap scanner management tool. I added some extra features like the ability to scan from the tool itself and prepopulating the scans with nmap arguments I use often. The tool dumps the XML scan results into a directory so that you don’t need to run the scans again. Check out the README to learn how to make a scan.
Is this the most innovative thing in the world? Definitely not. It’s just merging nmap scan results. The larger takeaway, I believe, is that programming with algebraic structures in mind when thinking about your types can help generate new ideas and getting folks interested in the Haskell language for security tooling. I really enjoyed building this project and learning more about Haskell. It’s been a fun rabbit hole that I’m extremely glad I went down. Check out the project at https://github.com/t94j0/haskell-nmap.
If you want to learn more about Haskell, I’d highly recommend Learn You a Haskell for Great Good! and Haskell from First Principles as well as Seven Sketches in Composability if you’re interested in category theory.
[1.] I’m trying to be funny on the internet. Wish me luck.
If you liked the story, consider following me on Twitter: 0xdab0