Securing a Browser Helper Object
Asked Answered
G

1

8

I'm currently in the process of building a browser helper object.

One of the things the BHO has to do is to make cross-site requests that bypass the cross-domain policy.

  • For this, I'm exposing a __MyBHONameSpace.Request method that uses WebClient internally.

  • However, it has occurred to me that anyone that is using my BHO now has a CSRF vulnerability everywhere as a smart attacker can now make arbitrary requests from my clients' computers.

Is there any clever way to mitigate this?

Gladiatorial answered 15/12, 2013 at 7:54 Comment(0)
J
7

The only way to fully protect against such attacks is to separate the execution context of the page's JavaScript and your extension's JavaScript code.

When I researched this issue, I found that Internet Explorer does provide a way to achieve creation of such context, namely via IActiveScript. I have not implemented this solution though, for the following reasons:

  1. Lack of documentation / examples that combines IActiveScript with BHOs.
  2. Lack of certainty about the future (e.g. https://stackoverflow.com/a/17581825).
  3. Possible performance implications (IE is not known for its superb performance, how would two instances of a JavaScript engines for each page affect the browsing speed?).
  4. Cost of maintenance: I already had an existing solution which was working well, based on very reasonable assumptions. Because I'm not certain whether the alternative method (using IActiveScript) would be bugfree and future-proof (see 2), I decided to drop the idea.

What I have done instead is:

  1. Accept that very determined attackers will be able to access (part of) my extension's functionality.
    • @Benjamin asked whether access to a persistent storage API would pose a threat to the user's privacy. I consider this risk to be acceptable, because a storage quota is enforced, and all stored data is validated before it's used, and it's not giving an attacker any more tools to attack the user. If an attacker wants to track the user via persistent storage, they can just use localStorage on some domain, and communicate with this domain via an <iframe> using the postMessage API. This method works across all browsers, not just IE with my BHO installed, so it is unlikely that any attacker dedicates time at reverse-engineering my BHO in order to use the API, when there's a method that already works in all modern browsers (IE8+).
  2. Restrict the functionality of the extension:
    1. The extension should only be activated on pages where it needs to be activated. This greatly reduces the attack surface, because it's more difficult for an attacker to run code on https://trusted.example.com and trick the user into visiting https://trusted.example.com.
    2. Create and enforce whitelisted URLs for cross-domain access at extension level (in native code (e.g. C++) inside the BHO).
    3. For sensitive APIs, limit its exposure to a very small set of trusted URLs (again, not in JavaScript, but in native code).
    4. The part of the extension that handles the cross-domain functionality does not share any state with Internet Explorer. Cookies and authorization headers are stripped from the request and response. So, even if an attacker manages to get access to my API, they cannot impersonate the user at some other website, because of missing session information.
      This does not protect against sites who use the IP of the requestor for authentication (such as intranet sites or routers), but this attack vector is already covered by a correct implemention a whitelist (see step 2).

"Enforce in native code" does not mean "hard-code in native code". You can still serve updates that include metadata and the JavaScript code. MSVC++ (2010) supports ECMAScript-style regular expressions <regex>, which makes implementing a regex-based whitelist quite easy.

If you want to go ahead and use IActiveScript, you can find sample code in the source code of ceee, Gears (both discontinued) or any other project that attempts to enhance the scripting environment of IE.

Jumbled answered 15/12, 2013 at 13:39 Comment(8)
Chapeau à lui, excellent answer - especially given how undocumented this whole area is. Whiteboard URLs is what I've had in mind too. As an alternative - I can perform CORS requests, as for persistent storage (which is done by registry access), I don't see much harm in letting attackers write to a meaningless sub-area of the registry so I can only allow that. I think it's even enough to prefix the request urls with my api's base address but with CORS available I think that it would work much much better.Gladiatorial
@BenjaminGruenbaum If you're considering CORS, then cross-domain access is not really an issue, since any page can request the content, right? Try to keep your requests simple though, to avoid a preflight request (OPTIONS). And keep in mind that IE8 + 9 do not support standard CORS, but a very limited variant through the XDomainRequest object.Jumbled
I forgot to add that the cross-domain functionality of my extension does not share any state with IE, and that cookies and authorization is stripped and disabled, so there's no additional security issues except possible access to intranet sites. Because of the whitelist-approach, attackers cannot use my extension to access these intranet sites either, so I'm confident that my extension does not lower the security of my users.Jumbled
The problem isn't accessing my API, the problem is someone detecting my add-on and targeting the bank of the user to withdraw funds, or sending mass emails from their email account - by the book CSRF. I can live with a limited variant with the XDomainRequest, I also don't intend to support IE8 (which makes this so much easier ^_^ ). I'm checking testing Uri.host vs cross-domain. Thanks again for the extended information. There is not a lot of information available online on these subjects. The two main things I need to expose is db and requests and I think I can deal with requests now :)Gladiatorial
@BenjaminGruenbaum IE9 still requires XDomainRequest for CORS. I have just edited my answer to include a note about the CSRF scenario. Your extension's threat model looks similar to mine (the only exposed APIs are also persistent storage and cross-domain access).Jumbled
what did you do about persistent storage? It doesn't seem half as bad as the CSRF issue but it still enables attackers to track my users. I can whitelist the keys but that'd be extremely limiting and won't stop a clever attack anyway. I'm starting to consider writing the whole business logic part and everything that needs DB access in C++ (Or C#, which I prefer but have speed concerns about if it's fast enough), that'd be extremely expensive though (as it works quite fine in JS in Chrome and FF).Gladiatorial
@BenjaminGruenbaum I do not consider persistent storage as a threat. I've implemented an API very similar to localStorage (but without events), which stores data in a memory-mapped file backed by a file located in %AppData%\LocalLow%. As said before, the extension is only activated on a few domains, so shared storage is not going to be a threat. If an attacker wanted to persist values, and they have access to both domains, then they can just insert an iframe and use postMessage to communicate data. This works accross all browsers, not just IE with my BHO installed.Jumbled
Great, this answers all my questions. If you could edit more of the comments to the answer that'd be great. I'm sure I'm not the only guy it'll help.Gladiatorial

© 2022 - 2024 — McMap. All rights reserved.