[00:00.000 --> 00:07.400] So, yeah, a little bit about me. No one really cares about who the speaker is, so read this [00:07.400 --> 00:14.340] whenever you want. I do podcasting and blogging and shit like that. I am a firm believer in [00:14.340 --> 00:19.400] the wisest man is he that knows that he knows nothing. I am not an expert and I'm quite [00:19.400 --> 00:27.280] happy to admit that I know absolutely nothing. I kind of like edge case stuff. It's kind [00:27.280 --> 00:30.820] of ‑‑ it's freaky. Most people are like, oh, it's just an edge case, no one really [00:30.820 --> 00:35.540] cares. But the edge case stuff, the freaky stuff, the weird stuff kind of really interests [00:35.540 --> 00:40.660] me. It makes me think that's really cool, I should really dive into that. So this is [00:40.660 --> 00:44.840] part of the edge case stuff that people really don't give a shit about. But apparently all [00:44.840 --> 00:47.780] you guys do, otherwise you wouldn't have woken up early to come and see this. [00:49.020 --> 00:54.480] So I'm going to start with a quick warning. This presentation, it contains numbers and [00:54.480 --> 01:01.580] jokes and traces of peanuts. Who has ever seen me give a talk before? So if you had, [01:01.580 --> 01:07.740] you wouldn't be here. Everyone who has seen me give a talk before, I'm sorry, I use the [01:07.740 --> 01:15.320] same jokes every time. So just laugh when everyone else does. Not you, Ed, you have [01:15.320 --> 01:20.300] to stay. So I'm going to give everyone the TLDR on [01:20.300 --> 01:25.560] what I'm going to be talking about today. The goal of this talk is to describe the defensive [01:25.560 --> 01:34.400] uses of HTTP status codes. That sounds really sexy, doesn't it? This is an absolute must [01:34.400 --> 01:43.400] see at DEF CON on a Sunday morning. So back to why are you guys awake again? I'm going [01:43.400 --> 01:47.560] to run through the what, the why, the how, the goals and then we're going to bring it [01:47.560 --> 01:52.120] together and we're going to review what we've covered. So I'm going to try to run through [01:52.120 --> 01:58.260] this reasonably fast so I can get everything in. So let's start with the what. HTTP status [01:58.260 --> 02:04.560] code. Who has never seen an HTTP status code? Yeah, okay, I thought so. So we know what [02:04.560 --> 02:08.980] an HTTP request looks like. We're picking out the specific section. This is the status [02:08.980 --> 02:17.080] code or the response code. The terms are interchangeable depending on how much you had to drink. It's [02:17.080 --> 02:23.560] like a really small little thing every time you make a request or every time you get an [02:23.560 --> 02:27.920] answer from a server. It comes with some kind of status code. No one really cares what they [02:27.920 --> 02:34.500] are. The browser doesn't really tell you what it is, but it's an important feature of the [02:34.500 --> 02:40.260] HTTP standard. What I'm going to show you is a really small detail, but it's a really [02:40.260 --> 02:46.020] big impact. If you don't really pay attention to the status codes, then some bad things [02:46.020 --> 02:51.480] can seriously happen. So a little bit of history on HTTP status codes. This is an RFC. [02:51.480 --> 02:56.700] I'm sure everyone here has read that, right? I couldn't sleep last night. I thought maybe [02:56.700 --> 03:02.480] I should read the RFC again, but yeah, that didn't happen. So there's five main classes [03:02.480 --> 03:07.440] of responses. You get the one, 100, which is the informational stuff. You don't get [03:07.440 --> 03:12.400] to see that very much. You get the 200, which is most of the time success. Your web page [03:12.400 --> 03:16.740] is here. Here is the content. Thank you very much. Please go away. You get the 300, which [03:16.740 --> 03:22.160] is the redirect stuff. You get the 400, which means you fucked up. You get the 500, which [03:22.160 --> 03:28.860] means they fucked up. Simple as that, okay? There's also a wonderful RFC, and this one [03:28.860 --> 03:36.640] is actually worth reading for the 700 codes by John Barton. If you go to his GitHub page, [03:36.640 --> 03:45.300] there's an entire section. I like the meh. I am not a teapot. I specifically like this [03:45.300 --> 03:58.040] one, fucking unicode. So, yeah, there's like 300 of these things. So I have no idea how [03:58.040 --> 04:03.480] they squeezed it all into the 700 range, because there's 300 of them. These are amazing, and [04:03.480 --> 04:11.520] I have no idea where did the 600 range go? So, yeah, I really hope they accept that RFC [04:11.520 --> 04:15.420] and start implementing that in some stuff. So let's go through the basic stuff. This [04:15.420 --> 04:20.400] is the theory bit. It's boring, and I'm sorry, but this is the theory. So you get the 100 [04:20.400 --> 04:24.680] informationals. You get the 100 continue, switch protocols, processing. As I said, these [04:24.680 --> 04:30.460] are the things you don't get to see very much. Moving into the 200 stuff, it means it worked. [04:30.460 --> 04:35.280] It means it understood. So you're getting a 200 okay, which is most of the web is returning [04:35.420 --> 04:40.120] a 200 okay. You also get some weird stuff that you don't get to see very much, like [04:40.120 --> 04:49.160] 204 no content. Great, thanks for the header. There's also some interesting stuff that isn't [04:49.160 --> 04:55.040] supported by Apache. Low on storage space. I've never seen that one returned by a server, [04:55.040 --> 05:03.420] but I'd really like it. But they're not supported by Apache. You get the 300 redirection stuff. [05:03.420 --> 05:08.360] So most people know what a 301 is, what a 302 is. 300 you don't get to see very much. [05:08.360 --> 05:15.860] Multiple choices. It's like an exam. Tick boxes or something. 304 not modified as well [05:15.860 --> 05:19.780] is something you see quite a lot if you're looking at the way data flows backwards and [05:19.780 --> 05:24.140] forwards. You also get some weird stuff that isn't used anymore, like switch proxy. Sounds [05:24.140 --> 05:27.980] like fun. Use proxy is also interesting. If you return a proxy setting in the location [05:27.980 --> 05:32.780] header, it says, oh, you should use this proxy for your communications. I'm sure no one would [05:32.780 --> 05:39.760] use that for malicious purposes in any way. So moving on to the 400, which is the you [05:39.760 --> 05:48.240] fucked up section. So forbidden, unauthorized, usual stuff. 404 not found being quite a reasonable [05:48.240 --> 05:54.360] response for I search on random crap on the Internet. And then you get some interesting [05:54.360 --> 05:59.680] stuff. I quite like the 407 proxy authentication required. I'll talk a little bit more about [05:59.680 --> 06:05.240] that later on. Interesting ways to do some malicious stuff with that. This is a long [06:05.240 --> 06:13.540] list. I quite like the 418. I'm a teapot. It's only in April Fools and quite a lot of [06:13.540 --> 06:18.320] web servers don't implement it, but this is interesting. It's like I am indeed a teapot. [06:20.860 --> 06:26.380] Moving into the 500 stuff, internal server error, which is unfortunately used quite a [06:26.380 --> 06:32.280] lot for SQL injection. Oh, I got a 500 error. That must be a SQL injection trigger. You [06:32.280 --> 06:38.340] don't get to see it very much if you're not abusing websites. Still, it's interesting. [06:38.340 --> 06:44.640] Wow, that's a lot of fucking numbers. All right. So everyone here knows every single [06:44.640 --> 06:50.500] HTTP response code now, right? Great. I don't have to talk about them anymore. So why are [06:50.500 --> 06:55.960] we doing this? It started off as a little idea. I read a couple of books. I do that [06:55.960 --> 07:02.880] on occasion. I don't know if any of the authors are in the room. I'm really sorry. I'm plagiarizing [07:02.880 --> 07:08.460] your work. And I started to have a little think, what can we do with that? We can do [07:08.460 --> 07:15.400] some interesting stuff with scanners. And screwing with script kitties is a hobby. It's [07:15.400 --> 07:21.620] more of a life calling. And that sounds like fun. That sounds like something I want to [07:21.620 --> 07:26.740] do at a weekend. And I started to look around and there's a guy that everyone follows on [07:26.740 --> 07:33.700] Twitter, right? The Grug. He's not here because he's drunk, but he should be. He said in one [07:33.700 --> 07:38.000] of his quotes, stop dismissing obscurity as a security feature because unpredictability [07:38.000 --> 07:43.980] in your defense works to your advantage. Well, that's great. We can increase attacker costs [07:44.530 --> 07:51.600] being unpredictable. And we can waste attacker time. We can say that, you know, an attacker [07:51.600 --> 07:56.640] is going to waste three hours attacking a website that should take 15 minutes. Why should [07:56.640 --> 08:00.940] we just stand there and let someone smash us in the face? We should be more active on [08:00.940 --> 08:06.980] our defense. So there's some prior art. I kind of looked around. I was trying to find [08:06.980 --> 08:10.640] who else has talked about this stuff before. Because in my mind, this was just obvious [08:10.640 --> 08:14.840] stuff. I was like, someone's bound to have already implemented this stuff. There was [08:15.100 --> 08:22.800] a 2004 talk by Harun Mir and the guys at SensePost where they mentioned using HTTP status codes [08:22.800 --> 08:30.260] to slow down attackers. It was one line comment in a slide deck. That was it. Okay. Well, [08:30.260 --> 08:36.340] someone's mentioned it, so there must be more. There was an interesting paper by Gunter Ohlum. [08:36.340 --> 08:40.560] I probably totally mispronounced his name there. There's a PDF where he talks about [08:40.560 --> 08:45.140] stopping automated attack tools. I was like, okay, this must cover it. He covers lots and [08:45.140 --> 08:50.540] lots of stuff, but he doesn't really dig deep into using HTTP status codes to do this stuff. [08:50.540 --> 08:58.640] So I carried on, and I was informed, should we say, of a mailing list comment where Ryan [08:58.640 --> 09:05.000] Barnett said that, well, maybe we can reply with a 503 with a retry after header. That [09:05.000 --> 09:08.940] was interesting. I tested it out. It didn't really seem to work, because most scanners [09:08.940 --> 09:13.220] just completely ignore a retry after header. But maybe things have moved on. This was 2006 [09:13.220 --> 09:19.000] when that comment was made. So, yeah, no one seems to have discussed this stuff. So how [09:19.000 --> 09:24.960] are we going to work this in? So browsers have to be as flexible as possible. [09:24.960 --> 09:31.520] You get websites written by kiddies in notepad, and you get professional websites written [09:31.520 --> 09:36.720] in HTML5 with web APIs and SOAP interfaces, and the browser has to be able to support [09:36.720 --> 09:45.320] it all. And this leads to a certain amount of flexibility on how things are understood, [09:45.320 --> 09:50.160] how things are supported, which obviously leads to the dark side. And then, of course, [09:50.160 --> 09:56.300] there's RFCs, which some would say is the dark side. They're more of a guideline, really. [09:56.940 --> 10:00.960] This is the way you should do it, but we're not going to tell you exactly how, so it depends [10:00.960 --> 10:07.660] how drunk you were when you read it. Maybe this makes sense. So, yeah, what could possibly [10:07.660 --> 10:12.320] go wrong? You have 300‑page RFC and people who are going to interpret it, and you implement [10:12.320 --> 10:16.120] it into a piece of software which has to be as flexible as possible, otherwise things [10:16.120 --> 10:18.820] don't work. Things are going to start to go wrong. [10:18.820 --> 10:24.780] So I started to do a little bit of testing. I wanted to restrict myself to the big three. [10:25.040 --> 10:30.300] Internet Explorer, Chrome, Chromium and Firefox. No? Yes. [10:33.840 --> 10:42.300] Apparently Opera turned really bad, or there's Lynx, but who uses Lynx? One guy uses Lynx. [10:42.320 --> 10:50.320] Welcome to the 20th century. So I wanted to take the easy option on testing, [10:50.320 --> 10:54.200] so I thought, okay, well, there's man in the middle proxy. It's a Python‑based system [10:54.200 --> 10:58.700] for man in the middling HTTP connections. It allows you to set up this really interesting [10:58.700 --> 11:02.380] reverse proxy. It's all script‑based and it does all the work for you. You just write [11:02.380 --> 11:09.040] something like this in a script file. That's it. All this does is change every response [11:09.040 --> 11:14.940] code to a 200. That's easy. Even I can code that shit. [11:16.360 --> 11:19.500] Unfortunately, man in the middle proxy tends to use up all of the memory you have on your [11:19.500 --> 11:26.580] machine. Even if you have 8 gigabytes of memory in your laptop. I would highly recommend man [11:26.580 --> 11:32.160] in the middle dump, which doesn't cache everything into memory. Just a side note there. [11:32.160 --> 11:40.400] I also used PHP, the amazing personal home page. It allows you to set response codes, [11:40.400 --> 11:44.880] but there's some downsides. You can also prepend a file, which is going to allow you to set [11:44.880 --> 11:48.480] specific response codes or do some logic in the background. The problem is if the web [11:48.480 --> 11:55.240] server says, no, this is an incorrect request, the PHP is never going to get to actually [11:55.240 --> 11:58.720] see the request, so you can't set response codes. So you can do some interesting stuff. [11:58.720 --> 12:02.820] For testing, it's useful, but in production, it's not really going to be as useful as it [12:02.820 --> 12:10.980] could be. So I used a mismatch of Python and PHP for most of the testing. You don't need [12:10.980 --> 12:15.120] to write this down, because I'll release all the slides afterwards, but simple testing [12:15.120 --> 12:20.320] of browsers, how things are supported, you just call a PHP page, which sets the response [12:20.320 --> 12:24.600] code, you tell it what code in the URL, and you hope no one cross‑sites your website. [12:26.040 --> 12:29.900] As simple as that. You get a response, you get the requested response code and the actual [12:29.900 --> 12:36.200] response code, because with PHP, you can set that response code to 999 if you want, but [12:36.200 --> 12:41.880] Python is just going to say, oh, sorry, Apache is just going to turn around and say, I don't [12:41.880 --> 12:46.480] know what that response code is, and then it just returns a 500, which is the they fucked [12:46.480 --> 12:51.280] up section of it. So, yeah, you get to see what you requested, you get to see what the [12:51.280 --> 12:55.320] response was, and you get to see what the headers are, so simple JavaScript running [12:55.320 --> 13:01.580] in the browser, so great, I can run off and start testing these browsers, which seemed [13:01.580 --> 13:08.580] like an easy thing. I started to think, I've got all this data on how all these browsers [13:08.580 --> 13:16.540] work, and how can I graphically display that in a nice fashion? Let's just say that I'm [13:16.540 --> 13:27.240] not good at charting. Sorry, for the women in the room, also, I'm trying to keep this [13:27.760 --> 13:32.520] even across the sexes. So I didn't really know how to display this, so I spoke to some [13:32.520 --> 13:35.840] guys who do visualization, and they were like, oh, yeah, we can do this and we can do that, [13:35.840 --> 13:41.540] and it was just all shit. So what I ended up with was a table. [13:46.640 --> 13:50.860] Yeah, this is the reason why I cut it down to three browsers, because otherwise the table [13:50.860 --> 13:55.840] would be like this fucking wide. So, yeah, there's a full table online, which I'll release [13:55.840 --> 14:00.260] after the talk, which has a lot of other browsers and scripting languages in it, but this is [14:00.260 --> 14:04.960] the core three, so you start to see quite a lot of conformity in this section about [14:04.960 --> 14:09.840] how the browsers respond to things. So I run it into three sections, so can you load HTML [14:10.340 --> 14:15.980] with a 100 response code? Well, you can, but nothing appears, it doesn't render anything, [14:15.980 --> 14:20.460] so the browser just doesn't support it, unless it's an iframe with Chrome, in which case [14:20.460 --> 14:26.680] it tries to download it, because I guess Chrome just likes to download shit. [14:28.800 --> 14:34.060] What's kind of interesting, if you have Chrome on an Android phone and you respond with a [14:34.060 --> 14:41.260] 100 code, it tries to download it, but it never finishes, so you have to restart your [14:41.260 --> 14:48.840] Android to get it to stop, which is fun. I'm sure no one would fuck with that. [14:51.980 --> 14:55.800] So looking at this, you're like, okay, well, all the browsers are kind of mostly conform, [14:55.800 --> 15:01.860] except IE, obviously, which doesn't care about a 205 and just renders the stuff, it doesn't [15:01.860 --> 15:07.520] care. You start to see differences when you're looking at the 300 codes, for example, Firefox [15:07.520 --> 15:14.420] just doesn't load JavaScript if you respond with a 300 or a 301, IE pretty much just ignores [15:14.420 --> 15:19.000] everything if you respond with anything in the 300 range which isn't a redirection, but [15:19.000 --> 15:23.820] Chrome pretty much accepts everything because it doesn't give a shit. It's the honey badger [15:23.820 --> 15:29.500] of browsers. Moving kind of into the 400 stuff, you start [15:29.500 --> 15:33.860] to see more conformity, again, IE being the weird one. It just doesn't like loading iframes [15:33.860 --> 15:41.380] with weird response codes. And you see these at a time when it says 407 proxy, proxy, proxy. [15:43.040 --> 15:47.360] Basically what that means is that Chrome, depending if you have a proxy set or not, [15:47.360 --> 15:53.040] will load it. So if you have a proxy, an HTTP proxy set, then Chrome will load the content [15:53.040 --> 15:56.640] when it's responded with a 407. If you don't, then it won't. [15:58.680 --> 16:03.280] Again with the 500s, things are pretty standard, again, IE being kind of a little bit of a [16:03.280 --> 16:09.200] weird outlier on things. Okay. So think about this for a second. You've got browsers that [16:09.200 --> 16:13.980] kind of handle things in slightly different ways. What can we do with that kind of stuff? [16:15.520 --> 16:19.820] But a majority of stuff is like, okay, that's just content. I don't care what it is. It's [16:19.820 --> 16:24.400] loading stuff. It's like you get a 400 response and it's like, oh, I see HTML, I'm just going [16:24.400 --> 16:27.920] to render that for you. Or I see JavaScript, I'm just going to run that JavaScript for [16:27.920 --> 16:34.960] you. So most things, mostly, things are loaded quite normally. But there's some weird kind [16:34.960 --> 16:39.940] of outliers. So with HTML responses, almost all response [16:39.940 --> 16:44.520] codes are rendered correctly. It doesn't care. When you try and load an iframe and it comes [16:44.520 --> 16:50.420] back with a response, there's some special cases for IE because IE is special. But most [16:50.420 --> 16:55.320] of the time kind of things are even. And if you start looking at JavaScript, there's very [16:55.320 --> 17:00.260] limited support for it. Chrome being the exception because they just don't care. [17:00.900 --> 17:07.520] So we know what browsers interpret differently. So what do all the browsers have in common? [17:07.720 --> 17:14.320] What are they doing the same across the board? The 100 codes, retries, confusion, as I said, [17:14.320 --> 17:20.640] fun on Android, never-ending downloads. And it times out eventually. Because the browser [17:20.640 --> 17:24.820] thinks there's more coming. The browser thinks, oh, you're going to send more data in a minute. [17:24.820 --> 17:30.920] I'll just sit here and wait for you. Which is kind of interesting. The 200 codes, again, [17:30.920 --> 17:36.320] you get the no content or not modified. You get headers saying, no, there's nothing here. [17:36.360 --> 17:40.200] So as you would expect, all the browsers just ignore any kind of content that you're responding [17:40.200 --> 17:44.360] because it doesn't expect there to actually be any content within those things. [17:45.540 --> 17:51.940] So what about headers? Okay. So RFCs quite a lot of the time in kind of a muddy language [17:51.940 --> 17:59.220] say if you're responding with a free XX response code, whether it's 301 or 302 or 303, there [17:59.220 --> 18:05.080] should be a location header. It doesn't mean it has to. If you respond and you don't have [18:05.160 --> 18:08.340] a location header, it just kind of ignores the fact that it's meant to do a redirect [18:08.340 --> 18:15.200] and then renders whatever content you give it. Specifically, no location header, no redirect. [18:15.200 --> 18:19.840] This makes sense. Because you're responding with a 302, it's looking for the location [18:19.840 --> 18:23.620] header, it doesn't find one. Instead of just giving you an unhelpful error in your browser, [18:23.620 --> 18:29.160] it's just going to render what you returned and ignore. Simple as that. So the 401 unauthorized [18:29.160 --> 18:35.420] as well, if you're not sending back a www authenticate header, it's not going to prompt [18:35.420 --> 18:42.480] you. Simple as that. And I mentioned previously about the 407 proxy authentication required, [18:42.480 --> 18:47.360] the way Chrome deals with it. Again, if you're not requesting the authentication, then it's [18:47.360 --> 18:52.840] never going to prompt you. On the flip side, just because an RFC says a specific status [18:52.840 --> 18:59.660] code shouldn't have a header, doesn't mean it can't have a header. So if you read the [19:00.220 --> 19:07.140] RFCs, there's 300 multiple choices. Now, this shouldn't have a location header. It doesn't [19:07.140 --> 19:11.300] redirect you. It should come up with an HTML where you can specifically select where you [19:11.300 --> 19:16.400] would like to go. Unless, of course, you're Firefox or IE, in which case if you give it [19:16.480 --> 19:22.240] a location header, it's just going to redirect. But Chrome isn't. And there are so many headers [19:22.240 --> 19:25.180] out there you can play with. I've played with quite a lot of them. Most of them are not [19:25.180 --> 19:30.280] particularly interesting, unfortunately. But there's more work to be done in that kind [19:30.280 --> 19:34.240] of area. There's a load of headers like the retry after header that can really be played [19:34.240 --> 19:38.900] with and a little bit more research is required there. So each browser is handling something [19:39.140 --> 19:44.020] a little bit differently. We know how things are handled the same. We know how things are [19:44.020 --> 19:51.620] handled differently. I wonder what we can do with that. So what can we do with that? [19:51.620 --> 19:56.400] What are the goals? Okay. So each browser handles things differently. You have the handled [19:56.400 --> 20:00.300] codes, you have the unhandled codes, and then you get this little browser weirdness thing [20:00.300 --> 20:05.080] where it just does random stuff you just didn't expect it to do depending on the headers. [20:05.760 --> 20:11.880] So browser fingerprinting. Okay. So, yeah, you can check user agent strings, but that's [20:11.880 --> 20:18.260] client side controlled. You can easily spoof that stuff. But if you take the differences, [20:18.260 --> 20:23.100] you can really do some interesting fingerprinting work on Firefox, on Chrome, and on IE. So [20:23.100 --> 20:28.200] on Firefox, based on the information we have, it doesn't load JavaScript return with a 300. [20:28.700 --> 20:32.880] The other browsers do. So you simply return a JavaScript with a 300, and if the JavaScript [20:32.880 --> 20:40.580] runs, it's Firefox. Simple as that. Okay? With Chrome as well, it loads Java return [20:40.580 --> 20:45.260] with a 307, temporary redirect, without a location header, but the other browsers don't. [20:45.260 --> 20:48.860] So again, we can do the same kind of thing, and we can do some fingerprinting. And with [20:48.860 --> 20:54.560] IE, it loads JavaScript return with a reset content status code, and nothing else does. [20:54.600 --> 20:59.120] So if we can add all that stuff together, you can get a nice way of fingerprinting the [20:59.120 --> 21:03.540] main browsers without even bothering to look at the location header. Or you can use the [21:05.480 --> 21:10.460] user agent header, and then specifically say, well, I'm going to check that by seeing how [21:10.460 --> 21:15.980] your browser really works. So I'm going to do a quick demo. Well, actually, I lied. I'm [21:15.980 --> 21:19.700] going to run a quick video of a demo, because I didn't want to connect to the network here. [21:23.200 --> 21:29.580] First talk. So all this is doing is loading a PHP page, and then running through and loading [21:29.580 --> 21:37.760] three individual pages. It then checks the responses, checks the JavaScript, and says, [21:37.760 --> 21:44.240] so this JavaScript ran, this JavaScript didn't, so you must be using this specific browser. [21:44.320 --> 21:52.260] So if you zoom in, well, if I zoom in, there you go. So you can see the specific responses. [21:52.260 --> 21:58.520] You can see that it's loading an HTML, it's coming back with a 300, a 307, and a 205, [21:58.520 --> 22:01.860] which are the three specific response codes we talked about for the different browsers. [22:01.860 --> 22:06.860] It's then sending all of that stuff to a PHP page on the server, and the PHP page is returning [22:06.860 --> 22:12.620] and saying, okay, this is the specific browser. So obviously I'm returning back to the browser [22:12.620 --> 22:19.300] to display a pop‑up to say this is the browser. In most cases, you're sending it to the server, [22:19.300 --> 22:24.120] and then you're never responding back, because I know I'm running IE. I have the little IE [22:24.120 --> 22:27.000] bar at the top. I don't need you to do a pop‑up and tell me. [22:27.160 --> 22:31.080] But the server now knows exactly what kind of browser you're using. So if you're spoofing [22:31.200 --> 22:38.240] a user agent string, then I can say, okay, so user agent string says you're running Firefox, [22:38.240 --> 22:42.100] but you're actually running Chrome. That's suspicious, and that's something that we should [22:42.100 --> 22:47.520] be looking at, okay? So there's various other options for fingerprinting. [22:47.520 --> 22:52.040] This specific option I selected was kind of the easiest option. There's various other [22:52.040 --> 22:57.480] stuff. There's a 300 redirect, there's a 400 iframe on Internet Explorer. If you want to [22:57.480 --> 23:04.400] look at the proof of concept, if you go to C22.cc, fingerprint.html, it will run the [23:04.400 --> 23:09.540] same example I just ran. You can look at the traffic, and the code is available. I'll link [23:09.540 --> 23:13.200] to that at the end. So user agents can be spoofed. Everyone knows [23:13.200 --> 23:18.140] that. Even script kiddies, unfortunately, know that. But browser traits are really hard. [23:18.500 --> 23:23.620] Because your browser responds and does things in specific ways. So we've done that. We can [23:23.620 --> 23:26.420] fingerprint browsers. So what else can we do? Proxy detection. [23:26.420 --> 23:31.460] We specifically talked about the way Chrome handles things. And if you have an HTTP proxy [23:31.460 --> 23:35.860] set, you can specifically say, okay, I know they're using Chrome. I'm going to respond [23:35.860 --> 23:42.040] with a 407. If it loads the page, then they're using an HTTP proxy. There's unfortunately [23:42.040 --> 23:45.980] limitations here. It doesn't pick up with SOX proxies. But your average user isn't using [23:46.100 --> 23:53.720] a SOX proxy anyway. It's a limited interest, but it's something that needs further testing. [23:53.720 --> 24:00.000] As I said, all you do is respond with a 407 with a proxy authentication header or without [24:00.120 --> 24:04.020] a proxy authentication header. And if Chrome responds, then HTTP proxy is set. [24:04.080 --> 24:10.760] So while I was doing this research, I decided I was going to try a couple of different HTTP [24:10.760 --> 24:19.880] proxies. And one of the proxies I selected was Privoxy. It's quite a popular privatizing [24:19.880 --> 24:25.260] HTTP proxy. So I found while I was testing this, if you respond with a ‑‑ so your [24:25.260 --> 24:30.160] web server, you go to my web server, you respond with a 407 proxy authentication required, [24:30.160 --> 24:35.180] you get the pop‑up in your browser. But it doesn't say that my web server asked you [24:35.180 --> 24:40.300] for a username and password. It says Privoxy asked you for a username and password. Which [24:40.300 --> 24:44.100] is interesting. So why is my local proxy asking for a username and password, I thought. So [24:44.100 --> 24:51.300] I typed in test, test, and I clicked send. And my web server gets my username and password. [24:52.720 --> 24:57.120] That's kind of interesting. I'm sure we can use that for some malicious stuff. But this [24:57.120 --> 25:01.520] is a defensive talk. So I'm not going to dive too much into that. But it's kind of interesting. [25:01.980 --> 25:07.300] Let's just say proxies aren't always configured quite so securely as they could be. There's [25:07.400 --> 25:11.620] a fix for that now. So you can download the latest version. But it's not just Privoxy. [25:11.620 --> 25:16.600] Any transparent proxy, things like burp or zap, they're designed to pass everything you [25:16.600 --> 25:22.040] give it. So if my web server responds with a 407 and asks for authentication, burp suite [25:22.040 --> 25:26.520] will just pass it to your browser. Simple as that. So you can start screwing with people [25:26.520 --> 25:33.000] who you know are doing malicious things on your site with intercepting proxies. Of course, [25:33.000 --> 25:36.500] if you're doing a test with burp suite and it says what's your username and password, [25:36.500 --> 25:40.500] I'm probably not going to type in my real username and password. But you never know. [25:40.500 --> 25:46.700] Script kiddies type in weird stuff. So let's bring all this stuff together. So we've got [25:46.700 --> 25:51.940] status codes that are treated like content. They don't care. You've got status codes that [25:51.940 --> 25:56.240] really are not specifically well handled, specifically the 100 codes. And you've got [25:56.240 --> 26:02.140] lots of little browser quirks that we can abuse. So what can we do? We can play with [26:02.140 --> 26:07.980] things just in case there's children in the room. We can make the people who like RFCs [26:07.980 --> 26:14.340] cry into their beer. So let's try to use what we've discovered. Let's break some spidering [26:14.340 --> 26:21.280] tools. Cause some false positives, false negatives. Slow down attackers, which is probably one [26:21.280 --> 26:25.260] of the most important things that we can do. Give us time to respond to how people are [26:25.260 --> 26:31.900] attacking us. And then block successful exploitation. So even if they do manage to exploit the server, [26:31.900 --> 26:35.380] if you're responding specifically with different codes, maybe their exploit is not going to [26:35.380 --> 26:42.200] work. So let's talk a little bit about spiders. This is a very simplistic and naive view of [26:42.200 --> 26:49.180] spiders. But you access the target URL, you read the links, you test them. If true, continue. [26:49.180 --> 26:57.780] So if you get a 200 okay, that's true, right? And if you get a 404, that's false, right? [26:57.880 --> 27:04.920] But what happens if everything is a 200? And what happens if everything is a 404? You start [27:04.920 --> 27:09.420] to get some weird stuff. And what happens if everything is a 500? Sometimes if everything [27:09.420 --> 27:14.280] is a 500, then everything is a SQL injection attack. So if everything is a 200, you end [27:14.280 --> 27:19.900] up with this interesting loop of, oh, I found another directory. I will just keep scanning [27:19.900 --> 27:23.740] and keep scanning and keep scanning. You get this never‑ending spider. Unfortunately [27:23.740 --> 27:29.020] I couldn't find a picture of a spider eating itself. So if anyone has one, please send [27:29.020 --> 27:35.680] it to me. And if everything is a 404, what website? I don't know if you can see this [27:35.680 --> 27:41.520] at the back. This is the wonderful Acunetix tool, the script kiddies tool of choice. The [27:41.520 --> 27:48.860] crawler found zero pages, zero files, and validated zero findings. Yeah. So what website? [27:49.000 --> 27:54.040] There is no website there. Skipfish loves it. It just keeps going and going and going [27:54.040 --> 28:00.740] until it kills itself. I'm guessing at this point my test server just decided it didn't [28:00.740 --> 28:06.840] have enough memory to deal with all the responses. If you look closely, there is also 2,000 low, [28:06.840 --> 28:16.600] 2,000 medium false findings on the scan alone. So, yeah. Playing with people's spiders is [28:16.600 --> 28:22.880] kind of interesting. So false positives, false negatives. We can start to hide how bad or [28:22.880 --> 28:26.920] how good our servers are, start to really screw with people and waste their time. So [28:26.920 --> 28:32.700] most scanners use response codes in some way. They kind of have to. You speed up detection. [28:33.800 --> 28:40.700] You can't use rejects for everything. It's the easy solution. So if we start to respond [28:41.300 --> 28:47.260] with, again, 200 okay, 404, 500, and if we start to play with them and respond with random [28:47.260 --> 28:54.860] codes, random being a selection of codes that are handled well by all normal browsers, so [28:54.860 --> 28:58.920] the normal people browsing the website are not going to be affected in any way, you start [28:58.920 --> 29:04.940] to see some really interesting stuff. So it's a quick baseline using W3AF. I didn't particularly [29:04.940 --> 29:09.760] pick on these people. It just happens to be an interesting baseline. So a standard baseline [29:09.760 --> 29:17.240] for my test system was 79 informational points, 65 vulnerabilities, no shells, which kind [29:17.240 --> 29:22.900] of took an hour and 37 minutes to do a scan. So if everything responds with a 200 okay, [29:22.900 --> 29:29.460] you still get everything. So we're not winning on the false positives and false negatives. [29:29.520 --> 29:35.160] It takes you nine hours to run the scan, which is kind of interesting. It lets us win time, [29:35.160 --> 29:38.960] but it's not really working. So a 200 okay isn't really going to do what we need it to [29:38.960 --> 29:43.580] do. So if everything is a 404, it's a lot quicker to do the scan because you're not [29:43.580 --> 29:47.740] finding everything. But it's missing a majority of the information points and a majority of [29:47.740 --> 29:52.580] the vulnerabilities. So you're starting to see some interesting stuff. If we start responding [29:52.580 --> 29:57.960] with weird codes, they don't find everything. Okay. That's interesting. If you respond with [29:57.960 --> 30:05.200] everything with a 500, wow. False positives. If it's a 500, like I said, it's SQL injection. [30:05.380 --> 30:13.560] 9,000 informational points. Try digging through that report, you know. 9,000 confusing information [30:13.580 --> 30:18.320] and confirmed vulnerabilities. I can just see that pen test report, sorry. That vulnerability [30:18.320 --> 30:23.060] analysis. That's going to be about 1,000 pages long. Oh, no, we found all this stuff. We [30:23.060 --> 30:27.520] have IAS vulnerabilities and this and that. It's an Apache server, but we still have all [30:27.520 --> 30:33.340] of these IAS vulnerabilities. So any people who use Nessus in the room? No. [30:34.020 --> 30:39.440] So if we start using random status codes, I did multiple runs of this to make sure that [30:39.440 --> 30:44.320] I'm getting accurate. Because if it's being random, maybe I just had a bad run. It averaged [30:44.320 --> 30:50.940] out as giving you a reasonable amount of false positives. And it took less time to run the [30:50.940 --> 30:56.480] scan. What I found interesting on this was a majority of the things that it did find, [30:56.480 --> 31:01.360] it didn't find the real vulnerabilities, it just found weird stuff. So even though it [31:01.360 --> 31:05.540] found more vulnerabilities and you get lots of false positives, they're pretty much all [31:05.540 --> 31:09.420] false positives. So the real stuff just doesn't get found at all, okay? [31:10.620 --> 31:17.400] So skip fish and random, wow. It doesn't like random. Let's just say skip fish is particularly [31:17.400 --> 31:21.340] picky about it. So the first scan time took ten hours and the second scan time took four [31:21.340 --> 31:27.680] seconds. Yeah, and then again 16 hours. I ran it about five times and it would just [31:27.680 --> 31:32.380] randomly flick between times. So skip fish is a wonderful denial of service tool for [31:32.380 --> 31:39.820] web applications. I think in my proxy it sent like 33,000 requests inside five, six [31:39.820 --> 31:43.480] minutes. Yeah, it would pretty much take down everything. [31:45.800 --> 31:51.740] So we're not really slowing attackers down. So what can we do to slow the attackers down? [31:52.540 --> 31:59.220] What's our WAF really doing at the moment? A standard WAF, again, a naive view, oh, my [31:59.220 --> 32:04.680] God, I'm being attacked. Block or return an error whether or not that's a 403, a 500, [32:04.680 --> 32:11.320] or a 404, or a 200 with a nice message telling them to piss off. Profit? There's no profit [32:11.320 --> 32:16.920] there. Okay, for us as defenders, with my defender hat on, we've won nothing. All we've [32:16.920 --> 32:21.880] done is blocked an IP address or blocked an attack. They come back with an obfuscation, [32:21.880 --> 32:29.200] we bypass it, game over, okay? So why are we doing that? Remember this big list of things [32:29.220 --> 32:35.080] that browsers don't handle very well, specifically the 100 stuff? Well, scanners don't like [32:35.080 --> 32:40.380] them either. Surprising there, because a scanner thinks it's going to be a browser. It's trying [32:40.380 --> 32:46.200] to do everything that a browser does. So looking at the 100 codes, we can start to really screw [32:46.200 --> 32:49.120] with stuff. So does anyone remember the library topic? [32:51.300 --> 32:59.200] So it should be Tomlisten, not Timlisten. Apologies, Tim. So it was originally designed [32:59.220 --> 33:03.940] to slow the spread of code red, and it slows down attackers. I mean, this was a great idea. [33:04.720 --> 33:09.240] Did we forget that this was a great idea? Did we think that, okay, well, it's been done [33:09.240 --> 33:14.500] now, we can just forget about it? In our drive to kind of find new and interesting research, [33:14.500 --> 33:17.640] it's been done once, so we should just ignore it for the rest of time. [33:18.400 --> 33:24.740] So I had this interesting idea. How about an HTTP tar pit? People have probably talked [33:24.740 --> 33:30.180] about this a thousand times before, but, you know, it was interesting to me. Whoa. [33:34.800 --> 33:48.140] This is the problem when you run PowerPoint. Drink, drink, oh. [33:53.460 --> 34:00.820] Morning DEF CON. It's Sunday morning, you know what that means? Drink, that's right. [34:00.820 --> 34:09.360] Say a round of applause for our first-time speaker. How's he doing so far? Doing okay? [34:11.740 --> 34:15.080] All right, hook us up. I am not drinking all of those. [34:17.620 --> 34:23.460] All right, who's first time at DEF CON? First hand up, right here, come on up on stage. [34:29.960 --> 34:33.280] If it's Sunday morning, that means this is the hard core, right? Right here, you guys [34:33.280 --> 34:36.820] all got up, good job. All right. Congratulations. [34:36.960 --> 34:54.520] Cheers. That reminds me of last night. So where was I? Oh, yeah, I was in a tar pit. [34:54.720 --> 35:02.420] So simple scenario. So the WAF detects the scan. Again, we are at the oh, my God, attack [35:02.420 --> 35:09.040] section. It adds the IP address to the naughty list. And then it starts to rewrite all the [35:09.040 --> 35:15.780] responses. So you get the usual 100, 101, 102 status codes. We just randomly rotate [35:15.780 --> 35:20.840] between them, depending on how bored we are all the time. We can also use 204, 304, which [35:20.840 --> 35:25.040] could be useful, but it's not nearly as fun as the 100 status codes. [35:25.040 --> 35:32.000] So let's do some experimentation, shall we? There's no actual science included in this. [35:33.420 --> 35:41.000] So Nikto, wonderful tool. I like it a lot. I especially like the logo. So the baseline [35:41.000 --> 35:46.720] scan, 2 minutes, 18 seconds to find 18 findings. Simple as that. [35:47.640 --> 35:57.320] With the tar pit, yeah, we're winning some time there. Let's just say that. It's like [35:58.440 --> 36:04.100] a 340 fold increase in time. But it's still finding quite a lot of stuff. This is mostly [36:04.100 --> 36:09.620] informational stuff, like you have an Apache whatever version as your server header. Even [36:09.620 --> 36:14.120] if you respond with 100 code, it's still going to get that header. So most of that stuff [36:14.120 --> 36:19.300] is kind of uninteresting. Some of the findings, they disappear. And the script kitty spends [36:19.300 --> 36:22.960] 14 hours scanning your web server. So we're kind of winning. [36:23.380 --> 36:30.060] So W3AF, again, same baseline as before, 1 hour, 37 minutes, 65 findings. But wait a minute, [36:30.060 --> 36:35.540] this is going in the wrong direction. 18 minutes instead of 1 hour, 37. It's weird. That shouldn't [36:35.540 --> 36:41.100] be happening. But it didn't find anything. So I'm guessing there was some kind of algorithm [36:41.100 --> 36:45.320] there that said I'm just going to stop bothering to scan your web server now because it's kind [36:45.320 --> 36:47.540] of weird and I don't know what the fuck is going on. [36:49.960 --> 36:57.760] So yeah, back to the denial of service skip fish tool. 18 minutes, 10 seconds to find [36:57.760 --> 37:02.960] around, 2,500 low, mediums and a couple of highs, which unfortunately even on the baseline [37:02.960 --> 37:09.980] were mostly false positives, but whatever, each to their own. So 5 seconds. Again, we're [37:09.980 --> 37:13.900] going in the wrong direction. But there was no lows and there was no mediums and there [37:13.900 --> 37:18.420] was only three highs. What I thought was interesting was the three highs that it found were not [37:18.420 --> 37:25.480] any of the 12 highs that it found previously. So not only false positives but different [37:25.480 --> 37:29.980] false positives to the normal scan. So okay, it's kind of doing weird stuff and we like [37:29.980 --> 37:34.160] weird stuff because we're mucking around with automated scanners and we're screwing the [37:34.160 --> 37:39.380] script kiddies. So random is good. So Acunetix, as I said before, the script kiddy [37:39.380 --> 37:45.420] tool of choice. So you get a one‑hour scan, it's quite reasonable, with a huge amount [37:45.420 --> 37:49.180] of informational stuff that you probably don't care about. And again, we're going in the [37:49.180 --> 37:53.180] wrong direction and this HTTP target should be slowing stuff down but it's making stuff [37:53.180 --> 37:59.280] faster depending on what scanner you're using. But again, okay, that's an interesting ratio [37:59.280 --> 38:04.780] of complete false negatives. So it's just not finding stuff. So some of these scanners [38:04.780 --> 38:08.580] are just like, okay, now this web server is just playing silly buggers, I'm just going [38:08.580 --> 38:13.380] to stop bothering to scan it at all. What's interesting, it doesn't tell you that it's [38:13.380 --> 38:19.880] just going to give up. It just says, I'm finished. It just says, no, I'm done. So what do we [38:19.880 --> 38:24.100] find? So you can slow down some scanners, things like Nikto, others give up quicker [38:24.100 --> 38:29.060] because they just get tired of getting responses from the server or a timeout and say the server [38:29.060 --> 38:32.860] is not there anymore. If you look through a log file, I'm sure somewhere along the line [38:32.860 --> 38:36.980] it says the web server stopped responding even though it didn't. But you get a lot of [38:36.980 --> 38:43.580] unreliable and aborted scans. So up to 100% less findings. That's a win for us. [38:45.480 --> 38:51.040] So let's move on to blocking successful exploitation. So even if someone can get past all of this, [38:51.040 --> 38:56.520] they can find a high criticality in your web server. So we've made it hard for them to [38:56.520 --> 39:00.220] find them, but people are going to find these vulnerabilities no matter what. We've made [39:00.220 --> 39:05.140] it so that possibly it's going to take them 15,000 times longer to find the vulnerabilities, [39:05.140 --> 39:10.200] but they're going to find stuff. So let's stop them from popping shells with Metasploit. [39:11.120 --> 39:21.140] Now, how often does Metasploit reference status codes? Anyone care to guess? No? It's about [39:21.140 --> 39:26.400] 1,000. Give or take. This is not scientifically sound and it depends very [39:26.400 --> 39:30.020] much on how people are wording things and how they're using their variables, but this [39:30.020 --> 39:36.600] is a simple grab through searching for res.code, resp.code and response.code. These are the [39:36.600 --> 39:43.500] usual things that people use. And there's lots of dependency on status codes. Unfortunately [39:43.500 --> 39:49.760] even the stuff I wrote uses status codes. So I know it's bad programming, but it's quick [39:49.760 --> 39:54.300] and it's what we all do because we use status codes to check the response from servers. [39:54.300 --> 40:01.660] So here's an example of a simple snippet of code from one of the Metasploit checks. So [40:01.660 --> 40:06.920] all it's doing is checking if the response code is less than a 200 or more than a 300. [40:08.020 --> 40:14.560] So I can return a 500. That's great. I can return a 500 with the content. And then it's [40:14.560 --> 40:20.460] failing. So if it's not anywhere in the 200 range, which is the okay, then the exploit [40:20.460 --> 40:26.140] just fails. Simple as that. Okay, great. So if we're spoofing 404 but still giving [40:26.140 --> 40:29.880] you the content, then this exploit is always just going to fail. And if you're good enough [40:29.880 --> 40:33.900] to go in and edit the code and change things and you really know what's going on, then [40:33.900 --> 40:38.920] you're not really the target of this talk. We're targeting script kiddies who know absolutely [40:38.920 --> 40:42.340] nothing. All they know how to do is run the code and if it doesn't work they just cry [40:42.340 --> 40:48.420] in a corner. Interesting side effect, if it is a 401, it [40:48.420 --> 40:53.600] just starts to print out the response headers like the www authenticate or the authentication [40:53.600 --> 40:58.820] header. Of course, as we mentioned before, we don't need to send those headers. So what [40:58.820 --> 41:02.640] happens if you don't send those headers? You start to get errors within Metasploit [41:02.640 --> 41:06.700] because it's trying to print out stuff that it shouldn't really ‑‑ should be there [41:06.700 --> 41:10.980] but it's actually a nil value because we haven't actually set it at all because we haven't [41:10.980 --> 41:17.720] provided it. So that's an interesting side effect. So no match, no shell. Okay? No cookie [41:17.720 --> 41:21.960] for you. Simple as that. So quickly running through what we've talked [41:21.960 --> 41:28.940] about here, okay? So we can use status codes to our benefit. It's fun. It's useful. We [41:28.940 --> 41:33.580] can slow people down with it. But browsers can be quirky. So we need to do it in specific [41:33.580 --> 41:40.140] ways. And scanners and attack toolkits are, you know, they're set in their ways. This [41:40.140 --> 41:44.320] is the way we did it in 1990 and goddammit this is the way we're going to do it in 2013. [41:44.820 --> 41:53.300] Get off my lawn. It's just the way things are. Why change things if it's working? So my goal [41:53.300 --> 41:58.780] here is to make it not work. WAFs need to seriously get more offensive about their defense [41:58.780 --> 42:04.860] because they're being far too passive as far as I'm concerned. So just blocking a request, [42:04.860 --> 42:10.000] providing a snazzy little ASCII art that tells people to go and scan someone else's web server, [42:10.000 --> 42:13.880] it's great and it's fun but it's not really going to help us. And I'm not talking hacking [42:13.880 --> 42:23.440] back. I don't want to start hacking back people who attack my web service but I want to be [42:23.440 --> 42:28.320] more active in fighting back and saying to people that this is not right. If you're scanning [42:28.320 --> 42:31.880] my server I'm going to screw with you and I'm going to screw with you until you cry. [42:31.920 --> 42:37.880] It's just the way things are. So slowing attackers down is good. Making life harder for [42:37.880 --> 42:43.480] skitties is absolutely priceless. I should have put the MasterCard logo on that. So [42:44.580 --> 42:53.160] current tools are very much the same as APT. Yeah, I said that. They are adequate and they [42:53.160 --> 42:58.120] do what they do and until someone fights back and says this is not good enough anymore then [42:58.120 --> 43:01.160] they're just going to keep doing what they're doing. Simple as that. So they're only [43:01.160 --> 43:05.520] advanced as they need to be. It's just like people attacking you. If they can get you with [43:05.620 --> 43:10.580] a phishing attack then why would I bother wasting a zero day on you. Simple as that. [43:11.640 --> 43:18.280] I think this is the key to this entire talk. Screwing with skitties is fun. I've had this [43:18.280 --> 43:22.320] running on my web server for a while now and just checking the logs it's absolutely [43:22.320 --> 43:28.120] hilarious the amount of automated scans that hit your web server searching for like Tim [43:28.120 --> 43:35.460] Thumb and how long it takes them to finish just a simple scan of your web server. Just [43:35.460 --> 43:40.780] scanning your web server for random stuff. So how can people implement this? There's no [43:40.780 --> 43:44.260] point in me talking about this stuff if we don't know how we can implement this stuff. Let's [43:44.260 --> 43:49.980] talk about the ghetto option. We can implement it using PHP. It's the lowest common [43:49.980 --> 43:55.700] denominator. People probably wrote it in notepad but that's life. You can auto prepend a [43:55.700 --> 44:02.480] PHP file to say randomize the response code within a specific section of response codes [44:02.480 --> 44:07.680] that are supported by the browser. We're limited by resources that are PHP handled. If [44:07.680 --> 44:11.240] your web server starts to error out because people are sending stuff that isn't to be [44:11.240 --> 44:15.720] expected then the web server is going to respond back. There's limited functionality [44:15.720 --> 44:21.680] there. There's man in the middle dump. It's a real memory hulk. It will use everything [44:21.680 --> 44:25.900] you've got. If you put man in the middle dump as a reverse proxy in front of your web [44:25.900 --> 44:31.980] server you can have simple scripts that are just going to change the response codes. That [44:31.980 --> 44:37.700] works. It works. But it's not the best solution. So what's this enterprise approved [44:37.700 --> 44:45.680] solution? Everyone knows NGINX, right? It's like Apache but better. It's a usable [44:45.680 --> 44:52.360] implementation. NGINX is used quite often as a reverse proxy. And if you use something [44:52.360 --> 44:56.740] like NGINX lure you can write some interesting scripts that are going to change the [44:56.740 --> 45:03.480] response codes that are going out of NGINX. So you simply load NGINX lure and using NGINX [45:03.480 --> 45:08.740] status you can specifically set stuff. So the only problem is there's kind of a few bugs [45:08.740 --> 45:14.720] in the non‑Git version. Specific codes that are supported just tend to get returned as [45:14.720 --> 45:20.920] nil which is kind of a pain. But if you use the version from Git it shouldn't be so much [45:20.920 --> 45:27.980] of a problem. But if you do an apt‑get install and install NGINX and install the [45:27.980 --> 45:30.600] optional extras you're going to run across a couple of problems. [45:31.220 --> 45:37.620] So what does the future hold? What's the next step? Well, the next step, I've been trying [45:37.620 --> 45:43.060] to get this into mod security to ease adoption by implementing it into something that people [45:43.060 --> 45:47.680] are using already on a daily basis. Because no one wants to implement another layer of [45:47.680 --> 45:52.740] stuff. Because the more you install, you're increasing your attack surface. So you want [45:52.740 --> 45:56.800] to put something, change a couple of configuration files in mod security and just have it do [45:56.800 --> 46:01.960] this stuff without you having to think about it. But it's not simple. It's not easy. I've [46:01.960 --> 46:05.860] been discussing it with various people for about a year and everyone is like, yeah, that [46:05.860 --> 46:13.800] should be possible, maybe, kind of. But I don't know how. So this is kind of a long [46:13.800 --> 46:19.220] shot, but I need some help with this stuff. I'm not a C coder and I'm not into writing [46:19.220 --> 46:22.860] Apache modules, but if anyone is interested in this kind of stuff and they really want [46:22.860 --> 46:26.200] to implement it into mod security, then I would really appreciate their help. [46:27.120 --> 46:32.200] So how do we counter this research? We've told the scanners that they're crap. We've [46:32.200 --> 46:38.120] told the scanners that they aren't doing stuff in the right way. I really need a new microphone [46:38.120 --> 46:45.320] here. So less reliance on status codes. I know it's easy to say, but we're going to [46:45.620 --> 46:50.900] have to slow scanners down in order for them to be more reliable. Because right now they're [46:50.900 --> 46:54.680] just taking the response codes and ignoring everything else. So start paying more attention [46:54.680 --> 46:59.580] to the actual content of the site itself. Some scanners are doing this already, but [46:59.580 --> 47:04.000] things need to be double‑checked. You get better matching if you do that. The problem [47:04.000 --> 47:09.300] is Regex matching is kind of slow. It's going to use more memory, it's going to take more [47:09.300 --> 47:15.820] time, it's not easy. But this is the cat and mouse game. Every time we come up with something [47:15.820 --> 47:21.200] new or increase our security, then people who are attacking websites or testing websites [47:21.800 --> 47:28.020] increase the productivity and increase the accuracy of their tools. So hopefully we can [47:28.020 --> 47:33.700] move this to the next level. So that's all I've got. [47:33.700 --> 47:36.580] Any questions? So, yeah. [47:47.760 --> 47:53.760] So the question is, have I specifically looked at detecting specific scanners and how they [47:53.760 --> 47:59.140] look when they're attacking a web server? Yes, I have looked at it. Not as part of this [47:59.140 --> 48:03.160] research, as part of other research. Yeah, it's interesting stuff. You can also detect [48:03.160 --> 48:09.160] quite easily when Nikto is attacking your website. The problem is, it's the same as [48:09.160 --> 48:13.060] this stuff. As soon as you start detecting how specific scanners look when they hit your [48:13.060 --> 48:18.300] website, the scanners are just going to start randomizing how they request stuff. So it's [48:18.300 --> 48:22.480] another step in the kind of cat and mouse game. So, yeah. [48:26.140 --> 48:38.420] Okay. Yeah, so F5, you can write scripts to specifically do this stuff. So it's interesting. [48:38.420 --> 48:43.400] So I'm sure everyone here has an F5, yeah. So, yeah. [48:46.720 --> 48:51.300] So yeah, the question was, do different versions of browsers respond in different ways? At [48:51.300 --> 48:56.440] the beginning of my testing, I was checking all the different versions of IE. IE6 tends [48:56.440 --> 49:04.680] to do things in a kind of weird way. You get some weird stuff. Like with the 100 codes, [49:04.680 --> 49:09.780] it tries to download stuff. But it's ‑‑ between specific versions, they don't tend [49:09.780 --> 49:14.260] to change the logic at all. So I'm getting the wave. So if anyone has any further questions [49:14.260 --> 49:21.680] or any further comments, the code is available on my GitHub site. I'd just like to leave [49:21.680 --> 49:25.580] you with the thought that whatever doesn't kill you makes you smaller. Thank you.