December 2022 Archives

2022-12-19

Better Make Sure Your Password Manager Is Secure

Or Someone Else Will

tl;dr

As part of a security analysis, our colleagues kuekerino (T / M), ubahnverleih (T / M) and parzel (T / M) examined the password management solution Passwordstate of Click Studios and identified multiple high severity vulnerabilities (CVE-2022-3875, CVE-2022-3876, CVE-2022-3877). Successful exploitation allows an unauthenticated attacker to exfiltrate passwords from an instance, overwrite all stored passwords within the database, or elevate their privileges within the application. The individual vulnerabilities can be chained to gain a shell on the Passwordstate host system and dump all stored passwords in cleartext – Starting with nothing more than a valid username!

Details about these and all other identified security vulnerabilities in Passwordstate can be found in our published disclosure report [PDF].

Click Studios states that all vulnerabilites are fixed since Passwordstate 9.6 - Build 9653.

Securing Your Password Manager Is Crucial for the Security of Your Organization

Many enterprise organizations struggle with password management. Password management solutions simplify this process by generating, storing and managing our passwords. Storing passwords in a secure password manager is so far the best method to safe-keep passwords, but it is important to understand that the more secrets are stored within a single centralized location, the more valuable it will be for criminals. Therefore it is of crucial importance that the solution storing the secrets is secure.

We experienced first hand how severe that lack of security can be, when we conducted a pentest for a customer. The customer planned to migrate their password management to the solution Passwordstate by Click Studios and wanted to make sure that their passwords would be securely stored and can only be accessed by authorized users.

Passwordstate is an on-premise enterprise password management solution. It allows its users to store, access and share sensitive password material. The password manager has support for a vast amount of features, different access control systems and connectors to enterprise identity management solutions. With over 29,000 customers, "spanning from the largest of enterprises, including many Fortune 500 companies to the smallest of IT shops", it is widely deployed.

We started our analysis by setting up our own instance of Passwordstate with a machine-in-the-middle setup. This allowed more transparent and dynamic testing. Afterwards we used the whole application for a few hours to map as many of the available features as possible. Our first observation was that the core of the application uses a framework, but the various API parts had a more custom tailored feel. Some API components used a different authentication mechanism and we suspected that it was developed without the framework. This seemed to be a promising place to start, as custom written code most often is more prone to errors.

The first API we looked into was the browser extension API. Passwordstate has support for a browser extension, which can store, modify and retrieve passwords for users. As this API directly handles confidential credentials, it peaked our interest.

The browser extension authenticates against the API with a token and we wanted to know how it is generated. As the software is written in C#, it should have been easy to decompile it. To prevent decompilation, the vendor used code obfuscators – these can't hide the code completely, but can make it more time-consuming to decompile or understand the code. Contrary to a real attack, time is limited in pentests. So, instead of deobfuscating the code, we tried another approach: The changelogs of the software showed that code obfuscation was introduced a few major versions before. These versions cannot be downloaded on Clickstudios' website anymore, but the Internet Archive had some older versions available.

The decompiled version contained a surprise for us: The API token is not some randomly generated string or secret, neither is it cryptographically signed. Instead, the API token contained concatenated user information that was XOR encrypted with a hardcoded key. A decrypted example can bee seen here:

user;abc;def;144503

Even more surprising was the code, which validated the token: The only field from the string used for authentication and authorization was the username. This implied the following:

  • Tokens cannot be invalidated when they are compromised
  • Tokens are not changed on a user's password change
  • We can create our own token for a known username

The last point is crucial: We only need to know an existing username to craft a valid API token with the hardcoded XOR key. As a result we can access and modify all data which the browser extension can access and this includes all passwords of that user that have a URL entry attached to it. This is the default for any password stored through the browser extension. We were off to a great start, but there were some passwords left within the instance we could not access yet. So we decided we need to dig deeper to acquire them as well.

The fact that we retrieved the requested passwords from the API in cleartext got us thinking. Because this means that the passwords are either not stored encrypted on the server or are stored with only server-side encryption within the database. An inspection of the database on our installation showed that the latter was the case. In fact, the server-side decryption was already reversed by Northwave Security a few years back. They have published a proof of concept which allowed to extract the obfuscated AES key used for encrypting the database from different files on the system and snippets from the database. Afterwards it dumps all passwords stored within the database.

We consider this architecture a fundamental design flaw, as any attacker with access to the host system can dump all stored passwords on it! The linked code though is only working for builds until version 8903, afterwards it was mitigated with an update. There was no major announcement regarding a change of cryptographic implementation in Click Studios' changelog or release notes. This led us to believe that the fix may not address the root cause but only changed and subsequently obfuscated the decryption process enough to break the proof of concept tool. To verify our suspicion we generated the previously working encryption key with the tool:

Generated encryption key

We performed some in-memory searches to see if the key is still in use by the application in its previous form. Yes, it was! And right next to it was something which looked very similiar to a key as well. We tried decrypting the database with it and it worked. The following image shows the two keys next to each other. Can you spot the connection? A simple one-line patch is sufficient to make the password decryptor work again.

Memory Scan

But in order to get to the encrypted passwords, we would need access to the database or – even better – get a reverse shell.

We already mentioned the vast feature set of Passwordstate like its role based access system. Users with the administrator roles have a special menu that gives access to many administrative features, for example backing up the database or adding new users. Or – and this feature seemed particularly interesting to us – the ability to run arbitrary Powershell scripts on the host-machine: Code execution as a service! If we could find a way to elevate our privileges within Passwordstate to an administrator user, we could access the host system and dump all passwords. But remember, we may have access to the browser extension API so far, but that does not give us access to an actual session within the web instance.

As the Passwordstate user interface is a website, this provides a huge surface for cross-site scripting (XSS) attacks. We did not have to dig deep to find one: URLs could be assigned to passwords which can quickly be visited from within the password manager. The link validation was insufficient and allowed the use of the JavaScript protocol handler and therefore for easy XSS attacks with a single click.

The actual URL is mostly hidden in Passwordstates' user-interface, increasing the probability of an unsuspecting user clicking the link. And here comes the art of make humans clicking links: As an authenticated user this is easy – Passwordstate allows sharing of password lists. Inviting a colleague to the password list for the next project is common. And if the only place where the URLs are shared is the shared list, a click on the link is not unlikely.

But what seems even more authentic than a link in a shared password list? A link in a user's private password list. How do we do that? With an IDOR.

We already found a major vulnerability within the browser extension API and as hackers we know: One vulnerability seldom comes alone. One of the first things we checked with our unauthenticated API access was, if we can access other user's passwords. We had no luck with that, but discovered that it is possible to store new password entries within other people's password lists when the list's ID is known by using the following request:

POST /api/browserextension/addpassword/ HTTP/2
Host: XXX
Cookie: session-id=XXX
Content-Length: XXX
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

auth_key=XXX&PasswordList=anything&PasswordListID=1&Title=please+open+me&UserName=username&D
escription=please+open+me&URL=any_url&Password=password&WebsiteFav
icon=anything

This even worked for private password lists! When inspecting the request to the API, we quickly noticed the numerical and incremental nature of the IDs that are used in the requests. Simply by iterating, an attacker can add the XSS payload to every single password list in the system – And that is exactly what we needed to spray the XSS payload.

The Exploit

Now we had all the puzzle pieces for an exciting vulnerability chain that could get us from a remote attacker with only a valid username to accessing all passwords stored on the Passwordstate instance. The cherry on top is of course the reverse shell on the instance that allows an attacker to keep their access even when these vulnerabilities are fixed.

Let's see how the individual vulnerabilities can be combined:

  1. Forge an API token for a valid username
    Forge an API token for a valid username
  2. Iterate through all public and private password lists and add malicious password entries with the XSS payload in the URL field
    Iterate through lists
  3. Wait until an administrator opens the prepared password entry and cover it by opening a benign URL
    Wait until an administrator opens the entry
  4. Get a reverse shell
    RUN CMD
  5. Finally decrypt and dump all passwords stored within the Passwordstate instance
    Decrypt and dump

Conclusion

Password safety and therefore password management solutions are the foundation on which an organization's security infrastructure is built on. They are the keys to the queendom and as such they should be handled with the utmost care. Their security must be treated as a holistic endeavor from architecture to implementation and maintenance. A vast feature set often also implies a huge attack surface, with lots of room for errors.

The uncovered findings show the incredible importance of ongoing security audits for critical assets and red teaming engagements within organizations.

Acknowledgement

We want to thank Click Studios for the open and transparent communication within the disclosure process. Click Studios was responsive throughout the entire process and released their fixes swiftly after receiving our report.

Advisory & Timeline

Find the full technical details about these vulnerabilities, proof of concept code, the disclosure timeline and all other identified vulnerabilities in our disclosure report [PDF].


Posted by modzero | Permanent link | File under: security, software, hacking, exploit, crypto, advisory