Securely storing password from user to their third party services - security

I need to store password that our users use to connect to third party services (primarily their database). To add complexity to this, the user might be able to add more users later (of course with the same permission levels) so they would be able to connect to those services as well. What would be the best (secure) way to do it?
Storing the hash (and salt) won't be an option since we need to use the password to access to their third party services.
I know there is oAuth option, but their third party service might not have oauth in place. Also not sure if configuring oauth on their database would be that simple.
Another option is to have another system for storing the password (eg. KMS). Encrypt the service's password with the user's own password (master password) so the system can decrypt it later (but not without user's own password).
Something like these:
How do I securely store passwords to a 3rd party webservice in my database?
Security model: log in to third-party site with user's credentials
Is there a better way to do this kind of thing? What would be the security model look like and the checklist to securing it? Or even should I refrain from developing this system at all? Any insight would really be appreciated.
** EDIT **
As some comments suggested, I might be not clear enough on the situation and goals here. So to clarify:
We are trying to build a No-Code feature in which user might be able to connect to third party services holding their data or their own database. Something like Bubble
As for the goals (and threats), we are trying to make the key (password) relatively un-readable (and un-usable) by external threat or even our own developer but our system (with authorisation from the owner) can still use it
Not sure if this is ok to ask here (otherwise just ignore it), but I wonder what kind of method system like Bubble (their database connector plugin) use
The links I showed (and given by gusto2) above recommend the use of HSM, which is costly (even for the cloud solution). Is there a lower cost alternative method?

Related

How can I store a password that I will use to authenticate in a different platform?

I have logins for different platforms (say facebook credentials for example), that I want to securely store in a database. I want to be able to use the APIs to login to these platforms through the app (automatically).
Is there a safe way to store these logins without losing them (can't hash them).
Thanks
You don't want to know the safe way. You want to know the secure way. :)
Guess what, there isn't one. Imagine this. You want to store some sensitive data. You use encryption. Great. Now the data is secure. What do you do about the key? Let the user remember it? No, you wanted to automatically do stuff, so you need to have the key lying somewhere (not that the user can remember random >128 bits...). What do you do with the key then? Encrypt it? Well, you already done it once. You can obfuscate, hide, put access rights and so on. If you want stuff to happen automatically, there needs to be a key lying around somewhere.
Look at KeePass for example. Imaging you could have stuff as secure as KeePass is. This is as far as you can go.
It is probably too much risk for your app to store credentials for third parties. If I were your target user, I would certainly not trust a platform to store my credentials to facebook and others in a way that the platform itself might have access.
Let's assume you assessed and accepted this risk, and your users will trust you for some reason. One thing you need to acknowledge is that if your platform is compromised, all of the credentials stored will be compromised, but you can limit the impact of such a breach, and that's what you should do.
You should use a hardware security module. Now that's traditionally really expensive and complex, but you can now use a HSM as a cloud service. All major cloud platforms have CloudHSM solutions, and also higher level services based on the HSM itself.
The point in a HSM is that a stored key is never released. You generate a keypair in the HSM, and there is no way to extract the private key. For cryptographic operations (like encyprtion, decryption) you send data to the HSM and it does it for you, without you ever knowing the key. The point is that even if there is a compromise, the impact is limited, because attacker access is timebound, and also you can apply proper auditing and access control on the HSM itself.
But the HSM does not store website credentials, it stores keypairs. So you can use something like Amazon Secrets Manager (or you could build your own, but that's really tricky), which itself is based on AWS KMS, and encrypts your secrets with a key stored securely in the HSM.
So you would
create a KMS key, if you have large customers, then probably one KMS key per customer (or if corporations, they can probably provide their own KMS keys, see Bring Your Own Key, BYOK)
use secrets manager to store secrets, ideally encrypted with your customers specific key
run your app in say AWS with an IAM role that allow it to access the secrets in Secrets Manager
Note that a similar architecture can also be set up without AWS or any other cloud provider, but it's a lot more complex.
What this provides you is
auditability (who used which key/secret/credential, and when)
possibility to revoke access
timebound access to your credential store even for an attacker that did compromise your whole application
an option to let your users know if there was a compromise in which case they will need to change their credentials in downstream services
BYOK as described above
Note that this is a fairly complex thing tom implement and get right, and also costs non-negligible money to operate. You would need processes and technical controls to mitigate numerous other risks. This is just a brief introduction into what you could actually do to secure those secrets.

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.

I need an authentication / identity server

We need a new authentication server for our large business system (ERP). The previous authentication server was internally developed. Now that we need a new one we will first try to find an already existing authentication server that we can use. Can anyone recommend an authentication server? Remember that this is a business system, so things like Facebook login is not an option. Do microsoft / google or others have any authentication servers that can be installed and run locally?
Seems like you need to store the usernames in your DB, because you do not want to be dependent on 3rd party to store them for you. Furthermore, you do not want to force your users to have accounts in the 3rd party (e.g. Facebook, Google).
So AFAIK, the only option for you is to maintain your own authentication-server...
The good news: you have oauth-2 packages that you can use, and I've written a project that implements all authentication-server flows, such as registration, forgot password, etc.
You can see a demo here.
HTH.

How to securely store and share log in credentials?

Hi and thanks in advance,
I am looking for industry best practice or a ready made app to store and share passwords for for network resources.
My current situation is that I have a number of people that need to access applications as a specific superuser in order to access some features of these applications. The applications are third party build and cannot be changes to grant access to the required features for anyone but the superuser account. Normal admin accounts have elevated rights but things like creating accounts have to be done via the superuser account.
For security reasons I would like to periodically change the superuser accounts' password. Because of the number of people that need to be able to log in as superuser changing the password would be problematic and a logistical nightmare.
I'm looking to purchase or create an application that would:
Track who is looking up the password and to what resource
Allow me to specify what passwords a user can retrieve
The data should be stored and transmitted ultra securely
Preferable this would be an on-line application (I have Mac and Windows clients)
Keypass is great for this kind of thing. It provides a strong encrypted database of passwords and secure information. This can be accessed share via svn/dropbox/fileshare implementations using a master password.
This is more for a master database of secure data you can set up additional databases, maybe per user, but it starts to get a little away from what it's deigned for.
I would do a C# app that checks with a web service if the user can run the app and with what permissions, it would then be sent the encrypted credentials for a 1 time run, the service would log the request. This would all have to be done securely, so the service would use SSL and preferably certs between the systems. You have a good bit of research here to figure this all out, and you might have to use Java if you want mac... but I dont know how well that can launch apps as other users.
Solution #2 would be to use KeePass. You will have to be creative.

Resources