[FreeBSD] Stack overflow in ping

We discussed this vulnerability during Episode 174 on 06 December 2022

A pretty straight forward stack-based overflow in ping on FreeBSD. It is a little interesting though in that there is one caveat this is teh vulnerable code:

static void
pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)
{
    u_char *cp, *dp, l
	struct ip ip;
    /* ... */
	memcpy(&l, buf, sizeof(l));
	hlen = (l & 0x0f) << 2;
	memcpy(&ip, buf, hlen);
    /* ... */
}

This code is processing the IP header of an incoming packet. Thehlen variable is the length of the complete IP header, and it is based on the lower-nibble of the first byte from the user-controlledbuf. It then copies the header into the ip structure on the stack. The problem here is that struct ip is a “naked ip header.” it does not include space for any of the IP options that could be sent. The packet length hlen reads however reflects the full size including those optional parts. So if a packet has options, they will be copied onto the stack, beyond the allocated space.

On exploitation there are a couple considerations here:

  • As a network-attached program it is most likely going to be compiled with stack canaries so the classic technique would be difficult to pull-off here. However there are a lot of items on the local stack, so there is some potential to corrupt that data.
  • ping is a setuid binary, it will run as root, however it is in a capability sandbox, so its root but only with CAP_NET_RAW. So for a local attacker, it is a minor privilege escalation. Still something to be considered about with access to raw packets they can potentially mess with traffic on the system. For a remote attacker, this code path is in the response to a ping, so the victim would need to ping a malicious machine. Its concievable, but it is definitely an ask.