Go Headless, be vulnerable

During some routine network security testing recently, it was pointed out to me that my laptop had X running an open network port — anyone could connect to it and control my desktop as if they were me.

Being that I’m fairly conscious of network security, and particularly when you are surrounded by some very technical people with a mischievous sense of humour, this is something that I would never have manually configured.

At first I was confused; when I scanned my machine myself, the port was closed. Then, out of curiosity, I ran the scan again. Lo and behold, the port was open. I was now even more confused. What had changed?

Looking at my screens, the only difference was that I had not been running our ruby test suite during the first scan, whereas I had been running it during the second. Curiouser and curiouser.

Then it struck; I was running the end-to-end suite that drives browsers. To stop them popping up and stealing my focus, I was running in headless mode. This still launches the browsers, but in an xvfb session configured using the Headless gem.

Initially, I wondered if this gem was doing something a bit naughty. But digging through the source, I found this little beauty:

result = system "#{CliUtil.path_to("Xvfb")} :#{display} -screen 0 #{dimensions} -ac >/dev/null 2>&1 &"

Cool, all the gem does is shell out to xvfb — that’s fine, it’s just a wrapper gem, that’s understandable. But unfortunately, xvfb launches with tcplisten turned on by default.

Now, I’m sure you can see the problem with trying to add extra parameters in a nice way, as it’s just string interpolation for those two. Ah! But it is just a string…

HEADLESS = Headless.new( display: ( ENV['E2EDISPLAY'].to_i || 100 ), reuse: true, destroy_at_exit: headless_destroy_option, :dimensions => '1280x1024x24 -nolisten tcp' )

It’s not ideal, it’s not pretty, I’d much rather submit a patch to Headless (which I will do in due course), but this is a useful workaround to close a fairly substantial security hole.

The importance of this is far greater when you realise that all of our end-to-end continuous integration and regression tests were running with this, across many running nodes, meaning that X sessions were randomly opening up all over the developer network.

For me this has proven to be a good reminder that, although third-party libraries might not be the exact solution that you require, and may not even have considered something you hold dear, reading their source can provide an insight not only into how they work, but into how you might adapt them to your needs.

Print Friendly

Leave a Reply