How to Protect/Encrypt MongoDB Data - node.js

I have an existing NodeJS app that allows users to store personal information in a mongo database. This data must be encrypted in some form, or at least not tied to a particular user.
I was planning on using the NPM mongoose-encryption package, but it doesn't work with updating fields. Right now, passwords are hashed with a salt and both are stored in the user document. I was thinking another option could be hashing the user id and using that to associate other docs with the user. This way, if there is a security breach, the data will be unusable without knowing which user it belongs to.
Any thoughts/recommendation on this? What is the best way to protect users personally identifiable information?

Hashing user id or username might not be a good idea, it is ok for user login. but it might bring more pains when u trying to do some aggregation or statistics on the stored data, every time you make a query related to user id, u might need to hash it first and then construct the query.
Besides, user id/username column becomes unsortable and it is hard to build index on top of it, since hashing is not invertible.
Just my personal thinking.

Related

Encrypt all user data in my web application

This is not a typical StackOverflow question as it is quite specific and bound to my current project. Given my project (GitHub link), I would like to encrypt or handle all user data in a way that impedes me as a service provider to view data of specific users. This would probably not be feasible in a typical webapp with a rational SQL database. I am using Redis with data that is basically structured as follows:
Users can view their data filtered by two dimensions: A time range and a domain. These are further grouped by another dimension, which are multiple charts. So there is data for countries, top landing pages, etc (It's a web analytics app). Internally of course I also need to have the user baked in as dimension in the key that holds data for a chart and of course there is some indexing stuff going on.
Now here is the idea: I could hash the access key for this single charts - I am only doing direct key access anyway and no scanning (filtering over keys). Furthermore I would only save the hashed username in the database so the username becomes the missing information I don't have to retrieve the payloads.
This would leave me with the cleartext payloads, which represent specific charts given by specific user selections (Yes, I only save the user data in an aggregated form btw) but I would have no reasonable way to map a single chart to a specific user or domain. Given I have ~70 integrated users at the moment, it would be not feasible to try to manually map data points to specific users (But I could still see all domains a "user" uses).
Of course this is relying on the username being somewhat a secret and I would only save the hashed username to the database and only handle the cleartext username in ram. I can still greet the user since the cleartext username is saved in a cookie :-)
With usernames being too short and having almost no entropy of course I could brute force my own database in order to regain the missing links and access to all data individual users have. But before doing this the more obvious way to "cheat" would be to just run another software (without that hashing) on the server but still stating everything is encrypted. So my point is that the presented solution is good enough for a hosted service.
Does this sound plausible? Would such an approach add an additional layer of security or be meaningless because it is too easy to circumvent?
In my opinion I could compare this with locking a bicycle with a very cheap lock. Even if the lock is easily breakable it does have a strong symbolic meaning that someone that breaks the lock is doing something worse than stealing a bicycle that has no lock at all. So even it is not possible to protect user data from a hosting provider, it is possible to make the work to do so more "dirty" and such socially and legally less acceptable. Does this makes sense? :-)
So my question is: security by obscurity or sound approach?
Cheers!

There is a way (pattern) for secure data of other users in rest services?

In the context of expose user resources (user data) through restful sevices,
I want that the data of one of the users can't be accessed from other user, if the second user's not the owner of that data.
Instead of reinvent some complex model to map each user identity with its data (programatic solution)
, are there some best practices or design pattern or any kind of model that i can apply to this problem?.
With user profiles i assure that some kind of user can't access data of another kind of users but i cant be sure that user of the same profile not will access the another user data.
You'll either need to authenticate the user and then associate the user with the data (which you're calling complex/programatic) or you simply make the data unreadable to everyone except the user who creates it. Like the user encrypts all data with a private key and then it is stored on your server. This is a little different, because anyone can access the data, they just can't make much sense of it.
I don't recommend the second approach, as you'll have no ability to use the profile data (birthdates, interests, whatever you might have in that profile), and also, everyone can see the encrypted data.
But your idea that this is reinventing something complex is paradoxical, if it's so complex why reinvent it when there are a ton of plugin based authentication schemes that you can use. Is security in this case an afterthought? If so, it shouldn't be. If you are assuring this, it should be a high priority to deliver it.

How to migrate passwords to a different hashing method

When changing the password-hashing algorithm for an application, how should the system migrate the values already saved in the database? I am well aware of the fact that I can't migrate them in their hashed form but that I need to have the input data in order to calculate the new hash.
There are two situations in which I have access to the input data:
During login
When the user changes her password in her profile settings
obviously only during one of these I am able to save the new hash to the database to migrate the password.
Although all of my colleagues are voting for method one my gut tells me to not do that. Is there a recommended way?
I see no reason not to do this on logon. Is there a reason you don't want to do #1? You validate against the new hash, if that fails, validation against the old hash algorithm. If that works, I'd then write the new hash over the old one. This means that your passwords will be converted faster, since users probably logon more than they go to change their password. Unless you force people to, I doubt most will change it on their own.
Here's an alternative solution if you don't won't to touch the old authentication code (ie. switching to a new framework) or just want to rid yourself of the old password fields:
Backup the existing table of passwords and then delete all the existing entries in the passwords column in this table (and update the column type if necessary of course) so that it is ready to receive fresh passwords with the new encryption.
The next time users try to log in, check the passwords table and if the user exists with no password, then prompt them with "We have implemented a system wide upgrade and all accounts will need to be re-verified from email. We have sent you an email, please use the email to complete your account upgrade. We apologize for the inconvenience."
The users will go to their email and click a link that may say something like "Re-confirm my account". They will be taken to a page that requires some secure token parameter, received from the link given in the email. This page will now ask them to enter their username and password (more importantly password) to complete the upgrade. You can require they enter the password twice, to guard from typos. Technically, you are creating their password here. Just simply ask for it in 2 inputs labeled "password" and "confirm password".
There are of course both pro's and con's to this solution as well, in comparison to the others. The good thing is you don't have to add old hashing code in your new environment and have it sit there until the one day all your users have finally logged in again. But this solution comes with the price of writing extra code as well (code to send emails/token and so on). You'll have to compare that work to the work involved with your proposed solution of intercepting the form input coming in, checking against old hashing, and then passing onto new authentication code. Just another idea for you.
Look at this IT scenario: Company A Took over Company B with similar business model, All the customers need to be merged into one bigger system owned by Company A, while decommissioning user system in company B which has different password hashing algorithm,
The best Implementation to getting this done is to Force password Change for all migrated users via their registered email address.
It's hard to get specific advice without knowing specifics about the problem. I'm going to assume that the reason you want to change your password storage strategy is because your new strategy is going to be significantly more secure than your existing strategy.
If that's the case, then what's the possible advantage to waiting? The idea is to mitigate the existing risk. Users, realistically, very rarely change their passwords. If you want to migrate to a new storage strategy, you should probably do it at login or you're just going to have a big database full of passwords with dubious security.

How to set up a web-based password database

I've currently thought about a web-driven password database with multiple accounts and the login/passwords stored in a Database engine like MySQL or Oracle. Each password should only be available to some of the users:
User A logs in, creates a new login information and ticks some checkboxes to make this information available to User B and User C. User D and E should not see it.
My first thoughts:
The passwords are stored encrypted in the database.
The main problem here is of course, if you have access to the server you can take a look a the script and detect the decryption algorithm with enables you to de-crypt all the stored passwords at once.
So I thought, each user gets a master password to the password tool which is part of the encryption/decryption algorithm (user enters this master password and the logs in with his own credentials). This had the benefit that a third person could not simply take a look at the scripts to see how they are decrypted exactly as he had to know the master password. But of course it's still possible for users with very limited access to decrypt all of the passwords as they know the master password.
So basically my question is: how is it possible to have a webbased multiple user password database which is not just cracked easily by looking at the plain sources, if someone gets access to the server? Is it possible to make the decryption somehow dependent on the user logins which may officially see the password?
Thanks for any hints on this!
Notice to make things more clear:
It's intended to be a password database where login credentials for different applications are stored and users can log in and see what credentials they have to use for these applications. Like password manager tools like 1Password and so on. It's just a simple lookup table with username/password, it should not insert or interact with 3rd-party applications.
The solution is here:
Is it possible to have encryption with multiple private keys (PHP)?
Use a one way hashing algorithm like MD5 or SHA-1 (or some of its stronger variants). This way, there will be no way to reverse engineer stored passwords.
Have you looked at any products like Passwordstate? All the passwords are encrypted within the database, they can be shared amongst multiple people, all the pages are obfuscated for further protection, and it integrates with Active Directory for authentication.
There's a free 10 user license if you want to check it out.

How does hashing and salting passwords make the application secure?

As much as I understand it is a good idea to keep passwords secret from the site administrator himself because he could try to take a user's email and log into his mailbox using the same password (since many users use the same password everywhere).
Beyond that I do not see the point. I know it makes more difficult the dictionary attack but... if someone unauthorized got into the database, isn't it too late to worry about passwords? The guy has now access to all tables in the database and in a position to take all the data and do whatever he wants.
Or am I missing something?
The bigger problem is that people tend to use the same password everywhere. So if you obtain a database of usernames and unsalted passwords, chances are good they might work elsewhere, like hotmail, gmail etc.
The guy might be in a position to do everything he/she wants to your system, but you shouldn't allow him/her to do anything with other systems (by using your users' passwords).
Password is a property of your users. You should keep it safely.
Many of your users use the same credentials (usernames/passwords) at your site as they do at their bank. If someone can get the credentials table, they can get instant access to a bunch of bank accounts. Fail.
If you don't actually store passwords, then attackers can't steal your users' bank accounts just by grabbing the credentials table.
It relies on the fact that a hash is a one way function. In other words, its very easy to convert a password into a hash, but very difficult to do the opposite.
So when a user registers you convert their chosen password into a hash and store it. At a later point they login using their password and you convert the password to its hash and compares it this is because, to a high level of probablity if (passwordhashA == passwordhashB) then passwordA=passwordB.
Salting is a solution to a related problem. If you know that someones passwordhash is, say ABCDEF, then you can try calcuolating hashes for all possible passwords. Sooner or later you may find that hash('dog') = ABCDEF, so you know their password. This takes a very long time, but the process can be speeded up by using pre-created 'dictionaries' where, for a given hash you can look up the corresponding password. Salting, however means that the text that is hashed isnt a simple english word, or a simple combinationofwords. For example, the case I gave above, the text that would be hashed is not 'dog', but is 'somecrazymadeuptextdog'. This means that any readily available dictionary is useless, since the likelyhood of it containing the hash for that text is a lot less than the likelihood of it containing the hash for 'dog' This likelihood becomes even lower if the salt is a random alphanumeric string.
The site admin may not be the only person who gets access to your password. There is always the possibility of a dump of the whole database ending up on a public share by accident. In that case, everybody in the world who has internet access could download it and read the password which was so conveniently stored in cleartext.
Yes, this has happened. With credit card data, too.
Yes, it is highly probable that it will happen again.
"if someone unauthorized got into the database, isn't it too late to worry about passwords?"
You're assuming a poor database design in which the authorization data is comingled with application data.
The "Separation of Concerns" principle and the "Least Access" principle suggest that user credentials should be kept separate from everything else.
For example, keep your user credentials in an LDAP server.
Also, your question assumes that database credentials are the only credentials. Again, the least access principle suggests that you have application credentials which are separate from database credentials.
Your web application username and password is NOT the database username and password. Similarly for a desktop application. The application authentication may not necessarily be the database authentication.
Further, good security suggests that access to usernames and passwords be kept separate from application data. In a large organization with lots of database users, one admin should be "security officer" and handle authentication and authorization. No other users can modify authorization and the security officer is not authorized to access application data.
It's a quick audit to be sure that the security officer never accesses data. It's a little more complex, but another audit can be sure that the folks with data authorization are real people, not aliases for the security officer.
Hashed passwords is one part of a working security policy.
Of course, storing hashes of passwords instead of plain-text does not make your application secure. But it is one measure that increases the security. As you mentioned if your server is comprised this measure won't save you, but it limits the damage.
A chain is only as strong as its weakest link
Hashing passwords is only strengthening one link of the chain. So you will have to do more than that.
In addition to what has already been said regarding salting, there's another problem salting solves :
If you use the same salt everywhere (or no salt at all), it's possible to say just by looking at the database that user foo and user bar both have the same password (even if you don't know what the password is).
Then, if one achieve to get foo's password (using social engineering for example), bar's password is known as well.
Also, if the salt is everywhere the same, one can build up a dictionary dedicated to this specific salt, and then run a brute-force attack using this 'salted' dictionary.
This may be a bit off topic, but once in a while, I notice some websites are not using hashing (for example, when I click the forgot password button, they send me my password in cleartext instead of allowing me to chose another one).
I usually just unsubscribe, because I don't think I can trust a website designed by people not taking the elementary precaution of hashing passwords.
That's one more reason for salting:)
People seem far too complacent about this! The threat isn't some guy with shell access to your system or to the backup media, it could be any script kiddie who can see the unprotected (but dynamic) part of your site(*) and a single overlooked SQL injection threat. One query and suddenly he can log in as any user, or even as an admin. Hashing the passwords make it far less likely that the attacker can log in as any particular user using their password -or- update a record with their own password.
(*) "unprotected" includes any part of the site that can be accessed as a self-registered user. Contrast this to a bank site, for instance, where you must have an existing bank account to gain access to much of the site. An attacker could still open a bank account to gain access to the site, but it would be far easier to send big guys with bigger guns after him when he tries to crack the system.

Resources