Is it necessary to encrypt all the data in node.js - node.js

I am currently learning Node.js authentication. There's something I don't understand and I would be grateful if you could help me. Well I know how to protect password with "passport", "session"... Currently I am making ToDo list website. If hacker somehow got access to my database, he would see all the data users have written without knowing password, right?
So is it necessary to encrypt the whole data?

I'm no security expert but you can think security as layers. Encrypting the whole database is another layer of security. If a hacker would get physical access to the server and the hard drive was not encrypted, yeah he/she probably could read the data. But I would still think that it's more important to have the "accessing" layer secure (login process etc.)
You need to decrypt the data for your users anyway and if the login process is not securely programmed, the hacker could access the data that way.

Related

Security in nodejs

I am new to NodeJS and have made a web application login feature using passport.
I know when someone registers an account, the app needs to hash their password and save the hash to the database. But when I use console.log(), the object still contains the user's password in plain text. I have a feeling it's not safe but I'm not sure how to approach this. Can anyone explain what I am doing wrong here?
Irrespective of whether it is node.js or any other framework used for backend development, it is a good practice to pass the sensitive data such as passwords in encrypted format.
Typically we prefer using Json Web Tokens(JWT) - https://jwt.io/
You can use https://www.npmjs.com/package/jsonwebtoken to encrypt and decrypt it.
Don't bother too much with it.
If a malicious agent has access to the runtime environment of your server he will be able to do, possibly, everything. Even if you are using jwt he will be able to get the secret and decode it easily.
Focus on:
leaving the password encrypted in the database (as you did very well)
using SSL between you and the entry point on your servers network
making sure that you only expose the necessary, having a firewall/barrier in the exterior of your server is a very good pratice
sanitize and validate your server inputs to avoid injections and exploits
I just want to say only on don't use third party API or packages for it

Secure web programming - Best practises in authenticating users

Getting into web development and would like to become good at making secure websites. Any general typs/answers to any of the below would be greatly appreciated.
So got some questions on the authentication side of things:
How should the password typed on the client be encoded and sent to the server - assuming https is already in use? i have heard of some suggesting that only the hash is sent for security for example. Should it be encrypted client side - how?
Similar but on server side. How should the passwords be saved. Actual, hash, etc? Should they be encrypted - how?
Also, is there a kind of architecture that can protect the passwords in such a way that if one password is compromised, not everyone else's is? For example, if all passwords are stored in one file then access to only this one file would compromise every user on the system.
if only hashes must be stored - how to handle collisions?
Once authenticated should you just rely on session IDs to maintain authenticated status throughout? I have read on tips to reduce session highjacking and was therefore wondering whether it is a good idea/the only idea in the first place for keeping users authenticated.
Is there a safe way to provide an autoLogIn feature so that the browser remembers the password - similar to social network/web-email clients?
-------------
Extra - preventing attacks
Are there any tools or even just some common practises out there that must be applied to the username/password entries provided to prevent injection or any other kind of attacks?
If I use a Java development environment (using PlayFrameWork btw) how likely is it in general that attackers could include harmful code snippets of any kind in any form entries?
PS
As mentioned I will probably be using the Java PlayFrameWork to encode the website - can you suggest anything I should take into account for this?
Any tips on design patterns that must be followed for security purposes would be helpful.
Many Thanks
PPS
You could suggest passing the job on to an expert but if possible I would like to have some experience coding it myself. I hope that this is a viable option?
Will probably like to set up an e-commerce system FYI.
How should the password typed on the client be encoded and sent to the server - assuming https is already in use? i have heard of some suggesting that only the hash is sent for security for example. Should it be encrypted client side - how?
It should not be sent to the server in a way that can be recovered. The problem with SSL/TLS and PKI is the {username, password} (or {username, hash(password)}) is presented to nearly any server that answers with a certificate. That server could be good or bad.
The problem here is channel setup is disjoint from user authentication, and web developers and server administrators then do dumb things like put a plain text password on the wire in a basic_auth scheme.
Its better to integrate SSL/TLS channel setup with authentication. That's called channel binding. Its provides mutual authentication and does not do dumb things like put a {username, password} on the wire so it can be easily recovered.
SSL/TLS offers nearly 80 cipher suites that don't do the dumb {username, password} on the wire. They are Preshared Key (PSK) and Secure Remote Password (SRP). Even if a bad guy answers (i.e., controls the server), the attacker cannot learn the password because its not put on the wire for recovery. Instead, he will have to break AES (for PSK) or solve the Discrete Log problem (for SRP).
All of this is covered in great detail in Peter Gutmann's Engineering Security book.
Similar but on server side. How should the passwords be saved. Actual, hash, etc? Should they be encrypted - how?
See the Secure Password Storage Cheat Sheet and Secure Password Storage paper John Steven wrote for OWASP. It takes you through the entire threat model, and explains why things are done in particular ways.
Once authenticated should you just rely on session IDs to maintain authenticated status throughout?
Yes, but authorization is different than authentication.
Authentication is a "coarse grained" entitlement. It asks the question, "can a user use this application?". Authorization is a "fine grained" entitlement. It answers the question, "can a user access this resource?".
Is there a safe way to provide an autoLogIn feature so that the browser remembers the password - similar to social network/web-email clients
It depends on what you consider safe and what's in the threat model. If your threat model does not include an attacker who has physical access to a user's computer or device, then its probably "safe" by most standards.
If the attacker has access to a computer or device, and the user does not protect it with a password or pin, then its probably not considered "safe".
Are there any tools or even just some common practises out there that must be applied to the username/password entries provided to prevent injection or any other kind of attacks?
Yes, user login suffers injections. So you can perform some filtering on the way in, but you must perform HTML encoding on the output.
Its not just username/password and logins. Nearly everything should have some input filtering; and it must have output encoding in case its malicious.
You should definitely spend so time on the OWASP web site. If you have a local chapter, you might even consider attending meetings. You will learn a lot, and meet a lot of awesome people.
If I use a Java development environment (using PlayFrameWork btw) how likely is it in general that attackers could include harmful code snippets of any kind in any form entries?
Java is a hacker's delight. Quality and security has really dropped since Oracle bought it from Sun. The more paranoid (security conscious?) folks recommend not signing any Java code because the sandbox is so broken. That keeps a legitimate application properly sandboxed. From http://threatpost.com/javas-losing-security-legacy:
...
“The sandbox is a huge problem for Oracle,” Jongerius told Threatpost.
“Everyone is breaking in. Their solution is to code-sign and get out
of the sandbox. But then, you have full permission to the machine. It
doesn’t make sense.”
Its too bad the bad guys didn't get the memo. They sign their code the malware and break out of the sandbox.
Any tips on design patterns that must be followed for security purposes would be helpful.
You also have web server configurations, like HTTPS Only and Secure cookies, HTTP Strict Transport Security (HSTS), and Content Security Policies (CSP), Suhosin (hardened PHP), SSL/TLS algorithms, and the like.
There's a lot to it, and you will need to find the appropriate hardening guide.

Securing Firebase: Preventing administrators from being able to see all users' data in the Forge?

I'm building an app that stores users' potentially-private notes. It's a little weird to me that I can just go into the Firebase Forge UI and look up anything which anyone has written, and it also means that anyone who somehow gains access to my Firebase account can then go in and select "Export JSON" to get all of my users' data.
Obviously I am careful with my account and am a scrupulous human being, but it generally seems like good practice for administrators to not have access to all of our users' data.
The only way I can think of to accomplish this would be to store everything in stringified JSON that has been encrypted by the user's password, but that obviously makes dealing with Firebase much more annoying, and would prevent granular access to data below the point at which things are stringified and encrypted.
Edit: This is, on second thought, not specific to Firebase, but is the case with most/all data stores unless you go out of your way to make it otherwise.
The only way to guarantee information security is to hand roll your own encryption on the server. You could host your firebase connectivity server-side and have your user send the data to that via SSL and from there do your encryption and then use the SSL address of firebase to store.
On the clientside, things are suspect to CSS attacks. If you really want to go down this route you can use js encryption from this lib: http://code.google.com/p/crypto-js/. Note that crpto-js works well in isolation but you will also need to be sure your webpages are not tampered with (quite hard to do IMOP, cause you don't know whats infected the users machine)

How can you encrypt users' data server-side without ruining the experience?

Many users – myself included – would like the security of having everything they do on a web service encrypted. That is, they don't won't any one at the web service to be able to look at their: posts, info, tasks, etc...
This is also major complaint in this discussion of an otherwise cool service: http://news.ycombinator.com/item?id=1549115
Since this data needs to be recoverable, some sort of two-way encryption is required. But unless you're prompting the user for the encryption key on every request, this key will need to be stored on the server, and the point of encrypting the data is basically lost.
What is a way to securely encrypt user data without degrading the user experience (asking for some key on every request)?
-- UPDATE --
From #Borealid's answer, I've focused on two possibilities: challenge-response protocols, where no data (password included) is sent in the "clear", and non-challenge-response protocols, where data (password included) is sent in the "clear" (although over HTTPS).
Challenge-response protocols (specifically SRP: http://srp.stanford.edu/)
It seems that its implementation would need to rely on either a fully AJAX site or using web storage. This is so the browser can persist the challenge-response data during encryption and also the encryption key between different "pages". (I'm assuming after authentication is completed I would send them back the encrypted encryption key, which they would decrypt client-side to obtain the real encryption key.)
The problem is that I'm either:
fully AJAX, which I don't like because I love urls and don't won't a user to live exclusively on a single url, or
I have to store data encryption keys in web storage, which based on http://dev.w3.org/html5/webstorage/ will persist even after the browser is closed and could be a security vulnerability
In addition, as SRP takes more than one request ( http://srp.stanford.edu/design.html ), there needs to be some persistence on the server-side. This is just another difficulty.
Traditionally
If I'm ok transmitting passwords and data in the clear (although over HTTPS), then the client-side issues above are not present.
On registration, I'll generate a random unique encryption key for the user, and encrypt it using their password and a random salt.
In the database, I'll store the user's password hash and salt (through bcrypt), encrypted encryption key, encryption key salt, and encryption iv.
After an authentication, I'll also need to use their password to decrypt the encryption key so that they may view and enter new data. I store this encryption key only temporarily and delete it when they explicitly "log out".
The problems with this approach is that (like #Borealid points out) evil sysadmins can still look at your data when you are logged in.
I'm also not sure how to store the encryption keys when users are logged in. If they are in the same data store, a stolen database would reveal all data of those who were logged in at the time of theft.
Is there a better in-memory data store for storing these encryption keys (and challenge data during an SRP authentication)? Is this something Redis would be good for?
If the data need to be recoverable in the event of user error, you can't use something like a cookie (which could get deleted). And as you point out, server-side keys don't actually secure the user against malicious sysadmins; they only help with things like databases stolen offline.
However, if you're running a normal web service, you've already gotten pretty lucky - the user, in order to be unique and non-ephemeral, must be logged in. This means they go through some authentication step which proves their identity. In order to prove their identity, most web sites use a passed credential (a password).
So long as you don't use a challenge-response authentication protocol, which most web sites don't, you can use an encryption key derived from a combination of a server-side secret and the user's password. Store the encryption key only while the user is authenticated.
If you do this, the users are still vulnerable to sysadmins peeking while they're using the service (or stealing their passwords). You might want to go a step further. To go one up, don't send the password to the server at all. Instead, use a challenge-response protocol for authentication to your website, and encrypt the data with a derivative of the user's password via JavaScript before uploading anything.
This is foolproof security: if you try to steal the user's password, the user can see what you're doing because the code for the theft is right there in the page you sent them. Your web service never touches their data unencrypted. This is also no hindrance to the normal user experience. The user just enters their password to log in, as per normal.
This method is what is used by Lacie's storage cloud service. It's very well done.
Note: when I say "use foo to encrypt", I really mean "use foo to encrypt a secure symmetric key which is then used with a random salt to encrypt". Know your cryptography. I'm only talking about the secret, not the methodology.
None of those other solutions are going to maintain the feature set requested -- which specifically wants to preserve the user experience. If you look at the site referenced in the link, they email you a nightly past journal entry. You're not going to get that with JavaScript trickery per above because you don't have the browser to depend on. So basically this is all leading you down a path to a degraded user experience.
What you would want, or more precisely the best solution you're going to find in this space, is not so much what wuala does per above, but rather something like hush.com. The handling of user data needs to be done on the client side at all times -- this is generally accomplished via full client-side Java (like the Facebook photo uploader, etc), but HTML/JavaScript might get you there these days. JavaScript encryption is pretty poor, so you may be better off ignoring it.
OK, so now you've got client-side Java running a Journal entry encryption service. The next feature was to email past journal entries to users every night. Well, you're not going to get that in an unencrypted email obviously. This is where you're going to need to change the user experience one way or the other. The simplest solution is not to email the entry and instead to provide for instance a journal entry browser in the Java app that reminds them of some old entry once they get to the website based on a link in the daily email. A much more complex solution would be to use JavaScript encryption to decrypt the entry as an attachment inline in the email. This isn't rocket science but there is a fairly huge amount of trickery involved. This is the general path used by several web email encryption services such as IronPort. You can get a demo email by going to http://www.ironport.com/securedemo/.
As much as I'd love to see a properly encrypted version of all this, my final comment would be that journal entries are not state secrets. Given a solid privacy policy and good site security semantics, I'm sure 99% of your users will feel just fine about things. Doing all this right with true security will take an enormous amount of effort per above and at least some design/UE changes.
You should look into the MIT project CryptDB which supports querying an encrypted database using a subset of SQL. (see the forbes article, mefi thread, or Homomorphic encryption on wikipedia)
There is the Tahoe-LAFS project for cloud storage too, which conceivably could be leveraged into a fully anonymous social networking application, one day in the distant future.
If you want to perform computations on a server without even the server being able to see the data, you may be interested in knowing about fully homomorphic encryption. A fully homomorphic encryption scheme lets you perform arbitrary computations on encrypted data, even if you can't decrypt it. However, this is still a topic of research.
For now, I guess your best bet would be to encrypt all posts and assign meaningless (e.g. sequential) IDs to each one. For a more in-depth discussion of how to encrypt server-side data with today's technology, look up.

Encrypting 3rd party credentials

I have an application where I need to store 3rd party credentials to services like Amazon S3, FTP, SFTP, etc..
I know that it is possible to access some of those systems without passwords, but that has its own issues. If our customers gave us access to their S3 buckets via ACL we would still need to verify which bucket belongs to which user, same goes for SFTP and ssh key auth.
We will try our best to allow non-password alternatives where possible, but sometimes (FTP) it just won't be possible. Therefor I am looking for advice on how to store this sensitive data in our database (MySql) or elsewhere.
In the past I have read about people using TrueCrypt partitions that automatically unmount, but that would probably require decent intrusion detection. For now I'm interested in simple approaches that lead to reasonable security and can improved upon in the future.
Any advice on the subject would be highly appriciated!
There are a range variety of possibilities and since in my opinion you provide not enough info about the context, i will try to give you an overview from my point of view. I assume that here the most important aspect is confidentiality of your data and and authentication of the users. Integrity and availability of data is much less important.
If you want basic security, you can let MySQL handle it by means of username/password combinations and set access rights on the given account. However, since the access control mechanism of mysql is not fine-grained (you can set access control rules per table only, not per row) this will probably yield a bad database design.
If you want to have a non-password approach, you can give users client-certificates and let them prove their identity by presenting their client certificates (use TLS for that) or let them sign something (note their are dangers because you create a so called signing oracle).
Another approach is to encrypt your data in the database. You can do that by deriving a symmetric key from the password and encrypt the credentials with this data. The catch here is of course that your key derivation protocol should be good and this is not easy to accomplish (so if you choose this, i advice you to take existing key derivation protocols or use a streamcipher). Take a look here for a list of streamcipher http://en.wikipedia.org/wiki/Stream_cipher .
If you care very much for security you can start thinking about fancy solutions like authentication with smartcards, or a time synchronized tamper resistant device for generating acccess codes. However, note that these fancy solutions do not give you free security, implementing such systems if hard and costly (due to development and deployment) however, if done correctly they provide the best security.
Have the user supply a (strong) password when they set up an account (before they provide their passwords). Then encrypt all data for that account within your database using a key derived from a strong hash (SHA256 or something like that) of the user's password. That way if your servers get compromised, no data will be revealed because it is encrypted with the user's password (well, a hash of the user's password) and that password is not stored anywhere on your server.
You need to investigate the use of keystores. TruCrypt is an example of such a keystore, but this is a personal keystore, not intended for service level credentials.
You won't be able to avoid storing their passwords in a format that someone can get access to, the goal is to minimize who can access the information. Putting in the same MySQL as application data is asking for disaster.

Resources