📜 ⬆️ ⬇️

We get the master password from the password manager 1Password 4 blocked

New tools, old methods. We do reverse engineering and find the fatal flaw of 1Password.

Everyone loves password managers. They are great for many reasons. Personally, I have over 200 entries in my manager. With such a large amount of confidential data in one place, it is important to understand the scale of damage in the event of your record being compromised, be it malware, exploits or just a computer left unattended for a few minutes. The Washington Post recently published an article based on our research . This article helps to bring people that not all password managers are the same.

I truly believed that the blocked password manager was securely protected. If someone gets access to my computer, then the maximum can count on a bunch of random bytes, because the information is reliably cleared from memory.

This is true for 1Password 4 (Note that the latest version for today is the seventh). Before switching to it a few years ago, I checked that there are really no clear-text passwords in memory when the manager is in a locked state. So in the event of a compromise, the attacker will have to deal with the encrypted storage.
')

The vault is locked!

In this state, there are no password entries or a master password in the memory. Very reasonably and correctly, and 1Password 4 passed this test. Or not?

To get rid of boring details, I will say right away: we were able to recover the master password from a locked instance in 1Password 4, as shown below.


Unlock 1Password 4 and recover master password

The animation shows that 1Password 4 is first unlocked in the normal way, and then locked. After that we run our multipass utility, which successfully recovers the password. The utility exploits the incorrect processing of the password input field in 1Password 4, to restore the obfuscated master password buffer, de-fuse it, automatically unlock 1Password 4 and, finally, display the master password in the console.

Boring details


The first step in assessing the password manager: check for the presence of the master password in the memory in clear text. This is possible in any hex editor that can interact with the memory space of the process. For example, the free HxD editor. With it, you can open the 1Password 4 memory space.



We immediately find ourselves in the first readable area of ​​the 1Password 4 memory space.


HxD Memory Example

So far, nothing special. But you can perform a search. For example, what the situation looks like if you type a password in the 1Password 4 unlock window, but do not click the "Unlock" button:


The locked storage 1Password 4 with the entered master password in the field

Surely the password is somewhere in memory?

Open HxD, but searching for a string with our master password (“Z3Superpass #”) does not produce results.



It seems that 1Password somehow encrypts or obfusts the form as it is entered. If the procedure works correctly, then everything is fine.

Dive deeper


To find out why the master password cannot be found in memory when it is clearly present in the unlock dialog box, you should find the code that interacts with it. There are several ways. You can track keyboard and mouse event handling by localizing 'GetMessage', 'PeekMessage', 'GetWindowText', or other Windows APIs that typically handle user input. So we find the buffer where the keystrokes are written, and through them we go to the encryption / obfuscation routine. But this is a long and error-prone process, especially with large frameworks that sometimes manage memory very strangely, so in order to track the buffer you will have to make a lot of copies and transformations.

Instead, we use our own Thread Imager tool, designed to reverse-engineer “weird” proprietary protocols at the application level. It will help determine where in memory 1Password 4 interacts with our master password. The tool “automatically” identifies areas of the code in 1Password 4 that interact with the obfuscated password (it simply highlights the instructions that interact with the data of interest for further analysis). The result looks like this:


Thread Imager finds 1Password 4 code that interacts with the non-fussed master password

Since the master password is stored in memory in obfuscated form, the tool must first show where obfuscation occurs.

The fragment from the first result shows that the first appearance of the master password is accompanied by the transition of the code from the address 0x7707A75D to 0x701CFA10.


A detailed entry in the Thread Imager highlights the transition of the code from 0x7707A75D to 0x701CFA10, while the EAX and ECX registers refer to the buffer with the master password.

Exploring this place 0x7707A75D in the debugger (x64dbg) confirms our theory. Indeed, for the first time the string 'Z3superpass #' is encountered when the decoding function 'RtlRunDecodeUnicodeString' is completed from the ntdll.dll library.



After a little analysis, it is clear that these two functions are used to obfuscate the password: 'RtlRunEncodeUnicodeString' and 'RtlRunDecodeUnicodeString'. So the master password is hidden from primitive copying from memory, which is why we could not find it in the hex editor before.

If you examine the encoded buffer at the end of the RtlRunEncodeUnicodeString function, the encrypted string with the master password looks like this:


Encrypted master password

After RtlRunDecodeUnicodeString 'it is decoded:


Decrypted master password

Interestingly, this area is stored at the same address 0x00DFA790 and we can literally watch it change when entering a password in the 1Password 4 unlock window:



Vulnerability


'RtlRunEncodeUnicodeString' and 'RtlRunDecodeUnicodeString' are simple functions that modify a string with a simple XOR operation. This is not so bad: it looks like this is the standard method of masking all native Windows editing controls with the 'ES_PASSWORD' flag set.

The problem is that after unlocking 1 Password 4, the encrypted master password is not cleared from memory.

Worse, it remains in memory after blocking 1 Password 4. That is, we have a locked password store, but with an encrypted master password in memory.

And even worse, because we interact with the master password input dialog box, the same memory area is reused with the same XOR value, which gives us easy access to the encoded buffer to create the exploit.

Task


To create a reliable exploit for 1Password 4, you need to get a clearer idea of ​​how the master password is handled by the program workflows. Using the aforementioned tools, we constructed a diagram of the output data (figure below).



Using this diagram, it is easier to understand where and which libraries will be used in order to reliably identify areas in memory, from where you can extract the master password.

Exploit


What do we have at the moment? We have locked storage, and an obfuscated password is stored somewhere in the memory, since the program did not clean the memory properly.



To extract it, you need to call the procedure in 1Password 4, which initiates 'RtlRunEncodeUnicodeString' and 'RtlRunDecodeUnicodeString'. Thus, it will show the location of the memory buffer with a coded master password.


Obfuscated Master Password Memory Area

Without this buffer, you would have to plunge into the abyss of Windows internal procedures and controls and their associated memory management mechanisms. Perhaps such an analysis makes it easy to find a buffer, but we did not go this way.

It seems that the only way to call 'RtlRunEncodeUnicodeString' and 'RtlRunDecodeUnicodeString' is to enter the master password into the symbol in the dialog box. So we get the right buffer. But we do not know the length of the password.

We solved this problem by intercepting code that accesses the first character of our buffer, blocking an attempt to change. This routine is in the comctl32 message handling loop of the control element, which handles the management of the buffer of the corresponding elements. Calling 'memmove' with offset 0x70191731 overwrites the buffer with the character entered:


(Side effect: the highlighted line (yellow) updates the entire password line)

Now we finally got everything we need to create an exploit. The following steps will allow us to extract the master password:

  1. Hook 'memmove' to prevent overwriting the first byte of the master password.
  2. Hook 'RtlRunEncodeUnicodeString' to get the location of the obfuscated master password buffer.
  3. Hook 'RtlRunDecodeUnicodeString' to access the obfuscated buffer obtained in the previous step.
  4. Entering a character in the password entry field and discarding step 1 (saving the entire master password), redirecting step 2 to step 3 to decode the obfuscated master password.

To perform all these actions, create a DLL with the handler code of all these hooks. The library is injected into the 1Password 4 process, sending one character to the master password dialog box, launching the memmove, RtlRunEncodeUnicodeString and RtlRunDecodeUnicodeString steps that we can intercept - and performing our magic on recovering the obfuscated master password. Most of the magic happens in DetourRtlRunEncodeUnicodeString, this is a hook for the 'RtlRunEncodeUnicodeString' function, shown below:



Which leads us to the final result: unlocking locked 1Password 4 storage of any version using a buggy procedure in the used Windows API:



Summary


When we first went deeper into 1Password 4 internals, we expected to encounter some kind of complex security system and expected that all sensitive information would be cleared from memory, as it happens in PBKDF2 procedures and other areas where a master password is used. Relevant entries are also cleared. However, due to an oversight, the password entry field is treated as a standard Windows API control with a hidden password, which undermines the security of 1Password 4.

Source: https://habr.com/ru/post/441166/


All Articles