How to use encryption to bypass lack of trust of cloud provided database - security

Let's say I am creating a web app that focuses on privacy. I want to store all the users data in some DB on the cloud but don't trust cloud encryption. (Might be slightly related to zero knowledge)
Instead I would like a system in which the user creates a strong password which is used to encrypt and decrypt data from an api.
How do I store this password on a front end client following best practices.
Is it as simple as just applying a hash on both FE (frontend) and BE (backend)?
I'm looking for best practice advise.

Related

How to store third-party credentials (no api, no OAuth) for automatic reuse?

I've read several Stack Overflow threads, I still can't decide what is the best option for my case. And the most secure one.
Here is the story. My webapp is to help users automatically get an overview of some of their data available in some third-party website. I need to store for each user some third-party credentials. Each night or so, my server will connect to the third-party services on the users' behalf and retrieve the required data.
Most of those third-party sites do not implement any API or OAuth mechanism, so I was thinking to do some web scraping.
I've read in many places that storing the credentials in the DB is not a good idea - especially because my app needs access to the password (so it has to be encrypted in such a way I can easily reuse it).
So, I have two options left:
Whenever I access (via webscraping) the third-party service, I store on the server the cookies issued by that service, for future reuse. I encrypt them and keep them encrypted in a DB, and decrypt them only when I need them. The problem is that the cookie can be denied or expired after a while, and so the automatic process wouldn't work any more.
I store the credentials in the environment variables. I will be on Node.js and Heroku. That's an idea I found in another SO thread. But I'm wondering about the security of this idea. Is it really safe? No one can access them but me? And what about if I reach many users. Like 1000 users, with 10 services. That's 10000 credentials to store in the env variables. That doesn't seem like a good idea.
I found two interesting questions on Stack Overflow but they don't fit 100% with my use case.
Security model: log in to third-party site with user's credentials (that gave me the idea in point 1)
Rails storing third party credentials.. Anyone know best practice? (gave me the idea in point 2).
I add another answer because maybe this one will do the trick for you.
You said the main goal of your website is to have an overview of third party applications. But what if instead of updating this overview every night, you update it when the user logs in ? It changes everything, because you could use the user's password (of your website) as master password to encrypt (using AES) all the others.
If you do that, the communications between your server and the clients have to be encrypted with SSL pinning, because an attacker could perform a MITM, get the master password and all the others stored in the DB... (Even if in practice it's very hard because you need to hack the client AND the server)
Storing a lot of data that changes and grows in environment variables will never be practical, no matter if it's secure or not so this is pretty much out of the question, unless if you have a small fixed number of users.
Not storing credentials in the database is a very good advice, but the cookies are credentials and even if you store them encrypted, your app needs to be able to encrypt it to use it. (This is unlike the situation with verifying passwords of your users when you don't need to ever encrypt them, you only need to see if the provided passwords hash to the same values that you have stored).
This is a hard problem because to make it work you need to have some form of credentials (whether those are passwords or cookies) stored and ready to be used unencrypted (even if they are stored encrypted, you need to store the keys to encrypt it as well).
Also, what you are trying to do can be illegal. Mayke sure that you follow the TOC of every service that you're using or otherwise you may face legal trouble.
Plan for the attacker gaining admin access to the server. Your site will be very attractive to attackers, kind of a one-stop-shop for user credentials so you will need very good security of the login credentials.
There are more than two options for storing the credentials:
Use an HSM for the storage or individual credential encryption keys.
Keep the credentials on another dedicated server with no Internet access, 2-factor authentication and limit admin personal. Rate limit the access to this server and add rate alarms. Access this server on a per user credential basis over a non-Internet connection. The credentials will only be available to the Internet connected server in memory as used, not at-rest in a file.
Storing users credentials in a reversible way looks like a terrible idea anyway. But if you really want to store them, I suggest you to use the environment variables solution. But you can improve it. To limit the amount of data you store and don't have 1000000 variables as you said, you can just store an AES encryption key, store all credentials in a DB encrypted with this key, and you just have to get this key (which is in memory) and decrypt the DB. But there is another problem with this solution. As I said, this is stored in RAM memory, so it's not persistent, imagine your server has to reboot for X or Y reason... You will lose the AES key and also the credentials of your users... Moreover, if the attacker performs a memory dump, he will have access to the AES key...
I think the better idea is to store the cookies (in an encrypted way) and when this one expires, you alert the user (by mail, phone, notifications, ...) and ask him to fill his credentials again. But it's not a perfect solution ! Indeed the cookies are a type of credentials and shouldn't be stored either...

Encryption in an open-source program?

Currently I'm developing a Node.js webserver-app that I then want to make available for download and use. This app should feature accounts, so that you can log in with your account on the website created by the server.
Since that would require a password, I also have to think about security obviously. But now, I don't really know how I should protect the password while sending and receiving it.
For storage, I was about to simply create a hash of the password and store that hash somewhere, but what about the transfer?
I was thinking about SSL/https, but this would require a SSL certificate, and even if I got it for free somewhere, I couldn't share it in an open-source app(?).
I could also somehow hash the password in the website, and then just send the hash to the server, but I think this wouldn't be the highest standard of security as well, would it? Considering that no SSL would cause more disadvantages than just worse/none encryption.
Any ideas?
I was thinking about SSL/https, but this would require a SSL certificate, and even if I got it for free somewhere, I couldn't share it in an open-source app(?).
Use SSL/TLS. Even if it's an open source app, it doesn't mean that you need to share your private key too. This would undermine the whole concept.
Open source means that you share the code with some license. What the licensor does with it is not your consern as long as they conform to the license. If they want to use their own instance of your software under their own domain, they will have to create their own certificate (under their domain).
I could also somehow hash the password in the website, and then just send the hash to the server, but I think this wouldn't be the highest standard of security as well, would it? Considering that no SSL would cause more disadvantages than just worse/none encryption.
This is no solution, because you now changed the thing you want to protect to something else. The model doesn't change just because you hash it on the client. Now you need to protect the hash on the transport channel which is actually the same problem as you would have had before with sending a password.
Currently I'm developing a Node.js webserver-app that I then want to make available for download and use. This app should feature accounts, so that you can log in with your account on the website created by the server.
Federated accounts
If you want federated accounts across multiple instances of your app which are hosted by different parties.
You could look into OpenID as an identity provider for all instances of your app. You would then either require that users use a known OpenID provider or you setup your own default provider. You could release the code for your provider as open source, but it wouldn't be necessary for the app to function.
If the OpenID interface is not enough, there is always a way to establish a pairing between instances of your app. You would have to build an interface where different instances may share data.
Unconnected instances
If this is only about securing the communication without SSL/TLS, then I must say, this is impossible in the general sense.
You could however let every student register in person and use that password on client and server to derive a shared secret key (i.e. for AES). Then you could use CryptoJS to encrypt everything with AES and send it using AJAX. The problems are of course that (1) there must be a person that handles the registration and (2) this is vulnerable to man-in-the-middle attacks, because JavaScript crypto is bad.
Good thing is that Let’s Encrypt will be online soon. It will enable a semi-automated way to request free certificates for your domain. It will be so easy that you can do this as part of the normal NPM install workflow.
http://letsencrypt.org works great for this and is now available (I understand I am a little late to this one.)
You can check out https://github.com/DylanPiercey/auto-sni for automated Letsencrypt certificates.

How can an application store secrets in Google Cloud Datastore securely?

I am building an application that will run on Google App Engine (GAE). It will need access to data stored by the user in other systems (e.g. the user's Nest thermostat, Yahoo mail). The application running on GAE will allow the user to provide credentials for the other system. The application will store these credentials in Google Cloud (Datastore) for later use by an application running on Google Compute Engine on the users behalf. The application will also allow OAuth to allow the user to allow the application access the external system in the user's behalf. The application will need to store user credentials (username and passwords) or OAuth access tokens in the Google Cloud.
The application will need to encrypt the secrets before they are stored and be able to unencrypt the data to send it to the external systems. That is, the system will need to use symmetric encryption and therefor need to securely manage keys.
How can the application store these secrets in the Google Cloud Datastore (Datastore) securely? I think I am looking for something like the AWS CloudHSM for Google. That is, I would like to store each secret with a seed and key id and use the key id to get the key from a key management system. This implementation would also allow for key rotation and other standard security practices.
I think I am looking for a Google Cloud service or Google API that provides secrets management and only allows an app with the proper Google app identifier to access the secrets.
Is there a service within Google Cloud or Google APIs that will manage secrets? Is there another architecture that I should be considering?
By the way, the application uses Google Identity Toolkit (GitKit) to authenticate and authorize users to use the GAE hosted application. The application allows users to create accounts using either federate identities or username and passwords via GitKit.
Thanks,
chris
In the meantime, Google also added a Key Management Service: https://cloud.google.com/kms/
You could e.g. use it to encrypt your data before storing it in a database. Or, use KMS to encrypt an AES key to encrypt your data, and possibly keep a backup of your AES key somewhere in case you lose access to KMS.
App Identity Service might be what you are looking for https://cloud.google.com/appengine/docs/java/appidentity/#Java_Asserting_identity_to_other_systems
It lets you sign content with an application-specific private key, and provides rotating certificates to validate signed content.
So as far as I can tell the answer is that you can't. What you are looking for is an equivalent to KMS. That service let's you create and manage keys and do a bunch of your own crypto stuff. It's really cool and it will allow you to quickly do incredibly strong crypto with just a few simple lines of code. Azure has a similar service called KeyVault. It lacks automated key generation and rotation as far as I can tell, but other than that it's good. At the time of this response there was not an equivalent service for Google. They have an internal KMS which they used for crypto operations and you can provide your own keys, but that's pretty much it. Not quite the same thing that you get on KeyVault, and nothing like KMS.
That said there is hope. You can do one of two things:
Create a VPC and use an HSM from somewhere else. You could use RackSpace, or you could simply use AWS KMS. That sounds crazy but it's actually a good idea and the extra management is worth it. In general the most secure solution separate the keys from the encrypted data, particularly at rest. That means that keys in one data center and encrypted data stored in another data center is the most secure solution. That sounds like hard stuff, but thankfully I've made an opensource project which makes it very easy for you called KeyStor. With KeyStor you can get a data center that deals with encryption services set up in a day, no problem, and you can use AWS very cost effectively.
Set up your own cypto service, skip the HSM integration and simply be careful about who has access to the machines that maintain your keys. You can do this with KeyStor as well, and if KeyStor doesn't quite do what you want, that's why it's open-source. Take the code and build what you need to build.
You could store secrets in storage (e.g., in Datastore, Google Cloud Storage, or another storage system of your choice) and encrypt those with a key from Google's Cloud KMS.
Here's some documentation from Google on secret management, and here's a codelab on specifically encrypting data in Google Cloud Storage at the application layer using Cloud KMS.
For the Google Cloud managed service that provides the API for secure storage of secrets, see Google Cloud Secret Manager for more details.
Secret Manager is a secure and convenient storage system for API keys, passwords, certificates, and other sensitive data. Secret Manager provides a central place and single source of truth to manage, access, and audit secrets across Google Cloud.

Implementation of #BurtBeckwith best practice for OWASP Insecure Cryptographic Storage for Grails

In the book Programming Grails, Burt Beckwith gives some really good insights about how to develop Grails applications which follows OWASP Top 10 recommendations in chapter 9.
Punctually,I'm trying to implement the recommendation for Insecure Cryptographic Store. That reads as follows
Do not store passwords in config files, or even in files on the filesystem. Instead, create
a web page that you use to initialize the system where people trusted with passwords
enter the passwords (using SSL!) when the application starts up. Ideally, you shouldn’t
trust any one person with all of the information to start the system. For example, to use
JCE encryption, you will need to load a java.security.KeyStore , and this requires a
password, and you use this to create a javax.crypto.SecretKey , which also requires a
password. Use different passwords. If two people know the key store password and two
other people know the key password (it’s a good idea to have backup users in case
someone isn’t available), then no one person can decrypt the data or be coerced into
giving someone else access.
I want to secure the Amazon AWS[1] Access Credentials that will be used by the application in order to use the KMS[2] API call to secure encrypt and decrypt information.
I would like and example about how this can be achieved. My initial idea is to use a Service in the Singleton scope which holds the credentials and those credentials are setted by a Controller which is responsible of loading the KeyStore and the SecretKey used to decrypt a previusly encrypted and store AWS Access Credentials.
[1]http://en.wikipedia.org/wiki/Amazon_Web_Services
[2]http://aws.amazon.com/en/kms/

Storing SSH login credentials?

I am creating a web application that involves logging into servers via SSH and storing the details. Credentials will include root login details.
What are the best practices for storing this data safely and securely? Authentication using asymmetrical keys will be used be used but not the concern here.
The plan is to use MongoDB and Node.js.
The best way to encrypt data that is extremely sensitive like that, is to use AES 256.
You'll basically want to AES256 encrypt the login credentials in some sort of file (like a CSV), and make sure the encrypt key is stored somewhere extremely safe (on a computer not connected to the internet, for instance).
This is really the only way to handle that sort of information.

Resources