As part of the time that my company offers for research, my good friend and talented hacker Alberto Illera (@algillera) and me decided to “checkout” LastPass.
Many of you may already know (or even use) LastPass. It is a pretty well known password manager that stores all your passwords in a “vault” and keeps them secure. Additionally, it can automatically populate the credentials for you when you visit a website in which your are registered making it easy to use more secure, random and unique passwords. You will just have to remember the master password that decrypts the vault and that’s all.
LastPass comes in many forms. As a browser plugin, as a mobile app or even as Webapp.
As you may agree, a service that stores all your passwords sounds like a cool target so we decided to have “A look into LastPass”, understand how it works, check if it really keeps our passwords secure and why not? Try to find vulnerabilities.
How does LastPass work?
One of the advantages of LastPass is that your master password and vault are never sent in cleartext to their servers. That means that not even LastPass knows your passwords which in the NSA era is something to consider. LastPass encrypts and decrypts all your data locally in your machine using AES256. Data sent to LastPass is hashed with SHA256 and hardened with PBKDF2. You can find more information in their website.
We decided to put our efforts into their API, the website and specially into reverse engineering the Chrome plugin.
API and Website
We found several issues that we reported to them and while they did not consider some of our findings, they did acknowledge some of them.
Weak password policy
I was surprised to find out the the master password policy is that it needs to be at least 8 characters long. That’s it! No mandatory uppercase, numbers, special characters, etc. Again, this is the policy for your master password, the one that protects all your other passwords. I think there is no reason to allow master passwords like ‘aaaaaaaa’ or ‘qwertyui’.
Password reminder
It is part of best practices that the password reminder cannot be the
actual password not to have password reminders. 2 factor authentication should be the way to go but LastPass has this option. While indeed, the reminder cannot be the password itself, we found out that it can “contain” the password. If your password is say, ‘qwertyui’, your reminder cannot be ‘qwertyui’ BUT it can be ‘my password is qwertyui’. This might be because they hash the password so there is no way for them to tell that the sentence contains the password unless they hash the words separately to compare first.
While the reminder gets send to your email rather than being simply displayed in the website, if the email account gets hacked, one of the first things an attacker would do is to look for keywords like “password” to find emails regarding password resets, reminders, etc.
The number of PBKDF2 iterations is public
As mentioned above, the master password gets hashed with SHA256 + PBKDF2 with a certain number of iterations. While security by obscurity is not a good thing, I believe that keeping the number of rounds secret adds extra protection. Anyone can check how many iterations where used for any user.
It is worth noting that older accounts have the default rounds set to 500. With the power of the current desktop computer this is not enough nowadays. Steve Thomas points it out in this great post. Also, as explained in his post, you can see that LastPass “fixed” the problem with the first request being iterated just once by making it rounds publicly accessible which is what we reported.
Newer accounts default to 5000 now which is better but I recommend you to check and update the number of iterations accordingly in the settings panel. (I had it to 500 and my account is only 3 years old).
CSRF
The API call to CRUD new data such as new sites, secure notes, etc. is not CSRF protected. Actually it is, but you can simply remove the parameter containing the CSRF token and it will go through. While this sounds pretty devastating (imagine deleting all credentials of a user), it is not that simple to exploit. As mentioned above, all data is encrypted so you would need to know how to correctly encrypt the data (aka knowing the master password) in order to effectively perform the attack. Funny story, while doing tests I did probably broke something because I got an email from the CEO wondering what the hell I was doing…
Bypassing 2 factor authentication
LastPass allows 2 factor authentication in several ways. It supports Yubikey, Google Authenticator, Keypass and others. We just focused on Google Authenticator as we believe it is the most popular and it is free.
We realized that it was possible to obtain the QR Code to setup the Google Authenticator by just stealing the session id. This means that retrieving the 2 factor authentication QR code was actually bypassing 2 factor authentication!
The main problem was that the request was not protected by prompting for the master password again. Sensitive actions like changing passwords, personal information and, in this case, activating/deactivating 2 factor auth, should always prompt for the password again.
Best thing was that even if the victim would not have 2 factor auth enabled, you could still retrieve the QR Code. That would help in case the victim realizes that the account was hacked and activates 2 factor auth as counter measure. It doesn’t matter, the attacker has that already!
Browser plugin
Once we decided that we had enough material on the API, we moved on to the browser plugin. We worked specifically on the Chrome plugin but we are confident that all other browser work on the same code base.
The plugin is written in javascript so no fancy assembly here. Still, it was minimized and optimized so we where looking at function names and variables such as ‘a’, ‘ab’, etc which made it all more difficult to reverse engineer.
Alberto wrote a small script to help us understand what the plugin was doing. This script would add as the first line of every function some logic to print information about the method itself and the value of the parameters passed. With that, we had a chronological stack of function calls and their parameter values. These was a big help and helped us identify the interesting parts of the plugin logic.
What caught our eye was what was happening when the user would click the option “store password”. This functionality provides the commodity of never having to enter the master password again as it will be populated to the plugin and you will be automatically logged in.
We found that the username and master password was stored in a sqlite3 database in the system. This database is not encrypted and there is no need to be root to access it. The username is stored in cleartext but the master password is encrypted.
Our next target was to figure out how it was encrypted and see if we could decrypt it. With the help of our script, we understood that the database was encrypted using 2 different encryption modes: AES256 CBC and ECB. I am not sure why they support ECB and we did not bother finding out or how the choice to use on or another was made.
Once we knew how the password was encrypted, we had to find out how the IV and key was calculated and which was the data to be decrypted. It took us a while but finally we figured it all out.
The encrypted data stored in the database is base64 encoded and has two different formats depending if CBC or ECB was used for encryption:
- CBC: It includes ! at the beginning and | as the 25th character, e.g. !L5b/dOyu4EMdmWCYkASQaw==|cHTFJDy1DQi8dPY0AJL/1B==
- ECB: It is a simple base64 encoded string, e.g. u7W1PsEYsWrtAS1Ca7lOOH==
For CBC, the different parts correspond to:
- KEY: The key is the email hashed with SHA256 and converted to binary
- IV: The IV is the 24 first characters of the encrypted data stored in the password field (ignoring !)
- DATA: The data to be decrypted is the portion of the stored encrypted string left, starting at the 26th character (ignoring |)
For ECB, the key is the email hashed to SHA256 and converted to binary as well and the data to be decrypted is the stored encrypted string.
Metasploit Module
With all this information, we where finally able to obtain master passwords in cleartext. Woo hoo! Our attack only covers users that click the “Store my password” option though so, don’t store your master password!
We decided to write a metasploit plugin so our research would be actually helpful to the community. This work is still in progress but we are close to send the pull request to metasploit. If you want to have a better understanding of everything explained here, checkout the source code of our module in my github repository, I tried to add comments and write the code as clear as possible.
Responsible disclosure
As always, we made a responsible disclosure to LastPass. I want to stress how easy it was to work with the security team. The where very responsive and worked on fixing the issues we reported immediately. They also followed up with us from time to time and asked for our thoughts on every fix. It was a real pleasure to work with team!
This is a list of some of the things they fixed based on our disclosure to them:
- Retrieving the QR Code for 2 factor authentication does prompt for the master password now
- It also sends an email to the user informing of this action including information of the IP where the request was originated from
- The plugin warns that it is insecure to store the password locally when the option is checked
- They are working on detecting if the password hint contains the master password
Also, they showed their appreciation by adding us to their hall of fame and they also sent us some swag.
Is it 100% true that they encrypt locally and therefore cannot access password data on their end?
We’re not just taking their word for it – There is irrefutable evidence that this is the case?
Because I love LastPass and hope it really is as secure as possible.
From what I have seen during our tests yes. The traffic we inspected had nothing in clear text and all data sent to LastPass was encrypted. I also like LastPass and will keep using it. Just don’t store your password locally ;)
Well, if not keeping an offline copy of the LP database somewhere, then the risk of being completely shut out of your accounts in case lastpass.com is brought offline for some reason needs to be taken into consideration.
That is actually a very good point. I guess we have to consider now the risk/benefit here. How likely is that to happen and is it worth the risk of having a copy stored locally.
I guess a middle point would be having a backup stored in an external HD so you have a copy of your vault encrypted but it is not present in a machine connected to the internet.
I recently learned that some employers actively block access to lastpass.com, presumably to avoid the risk of employees storing work related passwords in the cloud. So, people within the corporate firewall who would like access to their LastPass info (e.g. for incidental personal use) do not have access to this unless they keep an offline copy.
Something that may help in that regard is the “LastPass Pocket” offering:
https://helpdesk.lastpass.com/lastpass-on-the-go-2/lastpass-pocket/
You can store your vault offline and encrypted, e.g. on a USB key or external hard drive, by exporting:
https://helpdesk.lastpass.com/tools/exporting/
Then LastPass Pocket can access this encrypted file once you provide your LP credentials. No details about the encryption mentioned in the LP manual.
Martin, have you looked into LastPass Pocket by any chance?
Very interesting John, thanks for sharing! I was not aware of this feature and is definitely worth looking at.
Respect to some employers restricting access to LastPass… that sounds a bit paranoid. The data is encrypted and LastPass has no access to the data nor your master password. Actually, an offline copy is way less secure that having it in the cloud in my opinion. It is always easier to hack a personal computer or loose the external HD where you store your encrypted copy than hacking LastPass servers. If they have some kind of local deployment (not sure if you can do that) then that’s different story but forcing your employees to keep local copies of your vault is not a good idea.
Thanks again for sharing! I hope I find some time to look at it
Thanks for the due diligence. Password managers need this sort of constant peer review to remain viable. It’s an “all your eggs in one basket” kind of situation.
Glad you enjoy the reading. I agree, the main problem with password managers is that you have a single point of failure…
Hi,
2 years ago I modified the Lastpass extension to steal the master password and on time password. Here is a video about that. https://www.youtube.com/watch?v=Bf2nYkn32DM I don’t think it can be fixed, though.
Good stuff! We looked into that too. Since the plugin is pure javascript, once you can modify the code you can do anything you want. We thought about it to steal all the passwords stored in the vault without having to know the master password. You add code when it is decrypted in memory and send it back to your server. Everything is possible!
What about extracting the master password from plugins that are logged in but not set to save the password? LastPass has an option to log out after X minutes, but if you don’t do that it stays logged in even after you close your browser. Have you investigated how this works and if it can be exploited?
That is done by using cookies. You stay logged in because the plugin will send to LastPass the valid cookie, not the username:password combination. That will only happen when the cookie is not valid anymore.
Originally, my Metasploit module was also stealing the session cookie in order to obtain the QR Code to bypass the 2Factor Auth but they fixed that now by prompting for the password again and warning the victim with an email.
Nice work!!!
As for the master password stuff, I am glad they are not -enforcing- some stupid rules as I use a 24 char hex key (192 bits) that most systems would not accept as it is too insecure.
A warning would be nice (like TrueCrypt does). Users should be educated, but allowed their own choices. http://xkcd.com/936/
Yep, I agree. My point was that the password policy allows very weak passwords and I thought that is something that could be improved. All chars but long passwords is also very good and definitely more convenient as you point out
Hi Martin,
Good Job. You explain what is the key, IV and data but you didn’t mention how they generate the key? Since they use base64 encoding, what is the method used for generation? I hope my question is clear.
Thanks
Hi Abdulla,
I may be missing something from your question but I do explain what the key is. It is the SHA256 hash of the email / username. Not sure what you mean by “how they generate it”. You mean the implementation in JS?
Great write up. I landed here as a result of a search looking for more information on how the chrome plugin works. Not much out there on this.
Based on your research and knowledge on the plugin, could you help clarify the following:
1. Lastpass stores an encrypted copy of your Vault locally on your machine, I assume an authenticated last pass plugin decrypts this vault and is able to access username/passwords on demand. Could a malicious plugin installed on chrome have access to this data?
Thanks.
Hi!
You are correct about the vault been stored locally and that for decryption you need to be logged in. In order for a plugin to be able to get access to the vault, it would need access to the filesystem to extract the data I explain in the writeup.
Another way would be that the plugin can access the DOM and steals the passwords when they are injected into the forms.
One last case would be that the plugin can access the LastPass plugin but that should not be possible due to SOP (Same Origin policy).
I will give a talk at Shakacon in 2 weeks about this and other, more effective attack vectors. Stay tuned as the talk will be recorded and I will publish the slides as well :)
Apologies, forgot to include this:
2. Would it be possible for an attacker to copy lastpass local data which according to their site is stored at: Windows Vista/7/8 Google Chrome: %LocalAppData%\Google\Chrome\User Data\Default\databases\chrome-extension_hdokiejnpimakedhajhdlcegeplioahd_0\
Take this data (along with the authenticated session id or cookie) and restore somewhere else on another computer, bypassing authentication and 2 factor auth??
I kinda answered this question above. If the plugin has filesystem access then yes for the files. You won’t be able to access cookies though due to Same Origin Policy. But the truth is, you don’t even need the cookies!
Thanks Martin.
For the second scenario I described above, wouldn’t a successful login using the master password or injecting an authenticated cookie be needed to decrypt the local vault if files are copied from another computer though?
Sorry for the delay, I missed this last one. If you log-in successfully with the master password, that means you have the master password. And if you have the master password, then you have the encryption key. If you have the encryption key, you can decrypt the vault.
Cookies are of no use in reality as in order to be able to see the vault content, you need to decrypt it first and the session id is unrelated to the encryption key.
Very interesting read. I have been using Lastpass ever since they released the plugin. I notice that you warn of checking the option “remember password” in the browser plugin.
I use the option in lastpass to only allow some computers to actually login to Lastpass. My home computer and my work computer are the only computers that can open Lastpass vault with the password and two factor authentication. Doesnt that mean that the attacker hast to sit at my desktop to use the master password? As I understand it I can even use my master password – once – with my two factor authentication (I use Transact) on a keylogging public computer at an internet café in Ukraine, or just givet it out to anyone, and it doesnt matter since after that the password only works on those two computers without the second verification by Transact (or google authenticator, the grid or the other two factor authentication options that Lastpass provides?
“My home computer and my work computer are the only computers that can open Lastpass vault with the password and two factor authentication” I meant that these two computers are the only computers that DONT need two factor authentication
“My home computer and my work computer are the only computers that can open Lastpass vault with the password and two factor authentication” I meant that these two computers are the only computers that DONT need two factor authentication
There are couple things here. It is important to note that 2FA is not used or is part of the vault encryption. That means that someone with your password and the encrypted vault will be still able to decrypt it. Therefore, login in a public computer in ukraine is probably still not a good idea if that data is downloaded. 2FA only protects authentication but if the data is already on the computer then it won’t matter.
In this post I only talk about the possibility of extracting the cleartext password but in november I will give a talk about LastPass and show additional methods to compromise the vault including 2FA bypass. Keep an eye for it: https://www.blackhat.com/eu-15/briefings.html#even-the-lastpass-will-be-stolen-deal-with-it
Hey Martin,
Nice article. I just noticed a typo @ “It is a pretty well know password” -> “It is a pretty well known password”
Cheers,
Sameer
Got plenty of them, so thanks!
おかげで、私は真は約強く感じ楽しむこの主題トピックに余分な学習します。あなたのように、達成可能な場合は、経験を達成あなたの思考はあなたの更新になる|追加データがブログウェブログを? 私のため役に立ち 。
can you work with me by phone or screen sharing on last pass?
I wonder if you might have a recommendation for working out when Last Pass is installed and enabled in a given browser? I am finding that with complex web sites / applications, Last Pass is having a significant performance effect and at the moment the Last Pass team are only disclosing UI based ways to determine when LP is working. I want to do this by calling a feature of LP if possible.
Additionally I would like to give the user the option to disable LP and re-enable it when they leave. Suspect that might be really tricky as I imagine that the Banks would already have done this if possible.
A version number for LP would also be helpful if you know how to grab that. That would sort of address the problem I have although finding out whether LP is enabled might require a slightly different approach if the version number is still accessible when it is disabled.