SSD Advisory – BusyBox (local) cmdline stack buffer overwrite

Vulnerability Description
BusyBox provides an arp applet which is missing an array bounds check for command-line parameter IFNAME. It is therefore vulnerable to a command-line based local stack buffer overwrite effectively allowing local users to write past a 16 bytes fixed stack buffer. This leads to two scenarios, one (A) where an IOCTL for GET_HW_ADDRESS (SIOCGIFHWADDR) fails and results in a corrupted va_list being passed to *printf() and one (B) where an attacker might provide valid params for the IOCTL and trick the program to proceed and result in a RET eip overwrite eventually gaining code execution.

Technical Details
By providing an overly long string for param IFNAME while setting -D (read HW Address from IFACE) and -s (set new entry) a strcpy operation can be reached that allows to write past the stack buffer ifreq.ifr_name[IFANMESIZ] [5,6]

Details: arp.c

The stack buffer overflow manifests in arp.c

Taint Graph

Vulnerable Code
1. No bounds check in arp_main

2. No bounds check in arp_set

3. No bounds check and buffer overwrite in arp_getdevhw

Arbitrary length (may be limited by os) string IFNAME overwrites 16 bytes fixed buffer ifreq.ifr_name[IFANMESIZ] [5,6].

4. stack is messed up before IOCTL for SIOCGIFHWADDR in ioctl_or_perror_and_die

We control any fields below ifr.ifr_name – which essentially is any ifreq field, see below – allowing us to call SIOCGIFHWADDR IOCTL with user controlled fields and pot. let it die or make it succeed. If the IOCTL fails it will make the process die in vsprintf() due to messed up va_args on stack. If the IOCTL succeeds, it will make the process continue, copy taken from [5]

5. a) IOCTL fails

6. b) IOCTL does not fail

As described in 3./4. the code proceeds with returning from arp_getdevhw eventually executing code from the strcpy() based overflow. (RET overwrite)

Proof of Concept
Brutally smash the stack buffer (provide any IP as arg HOSTNAME to bypass name resolver):

A debugging session shows that we messed up the va_list on stack with the user provided string.

crosscheck: valid run (no crash expected, IFNAME=AAAAA):

see inline comments: va_list on stack shown by x/10s p

now overflow va_list by providing IFNAME=A*(64+40+40) (crash expected):

see inline comment: va_list is messed up.

Remediation Steps
strcpy => strncpy(dst,src,n=sizeof(ifreq.ifr_name)-1) or less error prone but more overhead snprintf()

References
[1] http://busybox.net
[2] http://busybox.net/downloads/?C=M;O=A
[3] http://git.busybox.net/busybox/commit/networking/arp.c?id=88e2b1cb626761b1924305b761a5dfc723613c4e
[4] https://en.wikipedia.org/wiki/BusyBox
[5] http://lxr.free-electrons.com/source/include/uapi/linux/if.h#L203
[6] http://lxr.free-electrons.com/source/include/uapi/linux/if.h#L26

Vulnerable Versions
BusyBox version 1.23.1
BusyBox version after 1.4.0

Immune Versions
BusyBox version prior to 1.4.0

Vendor response
The vendor has released a patch to address the vulnerability

https://blogs.securiteam.com/index.php/feed