Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:15731
HistoryJan 16, 2007 - 12:00 a.m.

MOAB-14-01-2007: AppleTalk ATPsndrsp() Heap Buffer Overflow Vulnerability

2007-01-1600:00:00
vulners.com
30

Summary

The _ATPsndrsp function is vulnerable to a heap-based buffer overflow condition, due to insufficient checking of user input. This leads to a denial of service condition and potential arbitrary code execution by unprivileged users.

Remote exploitation might be possible (being verified, updates will be done as necessary) due to the exposure of the AppleTalk stack via different services in the system and the presence of similar issues in other functions, which will be detailed in forthcoming MoAB releases.
Affected versions

This issue has been verified on Mac OS X 10.4.8 (8L2127) x86. Previous versions might be affected.
Proof of concept, exploit or instructions to reproduce

The provided proof of concept will cause heap corruption, leading to a kernel panic on a call to m_free():

$ gcc MOAB-14-01-2007.c -o MOAB-14-01-2007
$ sudo appletalk -u en0 (or via Sharing -> Personal File Sharing)
$ ./MOAB-14-01-2007

Note: The AppleTalk stack can be started by different methods, either command-line based or through the GUI in the preference panels.
Debugging information

The following information corresponds to an up-to-date Mac OS X 10.4.8 (8L2127) system, and the provided proof of concept. It wasn't possible to dump a core file over network, as data structures related to the Yukon driver got corrupted, thus causing a second panic and preventing the dump functionality from working properly.

Sun Jan 14 22:15:18 2007
panic(cpu 0 caller 0x0035A8A3): freeing free mbuf
Backtrace, Format - Frame : Return Address (4 potential args on stack)
0x13eabe48 : 0x128d1f (0x3c9540 0x13eabe6c 0x131df4 0x0)
0x13eabe88 : 0x35a8a3 (0x3e9c7c 0x1 0x0 0x2e11848)
0x13eabea8 : 0x2867b9 (0x25c37500 0xffffffff 0x0 0x0)
0x13eabf28 : 0x29a0ce (0x3 0x1800400 0xffffffff 0x1770)
0x13eabf68 : 0x378337 (0x2e80bb8 0x2e11848 0x2e1188c 0x0)
0x13eabfc8 : 0x19acae (0x2e5b724 0x0 0x19d0b5 0x2767c80) No mapping exists for frame pointer
Backtrace terminated-invalid frame pointer 0xbffffb58

Kernel version:
Darwin Kernel Version 8.8.1: Mon Sep 25 19:42:00 PDT 2006;
root:xnu-792.13.8.obj~1/RELEASE_I386

(gdb) x/1i 0x19acae
0x19acae <lo_unix_scall+158>: mov %edi,%esp
(gdb) x/1i 0x378337
0x378337 <unix_syscall+755>: mov %eax,%esi
(gdb) x/1i 0x29a0ce
0x29a0ce <ATPsndrsp+96>: mov 16(%ebp),%edx
(gdb) x/1i 0x2867b9
0x2867b9 <_ATPsndrsp+205>: mov 8(%ebp),%edx
(gdb) x/1i 0x35a8a3
0x35a8a3 <m_free+80>: mov 0x4cd6b0,%eax
(gdb) x/1i 0x128d1f
0x128d1f <panic+382>: mov 4317808,%ecx

The source code below (coming from the original xnu-792 file) illustrates how the values are supplied by the user and used without validation of any type, for allocating a buffer and copying data over it. Both resplen and datalen are used with no bounds checking at all and the respbuf pointer is supplied by the user as well.

---------- bsd/netat/atp_write.c
1672 int
1673 _ATPsndrsp(fd, respbuff, resplen, datalen, err, proc)
1674 int fd;
1675 unsigned char *respbuff; <---- (!)
1676 int resplen; <---- (!)
1677 int datalen; <---- (!)
1678 int *err;
1679 void *proc;
1680 {
1681 gref_t *gref;
1682 int s, rc;
1683 long bufaddr;
1684 gbuf_t *m, *mdata;
1685 short space;
1686 int size;
1687 struct atp_state *atp;
1688 struct atpBDS *bdsp;
1689 u_int16_t *bufsz;
1690 char *buf;
1691 int bds_cnt, count, len; <---- (!)
1692 caddr_t dataptr;
1693
1694 if ((err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
1695 return -1;
1696
(…)
1707 /

1708 * allocate buffer and copy in the response info
1709 */
1710 if ((m = gbuf_alloc_wait(resplen, TRUE)) == 0) { <---- (no resplen check…)
1711 *err = ENOMEM;
1712 file_drop(fd);
1713 return -1;
1714 }
1715 if ((*err = copyin(CAST_USER_ADDR_T(respbuff), (caddr_t)gbuf_rptr(m),
resplen)) != 0) {
1716 gbuf_freeb(m);
1717 file_drop(fd);
1718 return -1;
(…)
gbuf_cont(m) = mdata;
1756 dataptr = mtod(mdata, caddr_t);
1757 for (count = 0; count < bds_cnt; bdsp++, count++) {
1758 if ((bufaddr = UAL_VALUE(bdsp->bdsBuffAddr)) != 0 &&
1759 (len = UAS_VALUE(bdsp->bdsBuffSz)) != 0) {

------------- [note: these are the original comments…]

1760 if (len > space) { /* enough room ? /
1761 gbuf_wset(mdata, dataptr - mtod(mdata, caddr_t));
/
set len of last mbuf /
1762 /
allocate the next mbuf */
1763 if ((gbuf_cont(mdata) = m_get((M_WAIT),
MSG_DATA)) == 0) {
1764 gbuf_freem(m);
1765 file_drop(fd);
1766 *err = ENOMEM;
1767 return -1;
1768 }
1769 mdata = gbuf_cont(mdata);
1770 MCLGET(mdata, M_WAIT);
1771 if (!(mdata->m_flags & M_EXT)) {
1772 m_freem(m);
1773 file_drop(fd);
1774 return(NULL);
1775 }
1776 dataptr = mtod(mdata, caddr_t);
1777 space = MCLBYTES;
1778 }
------------- bsd/netat/atp_write.c

There's available documentation about double free() issues and previous heap based buffer overflows in the Mac OS X kernel. The interesting point about these issues is that AppleTalk is considered a legacy feature, and the code style and general quality is really poor. I would like to thank Ilja Van Sprundel for commenting about it as a potential area for new issues.
Notes
Workaround or temporary solution

Disable the AppleTalk stack, and any associated service:

$ sudo appletalk -d