WEBVTT

00:00.000 --> 00:02.340
So, yeah, a little bit about me.

00:02.760 --> 00:08.140
No one really cares about who the speaker is, so read this whenever you want.

00:08.140 --> 00:10.580
I do podcasting and blogging and shit like that.

00:12.520 --> 00:17.060
I am a firm believer in the wisest man is he that knows that he knows nothing.

00:17.440 --> 00:22.200
I am not an expert and I'm quite happy to admit that I know absolutely nothing.

00:24.680 --> 00:26.820
I kind of like edge case stuff.

00:26.980 --> 00:28.900
It's kind of ‑‑ it's freaky.

00:28.900 --> 00:31.480
Most people are like, oh, it's just an edge case, no one really cares.

00:32.000 --> 00:36.020
But the edge case stuff, the freaky stuff, the weird stuff kind of really interests me.

00:36.020 --> 00:39.460
It makes me think that's really cool, I should really dive into that.

00:39.460 --> 00:43.720
So this is part of the edge case stuff that people really don't give a shit about.

00:43.720 --> 00:47.780
But apparently all you guys do, otherwise you wouldn't have woken up early to come and see this.

00:49.020 --> 00:50.980
So I'm going to start with a quick warning.

00:51.220 --> 00:56.780
This presentation, it contains numbers and jokes and traces of peanuts.

00:58.040 --> 01:00.420
Who has ever seen me give a talk before?

01:00.960 --> 01:02.580
So if you had, you wouldn't be here.

01:03.920 --> 01:09.320
Everyone who has seen me give a talk before, I'm sorry, I use the same jokes every time.

01:09.660 --> 01:12.800
So just laugh when everyone else does.

01:14.220 --> 01:16.080
Not you, Ed, you have to stay.

01:17.060 --> 01:21.960
So I'm going to give everyone the TLDR on what I'm going to be talking about today.

01:23.260 --> 01:27.760
The goal of this talk is to describe the defensive uses of HTTP status codes.

01:28.400 --> 01:31.340
That sounds really sexy, doesn't it?

01:32.580 --> 01:36.300
This is an absolute must see at DEF CON on a Sunday morning.

01:38.780 --> 01:41.900
So back to why are you guys awake again?

01:42.900 --> 01:50.760
I'm going to run through the what, the why, the how, the goals and then we're going to bring it together and we're going to review what we've covered.

01:51.000 --> 01:55.780
So I'm going to try to run through this reasonably fast so I can get everything in.

01:56.060 --> 01:57.360
So let's start with the what.

01:57.360 --> 01:58.680
HTTP status code.

01:58.680 --> 02:01.240
Who has never seen an HTTP status code?

02:02.040 --> 02:03.740
Yeah, okay, I thought so.

02:03.760 --> 02:06.480
So we know what an HTTP request looks like.

02:06.640 --> 02:08.300
We're picking out the specific section.

02:08.300 --> 02:10.640
This is the status code or the response code.

02:11.380 --> 02:15.360
The terms are interchangeable depending on how much you had to drink.

02:16.600 --> 02:24.400
It's like a really small little thing every time you make a request or every time you get an answer from a server.

02:24.400 --> 02:26.440
It comes with some kind of status code.

02:26.720 --> 02:28.460
No one really cares what they are.

02:28.460 --> 02:35.820
The browser doesn't really tell you what it is, but it's an important feature of the HTTP standard.

02:36.980 --> 02:41.420
What I'm going to show you is a really small detail, but it's a really big impact.

02:41.820 --> 02:47.160
If you don't really pay attention to the status codes, then some bad things can seriously happen.

02:47.400 --> 02:50.340
So a little bit of history on HTTP status codes.

02:50.480 --> 02:51.480
This is an RFC.

02:51.480 --> 02:53.300
I'm sure everyone here has read that, right?

02:54.800 --> 02:56.160
I couldn't sleep last night.

02:56.160 --> 03:00.320
I thought maybe I should read the RFC again, but yeah, that didn't happen.

03:00.940 --> 03:03.240
So there's five main classes of responses.

03:03.240 --> 03:06.920
You get the one, 100, which is the informational stuff.

03:07.040 --> 03:08.560
You don't get to see that very much.

03:08.680 --> 03:11.880
You get the 200, which is most of the time success.

03:11.880 --> 03:13.020
Your web page is here.

03:13.020 --> 03:13.920
Here is the content.

03:13.920 --> 03:14.560
Thank you very much.

03:14.560 --> 03:15.460
Please go away.

03:15.800 --> 03:17.980
You get the 300, which is the redirect stuff.

03:18.820 --> 03:21.040
You get the 400, which means you fucked up.

03:21.200 --> 03:23.320
You get the 500, which means they fucked up.

03:25.140 --> 03:26.400
Simple as that, okay?

03:26.480 --> 03:35.180
There's also a wonderful RFC, and this one is actually worth reading for the 700 codes by John Barton.

03:35.460 --> 03:38.340
If you go to his GitHub page, there's an entire section.

03:39.240 --> 03:40.540
I like the meh.

03:40.980 --> 03:42.540
I am not a teapot.

03:43.960 --> 03:47.620
I specifically like this one, fucking unicode.

03:53.220 --> 03:56.820
So, yeah, there's like 300 of these things.

03:56.880 --> 04:01.060
So I have no idea how they squeezed it all into the 700 range, because there's 300 of them.

04:02.300 --> 04:06.260
These are amazing, and I have no idea where did the 600 range go?

04:06.580 --> 04:13.440
So, yeah, I really hope they accept that RFC and start implementing that in some stuff.

04:13.600 --> 04:15.320
So let's go through the basic stuff.

04:15.320 --> 04:16.420
This is the theory bit.

04:16.420 --> 04:19.700
It's boring, and I'm sorry, but this is the theory.

04:19.700 --> 04:21.120
So you get the 100 informationals.

04:21.120 --> 04:24.100
You get the 100 continue, switch protocols, processing.

04:24.180 --> 04:26.820
As I said, these are the things you don't get to see very much.

04:26.940 --> 04:30.460
Moving into the 200 stuff, it means it worked.

04:30.460 --> 04:32.420
It means it understood.

04:32.540 --> 04:36.380
So you're getting a 200 okay, which is most of the web is returning a 200 okay.

04:37.820 --> 04:41.420
You also get some weird stuff that you don't get to see very much, like 204 no content.

04:41.740 --> 04:43.320
Great, thanks for the header.

04:46.840 --> 04:50.420
There's also some interesting stuff that isn't supported by Apache.

04:51.920 --> 04:53.320
Low on storage space.

04:53.320 --> 04:56.420
I've never seen that one returned by a server, but I'd really like it.

04:56.420 --> 04:58.000
But they're not supported by Apache.

04:59.600 --> 05:03.420
You get the 300 redirection stuff.

05:03.420 --> 05:06.120
So most people know what a 301 is, what a 302 is.

05:06.540 --> 05:08.360
300 you don't get to see very much.

05:08.360 --> 05:09.420
Multiple choices.

05:09.700 --> 05:11.260
It's like an exam.

05:11.520 --> 05:13.100
Tick boxes or something.

05:14.640 --> 05:20.460
304 not modified as well is something you see quite a lot if you're looking at the way data flows backwards and forwards.

05:20.460 --> 05:23.520
You also get some weird stuff that isn't used anymore, like switch proxy.

05:23.880 --> 05:24.960
Sounds like fun.

05:25.000 --> 05:26.300
Use proxy is also interesting.

05:26.300 --> 05:31.500
If you return a proxy setting in the location header, it says, oh, you should use this proxy for your communications.

05:31.920 --> 05:35.040
I'm sure no one would use that for malicious purposes in any way.

05:36.860 --> 05:41.400
So moving on to the 400, which is the you fucked up section.

05:41.980 --> 05:45.100
So forbidden, unauthorized, usual stuff.

05:45.180 --> 05:51.720
404 not found being quite a reasonable response for I search on random crap on the Internet.

05:53.080 --> 05:54.760
And then you get some interesting stuff.

05:54.760 --> 05:57.560
I quite like the 407 proxy authentication required.

05:58.320 --> 06:00.480
I'll talk a little bit more about that later on.

06:01.000 --> 06:04.140
Interesting ways to do some malicious stuff with that.

06:04.500 --> 06:06.080
This is a long list.

06:08.380 --> 06:10.440
I quite like the 418.

06:10.440 --> 06:11.460
I'm a teapot.

06:11.460 --> 06:16.200
It's only in April Fools and quite a lot of web servers don't implement it, but this is interesting.

06:16.200 --> 06:18.320
It's like I am indeed a teapot.

06:20.860 --> 06:27.680
Moving into the 500 stuff, internal server error, which is unfortunately used quite a lot for SQL injection.

06:27.680 --> 06:28.760
Oh, I got a 500 error.

06:28.760 --> 06:30.500
That must be a SQL injection trigger.

06:31.960 --> 06:35.900
You don't get to see it very much if you're not abusing websites.

06:35.900 --> 06:38.340
Still, it's interesting.

06:38.340 --> 06:40.740
Wow, that's a lot of fucking numbers.

06:42.620 --> 06:43.240
All right.

06:43.240 --> 06:46.320
So everyone here knows every single HTTP response code now, right?

06:47.140 --> 06:47.980
Great.

06:47.980 --> 06:49.800
I don't have to talk about them anymore.

06:49.800 --> 06:51.140
So why are we doing this?

06:51.140 --> 06:53.000
It started off as a little idea.

06:53.360 --> 06:54.840
I read a couple of books.

06:55.280 --> 06:57.100
I do that on occasion.

06:57.480 --> 06:59.680
I don't know if any of the authors are in the room.

06:59.940 --> 07:01.260
I'm really sorry.

07:01.920 --> 07:03.640
I'm plagiarizing your work.

07:04.700 --> 07:07.340
And I started to have a little think, what can we do with that?

07:07.800 --> 07:10.300
We can do some interesting stuff with scanners.

07:11.040 --> 07:13.980
And screwing with script kitties is a hobby.

07:15.000 --> 07:16.800
It's more of a life calling.

07:18.720 --> 07:20.620
And that sounds like fun.

07:20.620 --> 07:22.640
That sounds like something I want to do at a weekend.

07:23.080 --> 07:27.280
And I started to look around and there's a guy that everyone follows on Twitter, right?

07:27.280 --> 07:28.180
The Grug.

07:28.400 --> 07:30.940
He's not here because he's drunk, but he should be.

07:31.960 --> 07:40.480
He said in one of his quotes, stop dismissing obscurity as a security feature because unpredictability in your defense works to your advantage.

07:40.920 --> 07:41.780
Well, that's great.

07:42.000 --> 07:45.920
We can increase attacker costs being unpredictable.

07:46.740 --> 07:48.980
And we can waste attacker time.

07:49.080 --> 07:55.920
We can say that, you know, an attacker is going to waste three hours attacking a website that should take 15 minutes.

07:55.940 --> 07:59.300
Why should we just stand there and let someone smash us in the face?

07:59.680 --> 08:01.960
We should be more active on our defense.

08:02.320 --> 08:05.120
So there's some prior art.

08:05.160 --> 08:06.360
I kind of looked around.

08:06.360 --> 08:08.520
I was trying to find who else has talked about this stuff before.

08:08.520 --> 08:11.060
Because in my mind, this was just obvious stuff.

08:11.060 --> 08:13.860
I was like, someone's bound to have already implemented this stuff.

08:14.480 --> 08:24.680
There was a 2004 talk by Harun Mir and the guys at SensePost where they mentioned using HTTP status codes to slow down attackers.

08:24.840 --> 08:28.080
It was one line comment in a slide deck.

08:28.080 --> 08:28.900
That was it.

08:28.900 --> 08:29.720
Okay.

08:29.720 --> 08:32.700
Well, someone's mentioned it, so there must be more.

08:33.400 --> 08:36.340
There was an interesting paper by Gunter Ohlum.

08:36.340 --> 08:38.880
I probably totally mispronounced his name there.

08:38.880 --> 08:42.100
There's a PDF where he talks about stopping automated attack tools.

08:42.100 --> 08:43.940
I was like, okay, this must cover it.

08:43.960 --> 08:50.540
He covers lots and lots of stuff, but he doesn't really dig deep into using HTTP status codes to do this stuff.

08:50.540 --> 09:03.760
So I carried on, and I was informed, should we say, of a mailing list comment where Ryan Barnett said that, well, maybe we can reply with a 503 with a retry after header.

09:04.560 --> 09:05.740
That was interesting.

09:05.740 --> 09:07.020
I tested it out.

09:07.020 --> 09:11.260
It didn't really seem to work, because most scanners just completely ignore a retry after header.

09:11.260 --> 09:12.500
But maybe things have moved on.

09:12.500 --> 09:14.740
This was 2006 when that comment was made.

09:15.020 --> 09:17.900
So, yeah, no one seems to have discussed this stuff.

09:18.380 --> 09:21.740
So how are we going to work this in?

09:21.860 --> 09:24.960
So browsers have to be as flexible as possible.

09:24.960 --> 09:37.580
You get websites written by kiddies in notepad, and you get professional websites written in HTML5 with web APIs and SOAP interfaces, and the browser has to be able to support it all.

09:37.760 --> 09:49.220
And this leads to a certain amount of flexibility on how things are understood, how things are supported, which obviously leads to the dark side.

09:49.680 --> 09:53.020
And then, of course, there's RFCs, which some would say is the dark side.

09:54.400 --> 09:56.300
They're more of a guideline, really.

09:56.940 --> 10:02.860
This is the way you should do it, but we're not going to tell you exactly how, so it depends how drunk you were when you read it.

10:03.920 --> 10:05.380
Maybe this makes sense.

10:05.380 --> 10:08.340
So, yeah, what could possibly go wrong?

10:08.340 --> 10:17.200
You have 300‑page RFC and people who are going to interpret it, and you implement it into a piece of software which has to be as flexible as possible, otherwise things don't work.

10:17.420 --> 10:18.820
Things are going to start to go wrong.

10:18.820 --> 10:21.400
So I started to do a little bit of testing.

10:22.320 --> 10:24.780
I wanted to restrict myself to the big three.

10:25.040 --> 10:27.760
Internet Explorer, Chrome, Chromium and Firefox.

10:28.860 --> 10:29.580
No?

10:29.580 --> 10:30.300
Yes.

10:33.840 --> 10:39.840
Apparently Opera turned really bad, or there's Lynx, but who uses Lynx?

10:40.620 --> 10:42.300
One guy uses Lynx.

10:42.320 --> 10:44.160
Welcome to the 20th century.

10:47.220 --> 10:52.220
So I wanted to take the easy option on testing, so I thought, okay, well, there's man in the middle proxy.

10:52.900 --> 10:56.660
It's a Python‑based system for man in the middling HTTP connections.

10:56.940 --> 10:59.840
It allows you to set up this really interesting reverse proxy.

10:59.920 --> 11:01.960
It's all script‑based and it does all the work for you.

11:01.960 --> 11:05.060
You just write something like this in a script file.

11:05.740 --> 11:06.540
That's it.

11:07.180 --> 11:10.220
All this does is change every response code to a 200.

11:12.400 --> 11:13.420
That's easy.

11:13.420 --> 11:14.940
Even I can code that shit.

11:16.360 --> 11:20.220
Unfortunately, man in the middle proxy tends to use up all of the memory you have on your machine.

11:21.920 --> 11:24.640
Even if you have 8 gigabytes of memory in your laptop.

11:25.220 --> 11:29.600
I would highly recommend man in the middle dump, which doesn't cache everything into memory.

11:30.340 --> 11:32.160
Just a side note there.

11:32.160 --> 11:36.640
I also used PHP, the amazing personal home page.

11:38.320 --> 11:41.680
It allows you to set response codes, but there's some downsides.

11:41.740 --> 11:47.140
You can also prepend a file, which is going to allow you to set specific response codes or do some logic in the background.

11:47.140 --> 11:57.120
The problem is if the web server says, no, this is an incorrect request, the PHP is never going to get to actually see the request, so you can't set response codes.

11:57.120 --> 11:58.720
So you can do some interesting stuff.

11:58.720 --> 12:03.480
For testing, it's useful, but in production, it's not really going to be as useful as it could be.

12:03.480 --> 12:10.120
So I used a mismatch of Python and PHP for most of the testing.

12:10.560 --> 12:24.600
You don't need to write this down, because I'll release all the slides afterwards, but simple testing of browsers, how things are supported, you just call a PHP page, which sets the response code, you tell it what code in the URL, and you hope no one cross‑sites your website.

12:26.040 --> 12:27.080
As simple as that.

12:27.080 --> 12:43.200
You get a response, you get the requested response code and the actual response code, because with PHP, you can set that response code to 999 if you want, but Python is just going to say, oh, sorry, Apache is just going to turn around and say, I don't know what that response code is,

12:43.200 --> 12:48.180
and then it just returns a 500, which is the they fucked up section of it.

12:48.220 --> 13:02.860
So, yeah, you get to see what you requested, you get to see what the response was, and you get to see what the headers are, so simple JavaScript running in the browser, so great, I can run off and start testing these browsers, which seemed like an easy thing.

13:03.140 --> 13:14.340
I started to think, I've got all this data on how all these browsers work, and how can I graphically display that in a nice fashion?

13:14.980 --> 13:17.940
Let's just say that I'm not good at charting.

13:22.120 --> 13:29.200
Sorry, for the women in the room, also, I'm trying to keep this even across the sexes.

13:29.900 --> 13:37.380
So I didn't really know how to display this, so I spoke to some guys who do visualization, and they were like, oh, yeah, we can do this and we can do that, and it was just all shit.

13:38.300 --> 13:41.540
So what I ended up with was a table.

13:46.640 --> 13:52.700
Yeah, this is the reason why I cut it down to three browsers, because otherwise the table would be like this fucking wide.

13:53.600 --> 14:06.460
So, yeah, there's a full table online, which I'll release after the talk, which has a lot of other browsers and scripting languages in it, but this is the core three, so you start to see quite a lot of conformity in this section about how the browsers respond to things.

14:06.460 --> 14:12.440
So I run it into three sections, so can you load HTML with a 100 response code?

14:12.720 --> 14:26.680
Well, you can, but nothing appears, it doesn't render anything, so the browser just doesn't support it, unless it's an iframe with Chrome, in which case it tries to download it, because I guess Chrome just likes to download shit.

14:28.800 --> 14:44.760
What's kind of interesting, if you have Chrome on an Android phone and you respond with a 100 code, it tries to download it, but it never finishes, so you have to restart your Android to get it to stop, which is fun.

14:46.820 --> 14:48.840
I'm sure no one would fuck with that.

14:51.980 --> 15:01.900
So looking at this, you're like, okay, well, all the browsers are kind of mostly conform, except IE, obviously, which doesn't care about a 205 and just renders the stuff, it doesn't care.

15:01.900 --> 15:18.900
You start to see differences when you're looking at the 300 codes, for example, Firefox just doesn't load JavaScript if you respond with a 300 or a 301, IE pretty much just ignores everything if you respond with anything in the 300 range which isn't a redirection,

15:18.900 --> 15:22.080
but Chrome pretty much accepts everything because it doesn't give a shit.

15:22.600 --> 15:24.880
It's the honey badger of browsers.

15:27.140 --> 15:32.500
Moving kind of into the 400 stuff, you start to see more conformity, again, IE being the weird one.

15:32.500 --> 15:35.660
It just doesn't like loading iframes with weird response codes.

15:36.400 --> 15:41.380
And you see these at a time when it says 407 proxy, proxy, proxy.

15:43.040 --> 15:48.420
Basically what that means is that Chrome, depending if you have a proxy set or not, will load it.

15:48.420 --> 15:54.960
So if you have a proxy, an HTTP proxy set, then Chrome will load the content when it's responded with a 407.

15:55.020 --> 15:56.640
If you don't, then it won't.

15:58.680 --> 16:04.800
Again with the 500s, things are pretty standard, again, IE being kind of a little bit of a weird outlier on things.

16:04.940 --> 16:05.320
Okay.

16:05.320 --> 16:07.740
So think about this for a second.

16:07.800 --> 16:11.440
You've got browsers that kind of handle things in slightly different ways.

16:11.820 --> 16:13.600
What can we do with that kind of stuff?

16:13.780 --> 16:18.420
But a majority of stuff is like, okay, that's just content.

16:18.420 --> 16:19.640
I don't care what it is.

16:19.640 --> 16:20.740
It's loading stuff.

16:20.740 --> 16:25.440
It's like you get a 400 response and it's like, oh, I see HTML, I'm just going to render that for you.

16:25.440 --> 16:28.480
Or I see JavaScript, I'm just going to run that JavaScript for you.

16:28.520 --> 16:33.800
So most things, mostly, things are loaded quite normally.

16:33.800 --> 16:35.880
But there's some weird kind of outliers.

16:36.540 --> 16:41.280
So with HTML responses, almost all response codes are rendered correctly.

16:41.340 --> 16:42.320
It doesn't care.

16:42.380 --> 16:49.060
When you try and load an iframe and it comes back with a response, there's some special cases for IE because IE is special.

16:49.900 --> 16:52.100
But most of the time kind of things are even.

16:52.100 --> 16:56.740
And if you start looking at JavaScript, there's very limited support for it.

16:56.740 --> 17:00.260
Chrome being the exception because they just don't care.

17:00.900 --> 17:04.540
So we know what browsers interpret differently.

17:05.300 --> 17:07.520
So what do all the browsers have in common?

17:07.720 --> 17:10.540
What are they doing the same across the board?

17:10.540 --> 17:16.420
The 100 codes, retries, confusion, as I said, fun on Android, never-ending downloads.

17:16.980 --> 17:19.240
And it times out eventually.

17:19.660 --> 17:22.120
Because the browser thinks there's more coming.

17:22.200 --> 17:24.820
The browser thinks, oh, you're going to send more data in a minute.

17:24.820 --> 17:26.800
I'll just sit here and wait for you.

17:27.960 --> 17:29.580
Which is kind of interesting.

17:29.660 --> 17:32.880
The 200 codes, again, you get the no content or not modified.

17:32.940 --> 17:36.320
You get headers saying, no, there's nothing here.

17:36.360 --> 17:44.360
So as you would expect, all the browsers just ignore any kind of content that you're responding because it doesn't expect there to actually be any content within those things.

17:45.540 --> 17:46.840
So what about headers?

17:47.520 --> 17:47.760
Okay.

17:47.760 --> 18:00.680
So RFCs quite a lot of the time in kind of a muddy language say if you're responding with a free XX response code, whether it's 301 or 302 or 303, there should be a location header.

18:01.340 --> 18:03.120
It doesn't mean it has to.

18:03.700 --> 18:10.960
If you respond and you don't have a location header, it just kind of ignores the fact that it's meant to do a redirect and then renders whatever content you give it.

18:12.920 --> 18:15.200
Specifically, no location header, no redirect.

18:15.200 --> 18:16.220
This makes sense.

18:16.220 --> 18:21.080
Because you're responding with a 302, it's looking for the location header, it doesn't find one.

18:21.080 --> 18:25.980
Instead of just giving you an unhelpful error in your browser, it's just going to render what you returned and ignore.

18:26.260 --> 18:27.300
Simple as that.

18:27.320 --> 18:35.940
So the 401 unauthorized as well, if you're not sending back a www authenticate header, it's not going to prompt you.

18:35.940 --> 18:36.980
Simple as that.

18:38.240 --> 18:43.540
And I mentioned previously about the 407 proxy authentication required, the way Chrome deals with it.

18:43.540 --> 18:48.560
Again, if you're not requesting the authentication, then it's never going to prompt you.

18:49.240 --> 18:56.560
On the flip side, just because an RFC says a specific status code shouldn't have a header, doesn't mean it can't have a header.

18:57.220 --> 19:03.740
So if you read the RFCs, there's 300 multiple choices.

19:04.720 --> 19:06.620
Now, this shouldn't have a location header.

19:06.740 --> 19:08.020
It doesn't redirect you.

19:08.020 --> 19:12.440
It should come up with an HTML where you can specifically select where you would like to go.

19:12.780 --> 19:18.340
Unless, of course, you're Firefox or IE, in which case if you give it a location header, it's just going to redirect.

19:18.860 --> 19:20.180
But Chrome isn't.

19:20.660 --> 19:23.380
And there are so many headers out there you can play with.

19:23.380 --> 19:24.500
I've played with quite a lot of them.

19:24.500 --> 19:27.220
Most of them are not particularly interesting, unfortunately.

19:27.420 --> 19:30.920
But there's more work to be done in that kind of area.

19:30.920 --> 19:36.760
There's a load of headers like the retry after header that can really be played with and a little bit more research is required there.

19:37.180 --> 19:40.160
So each browser is handling something a little bit differently.

19:41.380 --> 19:43.400
We know how things are handled the same.

19:43.400 --> 19:45.040
We know how things are handled differently.

19:45.900 --> 19:47.400
I wonder what we can do with that.

19:48.940 --> 19:51.620
So what can we do with that?

19:51.620 --> 19:53.000
What are the goals?

19:53.000 --> 19:53.140
Okay.

19:53.140 --> 19:55.900
So each browser handles things differently.

19:55.900 --> 20:05.080
You have the handled codes, you have the unhandled codes, and then you get this little browser weirdness thing where it just does random stuff you just didn't expect it to do depending on the headers.

20:05.760 --> 20:08.080
So browser fingerprinting.

20:08.200 --> 20:08.380
Okay.

20:08.380 --> 20:13.060
So, yeah, you can check user agent strings, but that's client side controlled.

20:13.060 --> 20:14.780
You can easily spoof that stuff.

20:15.420 --> 20:23.020
But if you take the differences, you can really do some interesting fingerprinting work on Firefox, on Chrome, and on IE.

20:23.020 --> 20:28.200
So on Firefox, based on the information we have, it doesn't load JavaScript return with a 300.

20:28.700 --> 20:30.060
The other browsers do.

20:30.060 --> 20:34.700
So you simply return a JavaScript with a 300, and if the JavaScript runs, it's Firefox.

20:34.760 --> 20:35.900
Simple as that.

20:36.180 --> 20:36.800
Okay?

20:37.380 --> 20:45.260
With Chrome as well, it loads Java return with a 307, temporary redirect, without a location header, but the other browsers don't.

20:45.260 --> 20:48.140
So again, we can do the same kind of thing, and we can do some fingerprinting.

20:48.420 --> 20:54.560
And with IE, it loads JavaScript return with a reset content status code, and nothing else does.

20:54.600 --> 21:02.040
So if we can add all that stuff together, you can get a nice way of fingerprinting the main browsers without even bothering to look at the location header.

21:02.160 --> 21:12.400
Or you can use the user agent header, and then specifically say, well, I'm going to check that by seeing how your browser really works.

21:12.500 --> 21:14.640
So I'm going to do a quick demo.

21:15.000 --> 21:15.900
Well, actually, I lied.

21:15.900 --> 21:19.700
I'm going to run a quick video of a demo, because I didn't want to connect to the network here.

21:23.200 --> 21:24.200
First talk.

21:24.200 --> 21:32.040
So all this is doing is loading a PHP page, and then running through and loading three individual pages.

21:33.880 --> 21:44.240
It then checks the responses, checks the JavaScript, and says, so this JavaScript ran, this JavaScript didn't, so you must be using this specific browser.

21:44.320 --> 21:50.520
So if you zoom in, well, if I zoom in, there you go.

21:50.520 --> 21:52.260
So you can see the specific responses.

21:52.260 --> 22:01.860
You can see that it's loading an HTML, it's coming back with a 300, a 307, and a 205, which are the three specific response codes we talked about for the different browsers.

22:01.860 --> 22:09.740
It's then sending all of that stuff to a PHP page on the server, and the PHP page is returning and saying, okay, this is the specific browser.

22:10.180 --> 22:15.580
So obviously I'm returning back to the browser to display a pop‑up to say this is the browser.

22:15.680 --> 22:23.180
In most cases, you're sending it to the server, and then you're never responding back, because I know I'm running IE.

22:23.180 --> 22:24.880
I have the little IE bar at the top.

22:24.880 --> 22:27.000
I don't need you to do a pop‑up and tell me.

22:27.160 --> 22:30.420
But the server now knows exactly what kind of browser you're using.

22:30.420 --> 22:39.640
So if you're spoofing a user agent string, then I can say, okay, so user agent string says you're running Firefox, but you're actually running Chrome.

22:39.640 --> 22:43.560
That's suspicious, and that's something that we should be looking at, okay?

22:44.080 --> 22:47.520
So there's various other options for fingerprinting.

22:47.520 --> 22:51.520
This specific option I selected was kind of the easiest option.

22:51.520 --> 22:52.480
There's various other stuff.

22:52.480 --> 22:56.520
There's a 300 redirect, there's a 400 iframe on Internet Explorer.

22:56.900 --> 23:06.260
If you want to look at the proof of concept, if you go to C22.cc, fingerprint.html, it will run the same example I just ran.

23:06.260 --> 23:09.240
You can look at the traffic, and the code is available.

23:09.240 --> 23:10.580
I'll link to that at the end.

23:10.580 --> 23:12.680
So user agents can be spoofed.

23:12.680 --> 23:13.460
Everyone knows that.

23:13.460 --> 23:15.480
Even script kiddies, unfortunately, know that.

23:15.880 --> 23:18.140
But browser traits are really hard.

23:18.500 --> 23:22.280
Because your browser responds and does things in specific ways.

23:22.400 --> 23:23.420
So we've done that.

23:23.420 --> 23:24.700
We can fingerprint browsers.

23:24.700 --> 23:25.300
So what else can we do?

23:25.300 --> 23:26.420
Proxy detection.

23:26.420 --> 23:29.600
We specifically talked about the way Chrome handles things.

23:29.800 --> 23:34.960
And if you have an HTTP proxy set, you can specifically say, okay, I know they're using Chrome.

23:35.180 --> 23:37.120
I'm going to respond with a 407.

23:37.220 --> 23:41.000
If it loads the page, then they're using an HTTP proxy.

23:41.200 --> 23:42.940
There's unfortunately limitations here.

23:42.940 --> 23:44.700
It doesn't pick up with SOX proxies.

23:44.780 --> 23:47.180
But your average user isn't using a SOX proxy anyway.

23:47.760 --> 23:53.720
It's a limited interest, but it's something that needs further testing.

23:53.720 --> 24:01.280
As I said, all you do is respond with a 407 with a proxy authentication header or without a proxy authentication header.

24:01.280 --> 24:04.020
And if Chrome responds, then HTTP proxy is set.

24:04.080 --> 24:11.660
So while I was doing this research, I decided I was going to try a couple of different HTTP proxies.

24:11.660 --> 24:16.440
And one of the proxies I selected was Privoxy.

24:16.920 --> 24:21.160
It's quite a popular privatizing HTTP proxy.

24:21.700 --> 24:33.060
So I found while I was testing this, if you respond with a ‑‑ so your web server, you go to my web server, you respond with a 407 proxy authentication required, you get the pop‑up in your browser.

24:33.260 --> 24:36.320
But it doesn't say that my web server asked you for a username and password.

24:36.320 --> 24:39.040
It says Privoxy asked you for a username and password.

24:40.020 --> 24:41.120
Which is interesting.

24:41.120 --> 24:43.920
So why is my local proxy asking for a username and password, I thought.

24:43.920 --> 24:47.380
So I typed in test, test, and I clicked send.

24:47.880 --> 24:51.300
And my web server gets my username and password.

24:52.720 --> 24:54.120
That's kind of interesting.

24:54.120 --> 24:56.380
I'm sure we can use that for some malicious stuff.

24:56.820 --> 24:58.340
But this is a defensive talk.

24:58.340 --> 25:00.040
So I'm not going to dive too much into that.

25:00.040 --> 25:01.520
But it's kind of interesting.

25:01.980 --> 25:06.760
Let's just say proxies aren't always configured quite so securely as they could be.

25:07.020 --> 25:08.140
There's a fix for that now.

25:08.140 --> 25:09.800
So you can download the latest version.

25:09.880 --> 25:11.620
But it's not just Privoxy.

25:11.620 --> 25:17.360
Any transparent proxy, things like burp or zap, they're designed to pass everything you give it.

25:17.560 --> 25:23.380
So if my web server responds with a 407 and asks for authentication, burp suite will just pass it to your browser.

25:23.380 --> 25:24.280
Simple as that.

25:24.620 --> 25:31.740
So you can start screwing with people who you know are doing malicious things on your site with intercepting proxies.

25:32.460 --> 25:39.180
Of course, if you're doing a test with burp suite and it says what's your username and password, I'm probably not going to type in my real username and password.

25:39.360 --> 25:40.500
But you never know.

25:40.500 --> 25:42.320
Script kiddies type in weird stuff.

25:43.900 --> 25:46.300
So let's bring all this stuff together.

25:46.300 --> 25:49.780
So we've got status codes that are treated like content.

25:49.780 --> 25:50.700
They don't care.

25:50.860 --> 25:55.940
You've got status codes that really are not specifically well handled, specifically the 100 codes.

25:55.940 --> 25:58.740
And you've got lots of little browser quirks that we can abuse.

25:59.040 --> 25:59.880
So what can we do?

25:59.880 --> 26:05.200
We can play with things just in case there's children in the room.

26:05.960 --> 26:09.360
We can make the people who like RFCs cry into their beer.

26:09.720 --> 26:13.340
So let's try to use what we've discovered.

26:13.340 --> 26:15.060
Let's break some spidering tools.

26:15.980 --> 26:18.220
Cause some false positives, false negatives.

26:19.000 --> 26:22.900
Slow down attackers, which is probably one of the most important things that we can do.

26:22.900 --> 26:26.440
Give us time to respond to how people are attacking us.

26:26.860 --> 26:29.080
And then block successful exploitation.

26:29.380 --> 26:35.960
So even if they do manage to exploit the server, if you're responding specifically with different codes, maybe their exploit is not going to work.

26:35.960 --> 26:38.600
So let's talk a little bit about spiders.

26:39.620 --> 26:43.100
This is a very simplistic and naive view of spiders.

26:43.240 --> 26:47.840
But you access the target URL, you read the links, you test them.

26:47.840 --> 26:49.180
If true, continue.

26:49.180 --> 26:53.400
So if you get a 200 okay, that's true, right?

26:53.400 --> 26:57.780
And if you get a 404, that's false, right?

26:57.880 --> 27:01.980
But what happens if everything is a 200?

27:02.220 --> 27:04.420
And what happens if everything is a 404?

27:04.420 --> 27:06.000
You start to get some weird stuff.

27:06.000 --> 27:07.560
And what happens if everything is a 500?

27:08.480 --> 27:11.900
Sometimes if everything is a 500, then everything is a SQL injection attack.

27:12.400 --> 27:18.620
So if everything is a 200, you end up with this interesting loop of, oh, I found another directory.

27:18.840 --> 27:21.700
I will just keep scanning and keep scanning and keep scanning.

27:21.720 --> 27:23.440
You get this never‑ending spider.

27:23.460 --> 27:26.100
Unfortunately I couldn't find a picture of a spider eating itself.

27:26.380 --> 27:29.740
So if anyone has one, please send it to me.

27:30.940 --> 27:33.940
And if everything is a 404, what website?

27:34.400 --> 27:36.120
I don't know if you can see this at the back.

27:36.120 --> 27:40.520
This is the wonderful Acunetix tool, the script kiddies tool of choice.

27:41.340 --> 27:46.540
The crawler found zero pages, zero files, and validated zero findings.

27:47.260 --> 27:47.700
Yeah.

27:47.700 --> 27:48.860
So what website?

27:49.000 --> 27:50.480
There is no website there.

27:50.900 --> 27:52.480
Skipfish loves it.

27:52.640 --> 27:55.640
It just keeps going and going and going until it kills itself.

27:57.660 --> 28:03.200
I'm guessing at this point my test server just decided it didn't have enough memory to deal with all the responses.

28:03.500 --> 28:11.880
If you look closely, there is also 2,000 low, 2,000 medium false findings on the scan alone.

28:12.040 --> 28:13.720
So, yeah.

28:14.120 --> 28:17.780
Playing with people's spiders is kind of interesting.

28:17.860 --> 28:20.220
So false positives, false negatives.

28:20.220 --> 28:26.320
We can start to hide how bad or how good our servers are, start to really screw with people and waste their time.

28:26.800 --> 28:29.920
So most scanners use response codes in some way.

28:29.920 --> 28:30.940
They kind of have to.

28:30.940 --> 28:32.700
You speed up detection.

28:33.800 --> 28:35.560
You can't use rejects for everything.

28:35.560 --> 28:37.040
It's the easy solution.

28:37.140 --> 28:58.600
So if we start to respond with, again, 200 okay, 404, 500, and if we start to play with them and respond with random codes, random being a selection of codes that are handled well by all normal browsers, so the normal people browsing the website are not going to be affected in any way,

28:58.600 --> 29:00.740
you start to see some really interesting stuff.

29:00.740 --> 29:03.780
So it's a quick baseline using W3AF.

29:04.000 --> 29:06.080
I didn't particularly pick on these people.

29:06.080 --> 29:08.240
It just happens to be an interesting baseline.

29:08.240 --> 29:19.540
So a standard baseline for my test system was 79 informational points, 65 vulnerabilities, no shells, which kind of took an hour and 37 minutes to do a scan.

29:20.120 --> 29:25.240
So if everything responds with a 200 okay, you still get everything.

29:25.500 --> 29:29.460
So we're not winning on the false positives and false negatives.

29:29.520 --> 29:34.100
It takes you nine hours to run the scan, which is kind of interesting.

29:34.100 --> 29:37.080
It lets us win time, but it's not really working.

29:37.080 --> 29:39.340
So a 200 okay isn't really going to do what we need it to do.

29:39.340 --> 29:44.620
So if everything is a 404, it's a lot quicker to do the scan because you're not finding everything.

29:44.620 --> 29:48.640
But it's missing a majority of the information points and a majority of the vulnerabilities.

29:49.260 --> 29:51.620
So you're starting to see some interesting stuff.

29:51.620 --> 29:55.140
If we start responding with weird codes, they don't find everything.

29:55.140 --> 29:55.440
Okay.

29:55.440 --> 29:56.540
That's interesting.

29:56.920 --> 29:59.960
If you respond with everything with a 500, wow.

30:00.780 --> 30:02.300
False positives.

30:02.380 --> 30:05.200
If it's a 500, like I said, it's SQL injection.

30:05.380 --> 30:08.220
9,000 informational points.

30:09.460 --> 30:11.960
Try digging through that report, you know.

30:12.280 --> 30:15.060
9,000 confusing information and confirmed vulnerabilities.

30:15.640 --> 30:17.720
I can just see that pen test report, sorry.

30:17.720 --> 30:19.440
That vulnerability analysis.

30:19.660 --> 30:21.740
That's going to be about 1,000 pages long.

30:21.740 --> 30:23.020
Oh, no, we found all this stuff.

30:23.020 --> 30:25.420
We have IAS vulnerabilities and this and that.

30:25.420 --> 30:28.880
It's an Apache server, but we still have all of these IAS vulnerabilities.

30:30.140 --> 30:32.840
So any people who use Nessus in the room?

30:32.840 --> 30:33.340
No.

30:34.020 --> 30:40.440
So if we start using random status codes, I did multiple runs of this to make sure that I'm getting accurate.

30:40.440 --> 30:43.280
Because if it's being random, maybe I just had a bad run.

30:43.440 --> 30:47.900
It averaged out as giving you a reasonable amount of false positives.

30:48.240 --> 30:51.700
And it took less time to run the scan.

30:52.100 --> 31:00.080
What I found interesting on this was a majority of the things that it did find, it didn't find the real vulnerabilities, it just found weird stuff.

31:00.240 --> 31:06.820
So even though it found more vulnerabilities and you get lots of false positives, they're pretty much all false positives.

31:06.860 --> 31:09.420
So the real stuff just doesn't get found at all, okay?

31:10.620 --> 31:13.680
So skip fish and random, wow.

31:14.500 --> 31:16.160
It doesn't like random.

31:16.160 --> 31:18.380
Let's just say skip fish is particularly picky about it.

31:18.380 --> 31:22.200
So the first scan time took ten hours and the second scan time took four seconds.

31:24.400 --> 31:26.040
Yeah, and then again 16 hours.

31:26.040 --> 31:29.620
I ran it about five times and it would just randomly flick between times.

31:29.620 --> 31:33.440
So skip fish is a wonderful denial of service tool for web applications.

31:34.200 --> 31:40.640
I think in my proxy it sent like 33,000 requests inside five, six minutes.

31:41.380 --> 31:43.480
Yeah, it would pretty much take down everything.

31:45.800 --> 31:49.220
So we're not really slowing attackers down.

31:49.340 --> 31:51.740
So what can we do to slow the attackers down?

31:52.540 --> 31:54.820
What's our WAF really doing at the moment?

31:55.500 --> 32:00.840
A standard WAF, again, a naive view, oh, my God, I'm being attacked.

32:01.000 --> 32:08.480
Block or return an error whether or not that's a 403, a 500, or a 404, or a 200 with a nice message telling them to piss off.

32:09.880 --> 32:10.700
Profit?

32:10.700 --> 32:11.980
There's no profit there.

32:11.980 --> 32:16.620
Okay, for us as defenders, with my defender hat on, we've won nothing.

32:16.620 --> 32:19.880
All we've done is blocked an IP address or blocked an attack.

32:20.000 --> 32:24.720
They come back with an obfuscation, we bypass it, game over, okay?

32:24.720 --> 32:26.780
So why are we doing that?

32:27.900 --> 32:34.200
Remember this big list of things that browsers don't handle very well, specifically the 100 stuff?

32:34.200 --> 32:36.020
Well, scanners don't like them either.

32:36.500 --> 32:40.040
Surprising there, because a scanner thinks it's going to be a browser.

32:40.040 --> 32:42.140
It's trying to do everything that a browser does.

32:42.140 --> 32:46.920
So looking at the 100 codes, we can start to really screw with stuff.

32:46.920 --> 32:49.120
So does anyone remember the library topic?

32:51.300 --> 32:54.380
So it should be Tomlisten, not Timlisten.

32:55.020 --> 32:56.860
Apologies, Tim.

32:57.580 --> 33:02.380
So it was originally designed to slow the spread of code red, and it slows down attackers.

33:02.380 --> 33:03.940
I mean, this was a great idea.

33:04.720 --> 33:07.140
Did we forget that this was a great idea?

33:07.140 --> 33:10.640
Did we think that, okay, well, it's been done now, we can just forget about it?

33:10.640 --> 33:17.640
In our drive to kind of find new and interesting research, it's been done once, so we should just ignore it for the rest of time.

33:18.400 --> 33:20.500
So I had this interesting idea.

33:20.680 --> 33:22.660
How about an HTTP tar pit?

33:23.600 --> 33:29.620
People have probably talked about this a thousand times before, but, you know, it was interesting to me.

33:29.620 --> 33:30.180
Whoa.

33:34.800 --> 33:37.420
This is the problem when you run PowerPoint.

33:44.860 --> 33:48.140
Drink, drink, oh.

33:53.460 --> 33:55.160
Morning DEF CON.

33:56.380 --> 33:58.360
It's Sunday morning, you know what that means?

33:58.520 --> 34:00.820
Drink, that's right.

34:00.820 --> 34:03.120
Say a round of applause for our first-time speaker.

34:06.960 --> 34:08.500
How's he doing so far?

34:08.540 --> 34:09.360
Doing okay?

34:11.740 --> 34:13.100
All right, hook us up.

34:13.100 --> 34:15.080
I am not drinking all of those.

34:17.620 --> 34:20.660
All right, who's first time at DEF CON?

34:21.040 --> 34:23.460
First hand up, right here, come on up on stage.

34:29.960 --> 34:32.580
If it's Sunday morning, that means this is the hard core, right?

34:32.580 --> 34:34.620
Right here, you guys all got up, good job.

34:34.880 --> 34:35.580
All right.

34:36.100 --> 34:36.820
Congratulations.

34:36.960 --> 34:37.500
Cheers.

34:41.020 --> 34:46.880
That reminds me of last night.

34:50.020 --> 34:51.260
So where was I?

34:52.660 --> 34:54.520
Oh, yeah, I was in a tar pit.

34:54.720 --> 34:58.020
So simple scenario.

34:58.940 --> 35:00.600
So the WAF detects the scan.

35:00.780 --> 35:03.360
Again, we are at the oh, my God, attack section.

35:04.120 --> 35:07.020
It adds the IP address to the naughty list.

35:07.680 --> 35:09.860
And then it starts to rewrite all the responses.

35:10.260 --> 35:14.640
So you get the usual 100, 101, 102 status codes.

35:14.640 --> 35:18.640
We just randomly rotate between them, depending on how bored we are all the time.

35:19.020 --> 35:25.040
We can also use 204, 304, which could be useful, but it's not nearly as fun as the 100 status codes.

35:25.040 --> 35:29.040
So let's do some experimentation, shall we?

35:29.420 --> 35:32.000
There's no actual science included in this.

35:33.420 --> 35:36.680
So Nikto, wonderful tool.

35:37.220 --> 35:38.160
I like it a lot.

35:38.160 --> 35:39.660
I especially like the logo.

35:40.360 --> 35:44.920
So the baseline scan, 2 minutes, 18 seconds to find 18 findings.

35:45.400 --> 35:46.720
Simple as that.

35:47.640 --> 35:54.840
With the tar pit, yeah, we're winning some time there.

35:54.840 --> 35:56.040
Let's just say that.

35:56.640 --> 36:01.320
It's like a 340 fold increase in time.

36:01.320 --> 36:03.480
But it's still finding quite a lot of stuff.

36:03.480 --> 36:09.200
This is mostly informational stuff, like you have an Apache whatever version as your server header.

36:09.380 --> 36:13.320
Even if you respond with 100 code, it's still going to get that header.

36:13.320 --> 36:15.280
So most of that stuff is kind of uninteresting.

36:15.280 --> 36:17.800
Some of the findings, they disappear.

36:18.320 --> 36:21.180
And the script kitty spends 14 hours scanning your web server.

36:21.180 --> 36:22.960
So we're kind of winning.

36:23.380 --> 36:29.160
So W3AF, again, same baseline as before, 1 hour, 37 minutes, 65 findings.

36:29.480 --> 36:31.560
But wait a minute, this is going in the wrong direction.

36:31.580 --> 36:33.840
18 minutes instead of 1 hour, 37.

36:34.200 --> 36:35.220
It's weird.

36:35.220 --> 36:36.160
That shouldn't be happening.

36:36.160 --> 36:37.620
But it didn't find anything.

36:37.680 --> 36:47.540
So I'm guessing there was some kind of algorithm there that said I'm just going to stop bothering to scan your web server now because it's kind of weird and I don't know what the fuck is going on.

36:49.960 --> 36:54.420
So yeah, back to the denial of service skip fish tool.

36:55.920 --> 37:07.160
18 minutes, 10 seconds to find around, 2,500 low, mediums and a couple of highs, which unfortunately even on the baseline were mostly false positives, but whatever, each to their own.

37:07.160 --> 37:08.520
So 5 seconds.

37:09.500 --> 37:11.300
Again, we're going in the wrong direction.

37:11.300 --> 37:15.140
But there was no lows and there was no mediums and there was only three highs.

37:15.660 --> 37:21.420
What I thought was interesting was the three highs that it found were not any of the 12 highs that it found previously.

37:22.400 --> 37:27.360
So not only false positives but different false positives to the normal scan.

37:27.360 --> 37:34.780
So okay, it's kind of doing weird stuff and we like weird stuff because we're mucking around with automated scanners and we're screwing the script kiddies.

37:34.780 --> 37:35.760
So random is good.

37:36.280 --> 37:40.440
So Acunetix, as I said before, the script kiddy tool of choice.

37:41.620 --> 37:47.720
So you get a one‑hour scan, it's quite reasonable, with a huge amount of informational stuff that you probably don't care about.

37:48.440 --> 37:55.660
And again, we're going in the wrong direction and this HTTP target should be slowing stuff down but it's making stuff faster depending on what scanner you're using.

37:56.600 --> 38:02.260
But again, okay, that's an interesting ratio of complete false negatives.

38:02.560 --> 38:04.080
So it's just not finding stuff.

38:04.080 --> 38:10.300
So some of these scanners are just like, okay, now this web server is just playing silly buggers, I'm just going to stop bothering to scan it at all.

38:10.300 --> 38:14.420
What's interesting, it doesn't tell you that it's just going to give up.

38:14.420 --> 38:15.700
It just says, I'm finished.

38:16.280 --> 38:17.740
It just says, no, I'm done.

38:18.560 --> 38:20.140
So what do we find?

38:20.140 --> 38:30.220
So you can slow down some scanners, things like Nikto, others give up quicker because they just get tired of getting responses from the server or a timeout and say the server is not there anymore.

38:30.380 --> 38:35.780
If you look through a log file, I'm sure somewhere along the line it says the web server stopped responding even though it didn't.

38:36.320 --> 38:38.840
But you get a lot of unreliable and aborted scans.

38:38.980 --> 38:41.880
So up to 100% less findings.

38:42.020 --> 38:43.580
That's a win for us.

38:45.480 --> 38:49.180
So let's move on to blocking successful exploitation.

38:49.180 --> 38:53.840
So even if someone can get past all of this, they can find a high criticality in your web server.

38:54.620 --> 38:59.540
So we've made it hard for them to find them, but people are going to find these vulnerabilities no matter what.

38:59.540 --> 39:06.960
We've made it so that possibly it's going to take them 15,000 times longer to find the vulnerabilities, but they're going to find stuff.

39:06.960 --> 39:10.200
So let's stop them from popping shells with Metasploit.

39:11.120 --> 39:15.600
Now, how often does Metasploit reference status codes?

39:16.180 --> 39:17.860
Anyone care to guess?

39:19.900 --> 39:20.320
No?

39:20.320 --> 39:22.200
It's about 1,000.

39:22.420 --> 39:23.480
Give or take.

39:23.480 --> 39:36.060
This is not scientifically sound and it depends very much on how people are wording things and how they're using their variables, but this is a simple grab through searching for res.code, resp.code and response.code.

39:36.060 --> 39:39.260
These are the usual things that people use.

39:39.260 --> 39:42.520
And there's lots of dependency on status codes.

39:42.980 --> 39:46.200
Unfortunately even the stuff I wrote uses status codes.

39:46.200 --> 39:54.300
So I know it's bad programming, but it's quick and it's what we all do because we use status codes to check the response from servers.

39:54.300 --> 40:01.640
So here's an example of a simple snippet of code from one of the Metasploit checks.

40:01.640 --> 40:06.920
So all it's doing is checking if the response code is less than a 200 or more than a 300.

40:08.020 --> 40:09.940
So I can return a 500.

40:10.540 --> 40:11.200
That's great.

40:11.200 --> 40:13.440
I can return a 500 with the content.

40:13.980 --> 40:15.380
And then it's failing.

40:15.800 --> 40:21.360
So if it's not anywhere in the 200 range, which is the okay, then the exploit just fails.

40:21.380 --> 40:22.200
Simple as that.

40:22.260 --> 40:23.000
Okay, great.

40:23.000 --> 40:28.780
So if we're spoofing 404 but still giving you the content, then this exploit is always just going to fail.

40:29.120 --> 40:36.580
And if you're good enough to go in and edit the code and change things and you really know what's going on, then you're not really the target of this talk.

40:36.580 --> 40:39.300
We're targeting script kiddies who know absolutely nothing.

40:39.300 --> 40:43.200
All they know how to do is run the code and if it doesn't work they just cry in a corner.

40:45.080 --> 40:54.380
Interesting side effect, if it is a 401, it just starts to print out the response headers like the www authenticate or the authentication header.

40:54.460 --> 40:57.420
Of course, as we mentioned before, we don't need to send those headers.

40:57.420 --> 41:00.860
So what happens if you don't send those headers?

41:00.940 --> 41:11.980
You start to get errors within Metasploit because it's trying to print out stuff that it shouldn't really ‑‑ should be there but it's actually a nil value because we haven't actually set it at all because we haven't provided it.

41:12.080 --> 41:13.680
So that's an interesting side effect.

41:14.080 --> 41:16.140
So no match, no shell.

41:16.640 --> 41:17.200
Okay?

41:17.200 --> 41:18.340
No cookie for you.

41:18.340 --> 41:19.100
Simple as that.

41:19.580 --> 41:22.740
So quickly running through what we've talked about here, okay?

41:22.740 --> 41:26.320
So we can use status codes to our benefit.

41:26.440 --> 41:27.160
It's fun.

41:27.780 --> 41:28.680
It's useful.

41:28.780 --> 41:30.380
We can slow people down with it.

41:30.960 --> 41:32.500
But browsers can be quirky.

41:32.500 --> 41:34.400
So we need to do it in specific ways.

41:35.120 --> 41:39.740
And scanners and attack toolkits are, you know, they're set in their ways.

41:39.900 --> 41:44.320
This 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:46.260
Get off my lawn.

41:48.460 --> 41:49.840
It's just the way things are.

41:49.840 --> 41:51.720
Why change things if it's working?

41:52.020 --> 41:54.740
So my goal here is to make it not work.

41:55.620 --> 42:02.120
WAFs need to seriously get more offensive about their defense because they're being far too passive as far as I'm concerned.

42:02.200 --> 42:12.520
So just blocking a request, providing a snazzy little ASCII art that tells people to go and scan someone else's web server, it's great and it's fun but it's not really going to help us.

42:12.720 --> 42:14.640
And I'm not talking hacking back.

42:14.660 --> 42:27.940
I don't want to start hacking back people who attack my web service but I want to be more active in fighting back and saying to people that this is not right.

42:27.940 --> 42:31.880
If you're scanning my server I'm going to screw with you and I'm going to screw with you until you cry.

42:31.920 --> 42:34.100
It's just the way things are.

42:34.100 --> 42:36.280
So slowing attackers down is good.

42:36.880 --> 42:40.020
Making life harder for skitties is absolutely priceless.

42:41.080 --> 42:43.140
I should have put the MasterCard logo on that.

42:43.380 --> 42:47.820
So current tools are very much the same as APT.

42:48.260 --> 42:49.520
Yeah, I said that.

42:50.860 --> 42:59.720
They are adequate and they do what they do and until someone fights back and says this is not good enough anymore then they're just going to keep doing what they're doing.

42:59.720 --> 43:00.420
Simple as that.

43:00.420 --> 43:03.240
So they're only advanced as they need to be.

43:03.380 --> 43:04.780
It's just like people attacking you.

43:04.780 --> 43:09.760
If they can get you with a phishing attack then why would I bother wasting a zero day on you.

43:09.760 --> 43:10.580
Simple as that.

43:11.640 --> 43:14.320
I think this is the key to this entire talk.

43:14.380 --> 43:16.260
Screwing with skitties is fun.

43:17.480 --> 43:33.600
I've had this running on my web server for a while now and just checking the logs it's absolutely hilarious the amount of automated scans that hit your web server searching for like Tim Thumb and how long it takes them to finish just a simple scan of your web server.

43:35.020 --> 43:37.720
Just scanning your web server for random stuff.

43:38.540 --> 43:40.540
So how can people implement this?

43:40.540 --> 43:43.700
There's no point in me talking about this stuff if we don't know how we can implement this stuff.

43:43.820 --> 43:46.320
Let's talk about the ghetto option.

43:46.340 --> 43:48.880
We can implement it using PHP.

43:49.140 --> 43:50.920
It's the lowest common denominator.

43:51.340 --> 43:54.160
People probably wrote it in notepad but that's life.

43:54.160 --> 44:04.040
You can auto prepend a PHP file to say randomize the response code within a specific section of response codes that are supported by the browser.

44:04.480 --> 44:07.500
We're limited by resources that are PHP handled.

44:07.580 --> 44:14.540
If your web server starts to error out because people are sending stuff that isn't to be expected then the web server is going to respond back.

44:14.660 --> 44:16.260
There's limited functionality there.

44:16.260 --> 44:17.880
There's man in the middle dump.

44:19.500 --> 44:20.920
It's a real memory hulk.

44:20.920 --> 44:22.580
It will use everything you've got.

44:22.580 --> 44:31.800
If you put man in the middle dump as a reverse proxy in front of your web server you can have simple scripts that are just going to change the response codes.

44:31.800 --> 44:32.540
That works.

44:32.540 --> 44:33.140
It works.

44:33.140 --> 44:34.740
But it's not the best solution.

44:34.740 --> 44:38.760
So what's this enterprise approved solution?

44:39.180 --> 44:41.200
Everyone knows NGINX, right?

44:41.680 --> 44:43.340
It's like Apache but better.

44:44.700 --> 44:46.920
It's a usable implementation.

44:47.500 --> 44:50.260
NGINX is used quite often as a reverse proxy.

44:51.140 --> 44:59.280
And if you use something like NGINX lure you can write some interesting scripts that are going to change the response codes that are going out of NGINX.

44:59.740 --> 45:05.660
So you simply load NGINX lure and using NGINX status you can specifically set stuff.

45:05.800 --> 45:10.180
So the only problem is there's kind of a few bugs in the non‑Git version.

45:10.340 --> 45:16.440
Specific codes that are supported just tend to get returned as nil which is kind of a pain.

45:16.440 --> 45:21.760
But if you use the version from Git it shouldn't be so much of a problem.

45:22.280 --> 45:30.600
But if you do an apt‑get install and install NGINX and install the optional extras you're going to run across a couple of problems.

45:31.220 --> 45:34.680
So what does the future hold?

45:34.720 --> 45:36.000
What's the next step?

45:36.000 --> 45:45.240
Well, the next step, I've been trying to get this into mod security to ease adoption by implementing it into something that people are using already on a daily basis.

45:45.240 --> 45:48.440
Because no one wants to implement another layer of stuff.

45:48.680 --> 45:52.400
Because the more you install, you're increasing your attack surface.

45:52.400 --> 45:58.760
So you want to put something, change a couple of configuration files in mod security and just have it do this stuff without you having to think about it.

45:58.820 --> 46:00.060
But it's not simple.

46:00.060 --> 46:01.040
It's not easy.

46:01.640 --> 46:08.760
I've been discussing it with various people for about a year and everyone is like, yeah, that should be possible, maybe, kind of.

46:09.780 --> 46:11.120
But I don't know how.

46:11.960 --> 46:16.280
So this is kind of a long shot, but I need some help with this stuff.

46:16.360 --> 46:26.200
I'm not a C coder and I'm not into writing Apache modules, but if anyone is interested in this kind of stuff and they really want to implement it into mod security, then I would really appreciate their help.

46:27.120 --> 46:29.440
So how do we counter this research?

46:29.820 --> 46:32.000
We've told the scanners that they're crap.

46:32.060 --> 46:36.240
We've told the scanners that they aren't doing stuff in the right way.

46:37.040 --> 46:38.800
I really need a new microphone here.

46:39.560 --> 46:42.380
So less reliance on status codes.

46:42.420 --> 46:49.880
I know it's easy to say, but we're going to have to slow scanners down in order for them to be more reliable.

46:50.020 --> 46:53.640
Because right now they're just taking the response codes and ignoring everything else.

46:53.640 --> 46:57.440
So start paying more attention to the actual content of the site itself.

46:57.440 --> 47:01.240
Some scanners are doing this already, but things need to be double‑checked.

47:01.240 --> 47:03.740
You get better matching if you do that.

47:03.740 --> 47:06.740
The problem is Regex matching is kind of slow.

47:07.160 --> 47:11.800
It's going to use more memory, it's going to take more time, it's not easy.

47:11.940 --> 47:13.820
But this is the cat and mouse game.

47:14.180 --> 47:25.740
Every time we come up with something new or increase our security, then people who are attacking websites or testing websites increase the productivity and increase the accuracy of their tools.

47:25.820 --> 47:29.400
So hopefully we can move this to the next level.

47:30.500 --> 47:33.700
So that's all I've got.

47:33.700 --> 47:34.740
Any questions?

47:35.580 --> 47:36.580
So, yeah.

47:47.760 --> 47:55.860
So the question is, have I specifically looked at detecting specific scanners and how they look when they're attacking a web server?

47:56.440 --> 47:58.500
Yes, I have looked at it.

47:58.500 --> 48:00.820
Not as part of this research, as part of other research.

48:00.820 --> 48:02.040
Yeah, it's interesting stuff.

48:02.040 --> 48:05.660
You can also detect quite easily when Nikto is attacking your website.

48:07.020 --> 48:09.680
The problem is, it's the same as this stuff.

48:09.680 --> 48:17.380
As soon as you start detecting how specific scanners look when they hit your website, the scanners are just going to start randomizing how they request stuff.

48:17.380 --> 48:21.240
So it's another step in the kind of cat and mouse game.

48:21.280 --> 48:22.480
So, yeah.

48:26.140 --> 48:26.600
Okay

48:31.140 --> 48:31.600
.

48:33.200 --> 48:37.100
Yeah, so F5, you can write scripts to specifically do this stuff.

48:37.100 --> 48:38.420
So it's interesting.

48:38.420 --> 48:41.060
So I'm sure everyone here has an F5, yeah.

48:42.280 --> 48:43.400
So, yeah.

48:46.720 --> 48:50.520
So yeah, the question was, do different versions of browsers respond in different ways?

48:50.840 --> 48:55.420
At the beginning of my testing, I was checking all the different versions of IE.

48:55.700 --> 48:59.500
IE6 tends to do things in a kind of weird way.

48:59.780 --> 49:02.380
You get some weird stuff.

49:02.680 --> 49:06.200
Like with the 100 codes, it tries to download stuff.

49:06.480 --> 49:11.200
But it's ‑‑ between specific versions, they don't tend to change the logic at all.

49:11.220 --> 49:12.900
So I'm getting the wave.

49:12.900 --> 49:21.040
So if anyone has any further questions or any further comments, the code is available on my GitHub site.

49:21.100 --> 49:24.440
I'd just like to leave you with the thought that whatever doesn't kill you makes you smaller.

49:24.760 --> 49:25.580
Thank you.

