297 lines
20 KiB
HTML
297 lines
20 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>sean cassidy : LostPass</title>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<link href='https://fonts.googleapis.com/css?family=EB+Garamond' rel='stylesheet' type='text/css'>
|
|
<link rel="stylesheet" href="https://www.seancassidy.me/theme/css/main.css" type="text/css" />
|
|
<link href="https://www.seancassidy.me/atom.xml" type="application/atom+xml" rel="alternate" title="sean cassidy ATOM Feed" />
|
|
|
|
<!--[if IE]>
|
|
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<header>
|
|
<h1><a href="https://www.seancassidy.me" id="site-title">sean cassidy </a> :
|
|
<a href="https://www.seancassidy.me/lostpass.html" id="page-title">LostPass</a></h1>
|
|
<time datetime="2016-01-16T08:19:00-08:00">Sat 16 January 2016</time><span class="category">in: <a href="https://www.seancassidy.me/category/programming.html">programming</a></span></header>
|
|
<article>
|
|
<p><strong>Updated 2016-02-04</strong>: LastPass has
|
|
<a href="/images/lastpass_notification_nobutton.png">removed the button from
|
|
notifications</a>
|
|
and now requires <a href="https://lastpass.com/support.php?cmd=showfaq&id=10072">email confirmation for all logins from new IPs</a>.
|
|
This substantially mitigates LostPass, but does not eliminate it.</p>
|
|
<p>I have discovered a phishing attack against LastPass that allows an attacker to
|
|
steal a LastPass user's email, password, and even two-factor auth code, giving
|
|
full access to all passwords and documents stored in LastPass. </p>
|
|
<p>I call this attack LostPass. The code is available <a href="https://github.com/cxxr/lostpass">via Github</a>.</p>
|
|
<p>LostPass works because LastPass displays messages in the browser that attackers
|
|
can fake. Users can't tell the difference between a fake LostPass message and
|
|
the real thing because there is no difference. It's pixel-for-pixel the same
|
|
notification and login screen.</p>
|
|
<p>I discussed LostPass at <a href="https://shmoocon.org">ShmooCon 2016</a>. You can <a href="https://raw.githubusercontent.com/cxxr/lostpass/master/lostpass_shmoocon_slides.pdf">read my slides
|
|
(PDF)</a>, or you can <a href="https://archive.org/details/Lostpass">watch the video</a>.</p>
|
|
<h1 id="pixel-perfect-phishing">Pixel-perfect Phishing</h1>
|
|
<p>A few months ago, <a href="https://en.wikipedia.org/wiki/LastPass">LastPass</a> displayed a message on my browser that
|
|
my session had expired and I needed to log in again. I hadn't used LastPass in
|
|
a few hours, and hadn't done anything that would have caused me to be logged
|
|
out. When I went to click the notification, I realized something: it was
|
|
displaying this in the browser viewport. An attacker could have drawn this
|
|
notification.</p>
|
|
<p><a href="https://www.seancassidy.me/static/images/"><img src="/images/lastpass_notification.png" width="100%" alt="LastPass error notification"></a></p>
|
|
<p>Any malicious website could have drawn that notification. Because
|
|
LastPass trained users to expect notifications in the browser viewport, they
|
|
would be none the wiser. The LastPass login screen and two-factor prompt are
|
|
drawn in the viewport as well.</p>
|
|
<p><a href="https://www.seancassidy.me/static/images/"><img src="/images/lastpass_login.png" width="100%" alt="LastPass login screen"></a>
|
|
<a href="https://www.seancassidy.me/static/images/"><img src="/images/lastpass_2fa.png" width="100%" alt="LastPass two-factor screen"></a></p>
|
|
<p>Since LastPass has an API that can be accessed remotely, an attack materialized
|
|
in my mind.</p>
|
|
<h2 id="the-attack">The Attack</h2>
|
|
<p>Here are the steps for LostPass, in order.</p>
|
|
<h4 id="visit-the-malicious-site">Visit the malicious site</h4>
|
|
<p>Get the victim to go to a malicious website that looks benign, or a real
|
|
website that is vulnerable to XSS. This is where we'll deploy lostpass.js.
|
|
Unlike most phishing attacks, users won't be on their guard because this isn't
|
|
supposed to be a secure website. It could be a funny video or image, even.</p>
|
|
<h4 id="check-for-lastpass-and-show-the-notification">Check for LastPass and show the notification</h4>
|
|
<p>If they have LastPass installed, show the login expired notification and log
|
|
the user out of LastPass. LastPass is vulnerable to a logout <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF</a>, so
|
|
any website can log any user out of LastPass. This will make it appear to the
|
|
user that they are truly logged out.</p>
|
|
<p><a href="https://www.seancassidy.me/static/images/"><img src="/images/lostpass_notification.png" width="100%" alt="LostPass notification screen"></a></p>
|
|
<h4 id="direct-the-victim-to-the-login-page">Direct the victim to the login page</h4>
|
|
<p>Once the victim clicks on the fake banner, direct them to an
|
|
attacker-controlled login page that looks identical to the LastPass one. This
|
|
is the login page for Chrome.</p>
|
|
<p><a href="https://www.seancassidy.me/static/images/"><img src="/images/lostpass_login.png" width="100%" alt="LostPass login screen"></a></p>
|
|
<p>Notice the domain, "chrome-extension.pw". This looks similar to the Chrome
|
|
protocol for real extensions "chrome-extension". There is an <a href="https://code.google.com/p/chromium/issues/detail?id=453093">open issue in
|
|
Chromium</a> to address this.</p>
|
|
<h4 id="get-the-credentials">Get the credentials</h4>
|
|
<p>The victim will enter their password and send the credentials to the
|
|
attacker's server. The attacker's server will check if the credentials are
|
|
correct by calling LastPass's API. The API will inform us if two-factor
|
|
authentication is required.</p>
|
|
<p>If the username and password is incorrect, we'll redirect the user back to the
|
|
malicious website, but this time, the LostPass notification bar will say
|
|
"Invalid Password".</p>
|
|
<p>If the user has two-factor authentication, redirect them to a two-factor
|
|
prompt, like so:</p>
|
|
<p><a href="https://www.seancassidy.me/static/images/"><img src="/images/lostpass_2fa.png" width="100%" alt="LostPass 2fa screen"></a></p>
|
|
<h4 id="download-the-vault">Download the vault</h4>
|
|
<p>Once the attacker has the correct username and password (and two-factor
|
|
token), download all of the victim's information from the LastPass API. We can
|
|
install a backdoor in their account via the emergency contact feature, disable
|
|
two-factor authentication, add the attacker's server as a "trusted device".
|
|
Anything we want, really.</p>
|
|
<h2 id="implications">Implications</h2>
|
|
<p>These steps mirror the exact path that LastPass does when a user is logged
|
|
out remotely. LostPass mimics steps 2 through 7.</p>
|
|
<p>Some things to note about why this is so effective:</p>
|
|
<ul>
|
|
<li>Many responses to the phishing problem are "Train the users", as if it was
|
|
their fault that they were phished. Training is not effective at combating
|
|
LostPass because there is little to no difference in what is shown to the
|
|
user</li>
|
|
<li>LastPass's login workflow is complex and somewhat buggy. Sometimes it shows
|
|
in-viewport login pages, and sometimes it shows them as popup windows</li>
|
|
<li>It is easy to detect LastPass and it was even easier to find the exact HTML
|
|
and CSS that LastPass uses to show notifications and login pages</li>
|
|
<li>It even phishes for the two-factor auth code, so 2FA is no help</li>
|
|
</ul>
|
|
<p>See <a href="https://github.com/cxxr/lostpass">the Github repository</a> for the code itself.</p>
|
|
<h1 id="faq">FAQ</h1>
|
|
<p>Here I've collected a list of questions that I've been asked about this.</p>
|
|
<h2 id="what-browsers-and-operating-systems-does-it-work-on">What browsers and operating systems does it work on?</h2>
|
|
<p>The attack works best against the Chrome browser because they use an HTML login
|
|
page. Firefox actually pops up a window for its login page, so it looks like
|
|
whatever operating system you're on. I have experimental support for
|
|
Firefox on OS X and Windows 8 in LostPass but it is not enabled by default. </p>
|
|
<h2 id="does-this-work-against-lastpass-40">Does this work against LastPass 4.0?</h2>
|
|
<p>Yes, I developed it specifically to work against LastPass 4.0. I did not
|
|
include any version detection information. </p>
|
|
<h2 id="what-can-i-do-to-safeguard-myself-or-my-company">What can I do to safeguard myself or my company?</h2>
|
|
<p>Here is a list of suggestions in no particular order:</p>
|
|
<ul>
|
|
<li>Ignore notifications in the browser window</li>
|
|
<li>Enable IP restriction (only available to paid plans)</li>
|
|
<li>Disable mobile login (although other attacks could use non-mobile API)</li>
|
|
<li>Log all logins and failures</li>
|
|
<li>Inform your employees of this potential attack</li>
|
|
</ul>
|
|
<h2 id="does-two-factor-authentication-help">Does two-factor authentication help?</h2>
|
|
<p><strong>Update</strong>:
|
|
<a href="https://lastpass.com/support.php?cmd=showfaq&id=10072">LastPass now requires email confirmation for all new logins</a>,
|
|
regardless of two-factor auth. The original answer to this question remains
|
|
below.</p>
|
|
<p>No. In fact, two-factor authentication makes this attack significantly
|
|
<em>easier</em>.</p>
|
|
<p>By default, LastPass sends an email confirmation when a new IP address attempts
|
|
to login to LastPass. This should stop the attack almost entirely, but it
|
|
doesn't. According to <a href="https://lastpass.com/support.php?cmd=showfaq&id=9222">LastPass's documentation</a>, the confirmation email
|
|
is only sent if you <em>don't</em> have two-factor authentication enabled.</p>
|
|
<p>Since LostPass also phishes for the two-factor auth code, it bypasses the email
|
|
confirmation step.</p>
|
|
<p>It is possible to make LostPass more effective against the case where it is
|
|
blocked by confirmation email (something like, "Please confirm your login via
|
|
email to continue"), but the attack was already potent enough.</p>
|
|
<h2 id="what-about-yubikeyu2fduo">What about Yubikey/U2F/Duo?</h2>
|
|
<p>I only checked Google Authenticator because that's what I had, but here's how
|
|
you can figure out if another two-factor authentication would have helped: if
|
|
you can tell the attacker what they need to know, then it won't help. So if you
|
|
type in a token, it won't help. If you get a push notification that is approved
|
|
and you let the attacker in, it won't help.</p>
|
|
<h2 id="how-can-i-check-if-ive-been-attacked">How can I check if I've been attacked?</h2>
|
|
<p>View your <a href="https://helpdesk.lastpass.com/your-lastpass-vault/account-history/">LastPass Account History</a> to inspect every login
|
|
attempt and which IP addresses it was done from.</p>
|
|
<h2 id="what-are-some-alternatives-to-lastpass">What are some alternatives to LastPass?</h2>
|
|
<p><a href="http://notlastpass.rockettech.net/">Here are some alternatives to LastPass</a>. I have not researched
|
|
any of these alternatives and cannot guarantee if they're safer than LastPass.</p>
|
|
<p>Things to look at:</p>
|
|
<ul>
|
|
<li>Browser extensions are riskier than native applications</li>
|
|
<li>An API makes it easier to steal a lot of data</li>
|
|
<li>Store only frequently used and low risk data in a password manager</li>
|
|
</ul>
|
|
<h2 id="how-is-this-related-to-the-attack-from-2015-by-garcia-and-vigo">How is this related to the attack from 2015 by Garcia and Vigo?</h2>
|
|
<p>Garcia and Vigo published an attack called
|
|
"<a href="http://www.martinvigo.com/even-the-lastpass-will-be-stolen-deal-with-it/">Even the LastPass Will be Stolen, Deal with It!</a>". Their work is a
|
|
sophisticated client-side attack that relies on bad design choices that
|
|
LastPass made that make it vulnerable to compromised machines.</p>
|
|
<p>My work comes at LastPass from a different angle: you don't have access to a
|
|
LastPass user's machine. Instead, you trick the user into giving you their
|
|
credentials.</p>
|
|
<h2 id="did-you-hack-lastpass">Did you hack LastPass?</h2>
|
|
<p>No.</p>
|
|
<h2 id="why-did-you-develop-this-attack">Why did you develop this attack?</h2>
|
|
<p>I think that the security industry's view of phishing is naive at best,
|
|
negligent at worst. Phishing is the most dominant attack vector and is used
|
|
by everyone from run-of-the-mill cryptolocker types to APTs. Don't just take
|
|
it from me, though. Take it from <a href="https://twitter.com/thegrugq/status/649164150858321921">the grugq</a>:</p>
|
|
<blockquote>
|
|
<p>It's surprising how critical good phishing technique is with these APT
|
|
attacks. Effective phishing is more important than 0day.</p>
|
|
</blockquote>
|
|
<p>The standard refrain is that we need better user training. That is simply not
|
|
good enough.</p>
|
|
<p>The real solution is designing software to be phishing resistant. Just like we
|
|
have anti-exploitation techniques, we need anti-phishing techniques built into
|
|
more software. Software security evaluations should also include how easy it is
|
|
to phish said software.</p>
|
|
<h2 id="why-are-you-releasing-this-as-a-tool-wont-bad-people-use-it-against-me">Why are you releasing this as a tool? Won't bad people use it against me?</h2>
|
|
<p>Unlike most exploits, this attack requires no sophisticated knowledge. A
|
|
simple right-click will get you the HTML. A tiny bit of JavaScript will glue
|
|
the pieces together. As soon as I published details of this attack, criminals
|
|
could make their own version in less than a day. I am publishing this tool so
|
|
that companies can pen-test themselves to make an informed decision about this
|
|
attack and respond appropriately.</p>
|
|
<p>This is backwards for most vulnerability disclosures. Most vulnerabilities are
|
|
easy-to-fix and hard-to-exploit. This is hard-to-fix and easy-to-exploit, so I
|
|
felt that a tool release was appropriate. There is also precedent for LastPass
|
|
attacks: Garcia and Vigo released a <a href="https://github.com/rapid7/metasploit-framework/blob/master/modules/post/multi/gather/lastpass_creds.rb">metasploit module</a> for their
|
|
attack.</p>
|
|
<h2 id="did-you-tell-lastpass">Did you tell LastPass?</h2>
|
|
<p>Yes. I informed them in November, and they acknowledged the bug in December.</p>
|
|
<p>This has been a long and confusing issue. At first LastPass understood this bug
|
|
to be mainly be a result of the logout CSRF. Then they suggested it wouldn't
|
|
work because of the email confirmation step. The GM of LastPass said that
|
|
LastPass, "can confirm this is a phishing attack, not a vulnerability in
|
|
LastPass." I obviously disagree.</p>
|
|
<p>One of the fixes they implemented to fix LostPass was to warn users when they
|
|
type in their master password into some website. However, they display a
|
|
warning message in the browser viewport, like all of their messages. On an
|
|
attacker-controlled website, it is trivial to detect when this notification is
|
|
added. Then the attacker can do whatever. In LostPass, I suppress the
|
|
notification and fire off a request to an attacker server to log the master
|
|
password.</p>
|
|
<p>We as an industry do not respond to phishing attacks well. I do not blame
|
|
LastPass for this, they are like everyone else. We need to take a long look at
|
|
phishing and figure out what to do about it. In my view, it's just as bad, if
|
|
not worse than, many remote code execution vulnerabilities, and should be
|
|
treated as such.</p>
|
|
<h2 id="is-what-youre-doing-right">Is what you're doing right?</h2>
|
|
<p>I think informing users about security concerns in the products they use is
|
|
important. Too often security researchers kowtow to corporations by not telling
|
|
users about vulnerabilities they should know about. I think of security
|
|
researchers (a group I do not identify with) as having a similar ethical code
|
|
to journalists: the public has a right to know. Your interviewee (target)
|
|
does not get to dictate how the interview (research) is published or disclosed.</p>
|
|
<p>Your own judgement is paramount.</p>
|
|
<h2 id="can-operating-systems-or-browsers-do-something-to-address-this-class-of-bugs">Can operating systems or browsers do something to address this class of bugs?</h2>
|
|
<p>Yes. </p>
|
|
<p>To spoof the "chrome-extension" protocol, I bought the domain
|
|
"chrome-extension.pw", which looks close enough. Connecting to
|
|
chrome-extension.pw over HTTP makes it look pretty similar to the built-in
|
|
protocol. There is an <a href="https://code.google.com/p/chromium/issues/detail?id=453093">open issue in Chromium</a> to address this.</p>
|
|
<p>It is harder to spoof in Firefox, where I had to draw each OS's native widget
|
|
manually using HTML and CSS. They're not perfect, either, but it's pretty
|
|
close. Here's an image of LastPass and LostPass for Firefox on Windows 8
|
|
side-by-side. Which one is which?</p>
|
|
<p><a href="https://www.seancassidy.me/static/images/"><img src="/images/lastpass_firefox.png" width="100%" alt="LastPass Firefox login"></a></p>
|
|
<p>Since the browser viewport can draw anything with pixels, we need to think
|
|
about how we authenticate native windows visually. UX is a very important
|
|
security concern. UAC's dimming of the screen in Windows is a step in the right
|
|
direction.</p>
|
|
<h1 id="more-information">More information</h1>
|
|
<p>For more information, look at <a href="https://raw.githubusercontent.com/cxxr/lostpass/master/lostpass_shmoocon_slides.pdf">my ShmooCon slides</a>,
|
|
<a href="https://archive.org/details/Lostpass">watch the video</a> and <a href="https://github.com/cxxr/lostpass">the source code to LostPass itself</a>. You
|
|
can also <a href="mailto:sean@seancassidy.me">email me</a> or
|
|
<a href="https://twitter.com/sean_a_cassidy">tweet at me</a>.</p>
|
|
<p><a href="https://github.com/cxxr/lostpass"><img style="position: absolute; top: 0; left: 0; border: 0;" src="https://camo.githubusercontent.com/567c3a48d796e2fc06ea80409cc9dd82bf714434/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f6c6566745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_left_darkblue_121621.png"></a></p>
|
|
</article>
|
|
<ul class="tags">
|
|
<li class="tags" style="font-size: 13px; letter-spacing: 3px">tags:</li>
|
|
<li class="tags"><a href="https://www.seancassidy.me/tag/code.html">code</a></li>
|
|
<li class="tags"><a href="https://www.seancassidy.me/tag/bugs.html">bugs</a></li>
|
|
<li class="tags"><a href="https://www.seancassidy.me/tag/security.html">security</a></li>
|
|
<li class="tags"><a href="https://www.seancassidy.me/tag/crypto.html">crypto</a></li>
|
|
</ul>
|
|
|
|
<div style="width:40%" class="alignright">
|
|
<p style="text-align:left;font-size: 87%"><a
|
|
href="https://www.linkedin.com/in/seanacassidy/">Sean</a> is the Head of Security at <a
|
|
href="https://www.asana.com">Asana</a>, a work management platform for teams.</p>
|
|
<a href="https://twitter.com/sean_a_cassidy" class="twitter-follow-button" data-show-count="false" data-size="large" data-dnt="true">Follow @sean_a_cassidy</a>
|
|
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
|
|
</div>
|
|
|
|
<nav>
|
|
<p>related posts</p>
|
|
<ul class="related">
|
|
<li><a href="https://www.seancassidy.me/diagnosis-of-the-openssl-heartbleed-bug.html">Diagnosis of the OpenSSL Heartbleed Bug</a></li>
|
|
<li><a href="https://www.seancassidy.me/the-story-of-the-gnutls-bug.html">The Story of the GnuTLS Bug</a></li>
|
|
<li><a href="https://www.seancassidy.me/wrong-solutions.html">Wrong Solutions</a></li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<footer>
|
|
<nav>
|
|
<ul class="footer">
|
|
<li class="footer"><a href="https://www.seancassidy.me/pages/about.html">about</a></li>
|
|
<li class="footer">- <a href="https://github.com/cxxr">github</a></li>
|
|
<li class="footer">- <a href="https://twitter.com/sean_a_cassidy">twitter</a></li>
|
|
<li class="footer">- <a href="https://www.seancassidy.me/atom.xml">feed</a></li>
|
|
<li class="footer">- <a href="https://www.seancassidy.me/tags.html">tags</a></li>
|
|
</ul>
|
|
</nav>
|
|
</footer>
|
|
|
|
<script type="text/javascript">
|
|
var _gaq = _gaq || [];
|
|
_gaq.push(['_setAccount', 'UA-38980907-1']);
|
|
_gaq.push(['_trackPageview']);
|
|
|
|
(function() {
|
|
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
|
|
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
|
|
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
|
|
})();
|
|
|
|
</script>
|
|
<script src="https://www.seancassidy.me/theme/js/genius-blocker.js"></script>
|
|
</body>
|
|
</html> |