Loading ...
Sorry, an error occurred while loading the content.

ADsafe and bind

Expand Messages
  • Douglas Crockford
    ADsafe will block the bind method. The bind method proposed for ES3.1 is safe, but the bind methods provided by the current Ajax libraries are not because they
    Message 1 of 13 , May 22 5:54 AM
    • 0 Attachment
      ADsafe will block the bind method. The bind method proposed for ES3.1
      is safe, but the bind methods provided by the current Ajax libraries
      are not because they can bind to the global object. Since ADsafe does
      not allow the definition of methods that use this, little is lost by
      blocking bind.
    • David-Sarah Hopwood
      ... Don t some of these libraries have other aliases for bind-like methods? For example Prototype has bindAsEventListener , although I don t know of any
      Message 2 of 13 , May 22 7:12 AM
      • 0 Attachment
        Douglas Crockford wrote:
        > ADsafe will block the bind method. The bind method proposed for ES3.1
        > is safe, but the bind methods provided by the current Ajax libraries
        > are not because they can bind to the global object.

        Don't some of these libraries have other aliases for bind-like methods?
        For example Prototype has 'bindAsEventListener', although I don't know of
        any specific attack based on that in the context of ADsafe.

        --
        David-Sarah Hopwood
      • David-Sarah Hopwood
        ... While I remember, I think you also need to blacklist stack . -- David-Sarah
        Message 3 of 13 , May 22 7:22 AM
        • 0 Attachment
          David-Sarah Hopwood wrote:
          > Douglas Crockford wrote:
          >> ADsafe will block the bind method. The bind method proposed for ES3.1
          >> is safe, but the bind methods provided by the current Ajax libraries
          >> are not because they can bind to the global object.
          >
          > Don't some of these libraries have other aliases for bind-like methods?
          > For example Prototype has 'bindAsEventListener', although I don't know of
          > any specific attack based on that in the context of ADsafe.

          While I remember, I think you also need to blacklist 'stack'.

          <http://code.google.com/p/google-caja/wiki/ErrorExposesParameterValues>

          --
          David-Sarah Hopwood
        • marcel.laverdet
          ... I m kind of late to this (just joined this group) but this just seems like a losing battle. Trusting that a host hasn t opened themselves up to an attack
          Message 4 of 13 , Sep 5, 2008
          • 0 Attachment
            --- In caplet@yahoogroups.com, David-Sarah Hopwood <david.hopwood@...> wrote:
            >
            > Douglas Crockford wrote:
            > > ADsafe will block the bind method. The bind method proposed for ES3.1
            > > is safe, but the bind methods provided by the current Ajax libraries
            > > are not because they can bind to the global object.
            >
            > Don't some of these libraries have other aliases for bind-like methods?
            > For example Prototype has 'bindAsEventListener', although I don't know of
            > any specific attack based on that in the context of ADsafe.
            >
            > --
            > David-Sarah Hopwood
            >

            I'm kind of late to this (just joined this group) but this just seems like a losing battle. Trusting
            that a host hasn't opened themselves up to an attack by unsafely extending built-ins seems
            dubious. For instance consider this little number that Prototype comes with:
            Array.prototype.first = function() {
            return this[0];
            }

            To be clear, the attack that this opens you up to is as follows:
            var win = ([].first || 0)();

            Of course the attack assumes that the host uses Prototype and also has an iframe on the
            page, but I imagine such cases aren't hard to find. There's also several other ways you can
            get window without even depending on Prototype:
            ([].slice || 0)(0)
            ([].sort || 0)()
            ([].forEach || 0)(function(a,b,win){ })

            So now you're in a tough situation. Do you blacklist all of those vectors? I see you're
            currently using mozilla() to handle concat, reverse, and sort but that approach won't work
            consistently on all sites. Additionally you run into the problem that by poking around at
            Array.prototype you break hosts that use for (var ii in arr); for array iteration under the
            assumption that Array.prototype contains only DontEnum properties.

            My recommendation is to implement context-switching between the host environment and
            ADSafe environments. First loop through the prototypes of Object, Function, Array, String,
            Number, and RegEx and store a copy of everything you find in your own dictionary, while at
            the same time `delete'ing those properties. Then run through Array again and augment all
            known dangerous Array methods (there's a lot of them, according to my list: map, forEach,
            each, filter, every, some, reduce, reduceRight, sort, reverse, concat, and slice). After that
            you've strong-armed the environment into a much safer state. You can then run your
            untrusted code in a try \ catch block and restore the environment back to the state it was in
            before.

            Also, for what it's worth I've gotten around blacklisting "eval" in FBJS with the following trick:
            if (Object.prototype.eval) {
            window.eval = Object.prototype.eval;
            delete Object.prototype.eval;
            }

            Apparently if you delete Object.prototype.eval, eval no longer works in some versions of
            Konquerer, so that's what the window.eval assignment is for. We've been running under this
            environment for a while with no side-effects so you may want to give it a try.

            Cheers.
          • Kris Zyp
            Of course the attack assumes that the host uses Prototype and also has an iframe on the page, but I imagine such cases aren t hard to find. There s also
            Message 5 of 13 , Sep 8, 2008
            • 0 Attachment
              Of course the attack assumes that the host uses Prototype and also has an iframe on the
              page, but I imagine such cases aren't hard to find. There's also several other ways you can
              get window without even depending on Prototype:
              ([].slice || 0)(0)
              ([].sort || 0)()
              ([].forEach || 0)(function( a,b,win){ })

              So now you're in a tough situation. Do you blacklist all of those vectors? I see you're
              currently using mozilla() to handle concat, reverse, and sort but that approach won't work
              consistently on all sites. Additionally you run into the problem that by poking around at
              Array.prototype you break hosts that use for (var ii in arr); for array iteration under the
              assumption that Array.prototype contains only DontEnum properties.

              When does mozilla() not work to fix concat, reverse, sort, slice, and forEach? Is it when the host site also wants to fiddle with the prototypes (of course this could simply be documented to be unsafe)? Also, the mozilla() fix function replaces value in existing slots, it doesn't seem to affect the DontEnum property in the environments I quickly tried (nor break array enumeration). Is there are a particular environment where these replacements cause array enumeration breakage?
              Anyway, thanks for the help and information,
              Kris
            • marcel.laverdet
              ... the prototypes (of course this could simply be documented to be unsafe)? Also, the mozilla() fix function replaces value in existing slots, it doesn t seem
              Message 6 of 13 , Sep 8, 2008
              • 0 Attachment
                --- In caplet@yahoogroups.com, "Kris Zyp" <kris@...> wrote:
                >
                > Of course the attack assumes that the host uses Prototype and also has an iframe on the
                > page, but I imagine such cases aren't hard to find. There's also several other ways you can
                > get window without even depending on Prototype:
                > ([].slice || 0)(0)
                > ([].sort || 0)()
                > ([].forEach || 0)(function(a,b,win){ })
                >
                > So now you're in a tough situation. Do you blacklist all of those vectors? I see you're
                > currently using mozilla() to handle concat, reverse, and sort but that approach won't work
                > consistently on all sites. Additionally you run into the problem that by poking around at
                > Array.prototype you break hosts that use for (var ii in arr); for array iteration under the
                > assumption that Array.prototype contains only DontEnum properties.
                >
                > When does mozilla() not work to fix concat, reverse, sort, slice, and forEach? Is it when the host site also wants to fiddle with
                the prototypes (of course this could simply be documented to be unsafe)? Also, the mozilla() fix function replaces value in
                existing slots, it doesn't seem to affect the DontEnum property in the environments I quickly tried (nor break array
                enumeration). Is there are a particular environment where these replacements cause array enumeration breakage?
                > Anyway, thanks for the help and information,
                > Kris
                >

                mozilla() does not work if you haven't called it on a vulnerable method (of which there are at least a dozen in Firefox). In the
                current version of adsafe.js, only concat, reverse, and sort are correctly fixed with mozilla(). Also, like I said it's very common to
                augment Array with unsafe methods. It's also unreasonable to expect a host environment to understand the dangers of
                augmenting Array.prototype. Many libraries augment Array.prototype, and in most cases the host won't even be aware.

                You're correct that the current use of mozilla() won't break any browsers since it only replaces widely-implemented methods,
                however right below that Array.prototype.filter is created if it doesn't exist. If filter doesn't exist it won't have DontEnum set, and
                will therefore create an enumerable property on Array.prototype. This will affect at least IE6.

                Also a quick side note -- I just noticed in adsafe.js this line:
                Object.prototype.eval = null;

                I think this was recently added because I didn't notice it earlier? Anyway, it's important to check for the existence of
                Object.prototype.eval before attempting to null it out or you end up creating a globally-inherited property for which DontEnum
                is not set. That will of course break pretty much any existing code that doesn't use hasOwnProperty in every for(in) loop.
              • Kris Zyp
                ... Understood. I think the situation may be a little different for me than for the ADsafe in general, since I am focused on a Dojo-specific impl of ADsafe.
                Message 7 of 13 , Sep 8, 2008
                • 0 Attachment
                  > mozilla() does not work if you haven't called it on a vulnerable
                  method (of which there are at least a dozen in
                  > Firefox). In the
                  > current version of adsafe.js, only concat,
                  reverse, and sort are correctly fixed with mozilla(). Also, like I said it's
                  > very common to
                  > augment Array with unsafe methods. It's also
                  unreasonable to expect a host environment to understand the
                  > dangers of
                  > augmenting Array.prototype. Many libraries augment
                  Array.prototype, and in most cases the host won't even be
                  > aware.
                   
                  Understood. I think the situation may be a little different for me than for the ADsafe in general, since I am focused on a Dojo-specific impl of ADsafe. Since we are the host library, I think we have a more leeway in saying that it is not safe to use Dojo Secure with other libraries (that might augment Array.prototype), or to augment Array yourself. On the otherhand, ADsafe presumably aims to work with all libraries (even prototype augmenting ones), although I would think even ADsafe would have to setup some limits, since there are so many ways to make a host environment unsafe that ADsafe simply can't defend against.
                   
                  Of course I still need to make sure mozilla() is called on all vulnerable methods...
                   
                  Once again, thank you for the insights,
                  Kris
                • Douglas Crockford
                  ... has an iframe on the ... several other ways you can ... vectors? I see you re ... that approach won t work ... I looked at the Mozilla array methods, and
                  Message 8 of 13 , Sep 8, 2008
                  • 0 Attachment
                    --- In caplet@yahoogroups.com, "marcel.laverdet" <marcel@...> wrote:
                    > Of course the attack assumes that the host uses Prototype and also
                    has an iframe on the
                    > page, but I imagine such cases aren't hard to find. There's also
                    several other ways you can
                    > get window without even depending on Prototype:
                    > ([].slice || 0)(0)
                    > ([].sort || 0)()
                    > ([].forEach || 0)(function(a,b,win){ })
                    >
                    > So now you're in a tough situation. Do you blacklist all of those
                    vectors? I see you're
                    > currently using mozilla() to handle concat, reverse, and sort but
                    that approach won't work
                    > consistently on all sites.

                    I looked at the Mozilla array methods, and wrapped the three that I
                    observed leaking the global object. Under what circumstances do slice,
                    forEach, et al, leak?
                  • Kris Zyp
                    ... If there is an iframe somewhere on the page, they can leak access to it (I was able to reproduce that). Kris ... From: Douglas Crockford To:
                    Message 9 of 13 , Sep 8, 2008
                    • 0 Attachment
                      > I looked at the Mozilla array methods, and wrapped the three that I
                      > observed leaking the global object. Under what circumstances do slice,
                      > forEach, et al, leak?
                      If there is an iframe somewhere on the page, they can leak access to it (I was able to reproduce that).
                      Kris
                       
                       
                      ----- Original Message -----
                      Sent: Monday, September 08, 2008 11:04 AM
                      Subject: [caplet] Re: ADsafe and bind

                      --- In caplet@yahoogroups. com, "marcel.laverdet" <marcel@...> wrote:
                      > Of course the attack assumes that the host uses Prototype and also
                      has an iframe on the
                      > page, but I imagine such cases aren't hard to find. There's also
                      several other ways you can
                      > get window without even depending on Prototype:
                      > ([].slice || 0)(0)
                      > ([].sort || 0)()
                      > ([].forEach || 0)(function( a,b,win){ })
                      >
                      > So now you're in a tough situation. Do you blacklist all of those
                      vectors? I see you're
                      > currently using mozilla() to handle concat, reverse, and sort but
                      that approach won't work
                      > consistently on all sites.

                      I looked at the Mozilla array methods, and wrapped the three that I
                      observed leaking the global object. Under what circumstances do slice,
                      forEach, et al, leak?

                    • Douglas Crockford
                      ... Thanks, Marcel, that was really helpful. ADsafe s mozilla function is now conditioned on the existence of slots for concat, filter, map, reverse, slice,
                      Message 10 of 13 , Sep 8, 2008
                      • 0 Attachment
                        --- In caplet@yahoogroups.com, "marcel.laverdet" <marcel@...> wrote:

                        Thanks, Marcel, that was really helpful. ADsafe's mozilla function is
                        now conditioned on the existence of slots for concat, filter, map,
                        reverse, slice, and sort.

                        I haven't found the leak in forEach. How does that one work?
                      • marcel.laverdet
                        ... As follows: var leak; ([].forEach || 0)(function(a,b,win) { leak = win; }); leak.alert(leak); Simple demo:
                        Message 11 of 13 , Sep 8, 2008
                        • 0 Attachment
                          --- In caplet@yahoogroups.com, "Douglas Crockford" <douglas@...> wrote:
                          >
                          > --- In caplet@yahoogroups.com, "marcel.laverdet" <marcel@> wrote:
                          >
                          > Thanks, Marcel, that was really helpful. ADsafe's mozilla function is
                          > now conditioned on the existence of slots for concat, filter, map,
                          > reverse, slice, and sort.
                          >
                          > I haven't found the leak in forEach. How does that one work?
                          >

                          As follows:
                          <iframe src="#"></iframe>
                          <script>
                          var leak;
                          ([].forEach || 0)(function(a,b,win) {
                          leak = win;
                          });
                          leak.alert(leak);
                          </script>

                          Simple demo:
                          http://llamaguy.com/adsafe/

                          It even works in Safari :D
                        • brendaneich
                          ... These vulnerabilities were first pointed out by Jeff Walden and Eli Friedman, then interns at Mozilla, in August 2007. Jeff wrote back then in reply to
                          Message 12 of 13 , Sep 8, 2008
                          • 0 Attachment
                            --- In caplet@yahoogroups.com, "Douglas Crockford" <douglas@...> wrote:
                            >
                            > --- In caplet@yahoogroups.com, "marcel.laverdet" <marcel@> wrote:
                            >
                            > Thanks, Marcel, that was really helpful. ADsafe's mozilla function is
                            > now conditioned on the existence of slots for concat, filter, map,
                            > reverse, slice, and sort.
                            >
                            > I haven't found the leak in forEach. How does that one work?

                            These vulnerabilities were first pointed out by Jeff Walden and Eli
                            Friedman, then interns at Mozilla, in August 2007. Jeff wrote back
                            then in reply to Marcel:

                            "... you need only call it on something that has a length property (or
                            a getter that doesn't throw), and so long as your provided function
                            *is* one, it'll get called for each item less than the pre-computed
                            length. Here's an example:

                            =====

                            <a onclick="boom();">click here</a>
                            <script>

                            function boom()
                            {
                            var win = null;
                            var forEach = [].forEach;
                            forEach(function(val, prop, thisp) {
                            win = thisp;
                            }, []);
                            win.alert("Hello world!");
                            }

                            </script>

                            =====

                            Aha, but that doesn't work, and for a simple enough reason: the test
                            console page (presumably you used this) doesn't have any subframes,
                            iframes, etc. Consequently, |window.length == 0| and there's nothing
                            to iterate over, so the callback is never called. However, it's a
                            reasonably safe bet that most Facebook pages *will* contain iframes
                            for ads, and with an iframe in the document it'll succeed. To
                            demonstrate this, simply run the following URL on the test console
                            after loading the given example:

                            javascript:var d = document;
                            d.body.appendChild(d.createElement("iframe"));[].v

                            Before I load that, the exploit fails. After I load it, it succeeds.

                            Jeff

                            0.
                            http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach
                            "

                            Separately, Eli wrote:

                            "Some other methods that are also vulnerable: Array.prototype.reverse,
                            Array.prototype.sort, Array.prototype.forEach (returns this in Safari 2
                            only), and Object.prototype.valueOf.

                            Also, combined with Array.prototype.push or Array.prototype.unshift or
                            the existence of a subframe, a similar vulnerability exists with
                            Array.prototype.forEach, Array.prototype.every, Array.prototype.map,
                            Array.prototype.some, Array.prototype.reduce (Fx 3 only),
                            Array.prototype.reduceRight (Fx 3 only), and Array.prototype.filter.

                            -Eli
                            "

                            So scrutinize all of the array extras, not just forEach, map, and filter.

                            HTH, and credit where due.

                            /be
                          • Douglas Crockford
                            ... Thanks. ADsafe is now wrapping concat every filter forEach map reduce reduceRight reverse slice some sort.
                            Message 13 of 13 , Sep 8, 2008
                            • 0 Attachment
                              --- In caplet@yahoogroups.com, "marcel.laverdet" <marcel@...> wrote:
                              >
                              > --- In caplet@yahoogroups.com, "Douglas Crockford" <douglas@> wrote:
                              > >
                              > > --- In caplet@yahoogroups.com, "marcel.laverdet" <marcel@> wrote:
                              > >
                              > > Thanks, Marcel, that was really helpful. ADsafe's mozilla function is
                              > > now conditioned on the existence of slots for concat, filter, map,
                              > > reverse, slice, and sort.
                              > >
                              > > I haven't found the leak in forEach. How does that one work?
                              > >
                              >
                              > As follows:
                              > <iframe src="#"></iframe>
                              > <script>
                              > var leak;
                              > ([].forEach || 0)(function(a,b,win) {
                              > leak = win;
                              > });
                              > leak.alert(leak);
                              > </script>
                              >
                              > Simple demo:
                              > http://llamaguy.com/adsafe/
                              >
                              > It even works in Safari :D

                              Thanks. ADsafe is now wrapping concat every filter forEach map reduce
                              reduceRight reverse slice some sort.
                            Your message has been successfully submitted and would be delivered to recipients shortly.