The Good Parts of JavaScript and the Web The Good Parts of JavaScript and the Web

Identifying Security Vulnerabilities - Solution

Check out a free preview of the full The Good Parts of JavaScript and the Web course:
The "Identifying Security Vulnerabilities - Solution" Lesson is part of the full, The Good Parts of JavaScript and the Web course featured in this preview video. Here's what you'd learn in this lesson:

Doug walks through the solution for patching security vulnerabilities on the array object in the vector() function.

Get Unlimited Access Now

Transcript from the "Identifying Security Vulnerabilities - Solution" Lesson

[00:00:00]
>> [MUSIC]

[00:00:03]
>> Douglas: So let's look at the attack that we've just outlined. So we've got a global variable, I'm calling it stash. Someone suggested a global variable and there it is. Then we will store into push a function which will take this and store it in that global variable. And then in order to get to this function to be executed, you call append.

[00:00:27] append will call the push, and because this is a method invocation, this will be bound to the array.
>> Douglas: So this attack exploits several confusions that are in this language. The principle confusion is, there are not arrays in this language. They don't behave like arrays in other languages.

[00:00:53] But we think that we do and even the people who built JavaScript engines, when they were shown this problem, they know how arrays in JavaScript work, at least better than anybody. And they couldn't see it because everybody thinks this is what arrays do. So when you have this I here, even though we know we don't have ints in this language, everybody thinks it's an int, right?

[00:01:15] So it doesn't occur to anybody that this could be anything else. But it's just a key, right? That in fact what JavaScript will do is it will take whatever you pass in. If it's not a string here it will turn it into a string.
>> Douglas: That's what JavaScript does but that's not how we think a programming language should behave, right?

[00:01:40] And when you have a system that does something other than what we expect, you get confusion and confusion can lead to security exploits, as in this case. The other source of this problem is that all variable bindings in the language are static, because functions scope, if array is defined there then this one will be bound to that one.

[00:02:04] It's predictable with the exception of this. This is bound dynamically. And so it's much harder to reason about what the value of this is gonna be at any instant because it can be different depending on where it's called and when it's called. And that turns out, if you're thinking about the security of systems or the reliability of systems, to be a bad thing.

[00:02:30] That's why I prefer to try to figure out ways of programming in this language that don't depend on this since this tends to be unreliable. So what you think of that problem, is that interesting? So, now that you understand the attack, how would you correct this code to prevent that attack from happening?

[00:02:50] Yeah?
>> Speaker 2: Just to give credit, Vincent in the chat room I think he had got this a little bit before we did, but then he's saying to fix it, he would just force the (i) to an int, like +i.
>> Douglas: That's exactly right. I would do that too.

[00:03:05] So, I would put a +i here. What that accomplishes is is plus will turn the string into a number. If you pass in a number, it just stays a number so it's a no op. But if you pass in the word push, it will turn it into a number.

[00:03:26] What number does push turn into? NaN, and so then turn NaN into a string. So, we'll be storing v at array.NaN which is stupid but at least it's not push. Right, so we get around that. The other thing we could do is not use push, instead use the old fashioned way of assigning to the current length.

[00:03:50] This illustrates another design error in the language that I think something as fundamental as appending to an array should be an operator. It should be something that's just built into the language which can't be corrupted, but it's not. JavaScript allows, and there's also the weird way of about how these get pound.

[00:04:14] So, ordinarily you would when you call push method, you're going to be using the inherited array.prototype.push. But when we assigned our own push property to this object using store, now push is local and so we don't look array.prototype.push. And that again doesn't match most people's mindset about how programming language should work.

[00:04:40] That's probably not the kind of behavior that you want this function to be able to to modify.
>> Douglas: So what do you think of that problem, was that fun, was that interesting?
>> Speaker 3: Yes.
>> Douglas: Sir.
>> Speaker 3: Yeah? Why not just give JavaScript real arrays, is it going to break it?

[00:05:01]
>> Douglas: Absolutely, break it. Yeah, there's code all over the Internet that assumes this terrible behavior
>> Speaker 3: And you can't just say that ECMA 6 is a new standard that has a new.
>> Douglas: I wish, the way, the web is unlike any other platform in that, if you're developing a server, you dictate what software is installed on that at what revision level and so on.

[00:05:30] You've got control over everything happening on the server so you can dictate that stuff. And so you can tolerate breaking changes because you decide when you're going to make the change. But on the web, you have to run with what ever it is that someone's got installed. And if they're running some awful old thing your code is still expected to run on that old thing.

[00:05:51]
>> Speaker 3: So for ECMA 6, they're gonna have to have some new. I'm sorry, I don't how to continue, sorry to, they're gonna have to have a new stuff that can eat ECMA 6, right?
>> Douglas: Right.
>> Speaker 3: So why not create a new thing instead of an array, call it a list.

[00:06:09]
>> Douglas: They could do that, in fact they have added new things in ES6, for example, there's a new thing called a map which behaves like objects should behave. It is more correctly like a hash table and there are new forms for doing that but it doesn't look like this.

[00:06:31] And so it's gonna be very difficult to get people to use it because it doesn't have the syntactic conveniences that this one has
>> Douglas: Yeah, so the-
>> Speaker 3: I know there are good answers for these things, I'm just
>> Douglas: No, I'm not trying to wave it off, I mean, the web is a really, once we make a mistake in a web standard we're stuck with it.

[00:06:55]
>> Speaker 3: [LAUGH]
>> Douglas: And all we can do is pile on more mistakes on top of it, we can't correct any of the stuff that's ever been done [LAUGH] And so working with web standards as you all know is incredibly frustrating because nothing ever gets better, it just gets bigger.

[00:07:12]
>> Speaker 3: They didn't get rid of the blank tag.
>> Douglas: Well, not entirely. I mean you can still write blink and it's not gonna give you headaches anymore, but it's still allowed, it's still building structures in the Dom, it's still there. And in fact, you can write CSS, which will cause the blink to come back to life.

[00:07:30]
>> Speaker 3: [INAUDIBLE] [LAUGH]
>> Douglas: So it's [LAUGH]
>> Speaker 4: Yeah, people have written JavaScript plugins in CSS.
>> Douglas: Yeah, it-
>> Speaker 4: Bring back the geocities page. Bring back the blink.
>> Douglas: Yeah, it's very, very hard to fix the Web. Cuz when something wrong happens, the problem with the wrong things isn't that they're useless, it's that they're dangerous and weird.

[00:07:55] And there are very clever people who will go wow, that's crappy, what can I do with that? And they'll figure it out. They'll take the stupidest thing you ever saw and it now becomes part of some popular library and we can't get rid of it anymore.