A Bit About Privacy on Javascript. Or, Take a Look, You Can’t See Me

So, it seems my last “talk” on nested functions left a big hole. I touched a little about privacy and showed a piece code that partially implements private variables. This code turned out to have a big hole in it. A security breach, if you’d like to call it that way. The code I showed was purely for demonstration purposes and it was not meant to be a full implementation of private variables. That, plus the fact that I don’t work with so-called data types lead to a poor implementation of a powerful concept.

Lets begin. I’m going to show the code first, because that is what you people like right? Then you go ahead and find holes in it. Then come back here and read the explanation of what is going on and why it is good. If you find holes in the implementation of private variables, let us know in the comments.

function foo(param1){
     this.constructor(param1);
 }
 foo.prototype = function(){
     var private = {};
     var i = 0;
     function c(p){
         var t = new Date().getTime() + i++;
         private[t] = p;
         this.constructor = null;
         this.getI = function(){
             return t;
         };
     }
     function b(){
         return private[this.getI()];
     }
     return {
         constructor : c,
         bar : b,
     }
 }();
 var c = new foo("private, I am");
 var d = new foo("or not so much.");
 alert (c.bar());

So, this is almost the same code as last time, but with a few minor changes and the introduction of one of those evil functions that get created everytime an outer function is called. OMG, I’m the worst programmer (lol).

First we changed private to an object. Yes, an object within an object. Objection?(If you know memes, you’ll get the joke). We need private to be an object to avoid the problem we had that caused the “private” variable to be modified by another object. Then we have our c function. Everything happens inside c. First, we create a variable t that holds the value returned by getTime, and we add i to it. This is in case two objects are created at the same time.

Next, we save our private value inside private with its reference set to t. Unset the constructor, and create a new method for the object on the fly. This is the part where people start dying because I created a function that gets created again every time the outer function executes.

So, why is Buzu teaching bad things? Short answer is I’m a rebel. Long answer is, it turns out this functions are not bad if used properly. There is nothing bad with a little function like this, and in fact, it makes a lot of sense. This function belongs to the object itself, not to the prototype. Besides, look at it, it’s so little and cute. How bad can it be?

Anyway, I hope you are still with me. The newly created method returns data that is not useful to an attacker. More over, if an attacker wanted to access the private property of another object. He would have to know when that object was created, and what the value of i was at that time, so it’s pretty hard. Now, even if an attacker guessed such value, how is he going to access private? it is inside a function that returned already. Now, how is that different from this:

function Foo(paramOne) {
    var thisIsPrivate = paramOne;

    this.bar = function() {
        return thisIsPrivate;
    };
}

var foo = new Foo("Hello, Privacy!");
alert(foo.bar()); // alerts "Hello, Privacy!"

Well, the short answer is, it is hella lot different. Long answer has to do with how many functions you have to create on each method. With the method I suggested, you only need to create one function no matter how many private variables you have. With this method, you need to create a function per private variable. That IS bad.

And, again, let me remind you that it is foolish to try to suggest privacy. If you want something to be private, make it so. Be proactive on your defence.

Now, I don’t usually work with data types, but I know them. They become useful if you find the need to extend objects, but I rarely find that need. In fact, most things can be done with pure objects. And with pure objects privacy can be achieved without functions that get created every time another function executes. Life is good when you work with pure objects. I would much rather have the ability to clone objects than to extend data types.

5 thoughts on “A Bit About Privacy on Javascript. Or, Take a Look, You Can’t See Me

  1. Hi. I’d agree that it isn’t always problematic to create functions inside functions…the importance of efficiency there all depends on what you’re doing. But unfortunately this method of creating private variables is just sort of…tacking more and more pieces of complexity on to something in the vain hopes of hiding something from attackers, and doesn’t even accomplish its goal (which I’m not sure is a necessary goal to begin with- attackers are not the real reason for private variables; rather it is maintaining coherent application state by controlling the means by which your own code modifies internal bits of things).

    You do accomplish one thing here: a private accessor that doesn’t get duplicated with every object. Though you also have- even worse- private variables then being stored in a shared object which will never get cleaned up. Imagine if you create and then discard hundreds or thousands of these objects in the course of the running of a program. Every single one of them still has its private data sitting in that shared object. The memory used will just grow and grow.

    Furthermore, the data hiding fails, at least according to the measure you’ve set for it (preventing modification of private variables even through use of the constructor). Consider, first, that for any object you can simply run:

    c.getI()
    or
    d.getI()

    This doesn’t really get you much, it just returns the internal index used within the shared private object. It does, however, show that trying to use a convoluted obfuscation technique (var t = new Date().getTime() + i++) doesn’t really accomplish anything, because that value may be obscurely generated, but it is still just sitting out in the open.

    But can you access the private variable, even knowing that? Not directly, but you can replace it for any given existing object. Why? Because you still have access to the constructor. Setting the constructor property of each new object to null doesn’t eliminate that, because the constructor is still publicly available on foo.prototype. So one simple call like this:

    foo.prototype.constructor.call(c, “now I have changed something in c”);

    will give c a new private value. (If you want to be technical, it isn’t changing it, it is replacing it; note that a call to c.getI() before and after this will yield different answers. But as far as any of c’s methods or anything using them are concerned, the private value has changed.)

    • Interesting. This is the reason I like to write this kind of posts. The amount of knowledge that can be shared through the comments is always a good reason to spend some time writing.

      Although, what you say is true, there are also ways to get around the problems in the code presented. It al depends, really, on what you are doing. For example, this:

      “Though you also have- even worse- private variables then being stored in a shared object which will never get cleaned up”

      could be fix rather easily. You build objects in such way that they clean up after themselves freeing memory. This of course would depend on your applications. Maybe the gains of freeing memory are not worth the overhead of doing so, maybe they are. But the memory problem can be easily fixed.

      This:

      “Setting the constructor property of each new object to null doesn’t eliminate that, because the constructor is still publicly available on foo.prototype. So one simple call like this:

      foo.prototype.constructor.call(c, “now I have changed something in c”);”

      Is far more interesting. I must admit that I didn’t consider it before. I will go back to my example and try to find a solution to this problem. I’m also looking into functional inheritance, which seems promising.

    • Check it out now:

      function foo(param1){
          this.constructor(param1);
      }
      foo.prototype = function(){
          var private = {};
          var i = 0;
          function c(p){
              var tSet = this.getI;
              if(typeof tSet === "undefined"){
                  var t = new Date().getTime() + i++;
                  private[t] = p;
                  this.constructor = null;
                  this.getI = function(){
                      return t;
                  };
              }
          }
          function b(){
              return private[this.getI()];
          }
          return {
              constructor : c,
              bar : b,
          }
      }();
        
      var c = new foo("private, I am");
      var d = new foo("or not so much.");
      foo.prototype.constructor.call(c, "now I have changed something in c");
      alert (c.bar());
      

      I do not recommend using this in production, but it demonstrates that the hole you found can be easily patched. It might not be the best way to do it, and it certainly isn’t the best way to code, but without spending too much time on it, or thinking too much into it, we found a way to patch the code. If you find more problems with the code, let me know. I would like to continue this discussion😀

  2. Glad to see others taking a conversational approach. Especially on a language like JavaScript, where there aren’t really any definitive texts (other than the standard itself), just a lot of clever developers and even more not-so-clever ones who have written lots of guides, tutorials, and descriptions of things, probably the best way for us all to figure out how things work and what are the best practices is to toss ideas out there to spark discussion.

    Anyway, I think there’s still a way around the data hiding here. Try:

    var asdf; // undefined variable
    c.getI = asdf; // now c’s getI is undefined
    foo.prototype.constructor.call(c, “a new value”); // passes the “undefined” check

    And this actually inadvertantly reveals a more fundamental problem with the idea of trying to treat data hiding in JavaScript as having any capacity for actual security. Even if you set up an object with values stored internally where they can’t be accessed except by public methods, you can’t prevent people from replacing those public methods. For instance, someone could at any point say:

    var myOwnSubstitutePrivateVar;
    c.bar = function() { return myOwnSubstitudePrivateVar; };
    and if you had a setter, called setPrivateVar():
    c.setPrivateVar = function(newValue) { myOwnSubstitutePrivateVar = newValue; };

    The outside code wouldn’t have access to the actual private variable, but it would be substituting itself for the public interface on the object, thereby intercepting any use of it and allowing one’s own variable to act as the de facto storage for the private information, as far as any users of the object are concerned.

    • Indeed, there is still a whole there. We could patch it once again rather easily, but then we have a bunch of patches rather than quality code. So, I think a fresh start would be better. We found that we need more privacy, and maybe the way we are trying to do it is actually not the best one.

      Te question then becomes, what is the best way to actually program with objects in Javascript. Should we turn to a functional style instead? And I don’t mean it in the sense of writing functions that don’t have side effects, but in the sense of using functions to accomplish what we want.

      The problem of course, is that there is no easy way to keep state of different pieces of code without objects. So, lets look at functional objects. This is a bit of what I wanted to talk about in my next post, but I think it is worth touching this a bit here.

      Lets look at how we create objects with functions.

      var obj = function(p){
          var private = p;
          return {
              getPrivate : function(){
                  return private;
              }
          }
      }
          
      var a = obj('private I am');
      var c = obj('Me too!');
      obj.call(a, 'not!');
      
      alert(a.getPrivate());
      

      One of the first problems we can see here is that a new object is created every time we call the “constructor” function. This means, each member of the object is created again. On huge objects, with lots of instances this will be a memory issue, but how many instances of an object do we really create on each app? It depends on the app, so once again, it becomes a matter of using the right tool for the problem at hand. But for the sake of this argument, which is about privacy, lets assume we can code this way without running into memory problems. What would the privacy issues be here?

Comments are closed.