New issue
Advanced search Search tips
Starred by 4 users

Issue metadata

Status: Fixed
Closed: Jul 2016

  • Only users with EditIssue permission may comment.

Sign in to add a comment

Issue 884: LastPass: design flaw in communication between privileged and unprivileged components

Reported by, Jul 27 2016 Project Member

Issue description

I'm looking at LastPass 4.1.20a on Windows, and can see some problems with the
design. It looks like the addon works by injecting elements and event handlers
into the page.

<input> boxes are modified with some css, and a click event handler is added
that instructs the addon to create a privileged iframe. A page can click the
LastPass icon programatically with javascript by creating a MouseEvent() with
the right x:y coordinates. Normally a page would not be permitted to navigate
to a resource:// url, but this just asks the add-on to do it.

i.e. something like this:

    // Trick LastPass intro drawing a privileged iframe by dispatching a
    // MouseEvent with the correct co-ordinates.
    function trigger_frame() {
        var el  = document.getElementsByTagName("input")[0];
        var pos = el.getBoundingClientRect();

        // Approx? I dunno
        el.dispatchEvent(new MouseEvent("click", {
            clientX: pos.width + pos.x - 16,
            clientY: pos.height + pos.y - 12,

The frame communicates with the add-on by posting messages to the window, and
an eventhandler on the window determines if it's trusted or not by checking
the origin. But that does not make sense, because the window belongs to the
attacker so they can just insert their own eventhandler before yours and
modify legitimate messages!

Like this:

    // PiggyBack on a legitimate message and overwrite it with our own message.
    function modify_message(a) { = "openURL";"javascript:alert(1)";

        // Cleanup
        window.removeEventListener("message", modify_message);

    // Insert my own EventListener
    window.addEventListener("message", modify_message);

That should trick lastpass into processing an openURL command. This allows
access to any of the privileged LastPass RPCs, so this is a complete compromise
of the lastpass addon. From here an attacker can create and delete files,
execute script, steal all passwords, log victims into their own lastpass
account so that they can steal anything new saved there, etc, etc.

A mostly complete list of the accessible privileged RPC's:

refreshGroupNames, lpReportError, closeTab, openTabDialog, openTabDialogKeyboard, repromptSuccess, makeBackgroundRequest, makeBackgroundRepromptRequest, makeBackgroundServerRequest, toggleVault4_0, toggleVault3_0, closepop, connect, focus, message, processCS, disablepasswordmanager, LP_do_login, openURL, start_trial, install_binary, reprompt_callback, reprompt_error_callback, omnikey_callback, update_prefs, copytoclipboard, update_prompts, openall, openAllSites, deleteGroup, copyusername, copypassword, copyurl, copynote, deleteAid, editAid, unlock_plug2web, gotourl, launch, open_login, addprofile, update_create_account_data, addcreditcard, editprofile, openprefs, openbaseurl, changemasterpassword, addDomainToMPWNever, MPWNoNag, openaddsecurenote, loggedOut, switch_identity, renameGroup, addEmptyGroup, moveSelectedToGroup, security_prompt, savePassword, checkgeneratepassword, fillform, changePassword, receiveTS, deleteformfill, addeditformfill, fix_tlds, moveIntoSharedFolder, increment_local_accts_version, rewritelocalfile, saveSite, showImageAttach, openAttach, exportAttachment, openLinkedSites, generate, ping_ack, basicauthmoreinfobtn, basicauthneverbtn, changepw, chooseprofilecc, createaccountbtn, custombtn, disablebtn, feedbackbtn, starttrialbtn, fillformffid, popupfillresize, recheckpagecontext, savesiteicon, savethesite, startsaveall, tryagainbtn, saveAllSite, saveSiteFromSubmit, saveFields, set_editfieldsopener, close_editfieldsopener, unprotect_data, change_master_password, make_lp_key_hash_iterations, lpvt_store_data_and_setsinglefactortype, delete_file, lpevent, applyattacharraychanges, update_site, fastDecryptAttachment, fastEncryptAttachments, get_saved_logins, delete_saved_login, update_fields, select_selectedtabid, closecurrenttab, add_identity, checkforupdates, clearforms, clearrecent, openabout, openaddsite, openchooseprofilecc, openexport, openfavorites, openfeedback, opengenpw, openhelp, openimport, doimport, openimportchrome, openlastpassexport, wlanexport, formfillexport, openpremium, openentconsole, opensearch, openseccheck, opensessions, openmyaccount, openvault, recheckpage, refreshsites, saveall, upgradetoserver, clearCache, loglogin, deleteNever, fillaid, openprint, getnotificationdata, getcpwmsg, disabletotp, enabletotp, invitetotp, closepopupfills, hidecontext, hideoverlay, hidetotp, slidedownoverlay, slideupoverlay, popupfillscreateack, autofillaid, autologinaid, fillcurrentaid, never, neverautofill, neverpage, neverdomain, getdata, getpopupfilldata, popupfillinputget, popupfillgetgenerateprefs, popupfillsetgenerateprefs, deleteaid, editaid, openchooseprofilecc, dosaveiframe, popupfillsaveget, dologinaction, dopwchallenge, set_share_folder_id, set_share_folder_group, disablesitealert, disableallalerts, lpdbg, cpwbot_finish_ack, cpwbot_validate_state_result, dopwchange, cpwbot_get_user_debug_messages, cpwbot_getpwchangestate, cpwbot_get_dialog_msg, cpwbot_preinit, cpwbot_halt, close_cpw_tabs, send_sms_passcodes, create_account, enable_credit_monitoring, clear_badge, resize_panel, resize_login_panel, resize_html_panel, resize_html_dialog, deletesavedpw, sr_add_secret, minimize_cpw_dialog, maximize_cpw_dialog, addAttach, onload_done, rebuildcontextonload, setbadgetextonload, openlastpasslegacy, opendebugtab, reset_history, savesite_dialog_changed.

Many of these are "relay" RPCs, that forward calls to other locations such as makeBackgroundServerRequest, message, processCS, message, getdata, etc. These add additional RPCs, a small sample of which is:

addIdentity, removeIdentity, updateIdentity, shareItems, unshareItem, acceptShare, rejectShare, inviteFriends, getSentShareData, getReceivedShareData, getFolders, getPublicKeys, create, rename, remove, accept, reject, addMembers, getMembers, removeMember, reinviteMember, updateMemberPermissions, getRestrictions, updateRestrictions, startDownloading, stopDownloading, restoreDeleted, purgeDeleted, convertToEnterprise, updateRecipient, addRecipient, removeRecipient, getRecipientInfo, getSharerInfo, acceptOffer, declineOffer, requestAccess, denyAccess, unlinkAccount, saveCustomNoteTemplate and so on.

I made a quick demo to demonstrate access to privileged RPCs. This demo should delete any file for you, because the delete_file RPC is super simple to use.

This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically
become visible to the public.
1.0 KB View Download

Comment 1 by, Jul 27 2016

Project Member
Issue 881 has been merged into this issue.

Comment 2 by, Jul 27 2016

Project Member
LastPass confirmed the issue, but said that the vulnerable code I pointed out is only used on their FireFox extension. They believe this is only exploitable there (I was indeed testing with FireFox).

I had just clicked install on, but apparently there are multiple versions in use. The version you get if you click install on is different, and may not be affected, I don't know if this means different versions for other browsers are affected or not.

Full mail:

Thanks again for responsibly reporting the issue.

We have verified that intercepting messages via the method you suggested is possible and is a problem. We have also verified it only affects firefox (chrome, ie, safari, opera, etc do not use the window for message passing in the same manner) and doesn't affect our primary firefox download (which is still 3.0 version).

We are working on a fix immediately and plan on releasing before the end of the week (if not sooner). We will provide an update when a fix has been released.

We were unable to get the trigger_frame function to work, despite hardcoding offsets. Do you happen to have a version of that hosted on a server that we can try?

This certainly qualifies for a cash reward, if you change your mind about bugcrowd we would be happy to compensate you for your findings.

My reply:

I just clicked on install on, I didn't know there were multiple versions available.
> We are working on a fix immediately and plan on releasing before the end of the week (if not sooner). We will provide an update when a fix has been released.

Excellent, thanks!
> We were unable to get the trigger_frame function to work, despite hardcoding offsets. Do you happen to have a version of that hosted on a server that we can try?

I just guesstimated the sizes - it probably changes with resolution. Here is how to fix it, open the console and do something like

input.addEventHandler("click", function(a) { console.log(a); })

Then click the icon manually and it should print the clientX clientY parameters. Copy and paste them into the testcase (instead of the pos.width guesses I made), and it should work. It works for me on a clean install of firefox in a clean windows vm, I'm not doing anything unusual.

Naturally, a more polished PoC would calculate the position properly.
> This certainly qualifies for a cash reward, if you change your mind about bugcrowd we would be happy to compensate you for your findings.

Thanks Bob, I'd be interested in donating it to charity if that's okay with you? 

I can't budge on our disclosure policy, but it sounds like you're not going to need anywhere close to 90 days anyway!

If that sounds acceptable, I'd like to donate it to Amnesty International.

Comment 3 by, Jul 27 2016

Project Member
LastPass replied and verified they could reproduce the MouseEvent trick, and were working on a solution.

They also sent me a pre-release build to verify.

Comment 4 by, Jul 27 2016

Project Member
Labels: -Restrict-View-Commit
Status: Fixed (was: New)
It looks like the fix is being automatically pushed out, so considering this issue public.

Comment 5 by, Jul 27 2016

Project Member
Note that it is not correct to say "both exploits do require tricking a user via a phishing attack into going to a malicious website". In fact, neither of the attacks described require phishing.

I assume the blog post was written by someone who is not familiar with the term phishing.

Comment 6 Deleted

Comment 7 by, Jul 28 2016

Project Member
Labels: Restrict-AddIssueComment-EditIssue

Sign in to add a comment