00:00:00.000-->00:00:07.542 >>Thanks for coming. This talk will be more about the research on web security. SSRF is an 00:00:07.542-->00:00:20.458 attack technique on web application. The first concept of SSRF was from 10 years ago. 00:00:20.458-->00:00:34.042 Since then, many exploitations and mitigations were developed. Sorry. In this talk I will show 00:00:34.042-->00:00:41.292 you some of my findings. These findings are not only able to bypass existing SSRF 00:00:41.292-->00:00:50.375 protections, but also lead to critical remote call executions. Also we will we will have we 00:00:50.375-->00:00:58.625 will give case studies in real world application, and a demo on GitHub Enterprise. Ok now if you 00:00:58.625-->00:01:05.667 feel like going to other talks, like Hacking Democracy or Open Source Safe Cracking Robots, 00:01:05.667-->00:01:13.542 this is your last chance. [audience laughs] Ok let’s go. Hi again, I’m Orange from 00:01:13.542-->00:01:21.917 Taiwan. Taiwan is a country in Asia, and we speak Mandarin Chinese. As you can see my 00:01:21.917-->00:01:28.833 English is not good. For this reason, I’ve prepared several notes for this talk. I will try 00:01:28.833-->00:01:37.375 my best to keep this talk. Thank you for bearing with me. I have just got my MS degree and work 00:01:37.375-->00:01:46.417 in a security startup. I can say that DEVCORE is the most professional red team in Taiwan. 00:01:46.417-->00:01:53.417 I’m a vulnerability researcher in DEVCORE. I can do reversing stuff, I know exploitation, but 00:01:53.417-->00:01:59.458 my favorite is still web security. [crowd member whoops] [speaker chuckles] 00:01:59.458-->00:02:04.875 Nice.[audience chuckles] I’m also a member of chrO.ot and HitCon. ChrO.ot is the earliest 00:02:04.875-->00:02:11.458 earliest hacker group in my country. In addition we host HitCon, the largest hacker 00:02:11.458-->00:02:21.750 conference in Taiwan. By the way, HitCon 2017 will take place on August 24 and 25. You’re 00:02:21.750-->00:02:31.417 welcome to join us. Here is a brief introduction of myself. I am a speaker, CTF player, and a 00:02:31.417-->00:02:39.208 bug bounty hunter. In web s- in web security I love server side vulnerability more than client 00:02:39.208-->00:02:48.500 side. To take control of a server is more fun for me. So I love remote code execution in 00:02:48.500-->00:02:58.042 particular. And you can see what vendors I report RCE to. Facebook, GitHub, Apple, Uber, 00:02:58.042-->00:03:07.583 and so on. Someone told me always put cats in your slides [audience laughs]. So that you 00:03:07.583-->00:03:13.500 can catch all the eyes and never fail, never fail your talk [audience chuckles] Nobody has 00:03:13.500-->00:03:22.292 cats, right? This is our agenda today. Our goal is to make SSRF great again. [audience laughs 00:03:22.292-->00:03:37.417 and cheers] First I will introduce SSRF and start with some quick fun examples. Next I 00:03:37.417-->00:03:44.833 will talk about my findings in both an attack surface in SSRF-bypass, and a new attack 00:03:44.833-->00:03:55.917 vector in protocol smuggling that enhances the existing SSRF. By combining this we can achieve 00:03:55.917-->00:04:03.292 more advanced exploitations or compromise the server. Of course we will have case studies and 00:04:03.292-->00:04:15.125 demo. What is SSRF? Ok Ok, I know this is Def Con, not SSRF 101 so I don’t need to talk 00:04:15.125-->00:04:25.208 about lots of trivial introductions. I suppose you all know what SSRF is. SS- SSRF in a 00:04:25.208-->00:04:32.625 word it can bypass the firewall and touch your intranet. So the attack surface is dependent on 00:04:32.625-->00:04:41.792 how big your intranet is. The larger your enterprise is, the more robust SSRF will be. For 00:04:41.792-->00:04:51.792 example, in a big company, there are lots of Struts2, Elastic, Redis, you can pawn by SSRF. 00:04:51.792-->00:05:03.250 Next, protocol smuggling in SSRF. It makes SSRF more powerful. There are several ways 00:05:03.250-->00:05:11.958 to smuggle protocols in your SSRF, and each way has it’s limitation. So, what protocol is 00:05:11.958-->00:05:21.667 good to smuggle? I have list here, and you can check. Okay our introduction part is over. 00:05:21.667-->00:05:30.667 Short, right? Before we start our topic. I want to make a survey. How many people use 00:05:30.667-->00:05:41.083 Python, please raise your hand. Wow. Ok. Def Con hasn’t come. [audience laughs] I want to ask 00:05:41.083-->00:05:47.583 you a question: if you want to access the web with Python, which library do you prefer? 00:05:47.583-->00:05:54.458 [unclear responses from audience] Eh nice- nice. I think that most Python guys use 00:05:54.458-->00:06:05.583 request based URLlib or URLlib2. Let’s start with a fun example. Think about this URL the red 00:06:05.583-->00:06:15.583 square is the space. So which address Python going to access? I’ll give you 5 seconds to put 00:06:15.583-->00:06:28.958 insert in your mind. 1, 2, 3, 4, 5, ok. Here’s the answer. [audience laughs] Actually even 00:06:28.958-->00:06:37.250 Python’s building libraries treat the same URL differently. URL lib access the blue part, 00:06:37.250-->00:06:48.042 and URLlib2 access the orange part, but green is requests-s. This sounds crazy. Python is 00:06:48.042-->00:06:58.917 really really hard. I don’t understand Python. [audience chuckles] Another showcase, it 00:06:58.917-->00:07:06.792 is easy to understand if there is a CRLF injection in HTTP and we can smuggle other protocols. 00:07:06.792-->00:07:15.625 But as you can see for the security console, most of SMTP servers breaks the HTTP 00:07:15.625-->00:07:25.583 connection. If server find the HTTP payton such er ge- slash, or post slash in the incoming 00:07:25.583-->00:07:36.125 request the server will cut off the connection. SMTP hates HTTP protocol and it seems 00:07:36.125-->00:07:45.375 unexploitable. Somebody might say “You can use Gopher.” We are not going to talk about Gopher 00:07:45.375-->00:07:54.208 today. Gopher is good but what if there, there is no Gopher support? Gopher is too easy, 00:07:54.208-->00:08:02.417 easy to break and not all not all programming languages support Gopher. But in a SSRF, 00:08:02.417-->00:08:15.542 the HTTP always exists. So we focus our attack scenario on the HTTP and HTTPS. Less smarter 00:08:15.542-->00:08:25.917 SMTP protocol over HTTPS. HTTPS is a secured protocol so the payload will be encrypted. So 00:08:25.917-->00:08:34.875 how? Let’s think about a question. What won’t be encrypted in a SSL handshake? 00:08:34.875-->00:08:48.625 Does anyone have an idea? Ok. The answer is SNI server name indication. We can send a HTTPS 00:08:48.625-->00:08:59.708 request and hope to defy to bypass the limitation. Smuggling SMTP over SSL SNI I think no one 00:08:59.708-->00:09:07.542 mentioned this before. During the SSL the hello messenger will be the handshake that exchange 00:09:07.542-->00:09:15.750 the metadata between the server and the client. And there is an SNI extension which specifies 00:09:15.750-->00:09:26.000 the remote host name in this messenger. So what if we can disrupt the hostname? Yes the 00:09:26.000-->00:09:36.875 yellow square. This space made it possible to embed Marshal’s payload in a domain name. So you 00:09:36.875-->00:09:46.792 can see with the space we can now inject new lines and data in the domain name. Okay why this 00:09:46.792-->00:09:55.542 works. We use a tree in Linux JULib C. And we we are introduce later. The data separated by 00:09:55.542-->00:10:06.042 newlines is SMTP protocol we smuggle. Our comment simply could cross the SMTP server to 00:10:06.042-->00:10:15.375 send the mail. This is the request and the response in parenthesis. You can see there 00:10:15.375-->00:10:24.583 is no HTTP payton here, but su- there is no HTTP payton slash er backslash or paused slash here. 00:10:24.583-->00:10:37.750 And a server recognize our payload as a valid comment. Uh Junk. [audience laughs and 00:10:37.750-->00:10:47.542 claps] So so we exploit the uh- we exploit the uh- [audience chuckles sympathetically] So we 00:10:47.542-->00:11:00.542 uh exploit the uh exploitable successfully. These 2 examples are interesting right? Ok let’s 00:11:00.542-->00:11:11.083 go to our main content. Yeah. Make SSRF great again. Today we’ve prepared 4 sections to 00:11:11.083-->00:11:22.208 make SSRF great again. First part URL parsing issues.This is all about inconsistency between 00:11:22.208-->00:11:31.708 the URL parser and the URL requester. It is common to fix an SSRF by validating the URL. 00:11:31.708-->00:11:44.208 But validating a URL is the hard work. Why? The spec of URL is defined in RFC3986 but only 00:11:44.208-->00:11:52.875 spec. with some implementation guidelines. WhatWG is a community trying to define a 00:11:52.875-->00:12:01.292 mode of implementation based on RFC. But in fact programming languages still prefer their own 00:12:01.292-->00:12:12.792 implementation mode. So there are lots of mistakes on URL parses. How RFC defines a URL. 00:12:12.792-->00:12:21.917 This is the URL components defined in RFC 3986. There are totally 5 parts, scheme, 00:12:21.917-->00:12:33.000 authority, path, query, and fragment. And this is what we will cover today. The scheme, 00:12:33.000-->00:12:43.250 authority, and path. For the scheme we only care about attack scenario under HTTP and HTTPS. 00:12:43.250-->00:12:51.625 For the authority and past, they are too complex to understand and we will take a look later. 00:12:51.625-->00:13:01.083 Finally, it’s the query and fragment. Umm I don’t care [audience chuckles]. This is the 00:13:01.083-->00:13:09.083 big picture of programs we will mention today. We classify the URL parsing issue into 3 types: 00:13:09.083-->00:13:17.542 port injection, host injection, and path injection. So does protocol smuggling. Smuggling on 00:13:17.542-->00:13:28.500 path, smuggling on host and the smuggling on SNI. Consider the following code in PHP. The code 00:13:28.500-->00:13:38.292 simply fetches the user provided URL. In order to prevent SSRF developers use the function 00:13:38.292-->00:13:49.542 parseURL to check whether the host and code are valid or not. So if you provide 127 dot 0 dot 00:13:49.542-->00:14:02.167 0 dot 1, and port 81, you will- you will not pass the check. But how about this URL? Everyone 00:14:02.167-->00:14:10.042 knows colon is the separate between the host and the port. RFC defined the spec but didn’t 00:14:10.042-->00:14:20.375 say how to implement. So will the colon be interpreted from the front or the back? It is 00:14:20.375-->00:14:31.542 interesting for this URL the PHP function parse_URL recognized 80 as perl number. But actually PHP 00:14:31.542-->00:14:40.208 readfile fetches the perl number 11211. Both parse url and readfile are the building 00:14:40.208-->00:14:48.833 functions in PHP but their behaviors are very distinct. So we can use these inconsistencies 00:14:48.833-->00:14:59.625 to bypass the trend. And how about this URL. Google dotcom number sign at Evil dot com. 00:14:59.625-->00:15:09.583 This is another interesting test. Parse_url will recognize google dot com as host name. But 00:15:09.583-->00:15:18.667 the readfile fetches evil dot com. This URL perfectly bypassed all the restrictions. But are 00:15:18.667-->00:15:27.083 you curious about which behavior is the right one? Let’s make a little survey again. If you 00:15:27.083-->00:15:35.208 think google dot com is the right one, please raise your hand. Ok ok [chuckles] I think 00:15:35.208-->00:15:43.375 the domain evil dot com already told you the answer. Several programming languages suffered 00:15:43.375-->00:15:53.167 from this issue, like PHP, Java, cURL, and Python. According to the RFC, the authority uh the 00:15:53.167-->00:16:00.750 authority part is preceded by a double slash and is terminated by the next slash, question 00:16:00.750-->00:16:11.458 mark, or a number sign. So the appropriate authority part is google dot com. Ok if you don’t 00:16:11.458-->00:16:19.625 like PHP, let’s exploit cURL. cURL is a world famous library and there are lots of language 00:16:19.625-->00:16:30.833 bindings. Think about how cURL would appraise this URL. Foo at evil dot com point eighty at 00:16:30.833-->00:16:41.375 google dot com. Most parsers recognize google dot com as a valid host name. But cURL 00:16:41.375-->00:16:49.875 fetches evil dot com. The inconsistency between the parser and cURL will also lead to 00:16:49.875-->00:17:00.292 security problems. I think we all agree that cURL is the world famous library with lots of 00:17:00.292-->00:17:08.708 language bindings. Therefore if an application uses librar- parsing library to track the URL 00:17:08.708-->00:17:17.708 but fetched this resource by cURL it might be vulnerable. This is very common in PHP 00:17:17.708-->00:17:27.542 because PHP building HTTP library sucks [audience laughs] After I find this problem I 00:17:27.542-->00:17:35.500 quickly report to the cURL security team. And they p- patch this in no time. But while 00:17:35.500-->00:17:41.792 checking the patch, I find we can simply bypass the ch-the patch by an additional 00:17:41.792-->00:17:50.000 space.[audience laughs] This is not the fault of cURL this also use a feature in Linux Glibc and 00:17:50.000-->00:18:01.917 we will talk about later. However I think cURL can be more strict, so I report again but 00:18:01.917-->00:18:08.792 this time cURL team replied: “cURL doesn’t verify that the URL is 100 percent syntactically 00:18:08.792-->00:18:17.167 correct. It is instead documented to work with URLs and assumes that you pass correct 00:18:17.167-->00:18:29.042 input.” CURL thinks this is programmer’s problems so this won’t be fixed but previous 00:18:29.042-->00:18:39.833 patch still applied on cURL 7 dot 54. The next attack vector is about a Unicode failure and 00:18:39.833-->00:18:49.500 Node JS. Look at the following code. In order to prevent directory traversal the code 00:18:49.500-->00:18:58.375 check there is no dot dot in the path. So you can access the file outside of sandbox directory. 00:18:58.375-->00:19:08.708 The question is if there is a password file on the web root, how to access the file? Does 00:19:08.708-->00:19:19.500 anyone have an idea? Ok the SS is using a unicode symbol full width N. This url actually 00:19:19.500-->00:19:31.208 access the file password under web root. Ok let’s explain why. The java si- the javascript is 00:19:31.208-->00:19:38.750 internal process the Unicode string as encoding you see as 2. So the unicode symbol N will be 00:19:38.750-->00:19:49.000 presented in FF 2 E. And the trigger thing is the buffer string in HTTP module will fold 00:19:49.000-->00:19:59.708 back and the FF will be streamed. And the remaining part is 2E, the S-key of that. The 00:19:59.708-->00:20:09.708 server will identify the dot dot slash as the parent directory. So we can download the password 00:20:09.708-->00:20:19.333 file and the webroot from the remote server. The double full width N is the new dot dot slash 00:20:19.333-->00:20:36.125 in NodeJS HTTP module. What the hell? [audience laughs and claps] I have nothing to say. 00:20:36.125-->00:20:44.833 [audience laughs] This technique can be also applied on protocol smuggling. Originally HTTP 00:20:44.833-->00:20:53.000 module prevents users from CRLF error injection. The HTTP module will encode the new line as 00:20:53.000-->00:21:04.292 percent encoding. So if we inject new lines in the path, our smuggling will fail. But we 00:21:04.292-->00:21:13.917 can break the protections by Unicode symbol FF0D and FF0A. The full with dash and the full 00:21:13.917-->00:21:23.792 with asterisk. The HTTP module cannot locate any new lines in the past. But our code still 00:21:23.792-->00:21:35.625 fall back and strip the FF. So our protocol smuggling will be used again. Next section is 00:21:35.625-->00:21:46.250 about features on Linux Glibc. First this is a weird feature in an SS function gethostbyname. By 00:21:46.250-->00:21:55.542 looking at source of Glibc there is a comment here. Convert an ascii string into an into an 00:21:55.542-->00:22:10.417 encoded domain name as per RFC1035. But what is RFC1035? The RFC 1035 describes the 00:22:10.417-->00:22:18.417 details of the domain system and protocol. But the surprise is the domain system, suppose, 00:22:18.417-->00:22:28.167 suppose there’s no conversion in gethostbyname. You can see the C program the result of 0 R 00:22:28.167-->00:22:38.875 backslash 0 9 7 NGE dot TW is equal to the result of orange dot TW. I roughly correct the 00:22:38.875-->00:22:46.333 Linux mem patch but I didn’t find anything to dedicate to this weird feature. I think this 00:22:46.333-->00:22:55.208 may be useful when bypassing some blacklist protections. And the softcode showed that 00:22:55.208-->00:23:03.958 gethostbyname will remove the backslash that is not followed by digit. This is also a good 00:23:03.958-->00:23:12.167 way to obfuscate your domain name with lots of backslashes. You can see I printed out a host 00:23:12.167-->00:23:22.250 to show that the escaping process is done by gethostbyname. The next feature 00:23:22.250-->00:23:29.875 is about a Linux getaddressinfo. Getaddressinfo will strip trailing rubbish followed by a 00:23:29.875-->00:23:38.958 valid IP format and a whitespace. You can also see a C program the domain 127 dot 0 dot 00:23:38.958-->00:23:53.333 0 dot 1 space FOO is valid and returns 127 dot 0 dot 0 dot 1. Getaddressinfo is a very 00:23:53.333-->00:24:02.000 fundamental function in Linux in Linux. For example the function gethostbyname in Python’s socket 00:24:02.000-->00:24:12.917 module relied on Linux get address info. So the CIO, CRNF FOO in the domain name will be 00:24:12.917-->00:24:21.417 removed. This makes it possible to do more compressed attacks best under polluted domain name. 00:24:21.417-->00:24:33.417 OK let’s talk about how to exploit NSS features on URL parsers. URL parsers might 00:24:33.417-->00:24:43.583 recognize all of the third part as hostname. But HTTP request still fetch 127 dot 0 dot 0 dot 00:24:43.583-->00:24:54.375 1. The percent 25 09 is a special one and need more explanations. Why double 00:24:54.375-->00:25:03.333 encoding works. After digging the source, we find that libraries such as cURL decode 00:25:03.333-->00:25:15.917 the URL twice. So these paytons are useful when breaking some self domain checks. Next exploit 00:25:15.917-->00:25:24.625 NNS features and protocol smuggling. First, why this works. This is because that HTTP 00:25:24.625-->00:25:33.458 protocol 1 point 1 requires a host header. And most of libraries embed hostname into 00:25:33.458-->00:25:43.375 HTTP request. So the idea is if we can inject new lines in the host name, we have the ability 00:25:43.375-->00:25:52.708 to smuggle protocols in HTTP. For example the data with new lines in the host name will be 00:25:52.708-->00:26:01.125 recognized as the valid reader’s commit. You can see we smuggle the slave of command over the 00:26:01.125-->00:26:10.208 HTTP protocol. By the way the slave of is a nice command that you can make over traffics. This 00:26:10.208-->00:26:22.000 is useful, this is a useful trick when you are facing some blank SSRF. SNI injection is 00:26:22.000-->00:26:31.000 also the same idea. During the SSL, the SNI extension will embed hostname in the hello 00:26:31.000-->00:26:38.000 messenger. So if we inject new lines in the host name, we can find out the command in the 00:26:38.000-->00:26:53.500 encrypted message. Let’s break the patch of Python CVE 2016 5699. It’s the CRLF injection in 00:26:53.500-->00:27:03.542 the function put header of module HTTP lib. It also affects both URLLib and URLLib2 because 00:27:03.542-->00:27:12.750 they use HTT- HTTPLib to construct their HTTP requests. Python uses a regular equation 00:27:12.750-->00:27:23.042 to ensure there is no new lines in the header. Otherwise it will rest in error. But Python makes 00:27:23.042-->00:27:32.000 an an exception of the tap and space followed by the new line. So we can break the patch by 00:27:32.000-->00:27:43.000 deleting space. You can see with the space of the URLlib and URLlib2 are vulnerable again. 00:27:43.000-->00:27:51.833 But this brings out a new problem. There is one more leading space in our hello. Does 00:27:51.833-->00:28:03.333 protocols normally work this way? The answer is yes thanks to Redis and Memcached. As you can 00:28:03.333-->00:28:11.708 see, the slave of command starts with a leading space, but the server still reply OK. Redis and 00:28:11.708-->00:28:22.458 Memcached will strip the leading space so our exploit works again. Next attack vector is 00:28:22.458-->00:28:32.125 about IDNA standard. IDNA defines a standard of unicode in domain name system.There are 2 00:28:32.125-->00:28:43.167 primary versions of IDNA. IDNA 2003 and 2008. But IDNA 2008 is too strict. So most of parsers 00:28:43.167-->00:28:54.125 followed IDNA 2003 with UTS 46 transition. The IDNA supposed lots of weird unicode 00:28:54.125-->00:29:02.167 transitions. For example the circled alphabet will be recognized as a valid letter in 00:29:02.167-->00:29:14.208 domain name system. And the unicode 2003 sealed with joiner will be removed in IDNA 2003 00:29:14.208-->00:29:23.667 with UTS 46 transition. So if the parser and the requester adopt different IDNA standards, 00:29:23.667-->00:29:33.917 it might be a security problem. A very fun example is the latin letter small sharp S. This is a 00:29:33.917-->00:29:42.375 javascript example that you can run on your browser consoles. You can see the symbol in 00:29:42.375-->00:29:50.417 lowercase is a sign of itself but in uppercase it becomes a double capital S. And the 00:29:50.417-->00:29:58.833 redirection in process will go to wordpress dot com. This is useful when breaking some 00:29:58.833-->00:30:09.667 blacklist and we will give you a real case study later. OK cat studies. [audience laughs] This 00:30:09.667-->00:30:18.667 is not typo. C A T studies. Let’s study some real world cases. WordPress is a very 00:30:18.667-->00:30:28.208 famous web application and it had lot of attentions on SSRF. But we still find 3 different 00:30:28.208-->00:30:36.500 ways to bypass the protections. Bugs has been reported several months ago, but still aren’t 00:30:36.500-->00:30:45.208 patched. For the Responsible Disclosure Process, is Def Con heaven? [laughs] I will use MyBB 00:30:45.208-->00:30:52.917 as my case study instead. However these techniques are very general, so I think you can 00:30:52.917-->00:31:03.458 use them in anyway. This table shows the components, WordPress, VBulletin, and MyBB will use to 00:31:03.458-->00:31:14.208 trick a URL. The main concept of the bypass is finding different behaviors among the parser, DNS 00:31:14.208-->00:31:20.667 checker, and the requester. If you find one then you have the ability to bypass the 00:31:20.667-->00:31:32.083 restriction. OK this is the source of myBB. The first bypass is not a new trick. Eh it is 00:31:32.083-->00:31:40.833 time-of-check to time-of-use problem. MyBB uses parse URL to track whether the host name, 00:31:40.833-->00:31:50.042 scheme, and port are valid or not. And also use gethostbyname to resolve the domain ensuring 00:31:50.042-->00:32:00.500 that the address is not in blacklist. If the URL has order check myBB will fetch the 00:32:00.500-->00:32:09.083 resource by cURL. The problem is, the state-of-check and the state-of-use can be different. 00:32:09.083-->00:32:19.417 So we set up a DNS server and lay the first query to add our blacklist address, such as 1 dot 00:32:19.417-->00:32:28.917 2 dot 3 dot 4. After we pass the check myBB will fetch the URL and query the domain again. In a 00:32:28.917-->00:32:37.583 moment we change it, we we change the DNS record to 127 dot 0 dot 0 dot 1. The state in 00:32:37.583-->00:32:47.708 check is 1 dot 2 dot 3 dot 4 but the state in use is 127 dot 0 dot 0 dot 1. So that we can 00:32:47.708-->00:32:58.833 bypass the protection. The next bypass is about the support of IDNA extender. cURL is a very 00:32:58.833-->00:33:06.208 intelligent library which can automatically convert a kernel domain name to an to an IP 00:33:06.208-->00:33:17.500 address. But PHP gethostbyname can’t. This inconsistency also leads to SSRF bypass. You can 00:33:17.500-->00:33:25.792 see for the URL gethostbyname will return false and as it should but cURL still fetches 00:33:25.792-->00:33:35.958 127 dot 0 dot 0 dot 1. The last bypass is the inconsistency between the parser and the 00:33:35.958-->00:33:44.458 requester. We measured several URL parsing bugs before. By using these bugs, we can bypass 00:33:44.458-->00:33:53.958 all the restrictions. For the number sign bug the parse URL recognizes google dot com as 00:33:53.958-->00:34:06.500 host name, but cURL fetches 127 dot 0 dot 0 dot 1. This is handy but has been fixed in PHP 7 dot 00:34:06.500-->00:34:15.917 0 dot 13. If you don’t like PHP, you can still exploit the bug in cURL. And the result is the 00:34:15.917-->00:34:26.083 same. This bug is also fixed in cURL 7 dot 54 but most of the patches didn't keep up. For 00:34:26.083-->00:34:38.625 example, the light cURL in the lighte- latt- latest version of Ubuntu is still 7 dot 52 dot 1. 00:34:38.625-->00:34:47.708 So I think most systems are still under threat. Or you can use the space technique we 00:34:47.708-->00:34:56.667 mentioned before. And this issue, cURL won’t fix. Ok let’s see our last case studies. 00:34:56.667-->00:35:04.292 GitHub Enterprise. GitHub Enterprise is a local version of GitHub that you can deploy the 00:35:04.292-->00:35:11.375 whole GitHub service in your private network. Most of the code are written in Ruby on 00:35:11.375-->00:35:19.333 Rails and obfuscated. The code base of GitHub Enterprise seems to be same as GitHub dot com, 00:35:19.333-->00:35:26.208 seems. And there is an environment- environment, whatever, that you can switch 00:35:26.208-->00:35:34.125 the mode from Enterprise to dot com version. If you want to study the security on GitHub I 00:35:34.125-->00:35:42.833 highly recommend GitHub Enterprise to you. [audience murmurs] In this case I will 00:35:42.833-->00:35:49.167 show you a beautiful exploitation that transformed vulnerabilities into a critical 00:35:49.167-->00:35:59.292 remote call execution. It also won the Best Report in GitHub 3rd Bug Bounty anniversary. Why 00:35:59.292-->00:36:06.792 are preying, why are preying on GitHub Enterprise? I know test there is an interesting feature 00:36:06.792-->00:36:14.792 called WebHook. WebHook can define a custom HTTP code back with specific, specific git 00:36:14.792-->00:36:24.417 commit occurs. GitHub used RubyGem Faraday to fetch external resource. And prevents 00:36:24.417-->00:36:34.208 and prevents users from SSRF by doing faraday restrict IP addresses. The gem seems to be 00:36:34.208-->00:36:42.667 just a blacklist, and can be bypassed by a zero. In Linux, the zero stands for local host. 00:36:42.667-->00:36:57.708 Ok we got SSRF now. However we still can’t do anything. Why? There are several limitations in 00:36:57.708-->00:37:03.875 this SSRF. Such as this SSRF only allow the scheme HTTP and HTTPS. And we can’t change the- 00:37:03.875-->00:37:12.083 change the scheme by the 302 redirection. This is also a POST best SSRF and we can’t even 00:37:12.083-->00:37:21.833 control the header or the POST data. The most important thing is there is no CRLF injection in 00:37:21.833-->00:37:33.500 this SSRF. We have an SSRF but with lots of limitations. My next I- my next idea is: is 00:37:33.500-->00:37:40.417 there any service we can liberate? It is a bit work. There are several service- 00:37:40.417-->00:37:47.042 services in sight. And each service plays on a different language implementation such as 00:37:47.042-->00:37:56.583 C, C plus plus, GOAL,and Tyson. With a couple days of digging, I find data service called 00:37:56.583-->00:38:04.417 Graphite on port 8 thousand. Graphite is a highly scaleable and real time sys- real time 00:38:04.417-->00:38:13.333 graphing system. Of course, we find another SSRF here. The second SSRF is simple. Graphite 00:38:13.333-->00:38:30.042 just fetched the URL, found the Get and run it. So we have 2 SSRFs now and we can combine 00:38:30.042-->00:38:41.625 these 2 SSRFs into an SSRF execution chain. The cool thing, right? And we’ve successful 00:38:41.625-->00:38:47.792 switched a POST best SSRF into a Get best SSRF. The 3rd bug is the CRLF injection in Graphite. 00:38:47.792-->00:38:50.542 As you can see, the implementation of the second SSRF is Python HTTPlib. Earlier 00:38:50.542-->00:38:57.125 we mentioned that HTTPlib suffered from CRLF injection. So with the CRLF injection we have 00:38:57.125-->00:39:08.250 the ability to smuggle protocols in this SSRF execution chain. However the next problem is: 00:39:08.250-->00:39:16.292 what protocol do I choose to smuggle? I spend lots of time to find out what vulnerabilities 00:39:16.292-->00:39:24.250 can be treated if I can control the Redis or Memcached. While reviewing the source, I am 00:39:24.250-->00:39:31.833 curious about, why GitHub can store Ruby objects? In Memcached? After some digging, I 00:39:31.833-->00:39:41.292 find GitHub used uh Ruby gem to store the cache. And the cache was ripped by Marshal. It is a 00:39:41.292-->00:39:51.000 good news. Everyone knows Marshal is dangerous. So our goal is clear. We use our SSRF 00:39:51.000-->00:39:57.583 execution trend to store Marshal's Ruby eh gem in Memcache. The next time GitHub 00:39:57.583-->00:40:05.833 fetches the cache the Ruby gem will deserialize the data automatically. And the result is 00:40:05.833-->00:40:15.125 we got a remote call execution. Here is the final payload. There are several parts. The the red 00:40:15.125-->00:40:24.625 part is the first SSRF bypass in webhook combined with the blue part, the second SSRF. The 00:40:24.625-->00:40:34.167 yellow is the memcached protocol we smuggled. And the final, that blue part is our malicious new 00:40:34.167-->00:40:48.125 reaction. In this case we eschew the commit ID hide NC orange W W hold 1 2 3 4 5. In this case I 00:40:48.125-->00:41:02.458 won 12,500 dollars from GitHub [audience applauds] Ok ok I have no time [chuckles]. I think this 00:41:02.458-->00:41:08.750 is a very critical case about SSRF execution chain and protocol smuggling in the world. 00:41:08.750-->00:41:22.417 Ok let’s watch the demo video- Remote Code Execution on GitHub Enterprise. OK this is GitHub 00:41:22.417-->00:41:33.542 Enterprise. Very similar to Github Ap- GitHub dot com right. Ok the version is 2 dot 8 dot 6. 00:41:33.542-->00:41:45.875 Eh? Oh yeah. In order to add a webhook we open our profile repositor- repository in the 00:41:45.875-->00:42:01.500 settings. Yeah. Click hooks and services and uhh add a webhook. OK here is the code back URL. We 00:42:01.500-->00:42:17.958 open our console. Echo hi. List our exploit file. And then load the er and load our exploit. 00:42:17.958-->00:42:33.083 Here is our SSRF payload. We pass the payload to the GitHub Enterprise. When we submit a 00:42:33.083-->00:42:42.458 file to SSRF execution trend, we are insert a malicious data to the memcached. OK we listen on 00:42:42.458-->00:42:52.542 port on 20 1 2 3 4 5 and wipe the commit back. The final step is to trigger the 00:42:52.542-->00:43:11.250 deserialization. We can search a keyword to trigger the RCE. [audience applauds] Ok ok ok, I 00:43:11.250-->00:43:18.875 have no time. [audience laughs] As you can see we got a shell. So with this SSRF execution 00:43:18.875-->00:43:24.500 chain and the protocol smuggling over the Memcached, we can execute arbitrary system commit 00:43:24.500-->00:43:38.333 on remote server. Mitigations. How to prevent such attacks in SSRF from 2 aspects. For 00:43:38.333-->00:43:45.875 application layer, use the only IP to connect, and remember don’t reuse the URL that user 00:43:45.875-->00:43:52.708 provided. For network layer use firewall or network policy to block intranet traffics. There 00:43:52.708-->00:43:59.958 are also projects that designed to prevent you from SSRF attacks. SafeCurl by Fin1te and 00:43:59.958-->00:44:08.500 Advocate by Jordan Milne. Ok we have no time. Thanks for friends back home, they inspired me to 00:44:08.500-->00:44:13.708 do this research. And thanks to many many people who helped me, Allen, Birdman, and Henry. This 00:44:13.708-->00:44:24.208 is the end of [audience applauds] my presentation. [audience cheers 00:44:24.208-->00:44:33.125 enthusiastically] OK OK. OK OK this is the end of my presentation. If you have 00:44:33.125-->00:44:38.875 further questions here here is my contact information. Orange at Chroot dot org, or you can 00:44:38.875-->00:44:45.583 find me on Twitter Orange underscore 8361. Thanks for staying with me. Thanks. 00:44:45.583-->00:00:00.000 [audience applauds]