CyberWire Daily - Exploits and vulnerabilities. [Research Saturday]

Episode Date: December 2, 2023

Ryan from Bishop Fox joins to describe their work on "Building an Exploit for FortiGate Vulnerability CVE-2023-27997." After Lexfo published details of a pre-authentication remote code injection vulne...rability in the Fortinet SSL VPN, Bishop Fox worked up a proof of concept demo. This research share how they were able to create that proof-of-concept exploit, step by step. The researchers state "Our debugging environment consisted of a FortiGate 7.2.4 virtual machine which we modified to disable some self-verification functionality. After bypassing these integrity checks, we were able to install an SSH server, BusyBox, and debugging tools such as GDB." The research can be found here: Building an Exploit for FortiGate Vulnerability CVE-2023-27997 Learn more about your ad choices. Visit megaphone.fm/adchoices

Transcript
Discussion (0)
Starting point is 00:00:00 You're listening to the Cyber Wire Network, powered by N2K. of you, I was concerned about my data being sold by data brokers. So I decided to try Delete.me. I have to say, Delete.me is a game changer. Within days of signing up, they started removing my personal information from hundreds of data brokers. I finally have peace of mind knowing my data privacy is protected. Delete.me's team does all the work for you with detailed reports so you know exactly what's been done. Take control of your data and keep your private life Thank you. Hello, everyone, and welcome to the CyberWires Research Saturday. I'm Dave Bittner, and this is our weekly conversation with researchers and analysts tracking down the threats and vulnerabilities, solving some of the hard problems, and protecting ourselves in a rapidly evolving cyberspace. Thanks for joining us.
Starting point is 00:01:53 We had actually all been in a training doing heap exploitation the week before this vulnerability was announced. And so as soon as we saw a major heap vulnerability come up, we all wanted to take a look and actually try to use what we had just learned and write this exploit. That's Ryan, a security researcher at Bishop Fox. He asks that we not use his full name. The research we're discussing today is titled Building an Exploit
Starting point is 00:02:25 for FortiGate Vulnerability, CBE 2023-27997. Yeah, the timing is everything, right? Yeah. Yeah. Well, let's walk through it together here. Can you take us through step by step? How did you and your colleagues approach this? So initially, when we started looking into it, we just went and tried to follow the blog post that Lexfo, the original researchers, Charles Fole published. Charles Fole published. So they have a really detailed write-up of all of the steps that are required. And so we just tried to replicate that. So we started by setting up an environment with a vulnerable system.
Starting point is 00:03:16 And I used Fortinet on an ESXi system just at home and figured out how to configure that, figured out, okay, I am able to hit this endpoint they're talking about, and then worked on just being able to get a crash proof of concept because that, in theory, should be pretty easily. And then once we actually had a crash proof of concept,
Starting point is 00:03:44 I worked on trying to get a debugging environment set up, meaning installing GDB, being able to have a root shell, because Fortinet appliances don't actually, well, they try not to let the user obtain a Linux shell. They don't even have a proper shell installed. If you run bin sh, it won't drop you into a shell. So there's a process of setting up this debugging environment. And then once we had the debugging environment
Starting point is 00:04:16 and we had something that could at least cause this to crash, then we could continue on with writing the rest of the exploit. Well, let's back up just a little bit. I think then we could continue on with writing the rest of the exploit. Well, let's back up just a little bit. I think, as you pointed out in the research here, that this bug is a heap-based buffer overflow. Can you describe that to us for folks who may not be familiar with that? Yeah, so in most programs you have two areas that you store data. One area is the stack, which is typically for temporary things. Maybe it's only used for the lifetime of a certain function. But if you want
Starting point is 00:04:56 something that's kept around for a long time, or maybe you have a lot of data, you'll allocate in the heap. And so the heap is just a big area of memory and you have a code that will manage this area and you can request, okay, I would like 1000 bytes, call a function, and it will return a pointer to an area where you can use 1000 bytes. And then when you're done with that area, you say, okay, I no longer need it, free this area, and it can then be reused. And so with a stack overflow, there's a lot of other program state that is stored on the stack.
Starting point is 00:05:39 And so if you're able to manipulate that, it can often be pretty easy and pretty deterministic how you would turn stack overflow into a full exploit. But on the heap, there is a lot of other stuff that is using it. It's a lot less deterministic, and there's a lot more work that needs to be done to manage the layout of the heap. lot more work that needs to be done to manage the layout of the heap. And there's less program state that's directly usable to get code execution. There's often a lot more setup and crafting fake objects and a lot more really deep stuff that you have to do to actually get a successful exploit.
Starting point is 00:06:22 to actually get a successful exploit. Well, walk us through how did you trigger your first crash? Yeah, so the actual bug relies on a difference between using two definitions of the size of the request that you're sending. So one definition is just the length of the request. It's a string, so it can check how long the string is. The other definition is that there's a size field embedded in this message that you're sending. It actually misinterprets the sizes. And so if you send it a message of one size, but then you set the length field to an extra thousand bytes, you can corrupt a bunch of data that's out of bounds of this buffer. There's some amount of manipulation you can do to make sure it crashes.
Starting point is 00:07:28 Sometimes it won't crash, but if you just send a bunch of requests where the size field is longer than the actual length of the message, eventually you will overwrite something sensitive and cause the application to crash. Thank you. continue to rise by an 18% year-over-year increase in ransomware attacks and a $75 million record payout in 2024. These traditional security tools expand your attack surface with public-facing IPs that are exploited by bad actors more easily than ever with AI tools. It's time to rethink your security. Zscaler Zero Trust Plus AI stops attackers by hiding your attack surface, making apps and IPs invisible, eliminating lateral movement, connecting users only to specific apps, not the entire network, continuously verifying every request based on identity and context, simplifying security management with AI-powered automation, and detecting threats using AI to analyze over 500 billion daily transactions.
Starting point is 00:08:50 Hackers can't attack what they can't see. Protect your organization with Zscaler Zero Trust and AI. Learn more at zscaler.com slash security. So you achieve your first crash here, then what do you set out to do next? So once you're able to achieve a crash, you want to start to make this a more controllable crash. So instead of writing to some unknown area in the heap, you want to actually know that immediately after my buffer is some object where there is a field that would be useful to overwrite. So you try to set up the allocations and deallocations
Starting point is 00:09:43 on the heap such that when you overflow your buffer and write data out of bounds, you are writing to something that you know and you can overwrite in a much more controlled way. So instead of trying to generate a crash just by throwing random data, you want a crash where you actually know what you're doing, control what you're overwriting,
Starting point is 00:10:08 and get a more controlled crash. Are you able to read the heap ahead of time to sort of map out what exists in there and how it's being allocated? No. So in this case, you would rely on knowing how the program works and understanding that even though it can feel non-deterministic,
Starting point is 00:10:30 there is a level of determinism where you can control exactly which data you're sending and know that, okay, if I send this data, this will be the actual layout of the heap. So in this case, each time you make a request, there are two buffers that get allocated in this region that you're manipulating. And the first buffer is a structure that is set up for the SSL context. And the second buffer is a structure that contains your actual data. And through a bit of manipulation,
Starting point is 00:11:11 you can swap that order so that you have your buffer followed by this SSL structure. And as long as you do your best to minimize any other noise and control the exact allocations that are occurring, you can make sure that you reliably have this layout. What is your ultimate goal here in this exercise? What are you looking to achieve? The ultimate goal is remote code execution.
Starting point is 00:11:43 With this specific setup, there's a pointer in this SSL structure that is a code pointer. And you want to overwrite this function pointer so that when it gets called, it jumps to code and you can hijack that code flow and obtain and use it to then create a ROP chain and gain arbitrary code execution.
Starting point is 00:12:13 And so ultimately, how did you end up doing that? What were the rest of the steps that were necessary here? So we used this function pointer to make a call to adjust the stack pointer to the beginning of the SSL structure. From there, we were able to have sort of complicated ROP chain that adjusted the stack pointer a few more times until it eventually pointed to data in our initial buffer, which we entirely control. From there, we could set up arguments for a call to system or popen or any other function. And we could use that to basically run arbitrary commands. basically run arbitrary commands.
Starting point is 00:13:06 And because, like I said earlier, Fortinet doesn't actually have a bin SH or a shell, we were able to use the node binary, so it does use node for a web server, and we were able to create a reverse shell with node where we run node from exec. I believe we used exec L specifically. Now, help me understand here, because one of the things you point out in your research is that the heap was not mapped to be executable.
Starting point is 00:13:39 So you had to get around that. Are there particular details you can highlight with that part of the process? Yeah, so typically if you do have controlled, writable, and executable memory, you're able to just directly jump to that code. So instead of doing this complicated drop chain, we would just set the function pointer to point to data that we control and execute it as code.
Starting point is 00:14:06 But in this case, we have to do this more complicated setup where we point the stack pointer to data that we control. And then we're able to reuse different parts of the binary that is already in memory and executable. And we essentially run the last couple instructions of a function and then let it return. And then it'll jump to the next address on the stack, which we also control. And you keep doing that in building up these little ROP gadgets,
Starting point is 00:14:37 these gadgets that do one small operation. And by combining a bunch of these gadgets where you're reusing code from the existing executable in memory, which is mapped as executable, you can actually still obtain arbitrary code execution. What was it like for you and your colleagues when you ultimately achieved what you'd set out to do here? I mean, it sounds to me like this journey was fun. What was the payoff like in the end?
Starting point is 00:15:12 Yeah, so it's, of course, always exciting when you get that first connect back with your reverse shell. So I was very happy when I finally got that working. We were also able to actually create a scanner that we could use and we released to help others identify what's vulnerable. And the payoff for the company was, of course, that we could go test on customer systems and say, hey, you're vulnerable, here's proof, and get people to patch. So there's really a lot of, for my team, it was mostly just really exciting. But for others, there was definitely a positive impact on their security awareness and posture.
Starting point is 00:15:59 Well, and based on the information that you gathered here, what are your recommendations for folks out there who are responsible for securing their organizations? Any words of wisdom to take away from this exercise? Patch. Just make sure you're patching. I mean, this is an unauthenticated remote code execution. It is a heap vulnerability, but we were able to develop a working proof of concept within a week. No doubt other threat actors would be able to do the same. The fix is to patch your system, and please do that. Our thanks to Ryan from Bishop Fox for joining us. The research is titled Building an Exploit for FortiGate Vulnerability, CVE 2023-27997.
Starting point is 00:16:56 We'll have a link in the show notes. Thank you. ThreatLocker is a full suite of solutions designed to give you total control, stopping unauthorized applications, securing sensitive data, and ensuring your organization runs smoothly and securely. Visit ThreatLocker.com today to see how a default-deny approach can keep your company safe and compliant. studios of DataTribe, where they're co-building the next generation of cybersecurity teams and technologies. This episode was produced by Liz Ervin and senior producer Jennifer Iben. Our mixer is Elliot Peltzman. Our executive editor is Peter Kilpie, and I'm Dave Bittner. Thanks for listening.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.