LastPass is a popular cloud-based password manager that has quickly become popular for those looking for an easy solution to create and keep their passwords safe. There are many software and cloud-based solutions available for managing passwords, such as RoboForm and KeePass, but for many users – myself included – LastPass is what they prefer.
Of course, as with any software that stores personal information, the question on how secure LastPass really is has come up in many discussions online. The “Trust No One” mentality has led many to believe that unless they can see the source, they won’t trust the software. This is one reason many prefer KeePass over LastPass. KeePass is open source (can be reviewed/fixed by anyone), while LastPass is closed (can only be reviewed and modified by the developers)
I endorse and use LastPass for all my passwords, but haven’t really looked into how LastPass manages my personal information, from the time I enter it into their browser add-in. I was curious at what is sent to LastPass, and the software does exactly what the developer says it does to secure my personal information. The good news is that there are ways of finding out, and in this post I will share my findings so you can make an informed decision, not just a decision based on what others say on the Internet. I am hoping that my tests will answer the question – is LastPass secure?
Looking into How LastPass Manages Your Data
The biggest concern about the security-conscious is that LastPass is closed, and that the code used to secure the data stored within the LastPass service cannot be reviewed. While the development of the software is closed, the code isn’t 100% hidden from the user.
LastPass has said many times, that the code used to secure the personal information that is stored within their service is written in JavaScript. Now, for those that aren’t Web developers, JavaScript is a scripting language that executes within the browser on your computer. The one thing about JavaScript is that it can be opened and read on your computer.
The LastPass code isn’t any different.
Anyone with knowledge of JavaScript, unfortunately I am not such a person, can easily review the JavaScript used by LastPass that secures the passwords and other information sent to the LastPass servers. Since I am not a JavaScript-knowledgeable person, I won’t review the code created by LastPass, but will instead look at the LastPass security from another perspective – what is sent from my computer to LastPass.
This is where a free tool called Fiddler comes in handy. Fiddler allows me to monitor the requests sent from my computer to the LastPass server. With the Fiddler tool I can see what is sent to LastPass in those requests, and what the LastPass server sends in response to the requests.
I have many years of experience with monitoring network traffic because of being involved in performance testing, that I feel confident in finding out what LastPass actually sends to its servers from my computer.
Before I continue, however, let me explain my testing approach:
- Create a new account using a test email:
- Email: testing@technicallyeasy.net
- Password: Password12345678
- Add a new site to the account.
- Add a secure note to the account.
- Add a profile to the account.
- Login through the LastPass website.
Note:
The password I am using for the test account is very weak, but it is for testing purposes only, always choose a long and strong password as your master password for LastPass. The LastPass account and email address have been deleted, so they are no longer active.
Now that I have listed the scenarios I will be testing, lets look at the data to see if LastPass is secure.
Test 1: Creating a New Account
For this test I will be creating a new account from within the Web browser (Firefox) add-in. To create the account I just click the LastPass add-in icon and then click the “Create an Account” link.
I follow the instructions on their forms, filling in the information requested, with the email and password being what I described above.
1. Verify Email Does Not Exist in LastPass
When you enter your email address, LastPass sends a request to their server to verify the email address doesn’t already exist in their system. This request occurs after you leave the email field when you create the account and the request includes the following querystring:
Name | Value |
---|---|
check | avail |
username | testing@technicallyeasy.net |
lang | en-GB |
mistype | 1 |
Bascially the email is sent to their server and the system replies with a simple “ok” message if the email doesn’t exist, or “no” if the account exists.
Note:
One thing I should mention is that all requests sent to the LastPass server from within the Web browser add-in are sent over a secure SSL connection. This means all requests are encrypted when they are sent to the LastPass server.
2. Create the Account
Once the rest of the form is completed, LastPass sends your account information to their server so your new account can be created. This is the first request that will help prove if LastPass is secure, as it occurs after you have entered your master password that will be used by LastPass for the security of your account. Lets look at the request sent to LastPass to create your account:
Name | Value |
---|---|
sentms | 1408151690427 |
username | testing@technicallyeasy.net |
testing@technicallyeasy.net | |
hash | ef6513d537ecd4d328d87e1e7760bcd447022779444bc3e0950b0941e393493a |
password_hint | Test password 18 |
improve | 1 |
loglogins | 1 |
timezone2 | -05:00,1 |
iterations | 5000 |
xml 1 | |
language2 | en-GB |
amo | 1 |
requesthash | crunknown1 |
requestsrc | cr |
encuser | |
hasplugin | 3.1.50 |
By reviewing the request above, I can see that LastPass does not encrypt my email address or password hint, which does seem unusual, but at least the request is sent over a secure SSL connection. You will notice that the password I created for the account (Password12345678) is not sent in the request, which is very interesting. I checked all requests before the account is created, and some of the requests after, and the password is not included in any of those requests, as well. The really important value in the above request, however, is the “hash” value.
As LastPass has said many times – it does not receive your master password. Instead it uses a hash value, derived from your master password. LastPass uses a function called Password-Based Key Derivation Function (PBKDF2) that uses SHA256 (a hashing algorithm). LastPass combines your email, password, and a specified number of iterations (in my case, the default 5000 iterations), with PBKDF2 to generate an encryption key (256-bit) associated with your LastPass account.
Your encryption key is not the hash you see above. The encryption key is not in the above request, which means your encryption key is not sent to LastPass. This encryption key has a few purposes – it is used to encrypt your data, and it is also used to generate the hash above. The encryption key is only generated, and used on your computer.
The hash above is called your “authentication hash”, and is what is used to authenticate your credentials with LastPass. The authentication hash is generated by performing another iteration of PBKDF2 using your encryption key and your password. This is the hash you see in the request above being sent to LastPass.
Note:
At the end of this post you can download an application I created that will allow you to create an encryption key and an authentication hash for various email and password combinations. The source is included, so you can see how LastPass calculates both values using PBKDF2 and SHA256.
The most important thing about the above request is that your master password is also not sent to LastPass. This is one point that LastPass has been stating from the beginning, and I’m sure many people have questioned that statement. The fact that none of the requests that have been sent to LastPass include the master password, proves LastPass’ statement about never receiving your master password.
3. Log Into LastPass
Once your account is created, LastPass automatically logs you in with the following request:
Name | Value |
---|---|
sentms | 1408151692871 |
xml | 2 |
username | testing@technicallyeasy.net |
method | ff |
hash | ef6513d537ecd4d328d87e1e7760bcd447022779444bc3e0950b0941e393493a |
version | 3.1.50 |
hp | 0 |
encrypted_username | BfU+7h76a9q+n7ggVy0bspgVPhObPoc1lKVPP5dFG0o= |
uuid | YZ#USjxD^a5k&cs6k&bCDY@4ZewrRa!^ |
lang | en-GB |
iterations | 5000 |
lostpwotphash | |
otp | |
sesameotp | |
gridresponse | |
multifactorresponse | |
outofbandsupported | 1 |
requesthash | BfU+7h76a9q+n7ggVy0bspgVPhObPoc1lKVPP5dFG0o= |
requestsrc | cr |
encuser | |
hasplugin | 3.1.50 |
What is interesting with this request is that the username is sent as both plain text and encrypted text. I am not sure why, but LastPass must have a reason. Once again you can see that the authentication hash is sent also, but the password or the encryption key are not sent to LastPass.
At this point, the account has been created and I have been logged into LastPass. Any request at this point will not have any knowledge of my master password, as it is too late to have it sent to LastPass. If you would like proof, continue reading to see what is sent in the next few requests I will be testing.
Test 2: Add a Website Login
The biggest reasons for using LastPass is to manage passwords for the many sites you visit. This is where the security of LastPass needs to be as strong as possible. For this test I am using the following information for a website (I manually added the website into LastPass).
- URL: http://www.example.com/login.php
- Name: Example
- Username: tester
- Password: Password1
- Notes: This is a test login.
Here is the request sent to LastPass:
Name | Value |
---|---|
sentms | 1408154348369 |
ajax | 1 |
extjs | 1 |
name | !Ak8TxfXbwkCpOsIZNW3MeQ==|yjy/G/U1//l4ycn9C6hhCg== |
url | 687474703a2f2f7777772e6578616d706c652e636f6d2f6c6f67696e2e706870 |
grouping | |
username | !dyT5dybkq0HbgCYbvsd5cQ==|fgzNv6uOk//371iOtbuFGA== |
password | !lEIb6jJY/3k1a8/1oPhibQ==|KFWn8nfmYsYCmIbLcYer0w== |
extra | !kEjFSalzcun+n4C87UUd3g==|U2iIvu6FI4GvKjQm19sk1Gu7EFPyfsxNS721Ui9Hi+4= |
aid | 0 |
openid_url | |
isbookmark | 0 |
iid | |
requid | 52344236 |
wxsessid | 6RVkMSsfr7pEwbmVgSZsI-JfjK9 |
sessonly | 0 |
token | MTQwODE1MzQyNC4yOS1WqfhJCcJoiVK8rAzVazfsigO9bXw8CA4y9/V+1tRPow== |
requesthash | BfU+7h76a9q+n7ggVy0bspgVPhObPoc1lKVPP5dFG0o= |
requestsrc | cr |
encuser | |
hasplugin | 3.1.50 |
As you see in the above request, LastPass only receives encrypted information about the new site. Nothing about the site is sent in plain text. The values are encrypted using the encryption key that is generated using your email, password and the number of iterations you have specified in your account. Since the encryption key is not sent to LastPass – as proven in the previous section – LastPass can’t decrypt your data.
Besides saving website credentials, LastPass can also save secure notes, which I will look at next.
Test 3: Add a Secure Note
Secure notes are another important feature of LastPass that I use quite often. I usually use it for storing information that I need to get access to on a frequent basis, but isn’t related to a website. Because of this, I tested out adding a secure note to see what is sent to LastPass.
First, here is the data I saved for the note:
- Name: TestNote
- Folder: Secure Notes
- Note Type: Generic
- Notes:
This is a test note.This is the second line of the test note.
This is yet another line.
I am hoping this is encrypted.
Here is the request when adding a secure note:
Name | Value |
---|---|
sentms | 1408153957654 |
ajax | 1 |
extjs | 1 |
name | !MDdDJ2eLmqv1oa+mFMzcmQ==|pEMJnS3jzrGYaQiF2FhHVw== |
url | 687474703a2f2f736e |
grouping | !ZIdYxUKi2OOJRsrQTO1zOQ==|xiJ4rdAUTEeGSjVj+6K10A== |
username | |
password | |
extra | !Mq06kTvT7qP5E+sIg8KRVw==|06obw+3+Nbx0kkMDak22aK6+joe34reQUkpFbaF05LUSk7aqGrfIZ9BSFCMVmWStzIWH0AG5Vvc3xI2WHQ+u1JJ+wgsBVVrXf041n1sRfpgNHyxewdVbm/BsjBCP32JNAE2VQW33kMnKrvFhcklIE1kBwVoxopnDyUNg49k5xqo= |
aid | 0 |
openid_url | |
isbookmark | 0 |
iid | |
requid | 52344236 |
wxsessid | 6RVkMSsfr7pEwbmVgSZsI-JfjK9 |
sessonly | 0 |
token | MTQwODE1MzQyNC4yOS1WqfhJCcJoiVK8rAzVazfsigO9bXw8CA4y9/V+1tRPow== |
requesthash | BfU+7h76a9q+n7ggVy0bspgVPhObPoc1lKVPP5dFG0o= |
requestsrc | cr |
encuser | |
hasplugin | 3.1.50 |
Just as LastPass does with website information, it encrypts the values, using your encryption key, for the secure note. You may notice that secure notes have username and password values, which are blank. The reason for this is that a secure note sends the same request to the LastPass server as a website addition, but since there isn’t a username and password assigned to a note, those fields are just left blank.
One other feature I use often because it saves me time, is the ability to automatically have LastPass fill out forms. Let’s look at that feature next.
Adding a Profile
If you are like me, you get tired having to fill out forms that need personal information. LastPass provides the ability to store your personal information in different profiles, that you can then use to automatically have LastPass fill on a Web form. Of course, much like everything else that you store in LastPass, the profile information needs to be secure – especially since it can contain financial information.
For this test, lets look at the data I will be using:
- Profile Name: Testing
Personal Information
- First Name: Paul
- Last Name: Salmon
- Username: TechnicallyEasy
Credit Card Information
- Name on Card: Paul Salmon
- Credit Card Number: 9999999999999999
- Expiration Date: August 2014
- Security Code: 999
The request sent to the LastPass server from my computer can be seen below:
Name | Value |
---|---|
sentms | 1408238380403 |
ffid | 0 |
profiletype | 0 |
profilename | !jgETje+aOXsWl4V+xL+aeA==|VE6as6ydWnZ3Ph3AtYcPEg== |
profilelanguage | !78URLBm/sr+jGrIJyiFDbA==|c0zvRiWWU0c0ERYkrxeQaw== |
firstname | !wdwkZK7F1L2AKj6WF7SVjg==|aF4aAbenFmrTOggxIFRUFg== |
middlename | |
lastname | !8/cJ0j8z87OcTJcg1EiByA==|Ahx5TthD4ZOsPtlZVvhpqw== |
lastname2 | |
firstname2 | |
firstname3 | |
lastname3 | |
mobileemail | |
company | |
ssn | |
birthday | |
gender | |
title | |
address1 | |
address2 | |
address3 | |
city | |
county | |
state_name | |
state | |
zip | |
country | !palH/g7LShVer319Hwu47Q==|SnsIPRliQksoFiVV2Voo4g== |
country_cc3l | !f+9sdzrY0maeU17LNAP4uw==|0YcKjmHEDQX979/bDg6HVQ== |
country_name | !B0xxqYuFYAfdUSk3Th6wVA==|/W6iFMz9fKb35Gu8Q3g7vA== |
phone3lcc | |
evephone3lcc | |
fax3lcc | |
mobilephone3lcc | |
phone | |
evephone | |
fax | |
mobilephone | |
phoneext | |
eveext | |
faxext | |
mobileext | |
ccname | !UsUa3+4CDFNRNJFunjeowg==|jlgOqtFhYzXKvxdFgA27IQ== |
ccnum | !hxYY9X5tcfTr7m8tUZ8CqQ==|4cvtvCMh4Uovdgl/Ni2rhyMdeFiO3XUdKhVobkJ4Jbc= |
ccstart | |
ccexp | !hD3ybkU5QotaDK3z/meMpQ==|7k0Pe8b/X6BYDLElzYdIWg== |
cccsc | !ss+APFgus+LpMMFuvTrIuA==|gQ8dndrv1rJ6ynmw05pH+g== |
ccissuenum | |
username | !dTqlKzFD22WUs9PsRDNpxw==|w1qvEtkQCsL6QL3P2fvY2A== |
timezone | !mh1a8jVcn6dOGsJSB+xUEA==|7GlcCa9ZL//iRGmL4e1tfQ== |
bankname | |
bankacctnum | |
bankroutingnum | |
customfield1cfid | 0 |
customfield1text | |
customfield1value | |
customfield1alttext | |
customfield2cfid | 0 |
customfield2text | |
customfield2value | |
customfield2alttext | |
customfield3cfid | 0 |
customfield3text | |
customfield3value | |
customfield3alttext | |
notes | |
iid | |
requid | 52344236 |
wxsessid | m8PIodTsIw8qge6wGEGURoWtvYd |
sessonly | 0 |
requesthash | BfU+7h76a9q+n7ggVy0bspgVPhObPoc1lKVPP5dFG0o= |
requestsrc | cr |
encuser | |
hasplugin | 3.1.50 |
As you can see the request for adding a new profile is larger than for adding a website or secure note. This is because there are many more fields that you can fill out for a profile. While there are many more fields, one thing is the same: LastPass encrypts all the values (including the values that were filled in by default) before sending the request to the LastPass server. This means, that even your credit card information is encrypted so you don’t have to worry about storing such information with LastPass.
Before I concluded about the security of LastPass, there was one more test that I wanted to try. All the previous tests were performed against the LastPass browser plugin, which is what I use 99% of the time. The last test I wanted to run would be logging into my account from the LastPass website.
Test 5: Logging Into the LastPass Website
While most of the time I log into LastPass from the browser plugin, there are times I do need to log into the actual LastPass website. I mainly log into the website when I need to change a security setting, as that is the only place where it can be done. Since I do use the website, I wanted to verify that the login is as secure as the browser plugin.
The data I use is the same as the previous requests – with my testing account. After clicking the “Sign In” button on the LastPass website, which uses SSL, my computer sent several requests to the LastPass server:
1. Get the Iterations Number
While I am not entirely sure what all the requests do, I have performed a guess based on analyzing the requests. The first request seems to retrieve the iteration count for the username. The request sent was:
Name | Value |
---|---|
testing@technicallyeasy.net |
The response to this request was simply the number of iterations – in my case “5000”.
2. Perform the Log In
Next, LastPass appears to perform the log in, as it is a similar request to the previous log in request that I have seen. Here is the request:
Name | Value |
---|---|
method | web |
hash | ef6513d537ecd4d328d87e1e7760bcd447022779444bc3e0950b0941e393493a |
xml | 1 |
adlogin | |
username | testing@technicallyeasy.net |
fullusername | |
encrypted_username | BfU+7h76a9q+n7ggVy0bspgVPhObPoc1lKVPP5dFG0o= |
otp | |
gridresponse | |
multifactorresponse | |
trustlabel | |
uuid | YZ#USjxD^a5k&cs6k&bCDY@4ZewrRa!^ |
sesameotp | |
lcid | |
lcidhash | |
domain | |
iterations | 5000 |
origusername | |
outofbandsupported | 1 |
outofbandrequest | 0 |
outofbandretry | 0 |
outofbandretryid | |
testing@technicallyeasy.net | |
password |
Once again, the email address is sent as both a plain text and encrypted text, but the master password, or encryption, is not sent to LastPass. The authentication hash that we have seen previously, has been calculated and sent during this request.
3. Display the Vault Template
The following request was puzzling to me, mainly because of the response I received. First, here is the request:
Name | Value |
---|---|
fromindex | 1 |
ac | 1 |
lpnorefresh | 1 |
fromwebsite | 1 |
newvault | 1 |
xmlerr | 1 |
hasplugin | 3.1.50 |
hasplugin | 1 |
wxsessid | lMuaygznLKy0OToiRvZSve59vE6 |
username | testing@technicallyeasy.net |
_dc | 1408232242995 |
The reason this request is puzzling is because the response that was returned was the actual HTML for the vault webpage. There was no account information on the webpage, so it looked more like the template. The next request, though made me think that LastPass sent the template of the vault webpage, and then that page sent the following request to the server.
4. Perform Log In Check
It seems that once the vault page is sent from LastPass, it makes a request to the server to perform a log in check, because the response was similar to what I received from previous logins. Anyway, here is the request:
Name | Value |
---|---|
sentms | 1408232243105 |
version | 3.1.50 |
method | ff |
hp | 0 |
uuid | YZ#USjxD^a5k&cs6k&bCDY@4ZewrRa!^ |
wxsessid | lMuaygznLKy0OToiRvZSve59vE6 |
requesthash | crunknown1 |
requestsrc | cr |
encuser | |
hasplugin | 3.1.50 |
Once again, the request doesn’t include either the master password or encryption key to do the check.
Summary
The security implemented by LastPass has been questioned many times online, mainly because of the closed-development approach for the service. As I mentioned earlier, most of what LastPass generates is done by JavaScript, so it can be reviewed by anyone with JavaScript knowledge.
However, since I am not very familiar with JavaScript, I took a different approach by monitoring and reviewing the requests sent by LastPass from my computer to the LastPass server. With that I can conclude a few things:
- All requests sent to LastPass are sent over a secured, SSL connection.
- The master password is never sent to LastPass.
- The encryption key used to encrypt the data stored by LastPass is only generated on the local computer, and is never sent to LastPass.
- Since LastPass doesn’t know the master password, an authentication hash is used to authenticate your account.
- All website information is encrypted locally and then sent to LastPass.
- All secure notes are encrypted locally and then sent to LastPass.
- All profile information is encrypted locally and then sent to LastPass.
- The LastPass website doesn’t send the master password to the LastPass.
All the testing that I have done has confirmed all the above statements as you can see in what I have presented in this post with a capture of the requests to LastPass from both the Web browser add-in and the LastPass website.
Knowing this, I feel confident that LastPass can keep my personal data safe and secure, especially when I also specific security settings within LastPass. Knowing this I will continue to use their service.
Application To Generate LastPass Encryption Key and Hash
I have created a small application that can generate both the encryption key and hash using an email, password and iteration number. You simply provide those three inputs and the encryption key and hash will be generated. The source files for the application are included.