Currently the api_password is set in plaintext within the configuration.yaml. For the secrets that grant access to services this makes sense. But the api_password is only used by Home Assistant. So as far as I know there is nothing preventing the use of a hashed password in this case. That way it also wouldn’t even be too dramatic if someone accidentally leaked the hash. After all that hash would still need to be cracked.
I would suggest to implement this optionally. So it could stay the way it is, but if the password is prefixed with a certain string, then the value following the prefix should be the hashed password. So valid configurations could be:
api_password: myplaintextsecret
api_password: {MD5}abcdef1234567890
api_password: {SHA256}fedcba09876543211
Other hashing methods may make sense as well. These are just the two algorithms that came to my mind first.
Obviously this won’t prevent the credentials from the secrets-file from being compromised if access to the configuration files is available. But even if the hash is leaked, an attacker won’t be able to directly access the API to unlock doors or disarm alarms. Or at least not without some effort to crack the hash.
Well, only kind of similar. The linked FR results in a bunch of API-dependent secrets and in my opinion only makes it more complicated and obscure to setup. For what he want’s to achieve I would see more value in the ability to simply set multiple (app-)passwords which all are valid (which indeed decreases entropy).
So for service A we can set password A, for service B we set password B. If service A gets compromised and the password leaked, then only this password has to be removed from the list of valid passwords, and other connected services wouldn’t need to be reconfigured. This is also related to the multiple users / accounts that is already being worked on.
What I suggest here is that the main HASS password (which like mentioned above could also be a list off passwords) should be definable in a hashed form. So here it’s not about external services being compromised, but instead if HASS itself or the local network gets compromised an access to the configuration files is available for the attacker. Yesm in this case the proposal from the other FR might be helpful as well. But that would heavily depend on the implementation since if there’s still a plaintext password for everyboyd to read, then the hashing could just be re-done by the attacker and all API-calls would work.
Essentially what I’m saying here: passwords that are not being used outbound should be protected. Whenever reports surface of big companies having lost userdata, the problem usually is, that they have stored customer data in plaintext. If they would encrypt / hash everything, then even a successful attack won’t leak sensitive data.
A new auth system is in the works that allows for different auth providers and password hashes. Once it’s ready to go it will replace the current api_password system
True. But it has last been worked on 2 months ago, and it seems like there are other priorities currently.
Of course the auth providers are the better solution in the long run. But right now we have multiple users reporting they have been hacked. And even though it may become obsolete, my proposed solution should be easy to implement and would improve security right away (if used).
I have created a small sample script to demonstrate what I have in mind. The current api_password in auth.py would just needed to replaced with an instance of apipw from my example and then the verify-method should be used in the rest of the code. Since it’s still a string it would even keep working with a plaintext secret in case the verify-method wouldn’t be used because it’s forgotten in some other part of the codebase.
So to emphasize again: the point is to be able to NOT store the api_password in plaintext while retaining the ability to do so for people that don’t mind. This may become obsolete sooner or later, but right now this seems to be a quick way to improve security in case of a breach.
But that still doesn’t take care of the password that’s in the configuration.yaml in plaintext. It can generate hashes to compare them (although Base 64 isn’t hashing and adds no security, the other format is binary, so not compatible with yaml), but it would still depend on a plaintext secret.
I have read the docs. The point is, that the documented solution is not yet production ready, and there’s no ETA on when it will be done. My proposal is simple and could be integrated quickly. If you think it’s ok to wait half a year and keep passwords in plaintext that’s perfectly fine. For myself though the recent posts about people getting hacked make me believe this issue should be taken care of as quickly as possible. And I believe a simple, backwards-compatible intermediate solution is far better then prematurely releasing the auth-provider functionality while it’s not thoroughly tested.
Independently of being implemented or not I feel we need to alert the user about it.
If is written on the current documentation maybe it needed to be better highlighted since people are missing.