Do I need to store personal details encrypted in firebase - firebase

I’m looking for some advice with regards GDPR and firebase, I’ve looked online and apparently firebase is GDPR compliant as it stores data securely during transit and the firebase servers themselves are encrypted. So if that’s the case would I even need to encrypt personal data locally before sending it to firebase?
Currently I’m encrypting all personal data but the issue is that I want to have an autocomplete function that searches for customers as the user types. Now this wouldn’t work currently as a search for ‘sha’ would not find ‘shaun’ because shaun is currently encrypted. So I’m wondering whether I even need to encrypt customer details at all as firebase is encrypted itself. The only issue is that me as a database admin can see everyone’s details in the database but surely that’s the case with all database admins in most apps as you can query the data in there to your hearts content and see everything about everyone?
As long as you are not sharing this data for any purposes outside of the apps terms and conditions this should be ok shouldn't it?

So a few things first , when you encrypt data at the DB level , any usage of that data at the application layer has to go through a level of decryption .
So in the example that you outline the autocomplete feature ideally will be served by an API and the API at the back-end will take the encrypted data through the decryption process to keep it in memory and return to the client appropriately.
Also it is not OK to assume that admin cannot go rouge , most of the data breaches and leeks happen from internal source. So it is better to keep the PII as encrypted in the DB.

Related

How to secure database without authentication?

I am creating an Unity game where I want to have global top 50 score list with usernames. I use Firebase realtime database. There is no need for user to authenticate. I am not that familiar with database security and pretty beginner with this concept. I am using Rest Api from Unity Asset store because it was pretty easy to send and get data from databse.
How can I be sure that every score sent to database is from my app?
Add a dedicated user with password to your database
Somewhere in you app, add those credentials e.g. in a ScriptableObject / in some component
Always use those credentials to authenticate
Note that your app can still be decompiled and thereby cheated.
You can at least make it more difficult by encrypting the data etc.
The only way really around is to have an account and sessioning server to assure a user is locked in with a valid session.
If you don't use Firebase Authentication, you can't restrict who can access your database. Anyone will be able to issues a query, and they can even do it using the Realtime Database REST API. All they have to know is the name of your project.
Even if you do use Firebase Authentication, anyone may still effectively authenticate and access the database outside of your app using other public APIs.
My experience is that you can't stop dedicated "users" from cheating global at high scores. I made a small handfull of trivial games for windows phone with global top 50. Even if your game is unpopular, and you obfuscate your code, and you are on an unpopular platform, and you encrypt your network traffic: somebody is going to jailbreak their phone, decompile your app, and inject their own high score into your game before high scores are sent to the global list. The only way I ever came up with to combat this was to keep track of play sessions -on the server- to make sure their scores were theoretically possible based on how long they were playing.
Disclaimer: I don't know anything about Firebase
From what I can tell, you will need to set up access for Default and Public sections of your configuration to tell the database who can and cannot access your database. Here's their documentation on Get Started with Database Rules.
In general database access, no one should know the details of your connection to a database, so all calls should only ever come from your app.

Is it good idea to store sensitive info in firebase?

In my Android application I have an idea to store in database some serial key. If user enters correct key he gets full version of application and the key is disabled on the server to avoid multiply usage of the same key, otherwise he can buy app in Google Play without a key.
For this I thought to use Firebase Database but after read this I have some doubts
Firebase Realtime Database
Store and sync data with our NoSQL cloud database. Data is synced across all clients in realtime, and remains available when your app goes offline.
Does it mean that firebase will duplicate the table with all available keys to all application users and some smart user can read the list from this copy at his phone?
Not all data is automatically duplicated to all clients. Only data that the client subscribes to is received by that client.
You can control what data each client can see through Firebase's server-side security rules. For example, you'll typically want to ensure that each user can only read their own data.
It probably isn't a good idea to store super-sensitive data like social security numbers or credit card numbers, but if you see https://firebase.google.com/docs/database/security/ you can see, that you can control access to data, & use validation, especially since you can regenerate the keys if they become compromised, it wouldn't be the worst option. If you look at https://firebase.google.com/docs/database/security/user-security you can see, that it's possible to write an app that uses it like google drive with a smartphone-based client.
Personally the answer would no. You may want to think about Google Play Subscriptions and In-App Purchases.
If you really have to then:
Create a key as a user buys the upgrade (server-side).
Store the device id/account id (hashed) and timestamp with the key.
Credit card details and expiry dates should be combined into one hash.
Just encrypt everything.
It's better to have a banned list than a list of approved key. Eventually you have to create more keys and it's easier just to maintain a list of banned keys.

Understanding the Firebase and purpose of google cloud functions

Let's say I'm developing app like Instagram: for iOS, Android and Web. I decided to use Google Firebase as it really seems to simplify the work.
The features user needs in the app are:
Authorization/Registration
Uploading photos
Searching for other people, following them and see their photos
I come from traditional "own-backend" development where I do need to setup a server, create database and finally write the API to let the frontend retrieve the data from the server. That's the reason why it's unclear to me how it all works in Firebase.
So the question is how can I create such app:
Should I create my own API with cloud functions? Or it's ok to work with the database directly from the client-side?
If I work with the database directly why do I need cloud functions? Should I use them?
Sorry for such silly questions, but it is really hard to get from scratch.
The main difference between Firebase and the traditional setup you describe is that with Firebase, as far as the app developer is concerned, the client has direct access to the database, without the need for an intermediate custom API layer. Firebase provides SDKs in various languages that you would typically use to fetch the data you need / commit data updates.
You also have admin SDKs that you can use server-side, but these are meant for you to run some custom business logic - such as analytics, caching in an external service, for exemple - not for you to implement a data fetching API layer.
This has 2 important consequences:
You must define security rules to control who is allowed to read/write at what paths in your database. These security rules are defined at the project level, and rely on the authenticated user (using Firebase Authentication). Typically, if you store the user profile at the path users/$userId, you would define a rule saying that this node can be written to only if the authenticated user has an id of $userId.
You must structure your data in a way that makes it easily readable - without the need for complex database operations such as JOINs that are not supported by Firebase (you do have some limited querying options tough).
These 2 points allow you to skip the 2 main roles of traditional APIs: validating access and fetching/formatting the data.
Cloud functions allow you to react to data changes. Let's say everytime a new user is created, you want to send him a Welcome email: you could define a cloud function sending this email everytime a new node is appended to the users path. They allow you to run the code you would typically run server-side when writes happen, so they can have a very broad range of use-cases: side-effects (such as sending an email), caching data in an external service, caching data within Firebase for easier reads, analytics, etc..
You don't really need a server, you can access the database directly from the client, as long as your users are authenticated and you have defined reasonable security rules on Firebase.
In your use case you could, for example, use cloud functions to create a thumbnail when someone uploads a photo (Firebase Cloud Functions has ImageMagick included for that), or to denormalize your data so your application is faster, or to generate logs. So, basically you can use them whenever you need to do some server side processing when something changes on your database or storage. But I find cloud functions hard to develop and debug, and there are alternatives such as creating a Node application that subscribes to real time changes in your data and processes it. The downside is that you need to host it outside Firebase.
My answer is definitely NOT complete or professional, but here are the reasons why I choose Cloud Functions
Performance
You mentioned that you're writing an instagram-like mobile device app, then I assume that people can comment on others' pictures, as well as view those comments. How would you like to download comments from database and display them on users' devices? I mean, there could be hundreds, maybe thousands of comments on 1 post, you'll need to paginate your results. Why not let the server do all the hard work, free up users' devices and wait for the results? This doesn't seem like a lot better, but let's face it, if your app is incredibly successful, you'll have millions of users, millions of comments that you need to deal with, server will do those hard jobs way better than a mobile phone.
Security
If your project is small, then it's true that you won't worry about performance, but what about security? If you do everything on client side, you're basically allowing every device to connect to your database, meaning that every device can read from/write into your database. Once a malicious user have found out your database url, all he has to do is to
firebase.database().ref(...).remove();
With 1 line of code, you'll lose all your data. Okay, if you say, then I'll just come up with some good security rules like the one below:
This means that for each post, only the owner of that post can make any changes to it or read from it, other people are forbidden to do anything. It's good, but not realistic. People are supposed to be able to comment on the post, that's modifying the post, this rule will not apply to the situation. But again, if you let everybody read/write, it's not safe again. Then, why not just make .read and .write false, like this:
It's 100% safe, because nobody can do anything about anything in your database. Then, you write an API to do all the operations to your database. API limits the operations that can be done to your database. And you have experience in writing APIs, I'm sure you can do something to make your API strong in terms of security, for example, if a user wants to delete a post that he created, in your deletePost API, you're supposed to authenticate the user first. This way, 'nobody' can cause any damage to your database.

Best way to encrypt and decrypt persisted data in Node.JS?

I'm writing a Node.JS application that will store chat logs to a datastore (i.e. MongoDB), along with some other user information. I'm already using bcrypt to store salted hashes for user passwords, so I'm covered there.
What the best method of encrypting persisted data? I'm talking about sensitive user data such as phone numbers, and the chat logs. If my database gets compromised, I don't want this information being usable.
I do need two-way encryption/decryption, however, because I need to be able to use the plain-text values (i.e. the phone numbers are for Twilio, the chat logs are for users to see their old messages).
I'm looking into node-crypto but I haven't been able to find any examples of doing this in a performant/realtime fashion.
UPDATE: I should've mentioned that the chat "logs" are actually full conversations that get pushed to "rooms" in real-time when users join them (i.e. they can see the entire chat history, or at least a subset of it). So, I'd need to be able to encrypt and decrypt on the fly pretty quickly (if not in real-time, at least with some sort of worker process).
The best thing to do is use require('crypto').
You will however need to port it to the clientside. Good luck with that. (Shouldn't be too hard with browserify)
Do it all server side, if you do it client side you will need to expose your encryption keys.

Encrypt data from users in web applications

Some web applications, like Google Docs, store data generated by the users. Data that can only be read by its owner. Or maybe not?
As far as I know, this data is stored as is in a remote database. So, if anybody with enough privileges in the remote system (a sysadmin, for instance) can lurk my data, my privacy could get compromised.
What could be the best solution to store this data encrypted in a remote database and that only the data's owner could decrypt it? How to make this process transparent to the user? (You can't use the user's password as the key to encrypt his data, because you shouldn't know his password).
If encryption/decryption is performed on the server, there is no way you can make sure that the cleartext is not dumped somewhere in some log file or the like.
You need to do the encryption/decryption inside the browser using JavaScript/Java/ActiveX or whatever. As a user, you need to trust the client-side of the web service not to send back the info unencrypted to the server.
Carl
I think Carl, nailed it on the head, but I wanted to say that with any website, if you are providing it any confidential/personal/privileged information then you have to have a certain level of trust, and it is the responsibility of the service provider to establish this trust. This is one of those questions that has been asked many times, across the internet since it's inception, and it will only continue to grow until we all have our own SSL certs encoded on our fingerprint, and even then we will have to ask the question 'How do I know that the finger is still attached to the user?'.
Well, I'd consider a process similar to Amazons AWS. You authenticate with a private password that is not saved remotely. Just a hash is used to validate the user. Then you generate a certificate with one of the main and long-tested algorithms and provide this from a secure page. Then a public/private key algorithm can be used to encrypt things for the users.
But the main problem remains the same: If someone with enough privileges can access the data (say: hacked your server), you're lost. Given enough time and power, everything could be breaked. It's just a matter of time.
But I think algorithms and applications like GPG/PGP and similar are very well known and can be implemented in a way that secure web applications - and keep the usability at a score that the average user can handle.
edit I want to catch up with #Carl and Unkwntech and add their statement: If you don't trust the site itself, don't give private data away. That's even before someone hacks their servers... ;-)
Auron asked: How do you generate a key for the client to encrypt/decrypt the data? Where do you store this key?
Well, the key is usually derived from some password the user has chosen. You don't store it, you trust the user to remember it. What you can store is maybe some salt value associated to that user, to increase security against rainbow-table attacks for instance.
Crypto is hard to get right ;-) I would recommend to look at the source code for AxCrypt and for Xecrets' off-line client.
Carl
No, you can't use passwords, but you could use password hashes. However, Google Docs are all about sharing, so such a method would require storing a copy of the document for each user.

Resources