Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts

Monday, January 23, 2017

Measuring web security mitigations

Summary: This past weekend I spent some time implementing a prototype for a web security mitigation, and I also spent some time thinking whether it was worth implementing as a web platform feature or not. In this blog post, I want to share how I approached the problem, which I hope you find useful, and to hopefully get your feedback about it too.

I've seen amazing progress on controlling the effects of XSS by adopting inherent safety on software engineering (a term which means focusing on completely eliminating the hazard) and I'm fairly confident that is today's most effective way to tackle it. However, there is always value in evaluating other types of controls beyond pure prevention - perhaps moving on to ways to minimize or contain its risk.

The way I see the problem is that the value of a mitigation can be measured by:
  • Impact - How many vulnerabilities was this mitigation designed to control?
  • Difficulty - What is the cost to adopt this mitigation on a system?
Measuring difficulty is somewhat easy, one should just try to apply the mitigation to real-life applications and see how difficult it is, however, measuring impact can be really difficult on a complex system.

The way this problem was approached in other fields was by measuring mitigations and controls across four metrics (wiki):
  • Moderation - How much are we limiting the impact of the problem.
  • Minimization - How much are we minimizing the number of problems.
  • Substitution - How much are we replacing risks with safer alternatives.
  • Simplification - How much are we removing problems, rather than adding complexity.
So, a naive way to look at this problem, is to evaluate the impact a mitigation has across these four metrics.

For example, I am a fan of Suborigins, an idea that aims to limit the impact a single XSS vulnerability can have by creating a more fine-grained concept of an origin. Suborigins is a good example of Moderation. It does not reduce the number of XSS vulnerabilities, it just makes it so that their impact is significantly reduced. On the other hand, we have the Angular sandbox - it aimed to limit the impact of the problem, but doing so effectively was extremely difficult, and eventually, the sandbox was removed completely.

Another good example is Minimization, and a great example of this is X-Content-Type-Options and X-Frame-Options. These are HTTP headers that allow a site owner to opt-out of behavior that can cause clickjacking, or some types of content sniffing vulnerabilities. If a website owner deploys these headers across their whole website then the amount of places that are likely to be affected can be drastically reduced. On the other hand, we have browser XSS filters and Web Application Firewalls. After many years, I think our industry reached consensus that they are not real security boundaries, and we largely stopped considering bypasses as security vulnerabilities.

Then we have mitigations that website owners can take that can Substitute a risky behavior with a less risky alternative. A good example for this is the use of JSON.parse instead of eval(). By providing a safe alternative to parse JSON content, the browsers have allowed website developers to write code that parses structured data without having to fully trust the data provider. On the other hand, we have DOM APIs (createElement / setAttribute / appendChild) as a replacement for innerHTML. While the use of DOM APIs is really safer, it's also so much more difficult and inconvenient that developers just don't use it - if the alternative is not easy to adopt, developers just won't adopt it.

And finally, we reach Simplification. A great example of a good simple API are httpOnly cookies, it does what it says, it restricts cookies so that they are available over HTTP only, and not JavaScript making credential stealing (and persistence) really hard in many cases. On the other hand, Ian Hixie eloquently explained the complexity problem with CSP back in 2009:
First, let me state up front some assumptions I'm making:
  • Authors will rely on technologies that they perceive are solving their problems,
  • Authors will invariably make mistakes, primarily mistakes of omission,
  • The more complicated something is, the more mistakes people will make. 
I think a valuable lesson (in retrospect) is that we should aim for baby steps (like httpOnly) that provide obvious simple benefits, and then build up on that, rather than big complex systems with dubious security benefits.


And that's it =) - The purpose of this blog post is not to make a scorecard of different mitigations and their merits, but rather to propose a common language and framework for us to discuss whether a mitigation is valuable or not. Hopefully, so that we can better focus our efforts on those that make the most sense for the internet.

Thanks for reading, and please let me know what you think below or on twitter!

Thursday, September 06, 2007

Allowing debug in a javascript library

Hi, some days ago I watched John Resig Tech Talk, about building a JavaScript library, where he pointed out some "good habits", when programming, and when doing js libraries, pretty interesting.

Any way, he mentioned that we shouldn't use try&catch because the coder "cant" debug his code, because we trap the error, and he is never able to see it.. so, I thought that an interesting way of letting the "error pass", but still have controll of the library is using setTimeout, to let the code run asynchronously.

The code I submitted to his blog, is:

setTimeout(function(){/*code here*/},0);

So, the error is reported to the user, and we dont loose the control of the code..

Some time after that I thought that, it could also be used for letting code runing in memory.. (but it's cancelled as soon as you leave the website).

Any way, as a programmer, I see this as a technique for running more than 1 process at one, as a security researcher, I see this as a technique for running XSS payloads in a more sigilous way.

Saturday, July 07, 2007

Passing Variables by Reference in JavaScript

Long time ago, when I was learning C, and I understood the use of pointers, I started thinking if there was a way to pass the JavaScript variables by reference.
I had a lot of ideas, but they didn't worked as spected.

For example, for global variables in a browser, I could use:

function modifyVar(varName,newVal){
window[varName]=newVal;
}
var x=123;
alert(x);
modifyVar("x",321);
alert(x);


anyway, this was only valid for "Global" variables..

Then I thought about using caller.call (even do it is not exportable).

function modifyVar(varName,newVal){
modifyVar.caller.call(eval,varName+"="+newVal);
}
var x=123;
alert(x);
modifyVar("x",321);
alert(x);

anyway, this didn't work neither, there was an strange error named "Too much recursion".

Then, a lot of time after that, (actually.. yesterday), I realized that the Objects in javascript are passed as reference, so..

function modifyVar(obj,newVal){
obj.value=newVal;
}
var m={value: 1};
alert(x);
modifyVar("x",321);
alert(x);


and the attribute was modified successfully :).


Any way, this wasn't good enough, I wanted to be able to send a variable as a parameter in an instruction, and be able to modify it's content inside the function.

There's when I realize (after some testing), that I can set any variable as an object, and allow it to have any primitive value I want, for example:

var w=Object("some string");


will behave just like:

var w="some string";


and that:

var w=Object(123);


will behave just like:

var w=123;


and the same for regular expressions, functions, other objects, etc..

So by means of this, I was able to transform any variable into a "referenceable" variable.

Any way, for modifying this variable, I couldn't use any Assignment Operators, because they would destroy the Object.. I needed to modify it's contents from "inside", using it's Methods.

So I found three methods that returned the value of an object:
  • toSource();
  • toString();
  • valueOf();

The last one is the most important one, it's value is the one that will be treated "officially", except for String and Source operations.. so by doing:

function modifyVar(obj,val){
obj.valueOf=obj.toSource=obj.toString=function(){return val}
}


we would actually be modifying the value of "obj".

any way, this wasn't just enough.. I wanted a way to reference variables as easy as in C or PHP.. so.. why not making a prototype function of object that allows me to modify the variable..

so I did this:

Object.prototype.$=function $(val){if(val)this.valueOf=this.toSource=this.toString=function(){return val};return val;};

so, variable.$("new val"); will modify the content of variable, "globally".

Here you can see the way this works:

// Object reference maker
Object.prototype.$=function $(val){if(val)this.valueOf=this.toSource=this.toString=function(){return val};return val;};


function value(variable){
// function to modify the variable through =
variable="new_value";
}

function reference(variable){
//function to modify the variable through reference
variable.$("new_value");
}

var w="standard"; // standard value

w=Object(w);// transform to object.
alert(w); // show that the value is still the same
// standard
value(w); // try to change it's content's via =
alert(w); // show if the content's have been modified
// standard
reference(w); // try to modify the content's via reference
alert(w); // show the new value
// new_value


Hope this is useful for anybody that requires to modify a "private" variable where it's not accessible.. here is an example of Object, and a way to modify its private variables (which shouldn't be possible due to the O.O.P. Paradigm)..

Object.prototype.$=function $(val){if(val)this.valueOf=this.toSource=this.toString=function(){return val};return val;};
function DownTown(){
var private=Object("You cant modify me");
this.get=function(){
return private;
}
this.export=function(callback){
callback(private);
}
}
var blackbox=new DownTown();
alert(blackbox.get());
blackbox.export(function(x){x.$("new val!")});
alert(blackbox.get());