What happens with OTP secrets when a user database get leaked? Could the attacker use them to gain your other sensitive information? How are they even stored on the server?
One of the widely used method to log into some service day is still via form of a password that is shared between you and the server and kept secret. Fortunately, it is becoming a common knowledge that this approach has some vulnerabilities. An attacker can get hold of your password, because he can among other things guess it or record it as you type.
It is also hopefully widely known that the passwords should not be stored in a plain text. When a database storing passwords that can be read easily is exposed, the attacker can try the obtained passwords in different services, gaining instant access if passwords are reused. Even if they are not reused, reading a password can reveal a pattern used to create it and consecutively help guess other passwords of the same user used in different services.
To protect the passwords against exposure, they are mathematically garbled in a way that cannot be ungarbled back, making sure that even the same passwords by different users are garbled into a different form. These processes are called hashing and salting respectively and the whole process is guaranteed to be repeatable. Any password garbled this way, will for the same user always result in the same form.
What happens when you type your password into the login field? It gets transmitted to the server, hashed and salted and then it is compared against the garble that is stored in a database. You are allowed access when both garbles match precisely. The problem is, since passwords are still delivered to the server in a way they can be read as a plain text, the attacker controlling such server can try to log in to other services with your reused password the moment you log in.
To mitigate this problem, one should never reuse passwords and use randomly generated ones consisting of hard to remember characters and sequences, that are also hard to type in properly. Service providers do not want to force their users to use this very secure, but completely inconvenient approach, because it would drive the business elsewhere. Also, server has absolutely no way to grantee that the user used unique password he not used on any other server.
OTP or one-time-password
Solutions to protect the user using a password against an attacker are available, but there is currently no such thing as a perfect security. A general approach is adding a layers of security up to a point, when it is still convenient enough to be used. One time passwords are commonly being used as one of such layers. Broadly speaking, you do not only present yourself with one password that you know, but also with another one that is generated for you.
To make that generated password usable over and over, it has to be different every time it is used, otherwise it is effectively just another password. Furthermore, any password to be characterized as a one time password, it has to be always rejected right after it was used the first time. One consequence of such property is that if an attacker manages to get hold of such password, but uses it after you, it is effectively useless and he is out of luck this time.
Making sure the generated password is different every time it has to be derived out of a varying starting information, also called seed value. For a server to be able to verify this password, it has to access the same seed value the password was generated from. Ignoring all other options again, an Unix timestamp fits the description. Using Unix timestamp is convenient, because it makes it easy to generate a short-lived one time password, which self-destroys not only when first used but also after some short time since first issued, regardless if used or not. This short time is generally less than a minute and makes it really hard for the attacker to successfully use such a volatile password, even when captured. This technique is called Timed One Time Password, or TOTP.
Unfortunately, an Unix timestamp is a public information the attacker has access to as well and cannot be used as a password as such. It has to be mathematically combined with some secret, that the attacker does not know. This secret is generated on the server and transferred to your device during the initial setup, for instance via scanning a QR code with your phone. This secret is called the OTP secret.
Storing OTP secrets
Now when we know that the OTP secret is combined with the timestamp to generate a short lived TOTP token as it is also called, we could dig a little deeper. We also know that the passwords are stored in a way that does not reveal anything when exposed. But what about the OTP secrets? Could they be garbled the same way the passwords are? I was genuinely interested in finding an answers to this question.
By searching the Internet I have concluded that unfortunately this would not work, also discussed here , because the server has to calculate the TOTP token from the secret and compare that with the token provided by the user, not just start with comparing straight ahead. For this to work, it has to be stored in a way that would allow to obtain the original secret.
The simplest way to fulfill this condition is to store the OTP secrets as a plain text. Imagine the scenario with the attacker getting access the database data again, but now not just with unreadable passwords but also with a very readable OTP secrets. How does the situation change? Well, he can now generate the TOTP tokens that would appear as if they were from you at will, effectively stealing the device you used to generate your tokens (something you own). He still cannot log in to the service impersonating you, because he cannot retrieve the password (something you know).
The combination of something you know with something you own is the base of a Multi Factor Authentication, or MFA for short. This technique describes precisely two factors and is usually referred to a Two Factor Authentication, or 2FA.
The obvious way to protect the OTP secrets is to encrypt them , also discussed here. This however works only when the general secret used to decrypt the OTP secrets of all users was not exposed with the database itself. Not ideal, but better than nothing.
Searching the Internet more, it became more clear to me that I am definitely not the only one thinking about protecting OTP secrets on the server, discussed here, here and here. Well it turns out that there is one solution.
Decrypting the OTP secret with a password provided by the user. Now, the attacker need the plan text password to get hold of a plain text OTP secret to generate his own TOTP tokens. You can pause for a moment at this point and try to think what is the downside of this approach.
Before I confirm you answer let me talk a little bit about the password managers. A password manager is an app that protects all your passwords with just a single one, called a master password. Your protected passwords can be very strong and completely unique and the only way to them is to break your master password. If a strong one is used, it could be quite hard.
Lately, a password managers started offering to generate the TOTP token as well. Many argue, that this boils down to a Single Factor Authentication. Breaking into the database where your passwords and your OTP secrets are stored is all the attacker needs to get into any of your services stored there. From the user's perspective, this is very convenient, yet it leads to a false sense of security. To make it clear, passwords and OTP secrets should be stored in a database protected by a two different means to be more secure.
To be honest, the concerns about storing the OTP secrets in a password manager along with the actual passwords led me to the discovery that OTP secrets could be exposed from either the user or the server. The fact itself to me is quite disturbing.
Yet as I said a few moments back, side on the server can be successfully decrypted with the password provided by the user. But there is a big but. If the user asks to send the new password, the server has to either deactivate the 2FA or instructs the user to reinitialize the OTP generation process every time the password changes. I am not really sure this implemented on any service though.
Managing security is quite a hassle. Sometimes I wish a I never started and just used some simple weak password everywhere, or even no password at all. But everyone should do his own research and conclude what level of privacy he wants to keep.
Weak and even weak reused passwords can be protected well enough for a regular user by enabling 2FA. Using strong passwords with a password manager is another approach. Combining both worlds brings the most security. Using the tempting way of protecting the OTP codes with the same master password that protects your other password is considered a bad practice. It decreases convenience while at the same time not providing the benefits the true second factor provides. Or does it? And will passwordless come soon enough that all this questions would be rendered obsolete?