Feature request: Add TOTP/HOTP/MFA security features, or allow OIDC-based authentication
(1) By Ethin Probst (ethindp) on 2024-08-14 20:02:09 [link] [source]
Hi there,
In light of all the various security incidents that have occurred on all manner of repository hosting services (though primarily GitHub and GitLab) due to insufficient security settings, I'd like to know if the Fossil developers would consider implementing TOTP MFA, or OIDC authentication, for user accounts, as well as possibly changing the password hash algorithm to Argon2ID or something equally secure. These measures would be primarily for non-localhost Fossil UIs such as this one, where external users from all over the internet have user accounts, and it isn't just you running fossil ui
. Of course, if configured appropriately, these settings would be applied even to fossil ui
-based interactions as well.
This however might run into a "pushing/pulling from remotes" problem, however, where a user tries to synchronize a local repository with a remote but cannot because extra authentication is now required. To sidestep this problem, I further propose something like a security token. The timeframe would be configured by the repository admin, obviously, but it would last until the expiration time, and then a new token would need to be issued. We could even automate it, theoretically, depending on how technical we'd want to get.
This probably seems unusually complicated, but something like OIDC is not absolutely necessary, and a simple TOTP-based 2-factor authentication method would probably be sufficient. So, this would come in two "phases" if you will:
- The password hashing algorithm upgrade would be simple enough. A library like monocypher could be pulled in to provide this functionality. It would require a mass password reset, but I don't think many would mind, since all it's really doing is re-hashing their passwords. The OWASP cheat sheet has good parameters for default settings.
- The next step would be implementing TOTP.
Would you guys be opposed to this feature?
(2) By Stephan Beal (stephan) on 2024-08-14 20:19:58 in reply to 1 [link] [source]
This however might run into a "pushing/pulling from remotes" problem, however, where a user tries to synchronize a local repository with a remote but cannot because extra authentication is now required.
Any new authentication mechanism would need to be opt-in at the hoster's discretion. We can't/shouldn't force any mechanism more complicated than the current one on users.
A library like monocypher could be pulled in to provide this functionality.
Any required third-party dependencies would make such a feature far less likely to be integrated. This project has a strong culture of not requiring third-party dependencies unless they are (A) ubiquitous (e.g. zlib and libssl) and (B) unduly difficult to reimplement ourselves. Some leeway can be given for optional features, but not for required ones.
It would require a mass password reset, but I don't think many would mind
With some 70-odd repos, i most certainly would :). Similarly, we have thousands of forum users across this project and sqlite.org, each of whom has a password which would need resetting.
This probably seems unusually complicated...
Indeed, but...
Would you guys be opposed to this feature?
Patches from someone who is proficient in such technologies would be thoughtfully considered.
(3) By Richard Hipp (drh) on 2024-08-14 20:27:22 in reply to 1 [link] [source]
I'm not opposed to improving security. An optional TOTP would be nice. Do you have code that you can contribute?
Constraints:
No new third-party dependencies. Adding a dependency on monocypher or similar, is unlikely to happen.
Must be easy to understand, easy to reason about, and easy to implement. This is strike against OIDC, I think.
About OIDC: Seems way to complicated. The current password has in Fossil hash *claims" to be SHA1, but it is really Marc Stevens Shatter-proof SHA1 variant. I don't think that is readily invertible. If you disagree, why not just upgrade to SHA3-512, the code for which is already in the tree? Why do we need a whole new authentication mechanism? Seems like it would be very disruptive to cut-over, doesn't it?
(4) By Ethin Probst (ethindp) on 2024-08-14 20:37:58 in reply to 2 [link] [source]
Any new authentication mechanism would need to be opt-in at the hoster's discretion. We can't/shouldn't force any mechanism more complicated than the current one on users.
Right, as much as it'd be nice if it could eventually be the default, this makes sense. The hoster would need to enable it.
Any required third-party dependencies would make such a feature far less likely to be integrated. This project has a strong culture of not requiring third-party dependencies unless they are (A) ubiquitous (e.g. zlib and libssl) and (B) unduly difficult to reimplement ourselves. Some leeway can be given for optional features, but not for required ones.
Monocypher is just a single .c and .h file, but if adversity to third-party deps extends even to those, OpenSSL definitely supports argon2. You can see a sample of it on the command line here, and via the API here.
With some 70-odd repos, i most certainly would :). Similarly, we have thousands of forum users across this project and sqlite.org, each of whom has a password which would need resetting.
What would you suggest in this instance? We could leave passwords as-is, but this opens them up to trivial brute-force attacks, I think, unless Fossil already uses some kind of memory-hard password hash function. Perhaps this could be another one of those "hosters discretion" things...
Patches from someone who is proficient in such technologies would be thoughtfully considered.
I've never implemented it, but from my research the algorithms seem decently easy to do. Though some kind of security audit would still be preferable. :) A full example (not in the most idiomatic C ever) is here if your curious how to do it. I don't have an existing contribution agreement with the Fossil project, unfortunately, and I've never contributed to Fossil before, so this entire process would be new to me.
(5) By Ethin Probst (ethindp) on 2024-08-14 20:42:37 in reply to 3 [link] [source]
If you disagree, why not just upgrade to SHA3-512, the code for which is already in the tree? Why do we need a whole new authentication mechanism? Seems like it would be very disruptive to cut-over, doesn't it?
I wasn't aware that it used that particular algorithm (and I'm not familiar with it to be honest). And for the record, yes, OIDC is extremely complicated, and from what I understand based on a project I actively monitor, the spec also has significant ambiguities. So that's probably a no-no. TOTP however is a very simple algorithm and involves just HMAC-SHA256/512 and some bit twiddling. It requires a base32 implementation, but those are all over the place.
As for SHA3, I forgot that Fossil supported that. It's not as secure as Argon2 but it's definitely a step up. I linked to a gist I found that implements the TOTP part with OpenSSL (OpenSSL doesn't implement it in libcrypto, which is honestly sad, but eh), but OpenSSL provides everything you'd need to do it.
(6) By Richard Hipp (drh) on 2024-08-14 22:24:10 in reply to 4 [link] [source]
We could leave passwords as-is, but this opens them up to trivial brute-force attacks
You know of trivial way to invert https://github.com/cr-marcstevens/sha1collisiondetection?
Maybe you mean, guess the password and try it. But unless you have access to the USER table in the repository on the server, you have to go through Fossil itself on each attempt, and Fossil will rate-limit you, making such an attach unfeasible. So you'd have to get at the USER table. But if you can see the USER table, you've probably already pwned the whole system, no?
If you want something stronger than hardened-SHA1, you could alternatively store a SHA3-512 hash. The code to do that is already in the tree. New passwords would go in as a SHA3-512 hash. The system could differentiate between older SHA1 passwords and newer SHA3-512 passwords based on the length of the hash, so existing passwords would not have to be reentered. So there is an easy migration path to SHA3-512 hashed passwords. I'm not sure that is really buying you any more real security, though.
(7) By Ethin Probst (ethindp) on 2024-08-14 22:28:01 in reply to 6 [link] [source]
I'm not a cryptologist, so no, I don't know a trivial way to invert it other than maybe GPU-based brute-forcing.
(8) By Richard Hipp (drh) on 2024-08-14 22:46:59 in reply to 7 [link] [source]
The algorithm used to compute the USER.PW value in the repository database is described here:
I think you are going to be hard-pressed to break this, even with a warehouse full of GPUs.
(9) By Ethin Probst (ethindp) on 2024-08-14 23:10:00 in reply to 8 [link] [source]
I can't look at it right now, GitHub is down for me, but I'll check it out when GH decides to be nice. :) In the meantime do you want me to see if I can implement a set of TOTP functions? And should my patch be a diff against the fossil repo or just standalone? (I've never manually made patches, I'm used to the pull request model.)
(10) By bohwaz on 2024-08-17 16:37:45 in reply to 8 [link] [source]
From what I understand, this is basically:
sha1(global seed + user login + user password)
I think the project-code is public, so it would be easy to generate a large list of potential passwords, the only thing blocking you will be fossil rate-limiting.
If your Fossil repo SQLite database leaks (including the password hashes), this means it would be trivial to guess someones password. And then try to use this password on other infrastructure / services. For example maybe this could give access to the users mailbox, if they use the same password everywhere.
Yes, no one should reuse the same password, but that's not what happens in real life.
The advantage of password-specific hash algorithms (bcrypt, Argon2id) is that they require a specific amount of CPU work / memory usage to generate the hash, making it costly to generate a hash table, and much harder to guess a password when you have the hash.
So this is a good practice. It doesn't protect against trying to bruteforce your password by doing login attempts (1), but against guessing your actual password from the leaked hash, and then using this on other services (2).
Fossil is already providing a protection against (1), but not against (2).
So having a password-specific hash algorithm would be a nice security improvement, in line with best practice. Also, this provides a random seed value for each password.
This would not require for everyone to reset their passwords, in fact Fossil would just do this:
- Re-hash all the existing passwords in the database using the new algorithm
- When you log in, Fossil would try to compare
pwhash(supplied password)
withstored hash
- If that fails, Fossil will try to compare
pwhash(sha1(project-code + login + password))
withstored hash
. - If that step works, Fossil will replace in database the existing hash with
pwhash(supplied password)
(upgrade mechanism)
With that logic, all existing hashes are protected, and you can still login with the old password.
As for TOTP, that would be great! You can implement this using SHA1, as I think most authenticator apps don't have real support for SHA256/512: https://labanskoller.se/blog/2019/07/11/many-common-mobile-authenticator-apps-accept-qr-codes-for-modes-they-dont-support/
(11) By Trevor (MelvaigT) on 2024-08-17 18:56:47 in reply to 10 [source]
With that logic, all existing hashes are protected, and you can still login with the old password.
Haven't you just halved the strength of your defence against ordinary online password guessing? Every guess now has two chances of generating an acceptable hash.
Better to record which algorithm the current hash uses (if it isn't obvious already, see the earlier comment about SHA1 vs SHA3). Having decided once to upgrade my algorithm I would be naive not to allow for the need to do the same again in the future.
guessing your actual password from the leaked hash, and then using this on other services
I doubt this is feasible. It is at least as hard as trying to find a collision. And doomed to fail if you really have found a collision...
Trevor
(12) By js on 2024-08-29 21:57:14 in reply to 6 [link] [source]
SHA-3 is not much better than SHA-1 against brute force of a leaked DB. The proper thing to use is something like scrypt or Argon2. With SHA-1 and even SHA-3, if the database gets leaked, it's reasonably bruteforceable these days.
(13) By Vadim Goncharov (nuclight) on 2024-10-26 14:23:30 in reply to 6 [link] [source]
If differentiating by length, then for new ones it's better to have format and salt specifier, like in passwd's $5$salt:hashedpass...
allowing to further upgrades in future if hashes happen to have same length.
But if you can see the USER table, you've probably already pwned the whole system, no?
The problems here are usually:
- Rainbow tables - precomputed hashes for many passwords, and
- main one - cross-site. It may be one one site pwned from where info will be tried on other sites, with higher probability to succeed then.
- small probability, but still - not a full pwn but some partial vulnerability getting parts of USER table, or avaoiding rate-limit, or something like that.
(14) By Vadim Goncharov (nuclight) on 2024-10-26 14:32:00 in reply to 2 [link] [source]
Any required third-party dependencies would make such a feature far less likely to be integrated. This project has a strong culture of not requiring third-party dependencies unless they are (A) ubiquitous (e.g. zlib and libssl) and (B) unduly difficult to reimplement ourselves. Some leeway can be given for optional features, but not for required ones.
Are dependencies from OpenSSH considered to be ubiquitous? Security is such a thing where it's better to NOT having your own implementation unless your are an experienced cryptography professional.
(15) By Stephan Beal (stephan) on 2024-10-26 16:17:00 in reply to 14 [link] [source]
Are dependencies from OpenSSH considered to be ubiquitous?
Fossil does not have a hard dependency on OpenSSH. If you try to use an SSH connection, fossil attempts to call "ssh". If it's not found, ssh:// URLs simply won't work. i.e. it's an optional feature which requires a binary at runtime, not a library at build-time, and as the snippet you just quoted said:
Some leeway can be given for optional features, but not for required ones.
The only hard third-party dependency fossil has is zlib, which fossil needs in order to compress artifacts.
(16) By Stephan Beal (stephan) on 2024-10-26 16:40:54 in reply to 13 [link] [source]
Rainbow tables - precomputed hashes for many passwords, and ... not a full pwn but some partial vulnerability getting parts of USER table,
Precomputed hashes or getting a 1-to-1 copy of the user table does not help an attacker crack fossil's user passwords because the user table does not contain all info used in the hashing.
The inputs for password hashes include random bytes which are specific to any given clone of a repo. Those bytes cannot be read except by someone with OS-level access to the repository database (in which case your system is already compromised, but an attacker would still have to brute-force the passwords for dozens or thousands of years to crack them). Every fossil-generated clone of that db gets its own randomly-generated seed against which to hash passwords.
User accounts can be cloned across repositories, including their password hashes, but the password hashes are useless on any clone except on the one where they were set.
(17.1) By Andy Bradford (andybradford) on 2024-10-27 23:41:41 edited from 17.0 in reply to 14 [link] [source]
> Are dependencies from OpenSSH considered to be ubiquitous? No dependency on OpenSSH specifically as there is an actual interface boundary here so in theory any command that provides the SSH interface should suffice; I don't know if anyone has ever tested with Tectia, but it should work as all it needs to do is wire up a tunnel over which Fossil can communicate. Fossil does have the --ssh-command argument that allows one to provide an alternative SSH command. If one is using ssh:// URLs then one needs a command to provide SSH. One is not constrained to use OpenSSH. Andy
(18) By Kirill M (Kirill) on 2024-10-28 06:50:45 in reply to 4 [link] [source]
TOTP verification itself is easy enough indeed, and the plass project also shows a simple, BSD licensed TOTP implementation, which uses HMAC from OpenSSL:
Initially there's some decoding of TOTP URL, to extract secret, period, digits, algorithm. The interesting lines are from 266.
If TOTP be used in Fossil, there'd have to be a UI to initialise the TOTP facility, show QR code to setup whatever authenticator user might be using (while also supporting showing the secret), a way to remember if a given OTP has been used very recently or not to prevent replay, and probably quite a few other minor matters which will start showing up.
If one wants more fancy auth, maybe look at what options REMOTE_USER authentication may provide instead?
(19) By Vadim Goncharov (nuclight) on 2024-12-29 18:15:09 in reply to 16 [link] [source]
Those bytes cannot be read except by someone with OS-level access to the repository
Interesting. Where are they stored?
Algo indicator still would be good, if extension is planned.