As I continue on in my series about how I’m designing my app (because designing software is fun, and writing about it even more so), there’s still one more piece to the puzzle. Even though I protect the data in transit from my web server to the end user, and have written a process to protect against myself, how do I prevent an attacker from changing the content after I’ve uploaded it?
As I’ve said before, I really doubt that I’d be a target. Maybe I’ll say something inflammatory one day and someone will try to get even with me (like say Apple’s iPhone has an exploit or something). But at the same time, I’m trying to set an example for all the other people out there who want to build an app.
Suppose a hacker wants to steal my content. If he is determined, I’m probably going to be vulnerable no matter what. However, what I want to prevent is him changing my config file which then results in everyone getting free content. Now that would truly suck.
How can I prevent this?
The best way that I can think of is doing encrypting the config file. I run a sanity check at home and encrypt the config file, and then upload it to the web server. When the user downloads the app, they connect to the web server and pull the encrypted file down and then decrypt it locally on their tablet. Thus, a hacker can break in all he wants, but unless he knows the secret key that I use to encrypt the file – which isn’t on the web server – he will not be able to tamper with the file. In effect, the entire config file is acting as its own digital signature.
My flow is like this:
Which results in this:
This creates the following security model:
- I no longer need to rely on the security of the web server because even if the hacker breaks in, he cannot change the heart of the content (the config) which would cost me money.
- I am relying upon the security of the device which should hopefully prevent the hacker from downloading the app and reverse engineering the code in order to acquire the secret key. Not 100% perfect but an acceptable risk.
- I still have to keep my own local system secure. However, I actively manage my own computer. I don’t actively manage the web server. Not 100% perfect but an acceptable risk.
- In the event that a hacker does manage to change the config, the worst is that users will not be able to get updated content.
- However, #4 is a real problem. How can I detect if the data has been corrupted (either maliciously or otherwise)? I was originally toying with using asymmetric encryption. I would upload a plaintext version of the config file, although the app wouldn’t use it. I would also upload an encrypted config file that used my private key. On the server itself I would decrypt it with the public key. All this would be done with an automated task that runs every so often.
Then, I would compare the cleartext config file with the decrypted config file. If they matched, then everything is fine. If not, then the data has been corrupted and I could fire off an alert of some sort.
The problem with this approach is that:
(a) Public-key encryption (PKI) is very non-performant.
(b) The research I’ve been doing on the Internet strongly suggests that you shouldn’t encrypt data-at-rest using Public Key Encryption.
(c) I’m writing Perl scripts to encrypt the data, and in spite of all my coding skills I’m having a difficult time getting PKI to work (don’t ask).
I’ll have to come up with something else to detect data corruption although it is lower on my list of priorities since the encryption does prevent the worst case scenario.
That’s the model I have adopted in order to prevent tampering. It’s not perfect (nothing is) but I have gone out of my way to mitigate risk.