Where should the security keys for attr_encrypted be stored? - ruby-on-rails

I have been looking at attr_encrypted, but it stores the keys in the code, which doesn't seem to be so secure. If my webserver gets breached, the encryption won't help much.
What are some options for which the data could still be secure if my webserver gets breached?

The keys have to be in memory in order to perform encryption and decryption. If your server is breached, you're pooched no matter how you store your keys; once an attacker has access to your local machine, all bets are off. If your app can decrypt data, they'll be able to, as well, depending on how much effort they're willing to spend to extract those keys.
attr_encrypted will protect you against things like SQL injections resulting in sensitive data being leaked, but if your app is compromised, then your attacker can get to anything your app can get to.
To make it harder, though, you can use password-encrypted keys. You can store your encrypted key on disk, and then when you deploy your app (or otherwise start it up), you will provide your password to decrypt the key into memory, then throw the password away. This still can't protect you against someone grepping through your process's memory, and it means that you have to have human interaction every time your app needs to start up (which could be a problem with automated monitoring) but it would substantially increase the difficulty of (but not prevent) extracting encryption keys from a compromised machine.

I use environment variables to set the keys. It's easy to have different approaches for dev or production.
An encryption concern:
# app/models/concerns/encryption.rb
module Encryption
extend ActiveSupport::Concern
module ClassMethods
def encryption_key
ENV['ENCRYPT_KEY']
end
end
end
In the model, use the concern's method.
class User < ActiveRecord::Base
include Encryption
attr_encrypted :name, :key => encryption_key
end
In development, use an .env file to store keys and retrieve environment variables with foreman. Heroku provides an easy way to set environment variables from the dashboard.

Related

Ruby on Rails - why should certain data be encrypted?

Encrypting data
Having just finished adding attr_encrypted to some models, I've come to think that a hackers job might not be that hard.
I've got a database on a different server to the app servers - however, chances are that if someone managed to get on to the db server, that person could also access the app server where the keys are stored (perhaps that assumption is incorrect) as they have the same type of security measures.
Issue 
Rails code is stored in a readable text format on the server, therefore the secret keys can be accessed. Surely if someone did get a hold of the database, and a hold of those keys the entire encryption of data becomes irrelevant as it simply (slightly) prolongs the hackers time to decrypt information.
If so, are there further security measure that can be taken, or have I completely missed the concept of encryption?
I've had a look around the attr_encrypted gem and associated readme and questions but could not find anything useful.
attr_encrypted protects your data from simple data leaks. Think NSA sniffing an inter-DC cable (where your db replication logs will be sent over) or disgruntled DBA (not having access to app source) dumping all your data into the internets.
If it is actual breach, intruders might not get access to both app code and database (depends on your architecture and security measures). If they have both, then yes, it's game over.
All in all, it's better to have it [for sensitive data] than not to have. Doesn't hurt, I'd say.
Don't put the keys in the app server and don't check them in to the git repository.
Instead, use environment variables. You can have different approaches for dev and production.
Very easy to do on Heroku (for example).
I have an encryption concern:
# app/models/concerns/encryption.rb
module Encryption
extend ActiveSupport::Concern
module ClassMethods
def encryption_key
ENV['ENCRYPT_KEY']
end
end
end
In the model, I do this
class User < ActiveRecord::Base
include Encryption
attr_encrypted :name, :key => encryption_key
end
In development, I use a .env file to store keys and retrieve with foreman.

Are Heroku's environmental variables a secure way to store sensitive data?

I use Heroku to deploy a Rails app. I store sensitive data such as API keys and passwords in Heroku's environment variables, and then use the data in rake tasks that utilize various APIs.
I am just wondering how secure Heroku's environmental variables are? Is there a way to hash these variables while retaining the ability to use them in the background somehow?
I came across a previous thread here: Is it secure to store passwords as environment variables (rather than as plain text) in config files?.
But it doesn't quite cover instances when I still need to unhashed password to perform important background tasks.
Several things (mostly my opinion):
--
1. API Key != Password
When you talk about API Keys, you're talking about a public token which is generally already very secure. The nature of API's nowadays is they need some sort of prior authentication (either at app or user level) to create a more robust level of security.
I would firstly ensure what type of data you're storing in the ENV variables. If it's pure passwords (for email etc), perhaps consider migrating your setup to one of the cloud providers (SendGrid / Mandrill etc), allowing you to use only API keys
The beauty of API keys is they can be changed whilst not affecting the base account, as well as limiting interactivity to the constrains of the API. Passwords affect the base account
--
2. ENV Vars are OS-level
They are part of the operating environment in which a process runs.
For example, a running process can query the value of the TEMP
environment variable to discover a suitable location to store
temporary files, or the HOME or USERPROFILE variable to find the
directory structure owned by the user running the process.
You must remember Environment Variables basically mean you store the data in the environment you're operating. The generally means the "OS", but can be the virtual instance of an OS too, if required.
The bottom line is your ENV vars are present in the core of your server. The same way as text files would be sitting in a directory on the hard drive - Environment Variables reside in the core of the OS
Unless you received a hack to the server itself, it would be very difficult to get the ENV variable data pro-grammatically, at least in my experience.
What are you looking for? Security against who or what?
Every piece of information store in a config file or the ENV is readable to everyone who has access to the server. And even more important, every gem can read the information and send it somewhere.
You can not encrypt the information, because then you need to store the key to decrypt somewhere. Same problem.
IMO both – environment variables and config files – are secure as long you can trust everyone that has access to your servers and you carefully reviewed the source code of all libraries and gems you have bundled with your app.

How can I encrypt a cached value before storing in Rails cache (on Heroku)?

I run a live RoR (Rails 3.21.11) application on Heroku that contains some sensitive (personally-identifiable) information that we'd like to cache out (~80kb of JSON on a per-user basis).
Since we run on Heroku, we obviously trust Heroku with this data.
However, to use memcached, we need to use a Heroku addon, such as Memcachier.
The business problem: we are not willing to put this sensitive information on a third-party provider's infrastructure unless it is symmetrically encrypted on the way out.
Of course, I can do this:
value = encrypt_this(sensitive_value)
Rails.cache.write('key', value)
But we envisiage a future in which ActiveRecord objects, as well as good ol' JSON, will be stored -- so we need every bit of data going out to be automatically encrypted, and we don't want to have to write an encryption line into every bit of code that might want to use the cache.
Are there any gems/projects/tools to do this?
Although I haven't had a chance to use this yet the attr_encrypted library might get you some or all of the way there.

Storing a shared key for Rails application

One of my Rails applications is going to depend on a secret key in memory, so all of its functions will only be available once administrator goes to a certain page and uploads the valid key.
The problem is that this key needs to be stored securely, so no other processes on the same machine should be able to access it (so memcached and filesystem are not suitable). One good idea would be just to store it in some configuration variable in the application, but newly spawned instances won't have access to that variable. Any thoughts how to implement this on RubyEE/Apache/mod_passenger?
there is really no way to accomplish that goal. (this is the same problem all DRM systems have)
You can't keep things secret from the operating system. Your application has to have the key somewhere in memory and the operating system kernel can read any memory location it wants to.
You need to be able to trust the operating system, which means that you then can also trust the operating system to properly enforce file access permissions. This in turn means that can store the key in a file that only the rails-user-process can read.
Think of it this way: even if you had no key at all, what is to stop an attacker on the server from simply changing the application code itself to gain access to the disabled functionality?
I would use the filesystem, with read access only to the file owner, and ensure the ruby process is the only process owned by this user. (using chmod 400 file)
You can get more complex than that, but it all boils down to using the unix users and permissions.
Encrypt it heavily in the filesystem?
What about treating it like a regular password, and using a salted hash? Once the user authenticates, he has access to the functions of the website.

Protecting user passwords in desktop applications

I'm making a twitter client, and I'm evaluating the various ways of protecting the user's login information.
Hashing apparently doesn't do it
Obfuscating in a reversable way is like trying to hide behind my finger
Plain text sounds and propably is promiscuous
Requiring the user to type in his password every time would make the application tiresome
Any ideas ?
You could make some OS calls to encrypt the password for you.
On Windows:
You can encrypt a file (on a NTFS filesystem)
Use the DPAPI from C
Use the DPAPI in .Net by using the ProtectedData class
CryptProtectData is a windows function for storing this kind of sensitive data.
http://msdn.microsoft.com/en-us/library/aa380261.aspx
For an example see how Chrome uses it:
http://blog.paranoidferret.com/index.php/2008/09/10/how-google-chrome-stores-passwords/
For Windows: encrypt the password using DPAPI (user store) and store it in your settings file or somewhere else. This will work on a per-user basis, e.g. different users on the same machine will have different unrelated encryption keys.
What platform?
On *nix, store the password in plain text in a file chmoded 400 in a subdirectory of the home directory. See for example ~/.subversion. Administrators can do anything they like to users anyway, including replacing your program with their own hacked version that captures passwords, so there's no harm in the fact that they can see the file. Beware that the password is also accessible to someone who takes out that hard drive - if this is a problem then either get the user to reenter the password each time or check whether this version of *nix has file encryption.
On Windows Pro, store the password in an encrypted file.
On Windows Amateur, do the same as *nix. [Edit: CryptProtectData looks good, as Aleris suggests. If it's available on all Windowses, then it solves the problem of only the more expensive versions supporting encrypted files].
On Symbian, store the password in your data cage. Programs with AllFiles permission are rare and supposedly trusted anyway, a bit like *nix admins.
You can't have your cake and eat it too. Either store the password (which you've ruled out), or don't and require it to be typed in every time (which you've ruled out.)
Have a good symmetric encryption scheme, it should make it difficult enough to decrypt the credentials that it won't worth trying.
Otherwise, if the service only requires the hash to be sent over the network, you can store the hast encrypted. This way even the decryption won't get the attacker closer to the solution.
However other users are true. If you store the data it can be found.
The key is finding the balance between security and usability.

Resources