Skip to content

Server Version 0.74.3 is generating duplicate user accounts after upgrading #4271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
CyberKaizen opened this issue May 30, 2025 · 4 comments · May be fixed by #4290
Open

Server Version 0.74.3 is generating duplicate user accounts after upgrading #4271

CyberKaizen opened this issue May 30, 2025 · 4 comments · May be fixed by #4290

Comments

@CyberKaizen
Copy link

Moving from a version of Velociraptor with the old version scheme 0.7.x to the new one 0.74.3.

There seems to be a strange issue where accounts made by SSO are duplicated after the user account logs into the upgraded server.

I've tried various things like completely wiping out the accounts including the backend files. But that does not stop this issue from happening again.

@scudette
Copy link
Contributor

What does "duplicated user accounts" mean exactly?

@CyberKaizen
Copy link
Author

CyberKaizen commented Jun 6, 2025

@scudette Like this it is presented as the same user two times in the GUI. /app/index.html?org_id=root#/users

Image

Also when you examine the results from GetGlobalUsers API call, there are duplicate user accounts as well.

The duplicate users have the same exact permissions and orgs assigned as each other.

What may also help in terms of context is that we are using Azure SSO authenticator.

@CyberKaizen
Copy link
Author

CyberKaizen commented Jun 7, 2025

@scudette Figured out the issue! It had everything to do with the backing datastore storage and maybe how the code handles storage of user account names to a file and how it is later retrieved. Specifically data in "root of velociraptor datastore directory/users/useraccountname.db" or "root of velociraptor datastore directory/orgs//users/useraccountname.db".

Assume I create a user account named, "[email protected]":

  1. After inserting the name into list of accounts for Org...
  2. Datastore creates a file named: "root of velociraptor datastore directory/users/[email protected]"
  3. Then let's say I later delete the account with VQL: 'SELECT user_delete(user="[email protected]", reallydoit=true) FROM scope ()'
  4. Account disappears from GUI when called with GetGlobalUsers API call to populate. However in the backend all files related to [email protected] file still exist and are not wiped out and removed from the datastore. this is a long standing behavior in which reallydoit still does not delete files from the datastore by design (as far as what I understand).

I make a new user account from the GUI named, "[email protected]", of course I as a end user have assumed that if there is no user in the GUI, this account does not or never existed and I am okay to make another one:

  1. After inserting the name into list of accounts for Org...
  2. Datastore creates a file named: "root of velociraptor datastore directory/users/[email protected]".
  3. GUI is accessed in browser, user visits /app/index.html?org_id=root#/users, and GetGlobalUsers API call is ran to populate GUI.
  4. What I believe now likely happens is that GUI - > API -> function for getting users -> function for parsing db files in datastore reads both "root of velociraptor datastore directory/users/[email protected]" and "root of velociraptor datastore directory/users/[email protected]". This causes GetGlobalUsers API call to respond with two users with the same name.

What's odd is that when the actual user account name created via GUI is stored in the db file with the exact string. For example, I create a user "[email protected]", in the db file it is stored as "[email protected]".

I was able to test my hypothesis by deleting ALL db or json.db files and directories related to the old user account name that were not deleted.

After making the GetGlobalUsers API call again, the duplicates disappeared.

In short:

  • Creating, storing, or deleting the GUI created user account name the case sensitivity is respected.
  • ReallyDoIt is not truly deleting the backing files causing a domino effect of compounding and difficult to troubleshoot issues.
  • Functions related to retrieving user account names and displaying them in the GUI, case sensitivity is not respected causing even further difficult troubleshooting (due to lack of unique identifiers like Orgs).
  • Both users which should be considered unique identities (if case sensitivity matters) are considered the same on retrieval and both will get the same ACL permissions as the other (would this cause a possible privilege escalation issue? tested, and no it would not).
  • The issue appears to be workflow specific: user visits /app/index.html?org_id=root#/users - > GetGlobalUsers API call -> function for getting users -> function for parsing db files in -> return of info to GUI via GetGlobalUsers API call

@scudette
Copy link
Contributor

scudette commented Jun 7, 2025

We used to have case sensitive user names but this caused a lot of confusion with systems that were not case sensitive so now we actually treat case sensitivity as duplicates. This looks like an edge case where we don't actually handle this correctly.

As for deleting the user account this is by design as the user account is essentially useless without any ACL permissions in the relevant orgs. So deleting a user just removes their permissions everywhere.

Then when adding the same user again it should reuse the same record file. Maybe that's where the bug lies, we don't normalise the user names properly in the data store

scudette added a commit that referenced this issue Jun 11, 2025
Previously there was a time based cache but we dont expect a lot of
users so we can reasonable keep the user list in memory
permanenetly. This helps to address potential problems in casing when
saving user accounts with different cases.

The new code deliberately catches these potential casing clashes and
ignores user accounts and acls for users who differ only in
case. This might help resolve #4271
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants