ping6 SEGV on Ubuntu Lucid

Problem description:

During the search for interesting targets to exploit memory allocation failures in suid binaries, a simple buffer overflow in ping6 on ubuntu lucid was found. Ping will initialize its static packet data send buffer using the size parameter -s from the command-line. This does only occur when no pattern is supplied (no -p option). This is also the reason, why I could not use this bug for privilege escalation: without -p, the buffer is initialized with a fixed byte pattern, so memory cannot be overwritten with user-controllable data.

How to reproduce:

Note: ping adds 8 bytes to size, so overflow starts with values > 127992

ping -s [value] ::1" 127997 - Address family not supported by protocol 128065 - 128065: No segfault, no response, first byte of hostname address overwritten 128066 - 128066: Instable, crashes sometimes 128067 - 128116: Address family not supported by protocol, segfault at TERM 128117 - 138456: Immediate segfault at 001f950b due to early main_loop term. Ping packet pattern used as hostname pointer when writing statistics Program received signal SIGSEGV, Segmentation fault. 0x0019250b in _IO_vfprintf_internal (s=0x2a84e0, vvvvvv format=0x804d81c "--- %s ping statistics ---\n", ap=0xbfb6a9a8 "@ABC") at vfprintf.c:1614 1614 vfprintf.c: No such file or directory. in vfprintf.c 138457 - inf : Segfault at 0804c960 when writing over page boundary

Since ping6 cannot send packets of this size, it will not receive any responses, so response message handling could not be tested trivially. But since ping6 will receive all responses on the interface, a second instance of ping can be started to create fake responses for testing. In a real world example, one would ping an external (attacker-controller) host, that sends the correct responses. For local faking, the ping packet identity must be the same for both ping instances. By default, the identity value is the pid of the process, so one could start a test ping as root:

gdb --args ping6 ::1 break getpid run disassemble __GI___getpid // lookup ip value of next return set $eip=0x?????a7e set $eax=[pid of other ping instance] continue

Future tests:

Further testing would be needed to find out if a crafted ping response could be used to trigger arbitrary code execution in combination with the bug.

Material, References

Last modified 20150407
Contact e-mail: me (%) halfdog.net