A lack of transparency results in distrust and a deep sense of insecurityDalai Lama
SMS Privacy Security Test Results
16th Oct 2017
On the 7th of August a security vulnerability was discovered in SMS Privacy and, after fixing it, I released a report and resolved to have the service professionally security-tested, and to publish the results. This is that.
The test was initially carried out during September by a professional security tester who unfortunately wishes to remain anonymous (it was not me). The test didn't find any major vulnerabilities, but there were a handful of surprises. I fixed the important vulnerabilities, and the service was re-tested during October, by the same person, to ensure that the fixes were effective.
As promised, I've made the full report public, and I've also summarised the report below.
If somebody performs an sslstrip-style attack, they'll get to see existing user cookies. This is not severe, but is easy to fix, so I fixed it.
This prevents SMS Privacy from being loaded inside an HTML frame, which could allow a clickjacking attack, in which the attacker tricks the victim into clicking buttons on the SMS Privacy user interface by drawing a different interface over the top. Again, not severe, but easy to fix, so I fixed it.
This prevents sslstrip-style attacks from being able to work. Not severe, but easy to fix, so I fixed it.
This prevents a man-in-the-middle attack where the attacker is able to provide a valid certificate for smsprivacy.org. This is a more severe attack than the above, as it doesn't require SSL to be removed, but it is also much harder to carry out. I opted not to implement this as it comes with a strong risk of breaking the website in the event that the SSL keys need to be replaced. Not a severe issue, and the fix comes with some risks of its own, so I opted not to fix it.
If an attacker compromises a session cookie, he can continue to use it for a long time. This is done for convenience. If you don't want compromised session cookies to be useful to an attacker, you should log out once you're done. Not a severe issue, and the fix comes with some tradeoffs with convenience, so I opted not to fix it.
Clicking the Logout button did not actually invalidate old sessions! In combination with long session lengths, this is quite a severe vulnerability, as it means a compromised session cookie always remains valid for a long time. This is a relatively severe issue, and the fix was easy, so I fixed it.
SMS Privacy has no password policy. This is on purpose. If users want to set weak passwords, that's their prerogative. I'm more interested in allowing users to use strong passwords than preventing them from using weak passwords. I don't even consider this to be an issue, so I opted not to "fix" it.
There actually was protection against brute-force login attempts, but it was extremely weak. The rate limit has been made stricter since the inital test. This is not a severe issue, but it was easy to fix, so I fixed it.
Once logged in as an admin account, there was no extra layer of access control to prevent an attacker from looking at the admin panel. Having an extra layer of access control might have mitigated the original vulnerability that prompted the security test in the first place. The admin panel is now restricted by IP address in addition to user account. This is a relatively severe issue, and the fix was easy, so I fixed it.
Voicemail recordings are stored in MP3 files with GUID filenames. The filenames are generated by the upstream connectivity provider, and an attacker who can guess these filenames would have been able to listen to other users' voicemails. These files are now restricted so that they can only be viewed by the correct user account (implemented with X-Accel-Redirect in nginx). This is a relatively severe issue, and the fix was easy, so I fixed it.
The test also found a couple of bugs. One was that there is almost no restriction on what characters are allowed in usernames, and that username comparison is case-invariant and not strict about whitespace. This is a result of using MySQL to look up usernames. I think it's useful rather than harmful, so I left it unchanged. The second was that trying to buy a number for a non-existent country would cause the application logic to timeout without sending a response, causing a 502 Bad Gateway error from nginx. This is now fixed.
It's encouraging that the test did not find any vulnerabilities as significant as the one which prompted it. It was helpful to have a professional take a look at the security, and the "easy wins" in security upgrades were well worth the price. I intend to have the site re-tested periodically and I'll publish anything interesting.
If you have any comments, questions, or concerns, please get in touch: firstname.lastname@example.org.