start	end	text
0	7400	So, yeah, a little bit about me. No one really cares about who the speaker is, so read this
7400	14340	whenever you want. I do podcasting and blogging and shit like that. I am a firm believer in
14340	19400	the wisest man is he that knows that he knows nothing. I am not an expert and I'm quite
19400	27280	happy to admit that I know absolutely nothing. I kind of like edge case stuff. It's kind
27280	30820	of ‑‑ it's freaky. Most people are like, oh, it's just an edge case, no one really
30820	35540	cares. But the edge case stuff, the freaky stuff, the weird stuff kind of really interests
35540	40660	me. It makes me think that's really cool, I should really dive into that. So this is
40660	44840	part of the edge case stuff that people really don't give a shit about. But apparently all
44840	47780	you guys do, otherwise you wouldn't have woken up early to come and see this.
49020	54480	So I'm going to start with a quick warning. This presentation, it contains numbers and
54480	61580	jokes and traces of peanuts. Who has ever seen me give a talk before? So if you had,
61580	67740	you wouldn't be here. Everyone who has seen me give a talk before, I'm sorry, I use the
67740	75320	same jokes every time. So just laugh when everyone else does. Not you, Ed, you have
75320	80300	to stay. So I'm going to give everyone the TLDR on
80300	85560	what I'm going to be talking about today. The goal of this talk is to describe the defensive
85560	94400	uses of HTTP status codes. That sounds really sexy, doesn't it? This is an absolute must
94400	103400	see at DEF CON on a Sunday morning. So back to why are you guys awake again? I'm going
103400	107560	to run through the what, the why, the how, the goals and then we're going to bring it
107560	112120	together and we're going to review what we've covered. So I'm going to try to run through
112120	118260	this reasonably fast so I can get everything in. So let's start with the what. HTTP status
118260	124560	code. Who has never seen an HTTP status code? Yeah, okay, I thought so. So we know what
124560	128980	an HTTP request looks like. We're picking out the specific section. This is the status
128980	137080	code or the response code. The terms are interchangeable depending on how much you had to drink. It's
137080	143560	like a really small little thing every time you make a request or every time you get an
143560	147920	answer from a server. It comes with some kind of status code. No one really cares what they
147920	154500	are. The browser doesn't really tell you what it is, but it's an important feature of the
154500	160260	HTTP standard. What I'm going to show you is a really small detail, but it's a really
160260	166020	big impact. If you don't really pay attention to the status codes, then some bad things
166020	171480	can seriously happen. So a little bit of history on HTTP status codes. This is an RFC.
171480	176700	I'm sure everyone here has read that, right? I couldn't sleep last night. I thought maybe
176700	182480	I should read the RFC again, but yeah, that didn't happen. So there's five main classes
182480	187440	of responses. You get the one, 100, which is the informational stuff. You don't get
187440	192400	to see that very much. You get the 200, which is most of the time success. Your web page
192400	196740	is here. Here is the content. Thank you very much. Please go away. You get the 300, which
196740	202160	is the redirect stuff. You get the 400, which means you fucked up. You get the 500, which
202160	208860	means they fucked up. Simple as that, okay? There's also a wonderful RFC, and this one
208860	216640	is actually worth reading for the 700 codes by John Barton. If you go to his GitHub page,
216640	225300	there's an entire section. I like the meh. I am not a teapot. I specifically like this
225300	238040	one, fucking unicode. So, yeah, there's like 300 of these things. So I have no idea how
238040	243480	they squeezed it all into the 700 range, because there's 300 of them. These are amazing, and
243480	251520	I have no idea where did the 600 range go? So, yeah, I really hope they accept that RFC
251520	255420	and start implementing that in some stuff. So let's go through the basic stuff. This
255420	260400	is the theory bit. It's boring, and I'm sorry, but this is the theory. So you get the 100
260400	264680	informationals. You get the 100 continue, switch protocols, processing. As I said, these
264680	270460	are the things you don't get to see very much. Moving into the 200 stuff, it means it worked.
270460	275280	It means it understood. So you're getting a 200 okay, which is most of the web is returning
275420	280120	a 200 okay. You also get some weird stuff that you don't get to see very much, like
280120	289160	204 no content. Great, thanks for the header. There's also some interesting stuff that isn't
289160	295040	supported by Apache. Low on storage space. I've never seen that one returned by a server,
295040	303420	but I'd really like it. But they're not supported by Apache. You get the 300 redirection stuff.
303420	308360	So most people know what a 301 is, what a 302 is. 300 you don't get to see very much.
308360	315860	Multiple choices. It's like an exam. Tick boxes or something. 304 not modified as well
315860	319780	is something you see quite a lot if you're looking at the way data flows backwards and
319780	324140	forwards. You also get some weird stuff that isn't used anymore, like switch proxy. Sounds
324140	327980	like fun. Use proxy is also interesting. If you return a proxy setting in the location
327980	332780	header, it says, oh, you should use this proxy for your communications. I'm sure no one would
332780	339760	use that for malicious purposes in any way. So moving on to the 400, which is the you
339760	348240	fucked up section. So forbidden, unauthorized, usual stuff. 404 not found being quite a reasonable
348240	354360	response for I search on random crap on the Internet. And then you get some interesting
354360	359680	stuff. I quite like the 407 proxy authentication required. I'll talk a little bit more about
359680	365240	that later on. Interesting ways to do some malicious stuff with that. This is a long
365240	373540	list. I quite like the 418. I'm a teapot. It's only in April Fools and quite a lot of
373540	378320	web servers don't implement it, but this is interesting. It's like I am indeed a teapot.
380860	386380	Moving into the 500 stuff, internal server error, which is unfortunately used quite a
386380	392280	lot for SQL injection. Oh, I got a 500 error. That must be a SQL injection trigger. You
392280	398340	don't get to see it very much if you're not abusing websites. Still, it's interesting.
398340	404640	Wow, that's a lot of fucking numbers. All right. So everyone here knows every single
404640	410500	HTTP response code now, right? Great. I don't have to talk about them anymore. So why are
410500	415960	we doing this? It started off as a little idea. I read a couple of books. I do that
415960	422880	on occasion. I don't know if any of the authors are in the room. I'm really sorry. I'm plagiarizing
422880	428460	your work. And I started to have a little think, what can we do with that? We can do
428460	435400	some interesting stuff with scanners. And screwing with script kitties is a hobby. It's
435400	441620	more of a life calling. And that sounds like fun. That sounds like something I want to
441620	446740	do at a weekend. And I started to look around and there's a guy that everyone follows on
446740	453700	Twitter, right? The Grug. He's not here because he's drunk, but he should be. He said in one
453700	458000	of his quotes, stop dismissing obscurity as a security feature because unpredictability
458000	463980	in your defense works to your advantage. Well, that's great. We can increase attacker costs
464530	471600	being unpredictable. And we can waste attacker time. We can say that, you know, an attacker
471600	476640	is going to waste three hours attacking a website that should take 15 minutes. Why should
476640	480940	we just stand there and let someone smash us in the face? We should be more active on
480940	486980	our defense. So there's some prior art. I kind of looked around. I was trying to find
486980	490640	who else has talked about this stuff before. Because in my mind, this was just obvious
490640	494840	stuff. I was like, someone's bound to have already implemented this stuff. There was
495100	502800	a 2004 talk by Harun Mir and the guys at SensePost where they mentioned using HTTP status codes
502800	510260	to slow down attackers. It was one line comment in a slide deck. That was it. Okay. Well,
510260	516340	someone's mentioned it, so there must be more. There was an interesting paper by Gunter Ohlum.
516340	520560	I probably totally mispronounced his name there. There's a PDF where he talks about
520560	525140	stopping automated attack tools. I was like, okay, this must cover it. He covers lots and
525140	530540	lots of stuff, but he doesn't really dig deep into using HTTP status codes to do this stuff.
530540	538640	So I carried on, and I was informed, should we say, of a mailing list comment where Ryan
538640	545000	Barnett said that, well, maybe we can reply with a 503 with a retry after header. That
545000	548940	was interesting. I tested it out. It didn't really seem to work, because most scanners
548940	553220	just completely ignore a retry after header. But maybe things have moved on. This was 2006
553220	559000	when that comment was made. So, yeah, no one seems to have discussed this stuff. So how
559000	564960	are we going to work this in? So browsers have to be as flexible as possible.
564960	571520	You get websites written by kiddies in notepad, and you get professional websites written
571520	576720	in HTML5 with web APIs and SOAP interfaces, and the browser has to be able to support
576720	585320	it all. And this leads to a certain amount of flexibility on how things are understood,
585320	590160	how things are supported, which obviously leads to the dark side. And then, of course,
590160	596300	there's RFCs, which some would say is the dark side. They're more of a guideline, really.
596940	600960	This is the way you should do it, but we're not going to tell you exactly how, so it depends
600960	607660	how drunk you were when you read it. Maybe this makes sense. So, yeah, what could possibly
607660	612320	go wrong? You have 300‑page RFC and people who are going to interpret it, and you implement
612320	616120	it into a piece of software which has to be as flexible as possible, otherwise things
616120	618820	don't work. Things are going to start to go wrong.
618820	624780	So I started to do a little bit of testing. I wanted to restrict myself to the big three.
625040	630300	Internet Explorer, Chrome, Chromium and Firefox. No? Yes.
633840	642300	Apparently Opera turned really bad, or there's Lynx, but who uses Lynx? One guy uses Lynx.
642320	650320	Welcome to the 20th century. So I wanted to take the easy option on testing,
650320	654200	so I thought, okay, well, there's man in the middle proxy. It's a Python‑based system
654200	658700	for man in the middling HTTP connections. It allows you to set up this really interesting
658700	662380	reverse proxy. It's all script‑based and it does all the work for you. You just write
662380	669040	something like this in a script file. That's it. All this does is change every response
669040	674940	code to a 200. That's easy. Even I can code that shit.
676360	679500	Unfortunately, man in the middle proxy tends to use up all of the memory you have on your
679500	686580	machine. Even if you have 8 gigabytes of memory in your laptop. I would highly recommend man
686580	692160	in the middle dump, which doesn't cache everything into memory. Just a side note there.
692160	700400	I also used PHP, the amazing personal home page. It allows you to set response codes,
700400	704880	but there's some downsides. You can also prepend a file, which is going to allow you to set
704880	708480	specific response codes or do some logic in the background. The problem is if the web
708480	715240	server says, no, this is an incorrect request, the PHP is never going to get to actually
715240	718720	see the request, so you can't set response codes. So you can do some interesting stuff.
718720	722820	For testing, it's useful, but in production, it's not really going to be as useful as it
722820	730980	could be. So I used a mismatch of Python and PHP for most of the testing. You don't need
730980	735120	to write this down, because I'll release all the slides afterwards, but simple testing
735120	740320	of browsers, how things are supported, you just call a PHP page, which sets the response
740320	744600	code, you tell it what code in the URL, and you hope no one cross‑sites your website.
746040	749900	As simple as that. You get a response, you get the requested response code and the actual
749900	756200	response code, because with PHP, you can set that response code to 999 if you want, but
756200	761880	Python is just going to say, oh, sorry, Apache is just going to turn around and say, I don't
761880	766480	know what that response code is, and then it just returns a 500, which is the they fucked
766480	771280	up section of it. So, yeah, you get to see what you requested, you get to see what the
771280	775320	response was, and you get to see what the headers are, so simple JavaScript running
775320	781580	in the browser, so great, I can run off and start testing these browsers, which seemed
781580	788580	like an easy thing. I started to think, I've got all this data on how all these browsers
788580	796540	work, and how can I graphically display that in a nice fashion? Let's just say that I'm
796540	807240	not good at charting. Sorry, for the women in the room, also, I'm trying to keep this
807760	812520	even across the sexes. So I didn't really know how to display this, so I spoke to some
812520	815840	guys who do visualization, and they were like, oh, yeah, we can do this and we can do that,
815840	821540	and it was just all shit. So what I ended up with was a table.
826640	830860	Yeah, this is the reason why I cut it down to three browsers, because otherwise the table
830860	835840	would be like this fucking wide. So, yeah, there's a full table online, which I'll release
835840	840260	after the talk, which has a lot of other browsers and scripting languages in it, but this is
840260	844960	the core three, so you start to see quite a lot of conformity in this section about
844960	849840	how the browsers respond to things. So I run it into three sections, so can you load HTML
850340	855980	with a 100 response code? Well, you can, but nothing appears, it doesn't render anything,
855980	860460	so the browser just doesn't support it, unless it's an iframe with Chrome, in which case
860460	866680	it tries to download it, because I guess Chrome just likes to download shit.
868800	874060	What's kind of interesting, if you have Chrome on an Android phone and you respond with a
874060	881260	100 code, it tries to download it, but it never finishes, so you have to restart your
881260	888840	Android to get it to stop, which is fun. I'm sure no one would fuck with that.
891980	895800	So looking at this, you're like, okay, well, all the browsers are kind of mostly conform,
895800	901860	except IE, obviously, which doesn't care about a 205 and just renders the stuff, it doesn't
901860	907520	care. You start to see differences when you're looking at the 300 codes, for example, Firefox
907520	914420	just doesn't load JavaScript if you respond with a 300 or a 301, IE pretty much just ignores
914420	919000	everything if you respond with anything in the 300 range which isn't a redirection, but
919000	923820	Chrome pretty much accepts everything because it doesn't give a shit. It's the honey badger
923820	929500	of browsers. Moving kind of into the 400 stuff, you start
929500	933860	to see more conformity, again, IE being the weird one. It just doesn't like loading iframes
933860	941380	with weird response codes. And you see these at a time when it says 407 proxy, proxy, proxy.
943040	947360	Basically what that means is that Chrome, depending if you have a proxy set or not,
947360	953040	will load it. So if you have a proxy, an HTTP proxy set, then Chrome will load the content
953040	956640	when it's responded with a 407. If you don't, then it won't.
958680	963280	Again with the 500s, things are pretty standard, again, IE being kind of a little bit of a
963280	969200	weird outlier on things. Okay. So think about this for a second. You've got browsers that
969200	973980	kind of handle things in slightly different ways. What can we do with that kind of stuff?
975520	979820	But a majority of stuff is like, okay, that's just content. I don't care what it is. It's
979820	984400	loading stuff. It's like you get a 400 response and it's like, oh, I see HTML, I'm just going
984400	987920	to render that for you. Or I see JavaScript, I'm just going to run that JavaScript for
987920	994960	you. So most things, mostly, things are loaded quite normally. But there's some weird kind
994960	999940	of outliers. So with HTML responses, almost all response
999940	1004520	codes are rendered correctly. It doesn't care. When you try and load an iframe and it comes
1004520	1010420	back with a response, there's some special cases for IE because IE is special. But most
1010420	1015320	of the time kind of things are even. And if you start looking at JavaScript, there's very
1015320	1020260	limited support for it. Chrome being the exception because they just don't care.
1020900	1027520	So we know what browsers interpret differently. So what do all the browsers have in common?
1027720	1034320	What are they doing the same across the board? The 100 codes, retries, confusion, as I said,
1034320	1040640	fun on Android, never-ending downloads. And it times out eventually. Because the browser
1040640	1044820	thinks there's more coming. The browser thinks, oh, you're going to send more data in a minute.
1044820	1050920	I'll just sit here and wait for you. Which is kind of interesting. The 200 codes, again,
1050920	1056320	you get the no content or not modified. You get headers saying, no, there's nothing here.
1056360	1060200	So as you would expect, all the browsers just ignore any kind of content that you're responding
1060200	1064360	because it doesn't expect there to actually be any content within those things.
1065540	1071940	So what about headers? Okay. So RFCs quite a lot of the time in kind of a muddy language
1071940	1079220	say if you're responding with a free XX response code, whether it's 301 or 302 or 303, there
1079220	1085080	should be a location header. It doesn't mean it has to. If you respond and you don't have
1085160	1088340	a location header, it just kind of ignores the fact that it's meant to do a redirect
1088340	1095200	and then renders whatever content you give it. Specifically, no location header, no redirect.
1095200	1099840	This makes sense. Because you're responding with a 302, it's looking for the location
1099840	1103620	header, it doesn't find one. Instead of just giving you an unhelpful error in your browser,
1103620	1109160	it's just going to render what you returned and ignore. Simple as that. So the 401 unauthorized
1109160	1115420	as well, if you're not sending back a www authenticate header, it's not going to prompt
1115420	1122480	you. Simple as that. And I mentioned previously about the 407 proxy authentication required,
1122480	1127360	the way Chrome deals with it. Again, if you're not requesting the authentication, then it's
1127360	1132840	never going to prompt you. On the flip side, just because an RFC says a specific status
1132840	1139660	code shouldn't have a header, doesn't mean it can't have a header. So if you read the
1140220	1147140	RFCs, there's 300 multiple choices. Now, this shouldn't have a location header. It doesn't
1147140	1151300	redirect you. It should come up with an HTML where you can specifically select where you
1151300	1156400	would like to go. Unless, of course, you're Firefox or IE, in which case if you give it
1156480	1162240	a location header, it's just going to redirect. But Chrome isn't. And there are so many headers
1162240	1165180	out there you can play with. I've played with quite a lot of them. Most of them are not
1165180	1170280	particularly interesting, unfortunately. But there's more work to be done in that kind
1170280	1174240	of area. There's a load of headers like the retry after header that can really be played
1174240	1178900	with and a little bit more research is required there. So each browser is handling something
1179140	1184020	a little bit differently. We know how things are handled the same. We know how things are
1184020	1191620	handled differently. I wonder what we can do with that. So what can we do with that?
1191620	1196400	What are the goals? Okay. So each browser handles things differently. You have the handled
1196400	1200300	codes, you have the unhandled codes, and then you get this little browser weirdness thing
1200300	1205080	where it just does random stuff you just didn't expect it to do depending on the headers.
1205760	1211880	So browser fingerprinting. Okay. So, yeah, you can check user agent strings, but that's
1211880	1218260	client side controlled. You can easily spoof that stuff. But if you take the differences,
1218260	1223100	you can really do some interesting fingerprinting work on Firefox, on Chrome, and on IE. So
1223100	1228200	on Firefox, based on the information we have, it doesn't load JavaScript return with a 300.
1228700	1232880	The other browsers do. So you simply return a JavaScript with a 300, and if the JavaScript
1232880	1240580	runs, it's Firefox. Simple as that. Okay? With Chrome as well, it loads Java return
1240580	1245260	with a 307, temporary redirect, without a location header, but the other browsers don't.
1245260	1248860	So again, we can do the same kind of thing, and we can do some fingerprinting. And with
1248860	1254560	IE, it loads JavaScript return with a reset content status code, and nothing else does.
1254600	1259120	So if we can add all that stuff together, you can get a nice way of fingerprinting the
1259120	1263540	main browsers without even bothering to look at the location header. Or you can use the
1265480	1270460	user agent header, and then specifically say, well, I'm going to check that by seeing how
1270460	1275980	your browser really works. So I'm going to do a quick demo. Well, actually, I lied. I'm
1275980	1279700	going to run a quick video of a demo, because I didn't want to connect to the network here.
1283200	1289580	First talk. So all this is doing is loading a PHP page, and then running through and loading
1289580	1297760	three individual pages. It then checks the responses, checks the JavaScript, and says,
1297760	1304240	so this JavaScript ran, this JavaScript didn't, so you must be using this specific browser.
1304320	1312260	So if you zoom in, well, if I zoom in, there you go. So you can see the specific responses.
1312260	1318520	You can see that it's loading an HTML, it's coming back with a 300, a 307, and a 205,
1318520	1321860	which are the three specific response codes we talked about for the different browsers.
1321860	1326860	It's then sending all of that stuff to a PHP page on the server, and the PHP page is returning
1326860	1332620	and saying, okay, this is the specific browser. So obviously I'm returning back to the browser
1332620	1339300	to display a pop‑up to say this is the browser. In most cases, you're sending it to the server,
1339300	1344120	and then you're never responding back, because I know I'm running IE. I have the little IE
1344120	1347000	bar at the top. I don't need you to do a pop‑up and tell me.
1347160	1351080	But the server now knows exactly what kind of browser you're using. So if you're spoofing
1351200	1358240	a user agent string, then I can say, okay, so user agent string says you're running Firefox,
1358240	1362100	but you're actually running Chrome. That's suspicious, and that's something that we should
1362100	1367520	be looking at, okay? So there's various other options for fingerprinting.
1367520	1372040	This specific option I selected was kind of the easiest option. There's various other
1372040	1377480	stuff. There's a 300 redirect, there's a 400 iframe on Internet Explorer. If you want to
1377480	1384400	look at the proof of concept, if you go to C22.cc, fingerprint.html, it will run the
1384400	1389540	same example I just ran. You can look at the traffic, and the code is available. I'll link
1389540	1393200	to that at the end. So user agents can be spoofed. Everyone knows
1393200	1398140	that. Even script kiddies, unfortunately, know that. But browser traits are really hard.
1398500	1403620	Because your browser responds and does things in specific ways. So we've done that. We can
1403620	1406420	fingerprint browsers. So what else can we do? Proxy detection.
1406420	1411460	We specifically talked about the way Chrome handles things. And if you have an HTTP proxy
1411460	1415860	set, you can specifically say, okay, I know they're using Chrome. I'm going to respond
1415860	1422040	with a 407. If it loads the page, then they're using an HTTP proxy. There's unfortunately
1422040	1425980	limitations here. It doesn't pick up with SOX proxies. But your average user isn't using
1426100	1433720	a SOX proxy anyway. It's a limited interest, but it's something that needs further testing.
1433720	1440000	As I said, all you do is respond with a 407 with a proxy authentication header or without
1440120	1444020	a proxy authentication header. And if Chrome responds, then HTTP proxy is set.
1444080	1450760	So while I was doing this research, I decided I was going to try a couple of different HTTP
1450760	1459880	proxies. And one of the proxies I selected was Privoxy. It's quite a popular privatizing
1459880	1465260	HTTP proxy. So I found while I was testing this, if you respond with a ‑‑ so your
1465260	1470160	web server, you go to my web server, you respond with a 407 proxy authentication required,
1470160	1475180	you get the pop‑up in your browser. But it doesn't say that my web server asked you
1475180	1480300	for a username and password. It says Privoxy asked you for a username and password. Which
1480300	1484100	is interesting. So why is my local proxy asking for a username and password, I thought. So
1484100	1491300	I typed in test, test, and I clicked send. And my web server gets my username and password.
1492720	1497120	That's kind of interesting. I'm sure we can use that for some malicious stuff. But this
1497120	1501520	is a defensive talk. So I'm not going to dive too much into that. But it's kind of interesting.
1501980	1507300	Let's just say proxies aren't always configured quite so securely as they could be. There's
1507400	1511620	a fix for that now. So you can download the latest version. But it's not just Privoxy.
1511620	1516600	Any transparent proxy, things like burp or zap, they're designed to pass everything you
1516600	1522040	give it. So if my web server responds with a 407 and asks for authentication, burp suite
1522040	1526520	will just pass it to your browser. Simple as that. So you can start screwing with people
1526520	1533000	who you know are doing malicious things on your site with intercepting proxies. Of course,
1533000	1536500	if you're doing a test with burp suite and it says what's your username and password,
1536500	1540500	I'm probably not going to type in my real username and password. But you never know.
1540500	1546700	Script kiddies type in weird stuff. So let's bring all this stuff together. So we've got
1546700	1551940	status codes that are treated like content. They don't care. You've got status codes that
1551940	1556240	really are not specifically well handled, specifically the 100 codes. And you've got
1556240	1562140	lots of little browser quirks that we can abuse. So what can we do? We can play with
1562140	1567980	things just in case there's children in the room. We can make the people who like RFCs
1567980	1574340	cry into their beer. So let's try to use what we've discovered. Let's break some spidering
1574340	1581280	tools. Cause some false positives, false negatives. Slow down attackers, which is probably one
1581280	1585260	of the most important things that we can do. Give us time to respond to how people are
1585260	1591900	attacking us. And then block successful exploitation. So even if they do manage to exploit the server,
1591900	1595380	if you're responding specifically with different codes, maybe their exploit is not going to
1595380	1602200	work. So let's talk a little bit about spiders. This is a very simplistic and naive view of
1602200	1609180	spiders. But you access the target URL, you read the links, you test them. If true, continue.
1609180	1617780	So if you get a 200 okay, that's true, right? And if you get a 404, that's false, right?
1617880	1624920	But what happens if everything is a 200? And what happens if everything is a 404? You start
1624920	1629420	to get some weird stuff. And what happens if everything is a 500? Sometimes if everything
1629420	1634280	is a 500, then everything is a SQL injection attack. So if everything is a 200, you end
1634280	1639900	up with this interesting loop of, oh, I found another directory. I will just keep scanning
1639900	1643740	and keep scanning and keep scanning. You get this never‑ending spider. Unfortunately
1643740	1649020	I couldn't find a picture of a spider eating itself. So if anyone has one, please send
1649020	1655680	it to me. And if everything is a 404, what website? I don't know if you can see this
1655680	1661520	at the back. This is the wonderful Acunetix tool, the script kiddies tool of choice. The
1661520	1668860	crawler found zero pages, zero files, and validated zero findings. Yeah. So what website?
1669000	1674040	There is no website there. Skipfish loves it. It just keeps going and going and going
1674040	1680740	until it kills itself. I'm guessing at this point my test server just decided it didn't
1680740	1686840	have enough memory to deal with all the responses. If you look closely, there is also 2,000 low,
1686840	1696600	2,000 medium false findings on the scan alone. So, yeah. Playing with people's spiders is
1696600	1702880	kind of interesting. So false positives, false negatives. We can start to hide how bad or
1702880	1706920	how good our servers are, start to really screw with people and waste their time. So
1706920	1712700	most scanners use response codes in some way. They kind of have to. You speed up detection.
1713800	1720700	You can't use rejects for everything. It's the easy solution. So if we start to respond
1721300	1727260	with, again, 200 okay, 404, 500, and if we start to play with them and respond with random
1727260	1734860	codes, random being a selection of codes that are handled well by all normal browsers, so
1734860	1738920	the normal people browsing the website are not going to be affected in any way, you start
1738920	1744940	to see some really interesting stuff. So it's a quick baseline using W3AF. I didn't particularly
1744940	1749760	pick on these people. It just happens to be an interesting baseline. So a standard baseline
1749760	1757240	for my test system was 79 informational points, 65 vulnerabilities, no shells, which kind
1757240	1762900	of took an hour and 37 minutes to do a scan. So if everything responds with a 200 okay,
1762900	1769460	you still get everything. So we're not winning on the false positives and false negatives.
1769520	1775160	It takes you nine hours to run the scan, which is kind of interesting. It lets us win time,
1775160	1778960	but it's not really working. So a 200 okay isn't really going to do what we need it to
1778960	1783580	do. So if everything is a 404, it's a lot quicker to do the scan because you're not
1783580	1787740	finding everything. But it's missing a majority of the information points and a majority of
1787740	1792580	the vulnerabilities. So you're starting to see some interesting stuff. If we start responding
1792580	1797960	with weird codes, they don't find everything. Okay. That's interesting. If you respond with
1797960	1805200	everything with a 500, wow. False positives. If it's a 500, like I said, it's SQL injection.
1805380	1813560	9,000 informational points. Try digging through that report, you know. 9,000 confusing information
1813580	1818320	and confirmed vulnerabilities. I can just see that pen test report, sorry. That vulnerability
1818320	1823060	analysis. That's going to be about 1,000 pages long. Oh, no, we found all this stuff. We
1823060	1827520	have IAS vulnerabilities and this and that. It's an Apache server, but we still have all
1827520	1833340	of these IAS vulnerabilities. So any people who use Nessus in the room? No.
1834020	1839440	So if we start using random status codes, I did multiple runs of this to make sure that
1839440	1844320	I'm getting accurate. Because if it's being random, maybe I just had a bad run. It averaged
1844320	1850940	out as giving you a reasonable amount of false positives. And it took less time to run the
1850940	1856480	scan. What I found interesting on this was a majority of the things that it did find,
1856480	1861360	it didn't find the real vulnerabilities, it just found weird stuff. So even though it
1861360	1865540	found more vulnerabilities and you get lots of false positives, they're pretty much all
1865540	1869420	false positives. So the real stuff just doesn't get found at all, okay?
1870620	1877400	So skip fish and random, wow. It doesn't like random. Let's just say skip fish is particularly
1877400	1881340	picky about it. So the first scan time took ten hours and the second scan time took four
1881340	1887680	seconds. Yeah, and then again 16 hours. I ran it about five times and it would just
1887680	1892380	randomly flick between times. So skip fish is a wonderful denial of service tool for
1892380	1899820	web applications. I think in my proxy it sent like 33,000 requests inside five, six
1899820	1903480	minutes. Yeah, it would pretty much take down everything.
1905800	1911740	So we're not really slowing attackers down. So what can we do to slow the attackers down?
1912540	1919220	What's our WAF really doing at the moment? A standard WAF, again, a naive view, oh, my
1919220	1924680	God, I'm being attacked. Block or return an error whether or not that's a 403, a 500,
1924680	1931320	or a 404, or a 200 with a nice message telling them to piss off. Profit? There's no profit
1931320	1936920	there. Okay, for us as defenders, with my defender hat on, we've won nothing. All we've
1936920	1941880	done is blocked an IP address or blocked an attack. They come back with an obfuscation,
1941880	1949200	we bypass it, game over, okay? So why are we doing that? Remember this big list of things
1949220	1955080	that browsers don't handle very well, specifically the 100 stuff? Well, scanners don't like
1955080	1960380	them either. Surprising there, because a scanner thinks it's going to be a browser. It's trying
1960380	1966200	to do everything that a browser does. So looking at the 100 codes, we can start to really screw
1966200	1969120	with stuff. So does anyone remember the library topic?
1971300	1979200	So it should be Tomlisten, not Timlisten. Apologies, Tim. So it was originally designed
1979220	1983940	to slow the spread of code red, and it slows down attackers. I mean, this was a great idea.
1984720	1989240	Did we forget that this was a great idea? Did we think that, okay, well, it's been done
1989240	1994500	now, we can just forget about it? In our drive to kind of find new and interesting research,
1994500	1997640	it's been done once, so we should just ignore it for the rest of time.
1998400	2004740	So I had this interesting idea. How about an HTTP tar pit? People have probably talked
2004740	2010180	about this a thousand times before, but, you know, it was interesting to me. Whoa.
2014800	2028140	This is the problem when you run PowerPoint. Drink, drink, oh.
2033460	2040820	Morning DEF CON. It's Sunday morning, you know what that means? Drink, that's right.
2040820	2049360	Say a round of applause for our first-time speaker. How's he doing so far? Doing okay?
2051740	2055080	All right, hook us up. I am not drinking all of those.
2057620	2063460	All right, who's first time at DEF CON? First hand up, right here, come on up on stage.
2069960	2073280	If it's Sunday morning, that means this is the hard core, right? Right here, you guys
2073280	2076820	all got up, good job. All right. Congratulations.
2076960	2094520	Cheers. That reminds me of last night. So where was I? Oh, yeah, I was in a tar pit.
2094720	2102420	So simple scenario. So the WAF detects the scan. Again, we are at the oh, my God, attack
2102420	2109040	section. It adds the IP address to the naughty list. And then it starts to rewrite all the
2109040	2115780	responses. So you get the usual 100, 101, 102 status codes. We just randomly rotate
2115780	2120840	between them, depending on how bored we are all the time. We can also use 204, 304, which
2120840	2125040	could be useful, but it's not nearly as fun as the 100 status codes.
2125040	2132000	So let's do some experimentation, shall we? There's no actual science included in this.
2133420	2141000	So Nikto, wonderful tool. I like it a lot. I especially like the logo. So the baseline
2141000	2146720	scan, 2 minutes, 18 seconds to find 18 findings. Simple as that.
2147640	2157320	With the tar pit, yeah, we're winning some time there. Let's just say that. It's like
2158440	2164100	a 340 fold increase in time. But it's still finding quite a lot of stuff. This is mostly
2164100	2169620	informational stuff, like you have an Apache whatever version as your server header. Even
2169620	2174120	if you respond with 100 code, it's still going to get that header. So most of that stuff
2174120	2179300	is kind of uninteresting. Some of the findings, they disappear. And the script kitty spends
2179300	2182960	14 hours scanning your web server. So we're kind of winning.
2183380	2190060	So W3AF, again, same baseline as before, 1 hour, 37 minutes, 65 findings. But wait a minute,
2190060	2195540	this is going in the wrong direction. 18 minutes instead of 1 hour, 37. It's weird. That shouldn't
2195540	2201100	be happening. But it didn't find anything. So I'm guessing there was some kind of algorithm
2201100	2205320	there that said I'm just going to stop bothering to scan your web server now because it's kind
2205320	2207540	of weird and I don't know what the fuck is going on.
2209960	2217760	So yeah, back to the denial of service skip fish tool. 18 minutes, 10 seconds to find
2217760	2222960	around, 2,500 low, mediums and a couple of highs, which unfortunately even on the baseline
2222960	2229980	were mostly false positives, but whatever, each to their own. So 5 seconds. Again, we're
2229980	2233900	going in the wrong direction. But there was no lows and there was no mediums and there
2233900	2238420	was only three highs. What I thought was interesting was the three highs that it found were not
2238420	2245480	any of the 12 highs that it found previously. So not only false positives but different
2245480	2249980	false positives to the normal scan. So okay, it's kind of doing weird stuff and we like
2249980	2254160	weird stuff because we're mucking around with automated scanners and we're screwing the
2254160	2259380	script kiddies. So random is good. So Acunetix, as I said before, the script kiddy
2259380	2265420	tool of choice. So you get a one‑hour scan, it's quite reasonable, with a huge amount
2265420	2269180	of informational stuff that you probably don't care about. And again, we're going in the
2269180	2273180	wrong direction and this HTTP target should be slowing stuff down but it's making stuff
2273180	2279280	faster depending on what scanner you're using. But again, okay, that's an interesting ratio
2279280	2284780	of complete false negatives. So it's just not finding stuff. So some of these scanners
2284780	2288580	are just like, okay, now this web server is just playing silly buggers, I'm just going
2288580	2293380	to stop bothering to scan it at all. What's interesting, it doesn't tell you that it's
2293380	2299880	just going to give up. It just says, I'm finished. It just says, no, I'm done. So what do we
2299880	2304100	find? So you can slow down some scanners, things like Nikto, others give up quicker
2304100	2309060	because they just get tired of getting responses from the server or a timeout and say the server
2309060	2312860	is not there anymore. If you look through a log file, I'm sure somewhere along the line
2312860	2316980	it says the web server stopped responding even though it didn't. But you get a lot of
2316980	2323580	unreliable and aborted scans. So up to 100% less findings. That's a win for us.
2325480	2331040	So let's move on to blocking successful exploitation. So even if someone can get past all of this,
2331040	2336520	they can find a high criticality in your web server. So we've made it hard for them to
2336520	2340220	find them, but people are going to find these vulnerabilities no matter what. We've made
2340220	2345140	it so that possibly it's going to take them 15,000 times longer to find the vulnerabilities,
2345140	2350200	but they're going to find stuff. So let's stop them from popping shells with Metasploit.
2351120	2361140	Now, how often does Metasploit reference status codes? Anyone care to guess? No? It's about
2361140	2366400	1,000. Give or take. This is not scientifically sound and it depends very
2366400	2370020	much on how people are wording things and how they're using their variables, but this
2370020	2376600	is a simple grab through searching for res.code, resp.code and response.code. These are the
2376600	2383500	usual things that people use. And there's lots of dependency on status codes. Unfortunately
2383500	2389760	even the stuff I wrote uses status codes. So I know it's bad programming, but it's quick
2389760	2394300	and it's what we all do because we use status codes to check the response from servers.
2394300	2401660	So here's an example of a simple snippet of code from one of the Metasploit checks. So
2401660	2406920	all it's doing is checking if the response code is less than a 200 or more than a 300.
2408020	2414560	So I can return a 500. That's great. I can return a 500 with the content. And then it's
2414560	2420460	failing. So if it's not anywhere in the 200 range, which is the okay, then the exploit
2420460	2426140	just fails. Simple as that. Okay, great. So if we're spoofing 404 but still giving
2426140	2429880	you the content, then this exploit is always just going to fail. And if you're good enough
2429880	2433900	to go in and edit the code and change things and you really know what's going on, then
2433900	2438920	you're not really the target of this talk. We're targeting script kiddies who know absolutely
2438920	2442340	nothing. All they know how to do is run the code and if it doesn't work they just cry
2442340	2448420	in a corner. Interesting side effect, if it is a 401, it
2448420	2453600	just starts to print out the response headers like the www authenticate or the authentication
2453600	2458820	header. Of course, as we mentioned before, we don't need to send those headers. So what
2458820	2462640	happens if you don't send those headers? You start to get errors within Metasploit
2462640	2466700	because it's trying to print out stuff that it shouldn't really ‑‑ should be there
2466700	2470980	but it's actually a nil value because we haven't actually set it at all because we haven't
2470980	2477720	provided it. So that's an interesting side effect. So no match, no shell. Okay? No cookie
2477720	2481960	for you. Simple as that. So quickly running through what we've talked
2481960	2488940	about here, okay? So we can use status codes to our benefit. It's fun. It's useful. We
2488940	2493580	can slow people down with it. But browsers can be quirky. So we need to do it in specific
2493580	2500140	ways. And scanners and attack toolkits are, you know, they're set in their ways. This
2500140	2504320	is the way we did it in 1990 and goddammit this is the way we're going to do it in 2013.
2504820	2513300	Get off my lawn. It's just the way things are. Why change things if it's working? So my goal
2513300	2518780	here is to make it not work. WAFs need to seriously get more offensive about their defense
2518780	2524860	because they're being far too passive as far as I'm concerned. So just blocking a request,
2524860	2530000	providing a snazzy little ASCII art that tells people to go and scan someone else's web server,
2530000	2533880	it's great and it's fun but it's not really going to help us. And I'm not talking hacking
2533880	2543440	back. I don't want to start hacking back people who attack my web service but I want to be
2543440	2548320	more active in fighting back and saying to people that this is not right. If you're scanning
2548320	2551880	my server I'm going to screw with you and I'm going to screw with you until you cry.
2551920	2557880	It's just the way things are. So slowing attackers down is good. Making life harder for
2557880	2563480	skitties is absolutely priceless. I should have put the MasterCard logo on that. So
2564580	2573160	current tools are very much the same as APT. Yeah, I said that. They are adequate and they
2573160	2578120	do what they do and until someone fights back and says this is not good enough anymore then
2578120	2581160	they're just going to keep doing what they're doing. Simple as that. So they're only
2581160	2585520	advanced as they need to be. It's just like people attacking you. If they can get you with
2585620	2590580	a phishing attack then why would I bother wasting a zero day on you. Simple as that.
2591640	2598280	I think this is the key to this entire talk. Screwing with skitties is fun. I've had this
2598280	2602320	running on my web server for a while now and just checking the logs it's absolutely
2602320	2608120	hilarious the amount of automated scans that hit your web server searching for like Tim
2608120	2615460	Thumb and how long it takes them to finish just a simple scan of your web server. Just
2615460	2620780	scanning your web server for random stuff. So how can people implement this? There's no
2620780	2624260	point in me talking about this stuff if we don't know how we can implement this stuff. Let's
2624260	2629980	talk about the ghetto option. We can implement it using PHP. It's the lowest common
2629980	2635700	denominator. People probably wrote it in notepad but that's life. You can auto prepend a
2635700	2642480	PHP file to say randomize the response code within a specific section of response codes
2642480	2647680	that are supported by the browser. We're limited by resources that are PHP handled. If
2647680	2651240	your web server starts to error out because people are sending stuff that isn't to be
2651240	2655720	expected then the web server is going to respond back. There's limited functionality
2655720	2661680	there. There's man in the middle dump. It's a real memory hulk. It will use everything
2661680	2665900	you've got. If you put man in the middle dump as a reverse proxy in front of your web
2665900	2671980	server you can have simple scripts that are just going to change the response codes. That
2671980	2677700	works. It works. But it's not the best solution. So what's this enterprise approved
2677700	2685680	solution? Everyone knows NGINX, right? It's like Apache but better. It's a usable
2685680	2692360	implementation. NGINX is used quite often as a reverse proxy. And if you use something
2692360	2696740	like NGINX lure you can write some interesting scripts that are going to change the
2696740	2703480	response codes that are going out of NGINX. So you simply load NGINX lure and using NGINX
2703480	2708740	status you can specifically set stuff. So the only problem is there's kind of a few bugs
2708740	2714720	in the non‑Git version. Specific codes that are supported just tend to get returned as
2714720	2720920	nil which is kind of a pain. But if you use the version from Git it shouldn't be so much
2720920	2727980	of a problem. But if you do an apt‑get install and install NGINX and install the
2727980	2730600	optional extras you're going to run across a couple of problems.
2731220	2737620	So what does the future hold? What's the next step? Well, the next step, I've been trying
2737620	2743060	to get this into mod security to ease adoption by implementing it into something that people
2743060	2747680	are using already on a daily basis. Because no one wants to implement another layer of
2747680	2752740	stuff. Because the more you install, you're increasing your attack surface. So you want
2752740	2756800	to put something, change a couple of configuration files in mod security and just have it do
2756800	2761960	this stuff without you having to think about it. But it's not simple. It's not easy. I've
2761960	2765860	been discussing it with various people for about a year and everyone is like, yeah, that
2765860	2773800	should be possible, maybe, kind of. But I don't know how. So this is kind of a long
2773800	2779220	shot, but I need some help with this stuff. I'm not a C coder and I'm not into writing
2779220	2782860	Apache modules, but if anyone is interested in this kind of stuff and they really want
2782860	2786200	to implement it into mod security, then I would really appreciate their help.
2787120	2792200	So how do we counter this research? We've told the scanners that they're crap. We've
2792200	2798120	told the scanners that they aren't doing stuff in the right way. I really need a new microphone
2798120	2805320	here. So less reliance on status codes. I know it's easy to say, but we're going to
2805620	2810900	have to slow scanners down in order for them to be more reliable. Because right now they're
2810900	2814680	just taking the response codes and ignoring everything else. So start paying more attention
2814680	2819580	to the actual content of the site itself. Some scanners are doing this already, but
2819580	2824000	things need to be double‑checked. You get better matching if you do that. The problem
2824000	2829300	is Regex matching is kind of slow. It's going to use more memory, it's going to take more
2829300	2835820	time, it's not easy. But this is the cat and mouse game. Every time we come up with something
2835820	2841200	new or increase our security, then people who are attacking websites or testing websites
2841800	2848020	increase the productivity and increase the accuracy of their tools. So hopefully we can
2848020	2853700	move this to the next level. So that's all I've got.
2853700	2856580	Any questions? So, yeah.
2867760	2873760	So the question is, have I specifically looked at detecting specific scanners and how they
2873760	2879140	look when they're attacking a web server? Yes, I have looked at it. Not as part of this
2879140	2883160	research, as part of other research. Yeah, it's interesting stuff. You can also detect
2883160	2889160	quite easily when Nikto is attacking your website. The problem is, it's the same as
2889160	2893060	this stuff. As soon as you start detecting how specific scanners look when they hit your
2893060	2898300	website, the scanners are just going to start randomizing how they request stuff. So it's
2898300	2902480	another step in the kind of cat and mouse game. So, yeah.
2906140	2918420	Okay. Yeah, so F5, you can write scripts to specifically do this stuff. So it's interesting.
2918420	2923400	So I'm sure everyone here has an F5, yeah. So, yeah.
2926720	2931300	So yeah, the question was, do different versions of browsers respond in different ways? At
2931300	2936440	the beginning of my testing, I was checking all the different versions of IE. IE6 tends
2936440	2944680	to do things in a kind of weird way. You get some weird stuff. Like with the 100 codes,
2944680	2949780	it tries to download stuff. But it's ‑‑ between specific versions, they don't tend
2949780	2954260	to change the logic at all. So I'm getting the wave. So if anyone has any further questions
2954260	2961680	or any further comments, the code is available on my GitHub site. I'd just like to leave
2961680	2965580	you with the thought that whatever doesn't kill you makes you smaller. Thank you.
