? Pending

User tests: Successful: Unsuccessful:

avatar PhilETaylor
PhilETaylor
12 Jan 2021
  • On 18th June 2020 I reported this to the Joomla Security Strike Team.
  • I asked for an update today, and was told it was confirmed but no action has been taken
  • I have been repeatedly told that Joomla 4 has not been released and therefore the JSST are not interested in Joomla 4 security issues being reported in private and they are to be done in the public tracker.
  • I tried to explain the problem and the solution today, in brief, but the @zero-24 was not understanding

So here is the proposed fix.

The problem is, with WebAuthn, it is possible to Enumerate users that exist and have WebAuthn enabled by simply going to /administrator/index.php login page, providing a username and clicking "Web Authentication"

This makes an Ajax call to check if that user exists and if they have WebAuthn enabled.

If the username doesn't exist, if there is an exception thrown, or if the username exists and they don't have WebAuthn enabled, then the Ajax returns false and the user gets a message:

Screenshot 2021-01-12 at 23 03 57

if the username exists and the user has WebAuthn enabled then the Ajax return a challenge - which is a json string like this example below, and the browser prompts for the user to use their WebAuthn device (fingerprint, yubikey etc)

{"challenge":"-XGWsHC2uM52C5Rgu6uiDFGmxjQL9DnIf_7o3QxIqTo","rpId":"aec9d095825e.ngrok.io","userVerification":"preferred","allowCredentials":[{"type":"public-key","id":"OGJkYzAxMjQ4YWEwYjZjY2E5MWQ3ZGUyZjFmNTM2OGM1YWFiZTJiMGIwNTk1NTY5ZGViZDEwMTY3OTM3NmI0Yw"}],"timeout":60000}

Therefore it is possible to Enumerate users based on the response to the Ajax call. (and its possible, after obtaining the CSRF token, to send CURL requests to the Ajax endpoint millions of times a min with different usernames) to quickly check millions of usernames

Ironically, the users with WebAuthn enabled on their account are probably more security minded (power users, or with Super Admin rights) and therefore identifying their usernames is a nice thing for hackers... although probably useless, as the accounts are secured by webauthn - doh!

Summary of Changes

The result of the changes is that a challenge is returned from all attempts to use Web Authentication button to login to Joomla.

If the user has previously registered a WebAuthn device, then the challenge returned is a valid challenge and that user can go on to authenticate as normal by using their device.

if the username doesn't exist, or is a valid user without WebAuthn set up on their account, a challenge is returned that is valid enough for the browser to prompt for a WebAuthn device, but not valid enough that providing a device will authenticate the session. Its a fake challenge that prevents a Timing Vector and User Enumeration.

Testing Instructions

VISIT YOUR SITE OVER HTTPS

Enable WebAuthn on USERNAME-WITH-WEBAUTH
DONT Enable WebAuthn on USERNAME-WITHOUT-WEBAUTH
Logout.

On the login page enter username USERNAME-WITHOUT-WEBAUTH and click Web Authentication Button - you should be prompted to provide a WebAuthn Device press by your browser - press/use any webauthn device - note that you are rightly rejected access

Note that the fake challenge json is different based on the username provided and is indistinguishable from a genuine challenge.

Screenshot 2021-01-12 at 22 57 13

On the login page enter username USERNAME-WITH-WEBAUTH and click Web Authentication Button - you should be prompted to provide a WebAuthn Device press by your browser - press/use your registered webauthn device - note that you are rightly GRANTED access and the page reloads and you are logged in.

Documentation Changes Required

None

// Paging @nikosdion as the only one who might be able to review this on a technical level.

avatar PhilETaylor PhilETaylor - open - 12 Jan 2021
avatar PhilETaylor PhilETaylor - change - 12 Jan 2021
Status New Pending
avatar joomla-cms-bot joomla-cms-bot - change - 12 Jan 2021
Category Front End Plugins
avatar PhilETaylor PhilETaylor - change - 12 Jan 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 12 Jan 2021
avatar PhilETaylor PhilETaylor - change - 12 Jan 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 12 Jan 2021
avatar PhilETaylor PhilETaylor - change - 12 Jan 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 12 Jan 2021
avatar PhilETaylor PhilETaylor - change - 12 Jan 2021
The description was changed
avatar PhilETaylor PhilETaylor - edited - 12 Jan 2021
avatar nikosdion
nikosdion - comment - 13 Jan 2021

I am not sure if we can call this user enumeration or if it really matters. It does not list users and does not relay any other information about the user. You can only test whether a username is valid or not. In fact, not even that. You can only check if a username is BOTH valid AND has a WebAuthn identity attached to it.

I'd also like to point out that the current flow is compliant to the W3C Recommendation “Web Authentication:
An API for accessing Public Key Credentials Level 1”
§12.3. See point 2:

The script asks the client for an Authentication Assertion, providing as much information as possible to narrow the choice of acceptable credentials for the user. This can be obtained from the data that was stored locally after registration, or by other means such as prompting the user for a username.

Since we always want to allow users to log in from a different device than the one they registered their authenticator the final "or by other means such as prompting the user for a username" needs to be implemented. The side-effect is that it essentially allows you to determine if a username exists and which credentials it is attached to.

Further to that, a username seems to be a public, known identifier or at least everyone treat it as one. There plenty of extensions such as forum, helpdesk, comment, social networking, blog, some content enhancement etc which use the registered username as the publicly visible identifier for someone's words. In some cases username enumeration is a valid feature. Social networks are built around the concept that usernames are public. It's not the 1990s anymore.

Can anybody tell me what is the practical problem from knowing a username without knowing anything else about it including but not limited to real name, email, password, privileges etc? If there is a practical concern then the JED needs to remove all extensions which publicly use a username including forum, helpdesk, comment, social networking, blog, some content enhancement etc extensions. Wouldn't that be utter stupid in the age of social media and usernames as public identities?

More so when we are talking about the security minded people who will have a very hard to brute force password because, unless I'm mistaken, that was the only practical concern with knowing usernames: if the user has a weak password you have half of what is required to log in and the other half is easy to find.

Moreover, how is using the WebAuthn endpoint to guess usernames any different than throwing random usernames and passwords to the login endpoint once you scrape the token? The request response time is practically the same, give or a take a few dozen milliseconds which is nothing compared to the 200 to 2000 msec a request would take to process anyway. Doing an extra request to verify the username like that is pointless form an attacker's perspective.

In any case, if we want to be so facetious about security then, yes, this PR does achieve the stated goal... unless the attacker has more than half a working braincell. By definition, your fake authenticator identifier is an SHA-256 which is used by exactly zero real world authenticators. All real world authenticators I've seen use a 512-bit string which is base64-URL-encoded i.e. base64 with + and / replaced by - and _ respectively. It is therefore trivial for an attacker to look for this discrepancy to identify whether they have a correct username which also has WebAuthn enabled.

As this PR is right now I wouldn't accept it. It does not achieve the stated goal and I'm not even sure the stated goal does make any kind of practical sense. If we really want to treat usernames as secrets then the JED needs to unpublished half of the extensions that do anything useful. Sorry, I do not see any practical concern here.

avatar PhilETaylor
PhilETaylor - comment - 13 Jan 2021

Your whole argument is based on your belief that the project should not address User Enumeration because usernames are now "public knowledge" in 2021 anyway.

Personally I kinda agree. If you go to Facebook.com and enter phil@phil-taylor.com as a username and no password, you are given my full name as Phil Taylor and my Facebook profile picture. That is User Enumeration. If you try to login with admin@joomla.org you get told ""admin@joomla.org" is not associated with any Facebook account." That is User Enumeration.

So I DO see where you are coming from, however its not for me to make that call. User Enumeration is still User Enumeration. and therefore it should be addressed on the basis that its User Enumeration.

This project, OWASP and all other best practices for secure application still (even though is not the "1990s anymore") still promote not allowing User Enumeration to take place by ensuring that, regardless of the input, an endpoint returns generic messages regardless of a user existing or not.

If it were the login page that was returning different messages based on if a user exists, then the Joomla project would consider that User Enumeration and would fix it. They have done. Repeatedly. Recently.

All this PR seeks to do is the same. Regardless of if a user exists or not, regardless of if a user has WebAuthn or not, is to make the response the same (or same "looking")

https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/03-Identity_Management_Testing/04-Testing_for_Account_Enumeration_and_Guessable_User_Account states:
"Ensure the application returns consistent generic error messages in response to invalid account name, password or other user credentials entered during the log in process."

Moreover, how is using the WebAuthn endpoint to guess usernames any different than throwing random usernames and passwords to the login endpoint once you scrape the token?

Its no different and that's the point. It should be, as far as possible, implemented in a way that prevents User Enumeration, just like the login page is.

Because regardless of what you throw at the Login endpoint - the failure message will be consistent so that User Enumeration cannot take place. This is the whole point. The login failure messages never said "User not found", or "Password incorrect", the error message returned is a GENERIC failure message - THATS THE WHOLE POINT.

In any case, if we want to be so facetious about security

Not me. Security Standards. OWASP.

By definition, your fake authenticator identifier is an SHA-256

I just reused the existing code, which also uses sha256 and does encode using base64 url as its reusing PublicKeyCredentialDescriptor from the web-auth libraries which does this when it serializes the credential to json

avatar brianteeman
brianteeman - comment - 13 Jan 2021

The problem is that username enumeration will always occur on a registration form. There is no way to avoid that.

avatar PhilETaylor
PhilETaylor - comment - 13 Jan 2021

The problem is that username enumeration will always occur on a registration form. There is no way to avoid that.

Correct. "This username is taken" is another example of User Enumeration.

So are you saying that Joomla no longer subscribes to the long held security standard of preventing User Enumeration wherever possible now? Should we just give up? What the point of PRs like #30787 then... reported to the JSST by @brianteeman and officially addressed by the JSST @joomla/security

avatar brianteeman
brianteeman - comment - 13 Jan 2021

Correct. "This username is taken" is another example of User Enumeration.

Yes it is ;)
image

avatar PhilETaylor
PhilETaylor - comment - 13 Jan 2021

I don't have a solution for User Enumeration at the registration page. And as you clearly point out with your screenshot, even mySites.guru (and literally every site on the internet that has a registration form) has this issue. The only solution is to allow multiple registered users with the same identity credential (Username/Email) but with different passwords, and I do not know of a platform/app that currently allows this, probably because if both users have the same (crap) password then they would end up in a condition where they could login to the wrong account.

Anyway, This PR is not about the registration form. Its about the WebAuthn endpoint.

I guess the Joomla Project needs to decide if its going to follow security principles promoted by OWASP and others, or not. Historically, and recently, the Joomla Project has taken every step it can to prevent User Enumeration. A quick google and I cannot actually find a statement from the project of what its level of security standard is.

The project can choose to accept or reject this PR. No hard feelings either way.

avatar nikosdion
nikosdion - comment - 13 Jan 2021

Your whole argument is based on your belief that the project should not address User Enumeration because usernames are now "public knowledge" in 2021 anyway.

No, it's not about "belief". A "belief" is something unsupported by facts and reality. Your saying that being able to verify if a username exists on a site is a Bad Thing is a belief because it is unsupported by facts and reality.

User Enumeration only makes sense as a tool to refine password brute force attacks. The idea is that if I know your username I can try to send different passwords (practically: known leaked passwords) to see if I can't hit a jackpot. Trying to send a deluge of common or plausible passwords to an endpoint to see if the username exists isn't the problem, especially when the endpoint will only give me a list of usernames which have WebAuthn enabled. These are the usernames I don't want to try attacking because they are far less likely to have a vulnerable password.

I don't care if this PR is implemented or not, I just don't think that it achieves the stated goal or that it's enough.

What I would much rather implement is an option in the WebAuthn plugin which PREVENTS user authentication with a password if WebAuthn is enabled. In this case it doesn't matter if I know who has WebAuthn enabled; I can't brute force their password.

Regarding the project's decision about User Enumeration, I think it's BS. If you want to completely prevent user enumeration you need to disallow self-registration (core or third party, including all e-commerce extensions!) and forbid any third party extension from showing a username in a publicly accessible page. This means you can't have e-commerce, forums, helpdesk, comment etc extensions. You end up with a static site generator. Is this really what the project wants or is the decision regarding user enumeration applied selectively? Neither makes sense.

In the end of the day usernames need to be treated as public identifiers and the effort being at preventing weak passwords which can be brute forced or, generally, any kind of passwords because they CAN be subverted. That's the whole point of implementing WebAuthn. If you want to commit suicide by removing WebAuthn because it will help you determine which users have chosen not to be hacked easily by weak and subverted passwords please go ahead. There are other ways to put sense back into the CMS, from third party extensions to forking depending on the severity of stupidity afflicting the project.

Do whatever, people. I am already working on a new version of WebAuthn which allows for client-side credentials, completely bypassing the problem of having to enter and validate the username. I am not contributing that back to the project because it'll never make it to 4.0 and I'm honestly done trying to reason about things that are obvious. I have better things to do with my life.

avatar PhilETaylor
PhilETaylor - comment - 13 Jan 2021

Your saying that being able to verify if a username exists on a site is a Bad Thing

No. I'm saying being able to verify if a username exists on a site is User Enumeration and the Joomla Project has always sought to prevent User Enumeration wherever possible.

Preventing User Enumeration is still part of the OWASP and other security standards.

What I would much rather implement is an option in the WebAuthn plugin which PREVENTS user authentication with a password if WebAuthn is enabled. In this case it doesn't matter if I know who has WebAuthn enabled; I can't brute force their password.

Outside the scope of this PR, and doesn't prevent the User Enumeration this PR addresses.
This new feature could easily be implemented as a separate PR.

I just don't think that it achieves the stated goal or that it's enough.

Why? Those comments would be welcomed to hear. All you have mentioned so far is the " fake authenticator identifier is an SHA-256", when infact its just reusing the code that was already there, already using SHA-256.

The PR stops User Enumeration by always returning a challenge and the challenges are always built the same way regardless if the user exists, doesn't exist, or has or has not webauthn enabled.

Regarding the project's decision about User Enumeration, I think it's BS.

Not my project. Not my decision. Not my problem. I reported the issue in June 2020 and was told it was confirmed and would be addressed. No one has yet addressed it so Im offering this PR.

It's not my job to defend the Joomla Project or defend that preventing User Enumeration is still required/not required in 2021, or that usernames are now public knowledge.

If you want to commit suicide by removing WebAuthn because it will help you determine which users have chosen not to be hacked easily by weak and subverted passwords please go ahead.

No one is talking about removing WebAuthn. This PR is addressing User Enumeration in the WebAuthn process. Just like User Enumeration would be addressed in any other Joomla endpoint.

avatar ceford
ceford - comment - 25 Jan 2021

Thank you for this discussion. I am too much of a security novice to comment or test myself. Maybe one way to learn is to watch and listen!


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/32021.

avatar zero-24
zero-24 - comment - 25 Jan 2021

Thank you for this discussion. I am too much of a security novice to comment or test myself. Maybe one way to learn is to watch and listen!

No need to have indepth security knowledge. The test is about checking whether webauth still works as expected after the pathc :)

avatar PhilETaylor PhilETaylor - close - 25 Feb 2021
avatar PhilETaylor
PhilETaylor - comment - 25 Feb 2021

Closing as no interest and no chance of being merged.

avatar PhilETaylor PhilETaylor - change - 25 Feb 2021
Status Pending Closed
Closed_Date 0000-00-00 00:00:00 2021-02-25 14:26:59
Closed_By PhilETaylor
Labels Added: ?

Add a Comment

Login with GitHub to post a comment