You don’t need read access to your passwords.
I run a small server that needs to be highly secure. I don’t have the luxury of a massive amount of free time.
In my case, I’m running a typical, simple MEAN stack, setup on AWS. NGINX was added (and should be added for most people), and provides a simple way to keep track who can connect to what.
However, my architecture suffers deeply from its low work-time resources. Even a single breach to some systems can be catastrophic. I manage blockchain assets; If one private key gets out, that money is gone.
This post lays out a proposed solution for increased user-account authentication, and better separation of privileges. The gist is — read/write authorization is revoked from the server and given to the user.
This solution was never implemented, and shouldn’t be considered unless an open source implementation is available.
A controlled environment
We will consider our database to be on a separate server with a separate control mechanism which is turing complete, this means yet-another-node server in the VPN, this one acts as a proxy between the web-service and database, and is necessary for some extra computations that need to be outsourced from the web-server. This will be referred to as the microservice, and your web service essentially acts as a proxy, with zero control, to the microservice.
Whether or not the microservice can be considered more secure than your web-server is up to you.
Consider also that you are running a MEAN server which only needs to handle a user password and email, for simplicity.
Take a look at the permissions of a MEAN web server.
Reads from the database often need to be passed from the database to the web-server in order to show usernames, emails, and misc. data to users.
However, writes to the database are often authorized from the user via an email.
Conceptually, I am arguing that this email-2fa can be used as authentication and authorization to modify the database.
In fact you may want to stop reading, and consider it yourself. What are some of the ways in which you can revoke your access to your critical user data(This is just one). Does it really get in the way?
For me the answer was, interestingly, that I can indeed have user-controlled databases.
From this idea, the idea that user 2fa is not just authentication, but authorization. Some separation of privileges and cryptography can be applied in a relatively straightforward manner.
Here’s how things work in a user-controlled database, and what the advantages are.
Password Checking
You never need to read a hash. Only the microservice needs to the read the hash. You can pass the hash to your database server, and get a boolean response. What does this mean in terms of security?
- Data exfiltration — In the case of a catastrophic web-server compromise via an injection or misconfiguration, it will be impossible for your hashes to be exported, as you don’t have access to them.
Password Resets
Password resets are user-authenticated. If your database-server handles the emails, users never even need to interact with your web-server.
This is a great starting point, but ultimately a bad idea. You’ll end up with email reset links that go to funny places, and people won’t trust it. On top of that, your database-server shouldn’t have any ports accessible to the internet.
This is fine. We’ve sort of forgotten this, but by sending out reset links, users can authenticate, AND authorize their own password resets. The authorization and authentication cryptography is already handled in the default logic of a password reset.
The database-server can send out a reset link using the web-server as a proxy. The database-server can receive authorization and authentication by using the web-server as a reverse proxy to retreive the key.
The data must remain encrypted so that the web-server cannot read it. This is a big weak point, because setting up the routing adds confusion and complexity to small architectures.
Email Resets
This works the exact same way as a password reset.
Displaying user data?
It can be done by setting up an account with read-access on your web-server to your database. This lets you pull out fun information like usernames and emails to keep your site looking up to date and informative. With good permissioning, it will only be able to read what you need it to read.
Setting up a read system like this does destroy one of the two benefits of this separation of duties.
- M̵y̵ ̵u̵s̵e̵r̵ ̵d̵a̵t̵a̵ ̵c̵a̵n̵n̵o̵t̵ ̵b̵e̵ ̵e̵x̵f̵i̵l̵t̵r̵a̵t̵e̵d̵.
- My user data integrity is hardened.
This is another reason why I abandoned this. The muddling of security. Each architecture implementation should be completely unambiguous. If you choose to not implement read access in any sense, however, then the problem does not exist.
Here’s what doesn’t work.
If the microservice is not more hardened than the web-server. Much of the usefulness breaks. How can you set up a microservice that is less prone to injection? Is this something that can be offered up as an easily configurable package or service? It has to handle email, db-communication, AND a web-server.
Ultimately, I love the idea of stuffing away your ability to even pull out a hash from your own database, but the implementation might inherently defeat itself.
Summary
You don’t need to read your password hashes. You don’t need to read your user emails, you don’t need to read or write to much of anything, your users do it. It’s not easy, and takes an entire day to set up. This article is one way to accomplish this separation.