 Really quickly, we're going to blitz through a lot of the talk today. We had the same talk at Black Hat with about 20 minutes more and didn't get a chance to cover everything in depth. So we might talk a little bit quickly. Really quickly, to go through the agenda, we're going to do who we are, what we do, what the talk's about, and why we actually care. We're going to touch on the background of timing attacks a little bit, and then we're going to start looking at timing more as we care about it. So as a channel for attacking networks, we look at timing as its own vector. We look at some of its privacy implications or privacy implications, just so that we can introduce a new acronym or make it more popular because there aren't enough of those going around. So we look at cross-site request timing. Then we'll add a D just to make it distributed, cross-site request timing, and then we'll go into questions and conclusion. So really quickly, Sense Post is a small computer security company based out of South Africa. We were formed way back in 2000, so it's quite a bit in internet years. Our analysts have written a few papers, spoken at a few conferences, so we've done Black Hat Def Con for about six years in a row now. Our guys have written in a few books, showing that the publishing industry is doomed, and we've done a little bit of training. Most of our time we spent preparing for this talk was just to pull these two Simpsonized me characters, so that's Marco down there and me next to him. Both of us just researchers at Sense Post, and down here we've got the mandatory blog, so if you've got nothing to do, go visit us online. So really quickly, what this talk is about other than timing and why you should care or who should care. If you're a developer, something that's interesting is that we've been protecting against info leakage for a long time, and we might not notice how timing is leaking information. If your pen tester is something that you'll pick up from all of the examples and demos, is that you could be missing huge attack targets, huge vectors just because you're not paying attention to it, and we're hoping that'll change going forward. And if you like new acronyms, you can start using XSRT and DXSRT when you hand in your pen test reports. So before we actually get into the nitty gritty of our tool and the techniques that we've got, we thought we'd give a very brief background into timing attacks and where they sit in terms of attacks against software and hardware. So basically, side-channel attacks, if we step even further back, have got this long and illustrious history against computing systems. And two of the very common hardware-based attacks are of course power analysis and EM emission analysis. But those are very specifically against hardware. And if we're looking at side-channel attacks against software, one of the attacks that crops up very often becomes timing attacks. Next slide. So in the traditional sense, timing attacks are generally used in crypt analysis, right? So the guys that are trying to break algorithms are trying to expose weaknesses in various algorithms. And timing attacks are remarkably efficient at this because they don't attack the math behind the crypto. They're attacking the implementation. So over the past couple of years, there have been a bunch of papers. We've listed four here. There's lots more. But these four are kind of the seminal papers for timing attacks against crypto. We started off with local attacks against RSA. That moved to attacks over the network, deriving RSA keys over the network. There were weaknesses that Daniel Bernstein showed in AES. And then finally, Clive Percival just two years ago showed timing attacks, again, local, but this time on hyperthreaded processes. So if we move away from crypt analysis, what we find on the web is actually there's not a lot of stuff to be had in terms of timing attacks. As long ago as 2000, Felton and Schneider had a paper in which they showed that there were various timing attacks that could be conducted, but they focused mostly on privacy and users' privacy concerns. So two of the attacks of the four that they had, two of them are relatively interesting for us. The one was a browser cache snooping attack. So basically the idea there was through JavaScript they could measure load times of pages and based on that load time they could determine whether you'd already visited that page in the past given it was in your cache. So there was a privacy implication there. They also had another attack where they used a Java applet to make DNS requests. Based on the timing of those DNS requests, again, they could snoop on your DNS cache determine if you had made that request somewhat previously. But if we move a little forward, we get to the slide that I titled in this entire presentation. I think it's fairly punny, so feel free to laugh. I call it Web Timepoint 0. You can grow in as well, feel free. It is that bad. Last year we had two papers at Black Hat by Grossman and Nitzel Kowski and also by Spy Dynamics. And basically those guys all released JavaScript-based port scanners. And although they weren't explicit timing attacks that they used, the tools used an implicit timing attack to gather information. So one of the legs of their tool was basically if you tried to make a connection to a site or to a host on a port and that connection timed out, you could infer certain information about that host. And that implicitly is a timing attack, right? You don't know that that port is actually closed, but based on a timeout you're saying, we're going to infer that there's nothing there. And then a little earlier this year, a couple of guys from Stanford released a paper where they explicitly brought timing attacks to the internet, to the web. So they were conducting timing attacks against websites to see what information they could derive. And it was quite interesting. What they found was that you could split them into two categories. The first was direct timing attacks. In a direct timing attack, the attacker would make a request to a site based on the time of the response and information. So one of the aspects they looked at was, for instance, you have these picture gallery software where users have galleries and they can mark some of them as private, some of them as public. And based on the length of time that it took to build the response when you try to view a user's gallery, you could determine how many galleries that user had, even if they were marked private. So it's a basic timing attack, but it serves that purpose. One of the others that we'll get to a little later is inferring the validity of a username based on the time that your request took to come back. And the second point that they had was cross-site timing, which we'll talk about a little. This is pretty interesting. What they found was you could send a browser or a victim JavaScript from your own malicious website. And then based on that JavaScript would conduct or would issue requests against third-party sites and based on the response of those, or the timing of the response of those, you could infer whether that victim was logged into third-party sites and so on. So that cross-site timing, we believe is quite an interesting field to look at. Okay, so now that the background's done, we're going to take a look at when you pin testing. Okay, one of the things that comes up is you quite clearly need to establish a good communication channel with the box that you're attacking. Okay, so we're going to take a quick look, a quick progression at some remote command execution attacks. You find in the old days there were tons of applications vulnerable if you can bring this up on screen reasonably. Okay, and so if we take a look at this application, this is a pretty straightforward command injection attack, allows you to put in an IP and instead we're going to tell it to also run our command. Okay, and in this case, what's clear is this application itself gives us the channel we need to get our data out of the network. Okay, so you'll notice whatever we do, the app comes back and the app gives us whatever it is we need to know. You don't see so much of that anymore, mainly because you don't see so many applications written by sysadmins anymore. Okay, instead what you find is lots of applications making trivial SQL injection mistakes. Okay, so if we take a really quick example of a SQL injection problem, you'll find that again with SQL injection you sometimes find yourself lucky enough that you find a SQL query that actually returns results to you. Okay, and if it's going to return results to you, then you're fully able to use the channel itself to start to get information back. So what I'm doing here is just Union Select name from sysobjects and what you should find is that your SQL query should concatenate and again, you're able to use the channel itself to start to get information back. Okay, this would be perfect except it doesn't occasionally that avenue isn't open to you. You often find that in the past, through completely poor firewalling, you could actually run your attack and then have the victim box send a shell all the way back to you. Okay, again, it's a total pleasure. You don't need to do a lot of work. You've got your channel with the box. Okay, so the question is what happens when things start getting a little harder? A little while back, we came up against a web application. It was actually just the search box of a web application that had code similar to the pseudocode sitting behind it. Okay, and what you'll find if you look at the pseudocode is that a regular expression search is being done with input that the user gives it without the user input being saved at all. Okay, so it basically gives you a chance to use malicious input which then gets passed to this backend regular expression. So it expects a move or it expects something else, and instead what we do is use a regular expression for eval and we throw that into our browser. Okay, so what you'll notice here, we're just throwing in the uname command and uname possibly ran, but there's no way for us to get feedback to know exactly what happened. Okay, in our example, that box was tightly firewalled so we found ourselves with no channel at all. What you did find though is that you're able to, instead of just asking it for a name, tell it to sleep 10 seconds. Okay, and what you should see down here is that the browser now hangs as this thing sleeps 10 seconds. Okay, which puts us in an interesting position. We're now able to get feedback on our command as it executed on the server. So instead of just telling it to sleep 10 seconds, we actually figure out that we're able to make our embedded command longer. Okay, so exactly the same way we said sleep 10, we're now telling Perl to call system to call sleep 10, which seems a little contrived, but actually the reason we're doing it is because we want the output of our sleep to go inside of Perl so that we can start mangling it on the remote system. Okay, what you'll find is this quickly leads you to much, much more complex Perl, and what you see down here is us saying run the command uname, then take the first character for uname, find out what it is or what its ordinal value is, and then sleep its ordinal value. Okay, so then we can say sleep the first character, sleep the second character, sleep the third character, and we should be able to get the results of our input, should be able to get the results of our command. Okay, so if I could get control of my presentation again. Okay, this leaves us with something like this. Okay, a script that we run, and you can see it slept 83 seconds, which gives us the S, 117 seconds for the U, 110 seconds for the N. It's painful, but you will find that you get the result sonnoss coming back eventually. Now clearly this has problems. Does anyone know the biggest problem with it? Sorry. Network delays for sure, and the second one, which is a lot more important, our analysts kept falling asleep while using this attack. Okay, so the results of that uname would have taken about 8 minutes, and if there were network delays, we were screwed. Okay, and that's because we were a little bit stupid. So we were sleeping the ordinal, we were sleeping 65 seconds to get the A, where with slightly more complex pull, we could break that A down into a string of birds, and then if it was a zero, sleep zero, and if it's a one, sleep one, and that way at the most, you're going to take 8 seconds to get back a single bite. So at the time, we threw it into a quick script that we cunningly called One Time. Okay, we're not really good at naming stuff. Okay, and basically you told One Time, run this command, and the two says, every time you see a one, sleep for two seconds, and every time you see a zero, sleep for zero seconds, and what you should find is using this, you can send whichever command you want to your target server, and you should get your results coming back purely via timing. Okay, we could wait for this thing to spell out Linux, but at this point we tight on time, so you're going to have to take my word for it. It's going all the way for Linux. Okay, I'll leave it after the end. Okay, but the concept should be pretty straightforward. At this point, we're making requests, timing how long it comes back, and able to infer whatever we need to from there. Okay, SQL injection, there was a presentation earlier today, and we're going to touch on some of that stuff, but you'll find that with SQL injection, in the past there was the possibility that actually you'd have, you'd be able to use the same channel also. So, for example, we could have done execmaster.xp, command shell, echo, Defcon, greater than C, InetPub, root, backslash, dc.html. Okay, and if that goes through, we should be able to go to the box. If my spelling was correct, we should be able to go dc.html, and we should be able to use the box as our channel again. Okay, but like we said, you don't get that happening much anymore. Okay, and oftentimes, you'll find that your SQL server doesn't necessarily come back to you. So, one of the problems you have when you're pen testing or when you're breaking into boxes is you need to know whether your command executed or not. Okay, and so often what people will do is they'll try to get their target to come back and touch them somehow, as kinky as that sounds. Okay, so either via Ping or SMB or Netcat, you're going to try to elicit a response that you can measure. So, what people figured out was that here again, you are in the position to use some sort of rudimentary timing. So, instead of telling it to create a file, we could have told it to ping itself 20 times. Okay, if I could type, I would tell it to ping itself 20 times. And then again, based on how long it took, we'd be able to say something that we did definitely had an effect on the server. Okay, something else that's interesting is that you could tell it to NSLookup something. Okay, because if you tell it to NSLookup, one of the interesting properties is that with NSLookup, even if you don't directly talk to its DNS server, its DNS server will ask its parent, it'll follow its DNS tree, and at some point, something will come to your name server. Okay, so you XP on it, you ask for moomoo.sensepost.com, and then you watch your name server to see if someone requested moomoo.sensepost.com. Okay, and this obviously becomes an interesting attack possibility for us, so it's something that we figured would be worth chasing. So, when we've come across this particular problem in past assessments, typically what we did was someone hold out a cmd.exe reference manual and we'd start digging through it for appropriate commands that we could use. And the one that always comes up is the for loop. So, for instance, what we can do is construct a really bad attempt at a DNS tunnel simply through cmd.exe. So, what we've got is, again, our vulnerable website, and this line that I'm going to cut in paste here is, give me that. So, this line that I'm going to cut in paste here is basically a piece of cmd.exe script. It's going to execute the DRR. So, you'll see the DRR on your right-hand side. And for each token, or for each line in that directory, it breaks it up into tokens based on spaces, and then it conducts an NSLOOKUP on basically the first token to our domain, which is sensepost.com. So, let's attempt that. What I've got to show you that everything is actually, in fact, sending DNS requests is a terminal here. We've got TCP dump running. So, you will see the request coming through. All right, all going well. What we'll see on this side are blar.txt.sensepost.com. And basically, we'll get that file listing, boot.ini and so on. And this is a little bit effective. We can get a basic idea of what's happening, but there are clearly problems with this approach. So, we'll let that thing run. And what this process works for is for small pieces of data, so file names. But where it breaks are on other things. So, if your file names contain spaces, the script will break. If you've got anything binary, that script's going to break. And also, if there's anything that you're trying to extract, it's over 255 characters, it's going to break. The reason for that, domain names can't be longer than 255 characters. So, clearly, we needed to think up a better way to do this. And just to rehash that, what we've got is a SQL injection point. So, we're executing code within a database, and we've got a method of extracting DNS queries. So, this naturally led us to a tool we call Squeezer. It's inspired by the Sec 1 SQL Injector. And what it gives you is basically a very simple shell that allows you to pull server-side data into tables. So, you could, for instance, execute commands, copy files, or execute SQL queries on the SQL server itself and dump that stuff into an intermediate table. And then what it also provides you with is, in this case, a DNS channel to extract that information. So, SQL gives you a bunch of ways to get data into an intermediate table, and it also can extract it by a DNS and one important other. Squeezer gives us binary-safe transport. We do conversions of stuff to Hex. So, basically, if you want to copy out binary files, that's all possible if you want to copy out or if you want to do a command execution and the output of those commands contains characters that are not part of DNS domain names. That's also fine. It also gives us a reliable transport mechanism so we can implement file copy over DNS. DNS typically is UDP right, and that's best effort, but Squeezer does a layer on top of that to give us reliability. The requirements for Squeezer, if you want to run it, you're going to need Ruby. You just need a standard Ruby 1.84. Install should be good, no extra modules required. We use t-speed dump as a quick hack to get hold of those DNS queries. You need access possibly to a DNS server on which to run Squeezer. And the last point there is that you need a fairly large injection point in a vulnerable application. You're going to be asking me how large. We've got various injection strings, but they typically range up to about 600 bytes. So you're trying to do a lot of stuff in t-SQL, and this is one of the drawbacks. So very quickly, this is how we do things. We send an initial HTTP request. What that does is it builds that intermediate table somehow. And in the case I'll show you that table's built with command execution. And then for each row, we've got a piece of t-SQL that takes each row in that database. It breaks it up into fixed size blocks, which will fit into a domain name. They are the requisite length. It converts that to hex. We add a header to that, and we initiate a DNS lookup. And then on the client side with Squeezer, we've just got t-speed dump running where we capture that, decode it, and store it in our reliability layer. And then basically the last point there is if blocks are missing, we just re-request them. And in that way, we get our reliability. There's a couple of things to just keep in your mind as you think about Squeezer. The way that we get data into the tables is not related to the way that we get it out. So I can use... We'll talk about other channels, but DNS is one channel to extract information. We'll also see timing as a channel there. But those are not related to putting data into the intermediate table. So I can combine my command execution with whatever channel I want. The second point is that by default we use XPCMD shell plus NS lookup to implement our DNS lookups. But often that stored proc isn't available or you don't have permissions and so on. And so the rhetorical question that I pose here, can we cause DNS requests to be initiated? Otherwise, I'm asking the question so I guess there's an answer. The answer is, of course. And there are a bunch of stored procs that'll happily do this for us. The one that we decided on was get file details. This is a stored proc that'll take a UNC path and based on that we can initiate lookups. So to show you, this is the permissions on that particular stored proc. As you can see, all that's required is execute permissions. You don't have to be essay at all. This is an example of a path that we might pass into get file details. You'll see it's a UNC path. We've got this header and then there's this fairly long hex string.senseface.com and a share. And what that does is it forces get file details to attempt to first look up this particular machine. And because of the way DNS works, of course, this request will eventually wind up with us. So we're going to do a very small demo of Squeezer to give you an idea of the test setup before we carry on. There's an attacker. He's going to be sending inbound TCP on port 80 to a vulnerable web server which passes SQL queries to back in database. But nothing can come out from that firewall. So we can't get... Well, for the sake of this example, assume you can't get error messages, you can't get Netcat Tunnels and all of that stuff. All we've got are DNS requests. Come here. Did you all see that? I'll try it again. In case you're sleeping, what we've got is some very silly ASCII Art animation. I figure that's about... That took us the other half of our time. Yeah. Okay. So what we've got with Squeezer is a simple config file. In the config file, there's a typical injection type stuff. So we'd specify a target host, we'd specify a target URL, HTTP methods to use, vulnerable parameters and all of that stuff. And based on this config file, Squeezer will construct the injection requests and send them off for us. We are a Ruby file. So as I said, Squeezer's got a couple of modes that it supports. The one is command execution mode, and that's what we're in at the moment. To give you an idea, again, we've got TCP dump running here. That's just all good. We'll switch back. So what I'm going to do is execute a simple directory listing in C drive, and you'll see our TCP dump that those requests are starting to come through. Again, these are all hexified, so it's kind of hard to interpret. But Squeezer will obviously decode all of that stuff for you with the output. So we can also break this up into blocks by default Squeezer's only requesting the line at a time, but we can request five lines at a time, and so on. And it supports lots of other funkiness. The one thing that I want to show you before we move on is it's also got a SQL extraction mode. So we've got a command mode where we can execute commands on the server. We've got a SQL extraction mode which will pull out various information from the SQL database. So the one is we've got a pre-built query that will extract table names. The interesting thing about this particular mode, the SQL mode, is that it uses the GetFileDetails stored proc, and you'll see that with the GetFileDetails stored proc we've got five requests come through for each domain name instead of the single one with NSLookup. So it's slower, and because UNC pods are shorter than domain names we can also extract less information at a time. But it is effective, and what we've got here are a list of the tables in the database. It's somewhat similar to Patrick Carlson's talk earlier. I don't know how many of you guys saw that. He's also got a similar kind of idea for extracting database schema. What Squeezer does support is it allows you to also execute arbitrary queries against the database. If you find out that there's a user's table with a password and a username column you can construct your own query quite easily. The toy example I'll give here is here's a query that will extract all of the columns in a particular table, the table sqcmd. That's basically the format of your arbitrary query is a column name, table names, and a where clause. It's fairly rudimentary, but what we'll see is that it does work. There's the first arbitrary data that we can extract. It's a column name of data, and so on. That's basically what Squeezer gives us at this point. We'll talk a little bit now about the other stuff. At this point you should be saying, what's all this DNS stuff? You were told that the stuff's about timing. The DNS stuff is cool. It gives us a channel of getting stuff out using DNS, but there is a reason we bring it up. That's because SQL Server also supports this wait for delay function. There's a few injection tools out there, SQL Injector, PowerShell, SQL Ninja, SQL Brute that try to use wait for delay, but most of them use them as a sort of Boolean operator. They do a M-I-S-A if I am wait for delay 10, if I'm not wait for zero. If you consider that what we've learned from Squeezer 1 and consider what we figured out from one-time.py, you can pretty quickly put two and two together and say, we can do the same thing on SQL Server. Let's execute our commands, let's dump it into a table on the database, and then let's use the same sleep commands to decide how we read our output. This gives us another chance to check a little bit of how lamely I was doing this. The first thing we came up with was something else cunningly named AnotherTime.py, and what AnotherTime did was you gave it all of your details for the SQL injection point, and then you just told it the command that you actually wanted to get back. Okay, and pretty simply, this is doing what we discussed. It's going to run your command on the target server and then sleep for two seconds for one, sleep zero seconds for zero, and at this point you're going to start to get your information back from SQL Server, but purely using timing as your vector. Okay, so where the previous one used DNS, in this case you assume even DNS can't come back to you, you're just going to get your data out using timing. Okay, I'm going to kill this really quickly. Does anyone know where this is going to go wrong? It's not our guy sleeping. Again, the problem is going to be potential latency on the line, which brings you to Marco's creveness. Okay, so when we implemented this in Squeezer, what we figured was actually we need to think about that timing issue a little bit more. So I'm going to give you a brief demo of the way timing works in Squeezer. So what I simply do is I switch my channel from DNS to time, and I can execute, we switch back into command mode, and then we can simply execute a hostname. Now, as Harun said, the problem with sort of specifying static values for, say, a threshold value. So a typical way to approach this would be to say, well, we'll ask the request to pause for two seconds, and anything that comes back over two seconds will take as a one bit, and anything under that will take as a zero bit. But the problem arises, if you get a request that takes 70 seconds, at that point you're not in any position to actually say if that was a zero bit or a one bit, because there's too much, there's too big a differential there, clearly something went wrong. So the approach that we took here was to introduce a calibration mode for the timing channel, and basically within the calibration mode what we do is send out a bunch of samples, sample requests for zero bits and one bits, and there are appropriate delays, and we do a bit of simple stats on that, and what we derive are two landing pads. Now, you'll see that over there, my hostname has come back, it's intranet mh, so the timing channel clearly works, I can simply switch between that and DNS. So to get back to what I was talking about, this thing, this is in the slides if you want, go and check this. It's basically a summary of what I said, but essentially what we get is this thing, we diagram with timings for one bits and zero bits, and so with a bit of simple stats, what we can do is derive two landing pads, one for the zero bit, one for the one bit, and then all we do is if a request lands, or if a request timing lands in one of these landing pads, we'll treat it as either a zero bit or a one bit. If it does not land there, then we can simply discard it. And so by doing that, what we introduce is a measure of control over the timing values that we get back. A couple more things with Squeezer, so just very briefly, we also support the original SQL Injector HTTP error message channel, so that means Squeezer's got three channels, you can get info out via DNS, via timing, and via HTTP error messages, dependent on your circumstances. It also supports file transfer, so you can copy files from a server to your local client, and the third point is H's word, you can just basically keep adding on there. But Squeezer's hopefully written in a way that it's fairly easy to add other modules to it, so if you've got other channels and so on or other modes you'd like to add, it should be pretty simple. Something I'd like to point out at this stage is that Squeezer is MS SQL Server-specific, and that turned out because that's what we conduct our assessments against for the most part. But we believe that most of these techniques should carry over to other databases if they have support for most of those, so DNS requests and a pause, literally you just need a pause function. So you can find out a little more about Squeezer at that website, the stuff's not up there yet, when we get back to South Africa we'll stick it up, but what you can find out, or where you will find Squeezer currently is on our blog, it's posted there. Okay, so I'm going to start talking even faster. Timing as its own vector starts to become interesting when you application pen testing, and it's not just because pen testers want to write down used genetic error messages in their report. Okay, you'll notice that any app that betrays or tells you whether you're a valid user or not is giving away information that's useful as an attacker. Okay, we have all ever been saying this for a really long time, so it's not that common for you to find an application that'll tell you you have an incorrect username or you have an incorrect password, because if we were able to trivially mine usernames on your system, that would be a pretty big deal. It turns out, though, that there's often subtle timing differences for valid user logins when the user exists and when the user doesn't. We just haven't been timing them that often. Okay, you find it particularly prevalent when some sort of hardware token is being used. If there's a round trip time that's needed for a valid user as opposed to an invalid user, it's pretty easy as a remote attacker to say when I put in this name, it took longer because it was going all the way to the hardware security device. Okay, so we spotted this example a little while back during testing. We're obviously not hitting the live site right now, but if you pay really careful attention, you should see that for user Bob Bob, that happens, and for user Marco, whatever, that took a millisecond longer. Okay, so in the example that we were looking at, you basically found yourself in a situation where if you threw a big enough username, if you threw a big enough, sorry, if you threw a big enough username at the target, you were actually in a position to time whether a user existed or not. I can't actually see what I called it. This was called yet another time. Okay, so you take yet another time, you pass it a huge user list, and basically what it does is times how long the login took to come back, and you can see there for user Marco, it figures that took a millisecond longer, it's doing some rounding, but basically it comes back and says that's a valid user while the others were not. Okay, this becomes interesting to us and scary at the same time, because we took a look at a whole bunch of popular web application scanners, and from the little reading that we did, none of them make any mention of ever checking for timing stuff, so they'd happily tell you that you've got a different error message for valid and invalid logins, but if that difference was coming through on a timing channel, most of those scanners would be blind. We've got a web app scanner called Suru. Some of you would know we put it into Suru, but we've actually only put it in after we discovered this, so if you've got another app vendor, you should probably speak to them and have it bolt into the tool, which brings us to another place where timing gets interesting, and that's with privacy or privacy. Okay, so for those of you who know the same origin policy or have heard of the same origin policy, basically it was there to protect you online. It said, if you get scripted from my page, my script shouldn't be able to figure out stuff about what you're doing on some other page. Okay, so the question is, how did Jeremiah and those other clever guys figure out how to do the port scanning coolness, and Mark already told you they used some sort of timing. They said, go fetch this resource and we'll time it, and based on time, we'll figure some stuff out, because it turns out that the same origin policy doesn't really work for timing stuff. So it does allow me to time what's going on on another page, even though the same origin policy is in place. Okay, so after Jeremiah and them came out with port scanning, there was the history hacks where they basically tried to figure out using CSS if you had visited another page or not. In honesty, like Marco said, way back in 2000, Felton had figured some of that stuff out, and basically what he did was, he tried to make a request to Scientology.org, logo.gif, figured it took 80 milliseconds, sent you a Java applet, and if you got it in 10 milliseconds, he said you got it from your cache, so clearly you visited Scientology.org before. Okay, at this point during our testing, we were actually really excited. We thought we invented a new acronym, so we thought we invented cross-site request timing. Unfortunately, Andrew Boatts earlier this year at a conference published it and discussed it, and we did pretty much the same vector as he did, which basically says if you visited LinkedIn or in this case Facebook, and if you made a request for friends.php, if you were logged in, you would get this page, which is a whole bunch of HTML, and if you weren't, you'd get this page, which is a very terse you are not logged in message. Okay, so obviously if I was timing stuff, I'd be able to figure out whether you were logged in or not based on how long that page took to load in your browser. Okay, so really simple, you visit my page, I have you make a request there, and I figure out if you logged into Facebook or not. There's a small problem that needs overcoming, and that's line latency. In South Africa, it takes us about a minute anyway to surf to anything, and so we needed something to normalize that. So what we do basically is introduce the concept of a base page, so you come to us, we tell you fetch friends.php, but also fetch login.php for example, and based on the ratio of those two pages, we get a latency neutral way of determining whether you are logged in or whether you aren't. The question down there is what about cached pages? We get to handle it simply, so we have you load the pages twice so that we're always getting your timing off your cached page and whether you cache it or not doesn't make a difference to us. Okay, so the quick example we're going to look at here is a webmail system. Okay, I'm going to quickly log into it, and actually this is the trickiest part, webmail sometimes breaks. Okay, so what you've got here is pretty straightforward, one guy logged into webmail, he visits my page, and my JavaScript basically loads two frames. One is the base page, and the other is his inbox, and based on that I say, yep, you are logged into webmail. Okay, and so we can test that and sign him out, and hopefully reloading this page should come back and say, sorry, you're not logged into webmail anymore. Okay, so like the slide says, this is entirely underwhelming because we're now able to tell someone on a web page whether he is or isn't logged into webmail. Okay, but why this is interesting is because we can actually export this information so that an attacker sitting out there on the internet is able to now figure out if the user is or isn't logged in. Okay, so what you're seeing is the request going to a complete stranger saying yes, this guy is logged in or no, he isn't. Okay, so if we summarize all of the things that we've spotted really quickly, you'll see a whole bunch of things starting to converge. Firstly, you have sites on the internet that'll tell you whether a user does exist or not based on timing. Then you've got something worse, is that you can figure out whether a session is valid or not effectively based on timing. And then you get the last bit, which says instead of using my timing, I can use your browser to figure out whether someone's logged in or put time on that. Okay, so really quickly, this allows us to introduce the last part of our acronym, which is distributed cross-site request timing. So basically, if you remember with timing.py, I could determine if a user existed or not. But now with JavaScript, instead of running the Python on my box, I can run it in JavaScript on your box when you visit my web page. Okay, the small problem you have is JavaScript's timer is not granular enough. Fortunately, a little while back, Lars Kinderman found that you could call Java applets directly and it's the trick that Jeremiah and PDP and guys used to get your IP address. So we use the same trick to import Java.Language.system's nanotimer. So we get a much higher res timer inside our script. Proof is that's a small number and that's a bigger number. Okay, but effectively what it allows us to do is have you visit us. We send you JavaScript. You run JavaScript trying to run a whole bunch of brute force attacks based on timing. And once you get a success, you come back and tell us whether it succeeds or not. Okay, which brings us to this last screen, which if you look at what's going on down here, we basically load, so some guy visits us. We send down this JavaScript and basically all this JavaScript is doing is trying a whole bunch of usernames in that user's browser and as soon as it actually finds valid usernames, it then comes back to us and says, hey, okay, this is going to go horribly pale. It's going to come back and say, when I tried user Harun, I actually found that user Harun existed on the system. Okay, so there's username Marco and there's username Harun coming through. Okay, so effectively we're looking at this Vizio here. We either inject our cross-site scripting onto some popular page, get ourself upvoted on Reddit or Slash. A post like Microsoft sucks should go a long way. Guys browse our site. As they get to us, we send them user lists. Okay, and everyone who visits our site becomes our zombie trying to log into this victim application. As soon as they find a user that exists based on timing, they send the success back to us. Effectively we've done nothing. You can't shut them down. You're trying to shut down the internet. They come back to us with valid users or valid sessions. Okay, so really quickly in conclusion, if you're developing, you need to make sure that you're not throwing information away via silly timing channels. You need to look at cross-site request forgery because lots of this uses the same sort of thinking. Network admins. You need to re-look at least privilege. Figure out whether your SQL server really needs to make DNS requests at all to stop the DNS channel. You need to be watching your network to look for timing stuff going through. If you're pen testing, if you're a researcher, some interesting area for research is going to be injecting fake headers into XSS because if you can do that, this whole attack goes into a whole different space. You can basically brute session IDs, the worlds you're oyster. Grab a copy of Squeezer from our blog. Send us feedback. Make sure we make Marko work on it. He doesn't have a social life anyway. Add modules. It's true. Add modules. Drop us feedback. Visit us on the blog. We don't get enough mail, so spam us anytime. And if you've got questions, we'll be down in the question room.