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

ADsafe, Take 3

Expand Messages
  • Douglas Crockford
    This is the definition of ADSAFE.get and ADSAFE.set. var ADSAFE = function () { var exclude = { apply : true, begetObject : true, call
    Message 1 of 17 , Oct 3, 2007
    • 0 Attachment
      This is the definition of ADSAFE.get and ADSAFE.set.

      var ADSAFE = function () {
      var exclude = {
      apply : true,
      begetObject : true,
      call : true,
      callee : true,
      caller : true,
      clone : true,
      constructor : true,
      'eval' : true,
      'new' : true,
      prototype : true,
      source : true,
      'this' : true,
      toSource : true,
      toString : true,
      watch : true
      };

      var reject = function check(object, name) {
      return !object || !name || typeof object === 'function' ||
      typeof name !== 'string' || exclude[name] ||
      name.charAt[0] === '_' || name.indexOf('$') >= 0;
      };

      return {
      get: function (object, name) {
      var value;
      if (reject(object, name)) {
      return;
      }
      value = object[name];
      if (typeof value === 'function') {
      return;
      }
      return value;
      },
      set: function (object, name, value) {
      if (reject(object, name) || typeof value === 'function') {
      return;
      }
      object[name] = value;
      return object;
      }
      };
      }();

      Are there any weakness in .get and .set that would allow a program
      that passed JSLint/ADsafe to alert?
    • collin_jackson
      /*@cc_on alert( Conditional compilation considered harmful ); @*/
      Message 2 of 17 , Oct 3, 2007
      • 0 Attachment
        /*@cc_on alert("Conditional compilation considered harmful"); @*/

        --- In caplet@yahoogroups.com, "Douglas Crockford" <douglas@...> wrote:
        >
        > This is the definition of ADSAFE.get and ADSAFE.set.
        >
        > var ADSAFE = function () {
        > var exclude = {
        > apply : true,
        > begetObject : true,
        > call : true,
        > callee : true,
        > caller : true,
        > clone : true,
        > constructor : true,
        > 'eval' : true,
        > 'new' : true,
        > prototype : true,
        > source : true,
        > 'this' : true,
        > toSource : true,
        > toString : true,
        > watch : true
        > };
        >
        > var reject = function check(object, name) {
        > return !object || !name || typeof object === 'function' ||
        > typeof name !== 'string' || exclude[name] ||
        > name.charAt[0] === '_' || name.indexOf('$') >= 0;
        > };
        >
        > return {
        > get: function (object, name) {
        > var value;
        > if (reject(object, name)) {
        > return;
        > }
        > value = object[name];
        > if (typeof value === 'function') {
        > return;
        > }
        > return value;
        > },
        > set: function (object, name, value) {
        > if (reject(object, name) || typeof value === 'function') {
        > return;
        > }
        > object[name] = value;
        > return object;
        > }
        > };
        > }();
        >
        > Are there any weakness in .get and .set that would allow a program
        > that passed JSLint/ADsafe to alert?
        >
      • Mike Samuel
        I dislike blacklists. See comments on hasOwnProperty below. ... Perhaps exclude.hasOwnProperty(name)? Right now you ll exclude valueOf, though whether that s
        Message 3 of 17 , Oct 3, 2007
        • 0 Attachment
          I dislike blacklists.  See comments on hasOwnProperty below.

          > var reject = function check(object, name) {
          > return !object || !name || typeof object === 'function' ||
          > typeof name !== 'string' || exclude[name] ||

          Perhaps exclude.hasOwnProperty(name)?
          Right now you'll exclude valueOf, though whether that's intentional I don't know.

          Also, if you do hasOwnProperty or (name in exclude) you're guaranteed not to cause any function calls as a result of coercing a non boolean value to a boolean.

          Since your language is advertised as non-prototypical, hasOwnProperty would seem more appropriate.
           
          > name.charAt[0] === '_' || name.indexOf('$') >= 0;

          Ok.  Since you've checked name is a string, it's safe to access charAt and indexOf directly.  Unless someone can poison the String, but that means they've already gained access

          And the prefix _ check should eliminate Firefox reserved names such as __parent__, __proto__, and __caller__.


          > };

          > return {
          > get: function (object, name) {
          > var value;
          > if (reject(object, name)) {
          > return;
          > }
          > value = object[name];
          > if (typeof value === 'function') {
          > return;
          > }

          Why disallow returning functions?
          If your concern is that using a getter breaks the association between the method and its `this` value, you can always return a bound method a la function (binding, method) { return function () { return Function.apply.apply(method, [method, binding].concat(arguments)); }; }


          > return value;
          > },
          > set: function (object, name, value) {
          > if (reject(object, name) || typeof value === 'function') {
          > return;
          > }
          > object[name] = value;
          > return object;
          > }
          > };
          > }();

        • Douglas Crockford
          ... Good one. I owe you a plate of shrimp.
          Message 4 of 17 , Oct 3, 2007
          • 0 Attachment
            --- In caplet@yahoogroups.com, "collin_jackson" <collinj@...> wrote:
            >
            > /*@cc_on alert("Conditional compilation considered harmful"); @*/

            Good one. I owe you a plate of shrimp.
          • Douglas Crockford
            ... hasOwnProperty would ... I like the idea of restricting access to the prototype chain. ... I want to control what functions they get access to. Functions
            Message 5 of 17 , Oct 3, 2007
            • 0 Attachment
              --- In caplet@yahoogroups.com, "Mike Samuel" <mikesamuel@...> wrote:

              > Since your language is advertised as non-prototypical,
              hasOwnProperty would
              > seem more appropriate.

              I like the idea of restricting access to the prototype chain.

              > Why disallow returning functions?

              I want to control what functions they get access to. Functions are
              capabilities.
            • collin_jackson
              I am concerned about browser differences in the handling of null bytes (and other special characters). Example:
              Message 6 of 17 , Oct 3, 2007
              • 0 Attachment
                I am concerned about browser differences in the handling of null bytes
                (and other special characters).

                Example: http://crypto.stanford.edu/jsonrequest/nullbyte.html

                The Adsafe checks pass on Firefox, and the code is harmless. On IE,
                the checks fail, and the code is dangerous. If you only checked the
                script on Firefox but the visitor viewed it in IE, you'd have a
                problem.

                Another concern is that if the code is copy-pasted from Notepad to the
                browser, the null byte may be converted to a space, so JSLint won't
                detect it. Is there a better way to feed code to JSLint other than
                copy paste?

                --- In caplet@yahoogroups.com, "Douglas Crockford" <douglas@...> wrote:
                >
                > --- In caplet@yahoogroups.com, "collin_jackson" <collinj@> wrote:
                > >
                > > /*@cc_on alert("Conditional compilation considered harmful"); @*/
                >
                > Good one. I owe you a plate of shrimp.
                >
              • Adam Barth
                This seems to get through the filter: (function() { var str = alert( script tags affect parsing )/* ; })(); /**/ Adam
                Message 7 of 17 , Oct 3, 2007
                • 0 Attachment
                  This seems to get through the filter:

                  (function() {
                  var str = "</script><script>alert('script tags affect parsing')/*";
                  })();
                  /**/

                  Adam
                • David Hopwood
                  Douglas Crockford wrote: [...] ... IMHO the rejections should not be silent; they should throw an exception. In any case, I prefer my suggestion to use
                  Message 8 of 17 , Oct 3, 2007
                  • 0 Attachment
                    Douglas Crockford wrote:
                    [...]
                    > return {
                    > get: function (object, name) {
                    > var value;
                    > if (reject(object, name)) {
                    > return;
                    > }
                    > value = object[name];
                    > if (typeof value === 'function') {
                    > return;
                    > }
                    > return value;
                    > },
                    > set: function (object, name, value) {
                    > if (reject(object, name) || typeof value === 'function') {
                    > return;
                    > }
                    > object[name] = value;
                    > return object;
                    > }
                    > };
                    > }();

                    IMHO the rejections should not be silent; they should throw an exception.

                    In any case, I prefer my suggestion to use object.get(name) and
                    object.set(name, value). That way, these methods can be added only to
                    prototypes of objects that should be indexable, rather than all objects
                    being indexable by default. Since implementations of .get and .set in user
                    code would not be able to use the [] syntax, there is then no need for
                    explicit checks. (The trusted ADsafe implementation can of course use
                    [] where it needs to.)

                    --
                    David Hopwood <david.hopwood@...>
                  • Douglas Crockford
                    ... Good point. I am now scanning for the presence of any control character. ... JSLint runs in a number of configurations, including Rhino and WSH, which read
                    Message 9 of 17 , Oct 3, 2007
                    • 0 Attachment
                      --- In caplet@yahoogroups.com, "collin_jackson" <collinj@...> wrote:
                      >
                      > I am concerned about browser differences in the handling of null bytes
                      > (and other special characters).

                      Good point. I am now scanning for the presence of any control character.

                      > Another concern is that if the code is copy-pasted from Notepad to the
                      > browser, the null byte may be converted to a space, so JSLint won't
                      > detect it. Is there a better way to feed code to JSLint other than
                      > copy paste?

                      JSLint runs in a number of configurations, including Rhino and WSH,
                      which read text directly from files.
                    • Douglas Crockford
                      ... In a .js file, it is harmless. In an .html file, it produces an error.
                      Message 10 of 17 , Oct 3, 2007
                      • 0 Attachment
                        --- In caplet@yahoogroups.com, "Adam Barth" <hk9565@...> wrote:
                        >
                        > This seems to get through the filter:
                        >
                        > (function() {
                        > var str = "</script><script>alert('script tags affect parsing')/*";
                        > })();
                        > /**/

                        In a .js file, it is harmless. In an .html file, it produces an error.
                      • Adam Barth
                        ... When embedded in HTML, it calls alert (at least in IE7 and Firefox 2): http://crypto.stanford.edu/~abarth/jslint/parse.html Adam
                        Message 11 of 17 , Oct 3, 2007
                        • 0 Attachment
                          On 10/3/07, Douglas Crockford <douglas@...> wrote:
                          > --- In caplet@yahoogroups.com, "Adam Barth" <hk9565@...> wrote:
                          > > This seems to get through the filter:
                          > >
                          > > (function() {
                          > > var str = "</script><script>alert('script tags affect parsing')/*";
                          > > })();
                          > > /**/
                          >
                          > In a .js file, it is harmless. In an .html file, it produces an error.

                          When embedded in HTML, it calls alert (at least in IE7 and Firefox 2):

                          http://crypto.stanford.edu/~abarth/jslint/parse.html

                          Adam
                        • Adam Barth
                          I think I misunderstood your comment below. I meant that, when embedded in an HTML file, the script does indeed produce an error in a browser, but the browser
                          Message 12 of 17 , Oct 3, 2007
                          • 0 Attachment
                            I think I misunderstood your comment below. I meant that, when
                            embedded in an HTML file, the script does indeed produce an error in a
                            browser, but the browser continues on and executes the alert.

                            I guess this really boils down to a question of how to use JSLint. I
                            was imagining a web developer using JSLint as follows:

                            1) A user supplies the site with some JavaScript that is supposed to be ADsafe.
                            2) The site operator runs the code through JSLint, rejecting the
                            submission if JSLint so advises.
                            3) If JSLint approves, the site embeds the script in an HTML document
                            served from his or her domain.

                            This script causes problems in this scenario because JSLint approves
                            of the script, but it escapes from the sandbox when embedded in an
                            HTML page.

                            Perhaps it would be safer to ban </ from scripts altogether (not just
                            in string literals as described in <http://www.jslint.com/lint.html>).

                            Here are some more dangerous examples courtesy of Collin Jackson:

                            <html><body><script>
                            //</script><script>alert("XSS");
                            </script></body></html>

                            <html><body>
                            <script>/*</script><script>alert("XSS");*/</script>
                            </body></html>

                            Adam


                            On 10/3/07, Adam Barth <hk9565@...> wrote:
                            > On 10/3/07, Douglas Crockford <douglas@...> wrote:
                            > > --- In caplet@yahoogroups.com, "Adam Barth" <hk9565@...> wrote:
                            > > > This seems to get through the filter:
                            > > >
                            > > > (function() {
                            > > > var str = "</script><script>alert('script tags affect parsing')/*";
                            > > > })();
                            > > > /**/
                            > >
                            > > In a .js file, it is harmless. In an .html file, it produces an error.
                            >
                            > When embedded in HTML, it calls alert (at least in IE7 and Firefox 2):
                            >
                            > http://crypto.stanford.edu/~abarth/jslint/parse.html
                            >
                            > Adam
                            >
                          • Mike Samuel
                            If you do want to allow ADsafe JS to be embedded in a script tag, you need to deal with ]] as well, since the following could be used to throw allert
                            Message 13 of 17 , Oct 4, 2007
                            • 0 Attachment
                              If you do want to allow ADsafe JS to be embedded in a script tag, you need to deal with ]]> as well, since the following could be used to throw allert

                              (function () {
                                var a = [[]]> 0; //&#x0a; ]];
                                //&#x0a; alert('hi');
                              })();

                              Once you have to deal with CDATA sections and entity expansion in HTML, you're opening up a huge can of worms.

                              mike




                              On 03/10/2007, Adam Barth <hk9565@...> wrote:

                              I think I misunderstood your comment below. I meant that, when
                              embedded in an HTML file, the script does indeed produce an error in a
                              browser, but the browser continues on and executes the alert.

                              I guess this really boils down to a question of how to use JSLint. I
                              was imagining a web developer using JSLint as follows:

                              1) A user supplies the site with some JavaScript that is supposed to be ADsafe.
                              2) The site operator runs the code through JSLint, rejecting the
                              submission if JSLint so advises.
                              3) If JSLint approves, the site embeds the script in an HTML document
                              served from his or her domain.

                              This script causes problems in this scenario because JSLint approves
                              of the script, but it escapes from the sandbox when embedded in an
                              HTML page.

                              Perhaps it would be safer to ban </ from scripts altogether (not just
                              in string literals as described in <http://www.jslint.com/lint.html>).

                              Here are some more dangerous examples courtesy of Collin Jackson:

                              <html><body><script>
                              //</script><script>alert("XSS");
                              </script></body></html>

                              <html><body>
                              <script>/*</script><script>alert("XSS");*/</script>
                              </body></html>

                              Adam

                              On 10/3/07, Adam Barth <hk9565@...> wrote:
                              > On 10/3/07, Douglas Crockford <douglas@...> wrote:
                              > > --- In caplet@yahoogroups.com, "Adam Barth" <hk9565@...> wrote:
                              > > > This seems to get through the filter:
                              > > >
                              > > > (function() {
                              > > > var str = "</script><script>alert('script tags affect parsing')/*";
                              > > > })();
                              > > > /**/
                              > >
                              > > In a .js file, it is harmless. In an .html file, it produces an error.
                              >
                              > When embedded in HTML, it calls alert (at least in IE7 and Firefox 2):
                              >
                              > http://crypto.stanford.edu/~abarth/jslint/parse.html
                              >
                              > Adam
                              >


                            • Douglas Crockford
                              ... be ADsafe. ... The usage I was anticipating was that ads would be delivered in individual .js files. Ultimately, I want to banish all in page script. But I
                              Message 14 of 17 , Oct 4, 2007
                              • 0 Attachment
                                --- In caplet@yahoogroups.com, "Adam Barth" <hk9565@...> wrote:
                                >
                                > I think I misunderstood your comment below. I meant that, when
                                > embedded in an HTML file, the script does indeed produce an error in a
                                > browser, but the browser continues on and executes the alert.
                                >
                                > I guess this really boils down to a question of how to use JSLint. I
                                > was imagining a web developer using JSLint as follows:
                                >
                                > 1) A user supplies the site with some JavaScript that is supposed to
                                be ADsafe.
                                > 2) The site operator runs the code through JSLint, rejecting the
                                > submission if JSLint so advises.
                                > 3) If JSLint approves, the site embeds the script in an HTML document
                                > served from his or her domain.
                                >
                                > This script causes problems in this scenario because JSLint approves
                                > of the script, but it escapes from the sandbox when embedded in an
                                > HTML page.
                                >
                                > Perhaps it would be safer to ban </ from scripts altogether (not just
                                > in string literals as described in <http://www.jslint.com/lint.html>).

                                The usage I was anticipating was that ads would be delivered in
                                individual .js files. Ultimately, I want to banish all in page script.
                                But I agree that ADsafe should be aware of in page script.
                              • Douglas Crockford
                                ... you need ... alert Is it sufficient to disallow
                                Message 15 of 17 , Oct 4, 2007
                                • 0 Attachment
                                  --- In caplet@yahoogroups.com, "Mike Samuel" <mikesamuel@...> wrote:
                                  >
                                  > If you do want to allow ADsafe JS to be embedded in a script tag,
                                  you need
                                  > to deal with ]]> as well, since the following could be used to throw
                                  alert

                                  Is it sufficient to disallow <![ ?
                                • Mike Samuel
                                  No because ]] can end a CDATA section introduced by the embedding XHTML page which would then allow the embedding script to play tricks with entities that
                                  Message 16 of 17 , Oct 4, 2007
                                  • 0 Attachment
                                    No because ]]> can end a CDATA section introduced by the embedding XHTML page which would then allow the embedding script to play tricks with entities that aren't recognized by your lexer.  Consider  /* &#42;/ .constructor /&#42;*/ where 42 === ord('*')

                                    Given that XHTML allows arbitrary entity definitions in DOCTYPE elements, you can't modify your lexer to recognize all entities, so if you want to restrict ADsafe JS to embeddable JS, the only thing you can do is disallow anything that looks like an entity in a pre-lexer pass.

                                    There's a few ways to do this:
                                    - require that the <, >, >=, >>, <<, %, &, and && operators and their self-assignment versions be separated by whitespace from other tokens
                                    - require that characters in [<>&%] in string literals and regular expressions be hex/octal/unicode escaped

                                    But even if you do that, if you advertise the output as "safe for embedding in script" tags, someone will go and put it in an onclick handler, and you can't produce javascript that contains string literals that is safe regardless of which quotes are used for html attribute values.

                                    And finally, embedding opens you up to all kinds of charset attacks.  IE guesses character encoding for HTML pages regardless of whether they are served with a Content-type header, but not for javascript files that have a content-type header.  You could approve javascript for embedding only to find that it causes the page to be interpreted in a completely different character set.  I can't think of any way to exploit it off the top of my head, but it would make me leery of embedding third-party javascript directly in my pages.

                                    mike





                                    On 04/10/2007, Douglas Crockford <douglas@...> wrote:

                                    --- In caplet@yahoogroups.com, "Mike Samuel" <mikesamuel@...> wrote:
                                    >
                                    > If you do want to allow ADsafe JS to be embedded in a script tag,
                                    you need
                                    > to deal with ]]> as well, since the following could be used to throw
                                    alert

                                    Is it sufficient to disallow <![ ?


                                     



                                     


                                  • Adam Barth
                                    Another situation you may or may not have considered is the following: (function(){ throw hi! ; })(); This brings up the issue of what exactly is ADsafe
                                    Message 17 of 17 , Oct 6, 2007
                                    • 0 Attachment
                                      Another situation you may or may not have considered is the following:

                                      (function(){
                                      throw "hi!";
                                      })();

                                      This brings up the issue of what exactly is ADsafe guaranteeing its
                                      users. One simple guarantee is that the JavaScript is unable to read
                                      or write any global variables and is unable to call any global
                                      function (except as mediated by the ADSAFE object). This fails here
                                      because this code is able to call the global "onerror" function.

                                      The simplest solution is to require ADsafe code to be written using
                                      the following idiom:

                                      ADSAFE.call(function(){
                                      ...
                                      });

                                      Here the supplied JavaScript does not actually invoke the anonymous
                                      function it declares but asks the ADSAFE object to call the function.
                                      The ADSAFE object can then call the function inside a try ... catch
                                      block and expose an interface, like ADSAFE.onerror, to embedding
                                      applications to handle exceptions from ADsafe JavaScript.

                                      This idiom might be useful for other ADsafe features as well as the
                                      ADSAFE object would have a pointer to the JavaScript function.

                                      Adam
                                    Your message has been successfully submitted and would be delivered to recipients shortly.