 All right, how do we impersonate people on WebSockets, and how do we fix that? I'm Tom, and, oh, well, that'll work, oh, that's fine, okay. I'm going to be using two open source libraries to demo this. The first one is Together.js, which is from Mozilla. It lets you do collaboration on web pages in real time, and then the other one for the WebSocket server. I'm going to be using a gem called Rubame. I picked it just because it was easy to use, and for the demo that's really all I care about. I should say that this is not like a, you know, a hack. This is a well-documented consideration, security consideration in WebSocket RFC. WebSockets don't provide client authentication. So it's the developer's responsibility to do that. And so for this demo, I've created two repositories. One is a Rack Web App, which has, you know, simple login and registration. Users ActiveRecord to store the user records. And then I've got, using that Rubame gem, I've got a hub for the WebSocket server. Together.js comes with a node server, and the same properties apply, whether you're using Mozilla's node server or this Ruby WebSocket server. So it turns out, for Together.js, it's really easy to do this demo to impersonate. You can do it in two lines of code. And so I'll do that. So there's Alice. There's Bob. And that's me. And so I'm going to go there and then see if I can shrink myself. All right, excellent. So, oh, well, first, before I do that, I should probably show how this thing works. And make sure my servers are running. That would be good. So there's my Web server. There's my socket server. Let's just restart it. Let's refresh everybody. So, all right, so Bob's working, Alice is working. This must be fascinating to watch me do this. All right, there we go. Okay, so Alice moves around. You can see on the other two, Bob and, oops, I was hoping that wouldn't happen. We're going to do a hard reboot. How's that? All right, yeah, this is like the Millennium Falcon if this thing stays together. All right, okay, so Alice moves around, Bob moves around, and here's Tom with the weather moves around. I'm going to be the attacker. And so, you know, the purpose is we don't want peers to be faked out and associate actions with people that are not. So, and together JS, not only do you have mouse movements being relayed to everyone in the group, but you also have chat ability. So you don't want people impersonating during chat, and we'll use that as a test. So let's get our session here. And then we just do s.client ID. And I can look in my JavaScript console to see the client IDs passed by and decide who I want to impersonate. So I'm going to impersonate Bob. So all I have to do is set this to Bob's ID. Oops, what did I do? Let's try that again. All right, so let's see now when I move around and my browser, you can see the other two people think I'm Bob, because all the messages that they're getting from me are using Bob's client ID that's set by the together JS browser library. So if I increase my screen, oops, so what's going on here? All right, let's do that. All right, so waiting for the, oh, you know what? Well, that's going to show a chat, but I don't see it popped up here. All right, we'll leave the chat out for now for some reason. I don't see the chat UI. OK, so the explanation is simple. Together JS doesn't know what web app is using it. So it has to assign its own client IDs. And so what we need to do is we need to, the web app, we need to use the web app's IDs instead of together JS, then we need to do some kind of verification on the socket server to make sure that people aren't impersonating each other. So I'm going to go back to the presentation. Heroku has a WebSocket authentication page where they say, well, you know, if you've got your web app and your WebSocket server on separate servers, it can make it using headers, you know, whether they be session headers or whatever, difficult or impossible to use. And so instead they present an alternative which is to use a ticket system, but I think that this ticket system is problematic because if they are on different servers, then you have this potential blocking situation where the WebSocket server, which is a real-time server, has to talk to the web app to verify the ticket. If they're on the same server, then you're just duplicating code, which is already being done and rack session cookie. So to solve this problem, we are going to rely on the headers. We can easily do this by the WebSocket handshake, gives us all the headers. So we can just get our, look for our TGS session header that we've set. And then for every session variable that we would like to verify, we need to put that there and we need to associate it with the client after we've done the same verification that the rack session cookie stuff does. So as you can see, I've just like copy and pasted stuff from rack session cookie. And so I thought it was important that I add some Ruby to my presentation. So you can see that I'm setting user ID and name, so those things will be verified. And so the reason we're doing user ID is because every message that gets sent attributes a cursor action or a text action with that ID, and the reason we're doing the name or in this case email is because that's the display name. And so we don't want anybody faking the display name. So let's fix this. And so all we got to do here is uncomment this code out that I cleverly commented it out to show the attack. I'll go and restart this. And now everything should be fixed. Get Alice and Bob back. Okay. And then I'm going to go ahead and refresh. Oh, I'm on the wrong. That's my presentation. Okay. So I'm going to refresh. Now I'm going to do that, set my client ID to six. And now if I try to impersonate Bob, it closes my connection and it doesn't get relayed to Alice or Bob. And I can't believe the chat. I didn't show up. Well, anyway, that's it. Thanks for your time.