>> Ben Livshits: Okay. Thank you very much for [inaudible] back with me. I'm Ben Livshits. Welcome to another meeting of our JavaScript book club or whatever we have here. We have an exciting visitor today, Jan Vitek, who is visiting us from Purdue University. He'll talk about a couple of recent results in the JavaScript space. >> Jan Vitek: All right. Okay. So thanks a lot for having me. And as Ben said, this talk will be about a couple of recent results, or it's more like work in progress, really, that we've been -- why a couple of results? Well, I just felt these were two interesting things, and I couldn't decide which one I wanted to present, so I said, well, let's try to do both. So we'll see if that works out. What's the -- and there is sort of a thread running between them, other than the fact that they're both on JavaScript. So let's start. So the first part of the talk is work that we did on trying to understand how the eval operator of the JavaScript language is used. So JavaScript has a way to turn a random piece of text into executable code. It actually has many ways to do that. Eval is the one that we will refer to in the talk, but there are other ways to do this. So basically you can at runtime turn text into code. Now, the question then is does it happen often, what do people do, how bad is it and why should we care. So essentially what we did was -- this is the big concern, you know, this slide summarizes it all, and essentially what we did was the following. We took the Safari WebKit browser and we instrumented it. And we instrumented it to record execution traces. And the execution traces contain a lot of information including the evals that you actually do. Then we created three datasets. The first dataset, which I'll refer to in this talk as interactive, is obtained by taking the hundred most popular Web sites and interacting with them for 15 minutes or so a number of times. The second dataset is taken by taking the 10,000 most popular Web sites and just loading the first page and seeing what happens, you know, recording the JavaScript that runs on page load. And the third dataset was created by essentially doing what I just said, and then once you have loaded the page randomly clicking on clickables. The different between the first -- the last two is that you have always some behavior that doesn't happen as you load the page but only happens when you interact with it. So by randomly clicking we sort of did our best approximation of a sort of interaction with the Web page. And so out of this the two numbers that should jump out are 91 and 59. So 91 is out of 10,000 Web pages, 91 percent of them use JavaScript. So if you need convincing that this is important, well, 91 is the number that you should use. And 59 is the percentage of Web sites in our interactive dataset that use eval. So majority of Web sites written in JavaScript. Most of the Internet uses eval. That's sort of the takeaway. So can't ignore it. Can't ignore it. And so one of the other results we got out of this is we have this database now of -- you know, this is maybe 300 -- well, is it 300 megabytes of eval strings that we collected? So large numbers of those. So what -- maybe I should modulate this a little bit further, say, well, why should we care about evals? Well, there's two reasons, and the reasons are performance and security. So I'll argue for both. So let's say we want to ignore eval. What happens. Well, here's a result we got in some other work we did with people I can't name. This is Firefox behavior and this is the speedup of Firefox over time on the standardized SunSpider benchmark. So what this tells you is 5 of 1.5 -from 1.5 to 3.6 you have a 13-fold speedup in performance, which is wonderful. Right? And then you look at the performance on a real Web site, like Amazon, there's a 3.1 speedup. And, more importantly, after Firefox 3, it's basically flat lined. So what does this tell us? Well, it tells us there's something -- probably something wrong with the benchmark. I mean, if this is representative, and it actually is, what is wrong with the benchmark? Well, the benchmark is static. It is, you know, loops and traditional control flow. This guy is doing the SMM Web site, so using eval, it's using all sorts of dynamic features. So ignoring how people actually use the features of the language is going to give you wrong results if you care about performance. So we can't do that. So that was half of the motivation. The other half of the motivation for looking at eval is one of security. So here is an example of what people do with eval. So imagine I have a programmer that wants to access the message field or some field of an object called resources. And for generality at development time, the programmer doesn't want to fix which of the many message field is going to be accessed. So it's sort what the programmer has in mind is that at the end of the day we will concatenate this string with some other string to form something like resources dot message underscore hello. That's the programmers' model here. And of course if what we -- this is just string concatenation. I could also do something like this. I could say this is resources dot message underscore method and vocation files the delete all. So what will happen here is assuming there is such a thing as a file object that has a delete all method. We'll evaluate the argument of the method. We'll call the delete all, it will do something, and then we'll find out that the resource object doesn't have a message method, and we'll return undefined. But this is -- both of these were fine pieces of JavaScript code that through eval give you behavior that sometimes may surprise you. So in this case, the programmer being careful implemented a validate method which hopefully will segregate these two cases. It will parse the input string and make sure that the input string does not actually delete your files. Or do whatever it is you don't want it to do. Of course this is really dumb code, because in JavaScript you could have done this much more safely by writing this. So in JavaScript any object is a hash map, so I can just create a selector by concatenating to field, and there's no use of eval, I'm not invoking code, not compiling, generating anything. So it's much safer. Could have been done on [inaudible]. So bottom line is eval is one of the sources of security breaches, and it's also part of what makes it hard to compile JavaScript efficiently. So the questions we wanted to answer are listed in no particular order here. So we wanted to know, well, does eval occur frequently in the real world, not in the benchmarks. Does it occur -are there many eval sites in your program or is it only one place. Is the data that we're evaling large? I mean, are we evaluating a few bytes or are we evaluating megabytes. Why does it matter? Well, if you're evaluating a few bytes, you can imagine maybe filtering those bytes, maybe parsing them, maybe statically analyzing them, proving that they're not breaking your security policy. If you're evaluating megabytes, it becomes harder. What is the scope of this eval? How far do they reach? I mean, eval will run code and that code will touch your data structures. Is it going to touch the data structure throughout the system or is it very local? What is the origin of these strings that we're feeding eval and is this stuff we're getting from the inputs or -- all of these are questions we would like to answer. So if I come back to our big slide I had in the beginning, there's some of the data there, which I didn't repeat, but what you can see is that's the numberer of eval codes we saw sort of between. And the interactive dataset was about 2,000, and overall on our big random Web site was 367. And another thing -- so yesterday we had the talk on [inaudible]. One of the things to note is that page load doesn't figure as many evals as clicking on the Web page. So that means we have to actually interact with the page to get it to do its stuff. So I'll give you now more data. So the first graph I want to talk about, looking at the number of call sites in -- of sites where eval gets invoked in your program, and this number -- and this is for our three different workloads or datasets, and you can see that in the interactive dataset the average is about 5. So there's typically a handful of places where you're going to be calling eval from your program. And it doesn't go over 30. And if you take the random -- well, the random is a dataset. You see that it goes all the way to 466 places where you're calling eval. So why does that matter? Well, if I want to validate the security of that Web site, that application, I have to look at 466 places where I may be getting input from -- yes. >>: What is static location? >> Jan Vitek: So these are static locations. >>: [inaudible] that you identified as being used. >> Jan Vitek: These are -- okay. So to be precise, these were locations that were exercised. So call sites in the text that were actually reached. So this is all tracing base data. So anything that we don't exercise we don't see here. So in some sense what this addressed is that, you know, the 100 top Web sites maybe better written than the average, which is not too surprising, because they tend to have few of these, and we can imagine that maybe half of them are doing JSON parsing, which is probably safe, and then a few other places that are doing sort of weirder stuff. Yeah. >>: [inaudible] inspect it by hand? >> Jan Vitek: No, we'll do that. Yes. I'm ->>: [inaudible] not hard to imagine. >> Jan Vitek: Yeah, that could be. That very well could be. So the next question we're wondering about was how big is the data. How big is the data that you're feeding eval. And it's sort of interesting. So this is size and this is the percentage that it accounts for. So essentially what this says is that if our interactive dataset at 65 -- so 65 percent of eval are less than 64 bytes. So over -- the majority of evals are less than 64 bytes. Majority of evals are less than 64 bytes. You see that, you know, it grows. And, for instance, for interactive dataset, 90 percent reaches, yeah, about 500 -- above 512 bytes. So evals tends to be small. But, on the other hand, they go all the way to 256kB. So what is happening at that end? Well, people using eval to do -- to LoadLibrary code. So it's a way to do lazy loading. They just say, well, if I think I'm going to need -- you know, I'm not going to tell the engine to actually compile or parse this JavaScript until I need it, and then I call eval, and poof, I got the code. So what does this tell us? Well, it tells us that, you know, there's certainly for -- on the small sizes I believe we could online analyze those. We could probably analyze those online, could verify it, validate them. But once you start talking about kilobytes of JavaScript code, it may be hard if you're doing any interesting static analysis to do it online or not. I mean, that depends. So depends what -- I mean, the speeds that were reported yesterday were quite encouraging, so it all depends. So the next thing we looked at was what kind of data. So we know the size, but what are they doing with that, what is the actual payload of that eval. And we categorize the evals in sort of buckets. And the first product that we see a lot is evaling JSON. So this is a JSON string, so this is -- the braces are really telling us when you eval this, create an object that has a field X with value 2. So this is this evaluation. That's a big bucket. Then another kind of is evaling stuff that kind of looks like JSON but has small, you know, sort of -- it's not exactly per the JSON spec, but it kind of creates objects too. We call this relaxed JSON. And the third big bucket is JSON assigned to a field. So there's a lot of that. So you assign that to either a field of an object or a local variable. The fourth big bucket is calls that have only a method -- a field identifier. That's the whole code. And that's a big bucket. I'll tell you how big the bucket is later. But the only thing it's doing is this. This is definitely a case of -- in many cases it's a case of ignorance, because you could just rewrite this without the eval, put a square brace around this, and use F as a string and -- okay. Okay. So that's the next. So here's a weird bucket that we found a lot of and we have no understanding or explanation why. So people seem to like to write type tests in evals. So the whole body of the eval is a type of expression that just checks if the type of sum -- here in this case it's a constructed field -- is undefined. We have no good reason -- no good understanding why people would do this. We looked through the Internet to see if somebody at some point had said this is a good idea, and we couldn't find that. And it's not even the right way to do this, because you could say, you know, this field is in -- is -- well, you could say -- I mean, you could use the in -- there's a keyword "in" in JavaScript that let's you test if something is present in an object. Next bucket, which is also weird, is this. So this is actually occurring enough that we found it worthy to mention. And it is a piece of code that tries, that throws -- I mean, so the order of evaluation is assign 14 to global variable V. Okay. Throw an exception, catch and discard it, move on. Okay. So this whole thing could be replaced with V equals 14. Or eval V of 14, rather. So there is one tiny thing is when you're evaling, you're in global scope. So there is a scoping issue. But other than that, the try and catch seems slightly unnecessary. Then a big bin is calls. So people have an eval that is doing only one thing, which is calling a method passing an argument. And then there's these library loads. So then when -- this is cases where you're loading a bunch of functions. And finally there's a bin for other where you're doing a combination of those and we just couldn't categorize it. Yes. >>: [inaudible] like completely useless and how many of them are -- like the original validate example that you had. >> Jan Vitek: So the question is how many of the argument -- so all of the arguments I gave here were extreme constants, just for the example. Right? And the question is how many times is this exactly what happens. And we'll see that in a bit, some number. And I have a graph for that. >>: [inaudible] >> Jan Vitek: Right. So we're getting there. So there's more data, and I'm sort of simplifying some -- just for due to time, but basically the call bin, the one where you do a method call, is the highest. JSON comes next. Then the bins with other stuff. And then it sort of decreases slightly. So this is -- so, you know, we're selling -- calls are 100,000 occurrences, JSON are about 800 -- 80,000 occurrences, and it goes down. Oh, I didn't say that we found a number which were either empty strings or, you know, actually -- either white spaces or empty strings. All right. So that is the dynamic. So these numbers are the number of strings fed to eval in our random dataset that had this [inaudible] dynamic. >>: [inaudible] so the empty string might have been the result of something -- >> Jan Vitek: Absolutely. So it may be a code -- there are many reasons why you may have that and you just -- well, you don't care, right, it's an empty string, so it doesn't matter. But it just looks ugly and silly when you're looking at them from the outside. So the next thing we looked at was we tried to understand how -- yeah. >>: [inaudible] did you look at all the coverage, like how many different sites did the typo thing, for example? What fraction of the [inaudible]. >> Jan Vitek: So we have that somewhere. I don't have it offhand. And there's another thing that we have, which is we looked at how often the same call site, you know, emits the same kind of, you know, instructions. Like, for instance, a call site, does it always do JSON? And we have data that sort of suggests most call sites are consistent. But there's some number of them, and I forget the exact one, where you can change. Sometimes it's one bin sometimes in the other. But it is interesting that a lot of these call sites are consistent, so maybe what you could do is once you've seen it do one pattern once, you can sort of specialize for whatever analysis or code generation you're doing for that pattern. Another thing to observe is if we got rid of JSON, if -- by that I mean if rather than evaling it we were parsing it, you know, not such hard thing to do, we would reduce, you know, somewhat the number of stuff that has to be taken care of. So we can get rid of this because we can parse it. Member access, you shouldn't write them in eval, so we should be able to get rid of that. Type of -- I can't figure out why. So the ones -- you know, there's a number of these categories you could get rid of, and then it could reduce the magnitude of the problem, not eliminate it unfortunately. So the next thing we did -- yeah? >>: [inaudible] any of these kind of strange usages where the result of maybe [inaudible] generate code or were they actually handwritten? Can you kind of get an idea as to ->> Jan Vitek: So, I mean, to some extent we could. We didn't. But we could because the -- you could look at the code and try to figure it out. I mean, clearly they're out of those 10,000 pages, there's a bunch that are [inaudible]. But yeah. So the next thing we wanted to know was how far reaching the code that you're running in eval is going to -- you know, how far is it going to reach in your program. And so we looked at this, and the way to read this is 10 percent of the dynamic eval we're running are reading and writing only to local scope. So 10 percent of the evals are completely local. So let's say JSON would probably be a case of stuff that should be completely local. It's creating a new object and it's storing to the fields of that new object. So in some sense it's safe from a security standpoint. It's neither going to endanger secrecy or integrate it. Then there's like 60 percent that is writing to local and reading from the global scope. That means, well, at least one bit of global data was red during the eval. But the nice thing is it's only writing to local. So that 60 percent is not going to endanger integrity but it may get a secret out of you. And then there is about 9 percent that is writing and reading global values. And I would be probably a little bit leery of that. Right? That does not look good. So the next thing we did is we took our bins and we ->>: [inaudible] stand for? >> Jan Vitek: Write and read. >>: [Inaudible] power. >> Jan Vitek: Oh, that's a typo. That's a typo. >>: What's the N? >> Jan Vitek: You don't want to know. Okay. I'll tell you. So what we were trying do is say L means you're the -- reading local variables in your call frame and M means reading variables in sort of the call stack. But it's not that important. So the next thing we did was we took our bins and we tried to see where do the strings that you feed to eval come from per bin. So we have this categorization. We said they're Ajax, strings that come through the Ajax protocol. There's strings that come either from calls to a native function or through -- or that you grab from your document. There's strings that are constructed by concatenating two or more constant strings. And there are strings that are constant, you know, hard wire, which was the question asked earlier, in the program. And so if you -- you categorize the -- and we did that for all bins. And how do we do that? Well, we -- essentially we taint, so we change the interpreter to taint these strings at creation, and then when you concatenate, so strings may start as a constant, then you concatenate it, then you flag that string as tainted and you propagate that through the execution. So it's a very simple form of taint analysis. So what should we say? Well, for one thing, there's very little Ajax anywhere. Ajax shows up here in the JSON bin, which makes sense. It shows up in the white space bin. I guess you're sending an empty message, most likely, in the relaxed JSON. And that's about it, all of the other places. And which is good. Right? That's probably what you would like. If you look at a constant string, well, they account for -- they show up in JSON, so there's some amount of JSON that is constructed as of constant, but they account for 50 percent of cases where you're accessing a single variable. So the code had eval X in it. And it goes for 80 percent of method calls in your code. Again, the call had -- and it counts for almost all the try catch. So you're not constructing these things, which is good probably. So all right. So that's pretty much where we stand. So essentially we have, and I'll conclude for this part, the thing -- well, we've looked at the behavior evals, and it occurs. It occurs a lot. It can be big. There is encouraging bits of data suggesting that if your site is well written, it is sort of more disciplined. And we're still working on trying to do more. We want to get all the forms of eval. You know, there are other ways to actually get eval to happen, so we want to know what they are and how often they occur. And we want to get better provenance information so we can tell you better which is user input and stuff like that. Yes. >>: So is one of the conclusions from this that from a performance standpoint one might want to actually have a preprocessing step that we take -- where you take a page, run it through, do eval for whatever you need to, and then actually execute and JavaScript using [inaudible] SunSpider, right? >> Jan Vitek: You said it. Definitely. I mean, if you look at -- look at the number of these that are static once you get a Web page. That's not a silly thing do. >>: With the analysis that you did, would that attract a renamed eval where someone will assign [inaudible]? >>: Yes. >> Jan Vitek: Yes. Because we are in the browser. So as long as you end up in the eval, we would have caught it. >>: Did you look at all the documents I write in terms of [inaudible]? >> Jan Vitek: So that's the other forms of eval, and we'll have that data soon. So it's coming. >>: So do you have a sense of the distribution of the other? >> Jan Vitek: Not yet. So we're running the experiment now. So we just -- yeah. >>: In the case of [inaudible] as a preprocessing step, just [inaudible] what you're left with is some legitimate forms of it [inaudible] used primarily [inaudible] still have to worry about [inaudible] what's your overall feeling about where this is going? Do you feel like it will basically eliminate a bunch of these things and then [inaudible] maybe through some [inaudible] recognized primitives or will there be more? >> Jan Vitek: So I guess -- so the question is if we remove JSON, if we remove the trivial cases, how many things are people doing with eval that they couldn't do otherwise? And I don't have a good feeling for that. Dynamic loading shouldn't be eval. I mean, we understand dynamic loading and we don't need to give the full power of you introspecting over the environment to load dynamic code. You just -- you know, you load a bundle of functions. That's one thing. But you don't have compute while you're doing this. So there is likely to be some call where you need it, and I'm not sure what will be left. But we could whittle it down. We could whittle it down a lot, and that would make life, you know, probably easier. >>: So do you get a sense of the use of these idioms and how it's split between the actual application unit and the libraries that they're loading, like J queries and stuff like that? >> Jan Vitek: No, I don't have ->>: Because maybe the reason you're seeing like that typo thing is because it's in a library everybody uses. >> Jan Vitek: Yeah, that could be. Yeah. >>: So [inaudible] I think our like estimate for the amount of evals are sort of frivolous, was about 8 percent, something like that. >> Jan Vitek: Yeah. Yeah. So we hope we could get rid of 80 percent of evals, and that leaves 20 percent you have to look at, yes. >>: [inaudible] eval with less version of say J query [inaudible] very complex language [inaudible] but perhaps you could take a site, Facebook, and try to have an eval-less version [inaudible] free version of something. >> Jan Vitek: And see what happens [inaudible]. All right. So I'll move to the second part, which I'll go through faster, because we've takable more time than I've planned. So the second part is another piece of work. It's looking at access control for JavaScript. And it's kind of motivated by eval. So here's the code I want you to understand. And, well, this is the MySpace worm. And if we had to focus on one -- on two lines, give me two lines, two lines, two lines, on two lines you need this. This is the part you really need to understand. So this is the worm, the MySpace worm. So what was going on. So somebody wanted to attack MySpace. And in order to do that, so MySpace used to be a popular Web site, you know, maybe familiar. And they were using -- so the attacker wanted to use JavaScript and to attack it. And he found that, well, MySpace was filtering, so they were looking at the data and they were sort of doing pattern matching and they would throw away JavaScript. But the reason I said it's two line, there's actually a line break at the end here. And the filter that MySpace was using considered the word Java and script and two words, which makes sense, you know, it's Java, new line, script. Now, of course the browser built by some company considered -- there were actually several browsers built by a number of companies, considered Java the new line to be nonsignificant character. So for the browser's perspective, Java and script because JavaScript. That's part of the attack. So you could -- they manage to get JavaScript recognized. And then you could have code. But the problem is this was already quoted twice. So they ran out of quotes. So they use eval to -because they needed quotes for doing stuff inside the code. So they used eval to grab another part of the HTML page, this expression here, and run that code. So eval was needed. Browser differences were needed. Another example from the same worm is in order for the attack to work, they had to send the documents, they had to send the Web page. MySpace was looking for the word inner HTML and not looking for the two string inner and [inaudible] HTML that could be computationally added. And that was the attack. So basically what's the problem? The problem is we're running untrusted code in our browser, and we want to secure it. And one way to secure it is to try to filter the code you're given. But as I've shown, the presence of eval makes it very hard to find static methods to filter that code because the code can be constructed on the fly and life becomes hard. So this project that I will try to talk to you about attempts to provide security for, you know, one part of this problem. And here's my example. So this is a page, a Web page from some news agency that you may choose to trust or not. But assumably, if you're going there, you have some expectation that they're not going to attack you, so there is a trust relationship between you and them. But on this Web page there is these two bits here which don't belong to CNN. They're ads. And the code that these ads is running is coming from a -- another code provider, which actually sometimes offloads even to another provider. So the code comes from God knows where. Well, actually for this page, we were loading places from all these URLs, some of them make sense, others don't. So the problem we're looking at is you're running a piece of code that is composed from different origins. There is one source, CNN, which is the trusted source, right, at least in news, and there are other places which may not be as trusted. So the question we were trying to solve is can we secure, can you provide security from those ads, those little bits of code that you get that get merged into your content. And it's really an access control problem, right? Because what you want to do is control what the JavaScript that is loaded through these ads can do unrestricted. And there have been a number of attacks that have used ads to endanger the security of your server. So the project we call JSLocker, because the Internet is minefield. And we -- our goal was to protect users from untrusted ads with the constraints that we don't believe we can change the code that is out there, so it has to run unchanged code, but we allow ourself, you know, the freedom to mess with the browser. So we sort of say sure, we can change the browser, we can change the code that's out there, what can we do, how far can we get. So in terms of problem statement, you can think of the problem as really being the -- coming from the fact that a Web application is really code that comes from multiple sources. Each of these sources is a principal, and they're manipulating objects. They're manipulating resources, your shared memory locations. And what we want do is control how they manipulate those resources. So it's an access control problem. And in an access control setting, you have two questions to ask: What is your access control mechanism, how are we going to monitor access to data, and what are the policies, how do you define who's allowed do what. So we propose a solution for both of those. So to simplify things, let's assume there are only two principals. There's the Web page, the host page, which we trust, say CNN, and then there is the untrusted codes, the ads. For simplicity we'll just take two principals. And your resources [inaudible] your objects, your functions that you're going to call on them. And what we propose as a mechanism is what I'll explain, something we call delimited histories and revocation. And as policies we're going to have predicates that can be written by users over these histories and revocations. So how does this work? Basically you're faced with access control decisions of this kind. So you're running in JavaScript and you get to a point in the code where you see somebody's trying to store a value into the field of let's say the global object, let's say. And this is an operation that is done by the untrusted part of the system. So the question is do we allow this or do we reject this. Okay. Well, if I see only this, it's very hard. I don't have much context. So what we're proposing is to say, well, we're going to give you a window on the computation, a history, and you can actually look what happened before that very instant. So at time T minus 1, you see the code was incrementing a counter. Yeah, that still looks pretty safe. And if you look at instant T minus 2, you'll see that the code read some user data and stored it into NM. So what this is doing is it's reading something, say, some secret, and then putting it in a globally visible object. So now you have enough context, if you see all of this, to make an access control decision. So the idea was of JSLocker is to say, well, we're going to record histories of computation performed by the untrusted code, and then before -- but then at some particular point in time, we're going to run a predicate over this history that will tell us this is valid or this is a security violation. So here's an example of a predicate which is the send after read policy, and the send after read policy says when you want to check a history, look at the history in order, see if there was a read of data that didn't belong to the untrusted principal. And if there was a read, remember that, and see if there is an attempt communicate over the Internet. And in the case a read proceeded it, stop. So very simple. If you've read a secret, we're not going to let you talk on the Internet. Simple policy. So the question is what does it mean to stop? Well, we could just stop the computation. With what we propose is a mechanism closer to transactions, which is to undo all the effect performed by the history. So the reason is, well, you know, if I just stop here, now I have part of my state that is inconsistent. I've incremented some stuff. And I would like to clean that up. Or maybe what I did is if I stop here, well, I still have the opportunity to register a function and I'm polluting the global name space. So want to be able to clean what the -- if we detect somebody is untrusted, want to undo its effects. So the ->>: [inaudible] >> Jan Vitek: Sorry? >>: [inaudible] >> Jan Vitek: Well, once we've ->>: [inaudible] >> Jan Vitek: Right. We can block it, but we want also to undo what it has already done. Because we already executed. We're not -- this is not static analysis. This is runtime. So we have a history of what you have done in the past, and now we are going to undo that history. So that's basically the thing. So we have a mechanism for in the browser recording histories of untrusted computation, and at particle points of time we'll validate that history and either we accept it and we say you can keep on, or we revoke it and we'll undo you. And a couple of odds and ends. We have to define what is a history start and what is a history end. When do we start recording. So what we do is we tag every object by its source. So if you download something from a an ad, it gets tagged as untrusted. And whenever you call a method of an untrusted object, we start the history. And when you leave that method, we end the history. So we know when you're executing untrusted code. And whenever you create new objects, we're going to tag them as well. And at the end of a history we're going to run the validation code. And if it succeeds, then you're fine. If not, we'll undo what you've done during that piece of execution. There are cases where in the middle of a history you may be trying to communicate, you try to send something on the Internet. So what happens then? Well, we support a form of eager validation. We know that the history is not over, but we're going to let you decide whether you want to kill the computation right now or not. Eval. So this is where we come back to eval. So one of the -- the danger is eval could be used to get trusted code to run a string that was created by untrusted code. And that would defeat our mechanism. So what we say is if you're running an eval, we're considered as untrusted. And all evals are run with history recording and potential unrolling. >>: So you're basically creating like a [inaudible] transaction log [inaudible] and rolling back to different points. But doesn't that require that you do for a whole page [inaudible] those global locates be operating on [inaudible] page? Not just frame itself. >> Jan Vitek: It is done -- so we're recording what happens for the whole page, but the recording only needs to -- so JavaScript is sequential, right? So the only -- it's only when you start executing an untrusted object, an object that was loaded or created ->>: [inaudible] the untrusted object [inaudible] something's done. And then returned back. >> Jan Vitek: Right. So if it's done by the trusted page, we assume it's trusted. So that's part -there's couple of things we don't do, and that's one of them. So we implemented this in WebKit in Safari browser. It's about 5,000 lines of changes spread over 29 files. I lied because I said -- I showed you a nice policy. The real policies are written in C++ and they're ugly. We validated this on real Web site. So our validation was done as follows. We started -- we took 50 Web sites and we ran them with the empty policy, so the policy that always says yes. And, as expected, 50 Web sites ran fine with the policy that always says yes. Then we ran the Web sites with two other policies, one which says you're not allowed to update global variables. You can create new ones, but you can't update a variable that somebody else created. So that's the add-only policy. And what we show here is that 36 Web sites ran just fine with that. There were eight Web sites where we worked as a very good ad blocker, so the ad just disappeared, which from a user standpoint is great; from the Web sites probably not acceptable, because they rely on these ads being displayed for their benefit. Five Web sites were kind of partially working and one completely died. So a more interesting policy I think is the send after read that I described. And there what is interesting is 42 of our Web sites just worked fine with this, so that means the ad never read a global value -- a global piece of information and then communicated on the Internet. In seven cases we saw ads that -- seven cases we saw ads that were trying to send data that they had read. And in one case -- so we wrote an ad blocker in those cases. And in one case the behavior of the Web sites was not working properly. Yes. >>: Was it data that they actually read that they tried to send back, or just the fact that they had ->> Jan Vitek: This is just a fact that they had. So a better -- so you sort of imagine since we're keeping track of the computational history, we could do better than that. This is just the simple-minded if you've read, we're not going to let you write. >>: So if [inaudible] Google Analytics, what it does, it seems like it's included in many, many Web sites. I'm curious if it violates this policy. >> Jan Vitek: So there's some things that we -- so I don't remember about Google Analytics, but I remember there is some cases where there were things that were -- that we had to just white list and say, yeah, sure, we're not -- we're loading this and -- because part -- part of it comes from the source, where you got the data. And some Web sites use other servers for their source and we would treat their own code as untrusted, so there's some issues there. Lastly, I want to say performance-wise, performance-wise the overheads of doing this are mostly in the 11 and 13 percent range. And of course there is one site here which runs a 106 slower, is two times slower. And why? Well, because most of it is run through eval. Okay? So the only thing it's doing, it's creating code and evaling it. And since -- and this is trusted code run by the trusted part of the Web site. But, as I said, our policy is all evals are considered evil and we -- that's why we get the massive slowdown. So -- yeah. >>: So it seems like -- so this overhead, what policy? >> Jan Vitek: Yeah, right. What policy was it? This was probably the empty policy we were looking at the logging and just overhead of keeping track of the histories. I don't think it was evaluating the actual policies themselves. Yeah. >>: I think my -- going back to the previous slide, my first reaction is that if you compare this to [inaudible] these are fairly low overheads [inaudible] if you compare this to browser based, it's limitation and enforcement of policies, this is quite high because we've seen overheads and ad space [inaudible] to 1 percent. >> Jan Vitek: You get a lot -- so I think it is high for -- there's potentially two things to say. One is we keep a lot of data, so it's doing quite a lot of actual recording. Secondly, we haven't optimized it at all. So I -- I think all I want to say with this is Web sites that are not eval based entirely don't slow down to a crawl. And if you're doing only evals -- so this is really the worst pathological case where we record everything and you have a 2X slowdown. So that gives you a range for naive implementation. This is what you get. Performance was not what we were after, so I don't want to make too much of a point of these numbers. So to conclude the talk, let's say there's different ways to do security for JavaScript. You can try to filter the text. You can try to rewrite, or you can try to integrate yourself in the browser. And what we're sort of arguing is the integration in the browser is the safest because that is where you have all the information, you can't be tricked by parsing errors, you really are in control of what's going. You believe that delimited histories are quite nice and powerful, and there's more things that we believe we could do. For instance, if we combine them with some static analysis, we believe we could get information flow out of them. And revocation is an interesting mechanism because it allows us to speculate over trust. We can say, well, we'll trust you, and if it turns out that we shouldn't have, we can undo what we -- we can take that back. So this work was done by these fine gentlemen. So Brian, who was at Purdue until recently, Christian Hammer and Gregor Richards, which some of you have known. And that's what I had to say today. >> Ben Livshits: [inaudible] [applause] >>: I'm curious, have you looked at all of what the information that's going back was? It seems like this would be a nice mechanism that you could just make available to people in general to find out what kind of privacy stuff is leaking from their Web sites. But you don't have to provoke ->> Jan Vitek: Yeah, you could just sort of say, oh, now that we know that you communicated, we can look at the history and trace that info. Because we have it all provenance encapsulated there. No, we haven't done that, but it's a ->>: [inaudible] even if you had to white list these things, I mean, it'd be useful to see what was going through there, right? >> Jan Vitek: A lot -- I suspect in our evaluation a lot of the broken cases are false conflicts, right? You read something, but that's not what you send out. And we just didn't carefully enough analyze this to check that there wasn't [inaudible]. So the false -- our false positive rate is probably unacceptable at this level in some sense. >>: One thing that Microsoft has had to deal with over the years is the degree to which any leaked information -- so there was a big stink about the Media Player where it was sending back two different pieces of information to two different sort of sources, that when you combine the two, you can figure out what the person's movie viewing history was. And it was a mistake. There was no intention to sort of correlate to, but somebody, some privacy guy, figured this out and it caused a lot of [inaudible] and we changed our policy, which is probably good. But, you know, one thing about the browsers is that there's all this JavaScript running on every Web site you visit that's collecting all this data, and people now just have no clue about how much information they're giving out, you know, Web source. And I think ->> Jan Vitek: The lack of isolation in JavaScript means that, you know, even an ad can potentially get at data that it shouldn't. So you can trust CNN to some extent. All of the other sites, you've never heard of them, right? >>: Maybe that space, if you really want [inaudible] is to look at the quantitative information from [inaudible] that's been out for quite a while. [inaudible] build a utility that would say, well, this site is leaking 27 bits whereas this site is only leaking two bits. And that could be used as a little, you know, browser plug that would sort of say, well, you know, maybe you take that into consideration. >> Jan Vitek: Well, yeah, yeah. Okay. So that's exactly where that started. So the NSF grant that funded this work was about can we find -- information -- you know, information flow doesn't work. It's useless. We know that. You can't program in it because even checking my password is leaking a bit. But it's only leaking a bit, right? So we should be able to -- so that was the idea. And, you know, this is where we are right now. So, as I said, work in progress. Yes. >>: Definitely valuable looking at the user input and whether that's then being translated [inaudible]. >> Ben Livshits: Okay. All right. Thank you. [applause]