 Okay, let's start. My name is Alfredo Ortega. I work as an explorer writer for cross-security. This talk will read about the OpenBSD bag. If you don't understand something that I am saying, you ask me and I will repeat. Okay, this is a bag that I discovered a couple of months ago, but like more four months ago. And it's an interesting bag and the exploit is interesting, too, and got pretty much publicity, so I'm going to explain it. Okay, let's start talking about how I discovered the bag. Okay, this is the history. This is the history. I was assigned to do a research about a patch in the OpenBSD kernel, namely the number 8 patch, a reliability fix. This was, in fact, a hang of the kernel, an infinite loop in the kernel caused by fermented ICNP packets. So my boss come and told me if I could reproduce this bag. So I started to try to build a fuzzer. Do you know what the fuzzer is? It's a little program to send my former packets and try to try to break the system to reproduce the bag. So I really didn't have very much information about the bag, so the only thing that I could do is to start trying and student the patch, trying to make a couple of fermented packets and sending to an OpenBSD system, trying to make it to work, to lock in an infinite loop. So the fuzzer is a very simple program. I made it in Python. It only makes two packets from the IPv6 protocol. The IPv6 protocol is, as you know, a very new protocol. It's not very much used. And it's got a lot of bugs. I will be presenting some of these bugs. And in the end, maybe I will do some live demonstration about another vulnerabilities. I spent about two days trying to build in my former packets, thinking how I could break the system. And in the end, I, in a lucky packet, managed to practice the system. I sent it to an OpenBSD virtual machine and the OpenBSD channel just hung up. But it was not an infinite loop like the patch. What's seeing, it was a complete hang up. The system just hung up and threw a stack trace of the bug. I was thinking this really is not the same bug that I was trying to find. Maybe it's a new bug. So the thing that I did was to download the latest version of OpenBSD kernel. It was, at the time, the 4.1 OpenBSD kernel. And trying to attack against that kernel. The attacks worked anyway. So in my hands, I didn't have what is called a serial day or a new patch vulnerability. In the time I was thinking it was a Daniel service and maybe it could result in code execution. But I was not really sure about it. So I reported to my boss, my boss reported to OpenBSD team and got fixed in about two days. They were very fast and fixed the bug. But they reported as a Daniel service of a reliability fix. And I was thinking that it was not a reliability fix. It really was an explotable bug because of the stack trace. So I started researching how to exploit this bug. Let's see, why the bug was hanging in the kernel. Okay, these are, let's see, in the, in the, a lot of Unix systems, the network packets are stored in a structures named mbuffs. The mbuffs are little packets of memory of a fixed length. They are about 256 bytes long. They are ordered in a linked list in memory and they store network packets inside them. And if the network packet is, if the network packet is too big to fit inside a mbuff, the mbuff got an external memory buffer. But the failure of the kernel was that the kernel was overwriting a lot of mbuffers in the way that it's showing there. Instead of writing into the first mbuff, mbuff one, the OpenBSD kernel was overwriting a lot of, of these buffers. And not only the buffer, but the hidden information inside the buffers and the couple of pointers that link the buffers, the linked list. So when the OpenBSD system was trying to free one of these packets, it made an unlink operation. That is an unlink operation. It's a exchange of two pointers to, to free the, the node between them. And because of the pointer was overwriting with garbage, at the time was garbage, the system was hanging, was making an illegal, an illegal operation and it's totally hanging. This seemed like a very exploitable bug because when you overwrite two pointers, you, you can use a very common technique named mirror copy or, or, or forward write to when you exchange two pointers and you can control the pointers, you can manage to write four bytes of data in every, in any place of the memory. So I, I think if I am overwriting a linked list, it's sure, it's, it's almost sure that it is a exploitable bug. So I started disassembling the OpenBSD kernel to see if I could exploit the bug. Well, maybe you can, it's, it's not a show it very well, but it, here is a disassemble of the function that was hanging. The function that was hanging was a free function. I see in the down, the M, free M function was crashing. The M free M function was crashing. That is the function that's free and no, a M buff. So I disassembled this function. That is the result. I must say that the OpenBSD kernel is an open source kernel and I really did have the, the C code of the source code of the, that function, but I am really more used to see it this way, to see it in assembly, to analyze the function in assembly is, is more used to me to see it this way. The function is starting the orange block and we can see, if we could see it, maybe is that the, the package to free is stored in the register. I must clarify that this, this December is for the Pentium and 32 bits only. OpenBSD run in a lot of architectures for this exploit is only for Pentium at 32, 32 bits, sorry. And in the start, this function plays the package to be freed in the one register, in the ASI register. And then it made a lot of operation using this register of reference. The point is, the point in what the, the kernel was breaking is making yellow is, well, you didn't can see it very well, but it is, it's exchanging the pointers here. In the block making, in the point, in the block, in the yellow, the point, the pointers of the linked list are being exchanged. And of course, the linked list was overwriting and it was trying to write in a position of memory that didn't not exist. So it worked exactly in the yellow block. So I say, okay, let's try to reach the yellow block with controller pointers. So I can write in any place of the memory. If I can write a value in any place of the memory, I can do a lot of things like make my user process root or open, I don't know, change the permission of the new process. There are not very much things that I could do, but some things it could be done and it would be exploited this way. And when I was analyzing this, I realized something. I realized that in the next block, in the block next to them, to the yellow block was a call and the referencing a pointer. It was getting a pointer from the block here in the arrow, in this part. Let's see. In this part, it's moving a value from the packet inside the eax register. And then, in the next block, it's jumping to this eax register. In fact, it's calling them. It is the same as jumping. So I could send a value here inside the packet and make that open VCD jump exactly what I want. So I can control the flow of execution. Much in a much easier way than trying to do the other trick of the yellow block, that writing in some part of the memory. It's much easier to jump to any place that I want because I could send my code and place my code or my shell code in some place of the memory and make the kernel jump it and I will get total control of the kernel. Of course, I will gain execution inside the kernel and it's not an ideal situation. The ideal situation was to gain control in a user process because kernel exploit is much difficult to do than a user exploit because in a user exploit, you got the kernel to do whatever you want. You can use the kernel to open a file or to open a connection. It's much easier. The kernel is made for that. When you do a user exploit, when only like a hundred instructions you can make the machine do what you want. It's a very small exploit. But in kernel mode, you really don't have a kernel. You don't have an operating system to make use of. So it's almost like you are your own operating system. Anyway, I was gaining execution inside the kernel and I was executing my code. So I told the open VCD people that in fact this bug was exploitable. I still didn't have the exploit. The exploit took me about a couple of weeks to make because it was a very difficult exploit and I was helped by a lot of people from coms for security. But anyway, now I am in the situation that I can't jump to any place that I want in the memory. But where I want to jump? Of course, I cannot jump to the same kernel because the same kernel is not my code. I want to jump to my code so I can overtake the system. First, I must place the code in memory in some way. While in this transparency, I marked the source code in C, the equivalent of that function. Here's the assembly and here's the part of the source code that makes the code. It's a little difficult to understand. In red, it's marked the part of the source code that jumped to the reference pointer. As you can see, it's much easier to understand in assembly than it is in C. It's a lot of micro expansions. I never will realize the bug looking only to the source code. Okay, that's better. Okay, in this drawing, you can see how the fragmented packets of ICMP v6 are placed in memory. In the right, we have the linker list of Mbuff or Mbuff chain with the corresponding headers. The headers of the Mbuff are pointer to the next Mbuff, pointer to the last Mbuff, pointer to the free function. The packets are placed in exactly that way in memory. Other places are overwriting a couple of Mbuffers or Mbuff. The arrow here, this arrow marked the exact position of where the pointer to jump is placed in memory. I must place a pointer here. This pointer will overwrite the free function inside the header. This function will call the pointer that I placed there. Here it says trampoline. You can really see it, but it says trampoline. Trampoline is a name for a position of memory that I want to jump. I want to jump to a trampoline. I put this pointer in the header of the Mbuff in exact position. You can be not even one byte disaligned. It must be exactly aligned to the pointer. Is this something very easy to do? No. Okay, let's continue. We can now jump to any place of the memory that we want. Where is the share code located? We know that the share code is located here. Here is a share code. It's placed next in the same packet. Because it's very easy to put the share code in the same packet that goes to our flow. So we got this portion of memory we got our code. The share code or the code that we want to execute. But we don't know where this is placed because the Mbuff are the dynamic, aligned places, and it could be in any place of the memory of the kernel memory. It's not in a fixed position. It will change. It will change from run to run and from kernel to kernel. But we know one thing. We know that the share code is pointed to the ASI register. The ASI register points exactly where our share code begins. Why is that? Well, because that is how the function was compiled. We remember that the packet in the beginning of the function was pointed to ASI. It was pointed here. So if the packet is pointed to ASI and we do an immediate jump to somewhere that we want, we must jump to some place memory that jumps back to the position of the ASI register. It's like a bouncing. We bounce in a point of the kernel memory that has an intrusion that jumps back to the ASI register. We must find a position of the kernel. This is the kernel. We must find a position of the kernel that got an intrusion that jumps back to the ASI register. This intrusion is a very small intrusion. They are no more than two bytes long. It's placed a thousand times in the kernel. So it's very easy to find one intrusion. It could be in any place of the kernel. It not only must be there and be executable. So we find one intrusion. It could be any. We find one intrusion that jumped to the ASI register and we simply jump there. So we jump in this intrusion. That intrusion jumps back towards shellcode and we are executing our shellcode now. We have complete control of the system. I was thinking, okay, game over. It's over, but it's not over. Because as I was seeing the kernel, you really can't do anything in kernel mode. I can't even open a file. I can't open a connection to the internet because I am running in kernel mode. And it's a very tricky, this is a really tricky part to make the exploit works in kernel mode. Because it must be like a mini-operative system. It should be. Okay. There are a lot of ways to do it, but this is the way that we implemented and this way it really works pretty fine. In kernel mode, there are not many things that you can do, but you can do very easily hook interruption. You can get the interruption table of the Pentium processor and you can hook, you can make that one interruption to zoom to you and you instead jump to the original interruption. So what I was, what I did was to hook this particular interruption, the system call, the operator system, communicate with the user process using interruption in Unix. One in Windows is similar, but in Unix, the interruption number used is always the 80 interruption. So I must hook this interruption, the 80 interruption, in the same way that they all implemented a style resident program from DOS. In DOS, there were a kind of program, maybe you remember that, that hooked the interruption, the timer interruption, or the keyboard interruption and in that way it started resident in memory. This is the same technique. By the way, we hooked the system call interruption. This is the original system call. We got a user process here. The user process make a system call, I don't know, open a file, or kernel, open an internet connection, and the kernel open the internet connection and returns to the user in the next instruction. Here is who the hook is made. The system process, the user process, jump to the hook that I have installed in the memory, and the hook, make something that I want, and then return to the original system call, and the system call is made and returned to the user. So the user really don't know if he don't realize that it's calling my call. It's calling the kernel, but it's not calling the kernel. It's calling my shell call in memory. Okay. So it's calling my shell call. What do we do in this situation? Okay, now we can see every system call of the system. We can see every process and every operation of all the process of the system. This is a very useful thing. So I implemented, this is the server call of the operation of the hook, the interruption hook. First, we don't want to affect any user process, because we will, in this way, we will hack the machine. We, not every user process are useful to us. Only the privileged user process are useful, the user process with a privilege of root. Because if we take over a process with no privileges, it will be very useful. We want to take over a user process with root privileges. So first, we want to see if the process calling us is root. Of course, this is a very hard thing to do, because we cannot simply get the process ID or the user's ID of the process, because again, we are in kernel mode. We must do a lot of tricks to do this. First, in user mode, you use a system call, getPID, or getProcessID. It's just simply of that. That's a system call, returns a number, a test number, says if you are root or not. But now, we must do a little magic here. We first search for this variable in the kernel memory, because the kernel can be any kernel, can be an OpenBSD3 kernel, or 4, or can be a custom compiler kernel. And this variable, the current process variable, in fact, it's an array, it's not a variable, could be any place in the memory. So we must search it. We must search through all the memories searching for patterns, for the specific patterns of memory that tell us where this variable is placed. These patterns are present in every OpenBSD version from 10 years ago, and are very easy to find. Once that we got this current process variable, we can see inside this variable, in fact, it's a structure, it's not a variable, what is the user ID of the process? So now, we got the user ID of the process. And if the user ID is zero, the process is root. And we can't take over this process. So if the process is root, we must attack this process. We know that the process has full privilege of the system, and it's much easier to execute code in user-lined or user-mode than in kernel-mode. So we got a process that is root, is calling us. We must take over this process. First, we must execute code in this process. We could just overwrite the return pointer. The return pointer of the process should be in, because we can overwrite any place in the memory. We could just overwrite the return address. But this is not a very good thing to do, because maybe this process, the process that are calling us, the binary that are calling us, is the libc. The libc is a library that is very important in the system. We can't just overwrite the libc, because the g-system will crash every process that we are using the libc. We cannot overwrite the binary. We must place our shellcode in another place. A good place to put our shellcode is the stack, because the stack is one for every process, and it's very easy to reserve memory on the stack, put our shellcode there, and execute our shellcode on the stack. But there is a problem with that approach that is this protection. This protection is a very good protection that OpenBSD got that says that no place in the memory that is writable is executable. The memory can be or writable or executable, but not bought. So that is exactly what we want to do. We want to write in the stack and execute in that place. So the OpenBSD channel will not let us to do this. We must disable this protection. This protection can be disabled, because we are kernel and we can modify every register of the painting processor, because we got complete control. So how we disable this protection? We extend the selectors. The selectors, OpenBSD implemented this protection, changing the selectors and making some selectors shorter, some selector larger. And the specific selector that is affecting that, it don't let us to execute our code in the stack is this selector, the code selector, of course. We must extend this selector. We extend this anyway. This is not very important, but this selector is very important. We must extend the code selector, or CS, to let us execute the code in the stack. This extending a selector can be made in a user process. A user process can extend selectors, because it don't have permissions to do that. But we aren't kernel, so we can extend this selector. Once that this protection is down, we simply copy the user mode in the stack and execute that. We modified the return address to the point of the stack. And when the system can restone, it will return to the stack. Instead of returning to the binary image of the process, it will return to the stack. And we execute there perfectly, because this protection is down. So now we are executing our shell code in a user process. And it's much easier to do two things in that place, like open a connection, or adding a user, writing a file, because now we are a user and we can make use of the kernel. In the end, of course, we must restore the original interruption vector, because if we don't do this, every root process will be taken over. We don't want that, because we want to take over only one process. We don't need that. We don't need to take over all the root process of the machine. So we restore or remove the hook, restore the original interruption vector. And that is, now we've got one process, the first process that are calling us, root and executing all code. This process could be anyone. It can be the send mail process, can be the Apache, I don't know who said Apache, the web server. In fact, I was seeing that every time I send the exploit, the send mail process was the first that was taken over. The send mail makes a lot of system codes, and it's root, and it's every, almost every time is the send mail process. It's the first that is attacking, but it's exploit. And if we are not root, if some other process call the kernel and yes, not root, we just continue with the original system call. And we don't know what I feed it, because we are really done, it's interested in attacking a process that is not root. Okay, this is a diagram. We've got a little problem here. There should be a line here, and a line here too. This is a map of the memory of the Pentium 32-bit processor, and the whole OpenBSD managed it. We got four gigabytes long, and the OpenBSD system reserves the first part of the memory for executing binary code here. So the only executable code can be placed here, in this small part of the memory. This could be grow a little, it is viable, can stand a little further, but only this place of the memory is executable. And this place of the memory is not executable, but it's writable. Here is the data memory, the heap and the stack. So this is the operation that we do. We extend the code selector that only reached here originally, and we extend it from two here, all the way to the world memory, so we can execute a code in this area too. We also extended the data segment just within free cost. It's not really necessary. Well, so a little last emblem, this is the implementation of the server code that I was showing. It may be a little, this gives some instruction that are not commonly used in user mode, like this one and this one, that store global description table and store local description table, because the selector are stored in these tables that the painting processor used to store the selector. So we first store the selector in some place in the memory, it can't be any place. We choose to store it in the ISP itself. This section of the code add a lot of operation used to assemble the selector, because the selectors are not continuous in memory. This assemble some place in one byte, some byte later are other parts of the selector. I don't know why this is, the Intel engineers made it that way, I don't know what it is because, but you must assemble the selector using a lot of boring operations, and these two find an instruction, extend the selector, place it only a bar way in a specific place of the memory, then we must load again the selector, here is not the part that loads the selector back into the painting processor, it's not sure what it is, it's next. Okay, but we are not really finished yet. I was saying this expert is a little complex, because OpenBSD is a clever system and in the next context switch will restore the selectors. So if we are happily executing this stack, but if the process, our context switches back, the process will crash, because the protection, this protection WXRX will be enabled again and the process will crash. The execution of the checker will be detected by the operating system. So we must try to get a portion of memory that are executed that are right over and execute over forever. How we do that? We can use to, we got two options to do that, in fact we maybe got more than two options, but these are the two options that I think of. The first one is to use another system called, because I am executing a user mode, I can call any system called that I want and I call this one that is named and protect. The system called is used to give any portion of memory any permission that I want. So I just unprotect all the stack. I say to the operating system that I know I want to execute calling the stack using this. And the operating system will make the world stack executable like it was Windows 95 and will be executable forever. We now do a couple of things to fix the original process because we don't want to design my process of the web server process to crash. We wanted to make a new process and to keep the original process attack to function to work okay to work normally. So we first fork the process, make a clone of the process and now we got two process that are the same. In one of those process we fix all the stack, we fix all the things that we overwrite and continue to execute normally. So if we attack the design my process, design my process we continue to execute like if nothing was happening and the forked process will be executing our code forever. Forever in a secure position of the memory because we unprotected that memory and it's over. Now we got a root processor executing our share code. There is another way to do this that is to do another function call that is called a map or memory map. We use after-operative system to give us a special portion of memory that is not in the stack but is writable and executable. So we just copy our share code in that new portion of memory and execute from there. And in the next context switch there is nothing that can stop our execution because it's a server portion of memory. Okay and this is the end of the exploit. We are now executing got a root process executing our code in user mode. This is a sample of what is what looks like this exploit. Here is a terminal of OpenBSD executing and asking for login prompts and I'm sending here the couple of packets. Inside the share code I have inserted a break point of introduction tree. So this blue part here in fact is the debugger of the kernel debugger of OpenBSD. The ddb is called. We can see maybe you can see here that it's not hanging. The kernel has stopped it because it's a break point. It's not a crash. Here we asked the debugger to continue to execution and here the OpenBSD system is continued with normal execution but now it's hooking. Now we got all code hooking in the interruption IT. Now I would like to do a live demo of this. I hope it works. It may be not work but to make a little more interesting I'm going to do a live demo. Okay now we are launching the build machine with the OpenBSD 4 operating system and we're going to launch another build machine using the Linux operating system that will send the package to this build machine. The build machine are connected together with a host-only network. It's like a virtual network between the two build machines. Maybe we're going to have some problems with the resolution. I hope not. I think we're going to have some problem with the resolution. Coru please make the screen a little smaller because I can't see the top of the screen. I can't move the window. Okay now the top please. There you go. Let's see. In the right side is the shell code. The writing is in Python language and I want to launch the shell code in the other window here. Okay here we can see that the OpenBSD channel has stopped it because the attack works and it's stopped in a break point because inside the shell code I have a place that's a break point and we can ask the operator to continue with the execution and the channel of course will be hooked with our shell code. Now the OpenBSD channel has a hook in the interruption and it's working perfectly normal like if nothing has happened but in fact our shell code is inside the interruption vector now. Okay that was one of the live demonstration but researching about the IPv6 protocol. The IPv6 protocol is not very much used and it's active by default in a lot of operating systems and that is a receipt for a lot of failures and a lot of bugs and vulnerabilities. I will to show another ones that I have discovered as a part of my research and okay using virtual machines. So we will continue with this. This couple of vulnerabilities are for the Linux operating system. We're going to use the Ubuntu distribution is one of the most used distribution of Linux. Okay this is a Linux kernel, the latest one, the 2.6.22 kernel and it's a custom kernel this one. Okay it's a custom kernel and I will send a couple of ICMP packets to him to see how it will respond. Here we can see that this is a Linux asking for a login. Sorry I get confused that was not the attack. Okay now we can see that the Linux kernel is hanging. This is because we have sent another couple of IPv6 packets. It's another protocol but the Linux kernel you can see as it's hanging. I'm going to show one thing. Maybe you can see the lights are blinking here. This is how a Linux kernel, a Linux kernel 4x4 protection is shown with. This Linux is hung very, very few times but when it hangs it's just blinking the caps lock key. It's very strange to see the Linux kernel hanging. It is hanging sometimes. This is a Daniel of Cerberus attack and in fact it's not a Saturday so it's patched. It's patched but it's in the very latest version of the Linux that has come out a couple of weeks ago but it's not back ported. You mean maybe you have a Linux system over here. I'm going to attack a completely actualized Ubuntu system to see if they have patched this vulnerability. You can see this is a kernel 2.6 to 20 slash 16. It's the latest one. I have actualized the kernel just around 12 PM midnight and it's what's the same kernel. This is the latest kernel for Ubuntu system. We're going to launch the same packets. Great. The Ubuntu system is perfectly. But we're going to launch the first attack. There's some other attack. Oh damn. So you got there a full patch of Ubuntu system that is still half a vulnerability. All of it because the IPv6 was activated by default. So this talk is over now but I want you to say only one thing. That is if you got a unique system or a Linux system and you got IP activated and you don't use it, please deactivate it. It's pretty easy to do because you can see there are very bad people there and they can do things like this. So thank you. Do you have any questions? You can ask me now. In the ICMP packet has data part that is supposed to be replicated in the answer of the ICMP packet and I placed simply in that portion of the packet. It's a big packet like a 1000 byte long. The shell code in fact is something like, I don't know, 700 bytes. It fits perfectly in the second ICMP payload. It's in that part. I could send the exploit in a lot or in another ways like, I don't know, floating the system with shell codes. The system will place the shell code any place in the memory. Maybe you are going to fill the memory with the shell code and I can't just jump anywhere in the memory because the shell code surely will be there because if I send 10 megabytes of traffic to the OpenBSD system, it's going to put it in some way, in some place in the memory. Okay. If there's no more question, thank you very much. That's all. Thank you for coming.