On Linux (Debian testing here), demonstrate the buffer overflow with
import subprocess
trigger_query = '2002:FFFFFFFF:FFFFFFFF:1'
result = subprocess.run(
['valgrind', '--tool=memcheck', './whois', '-h', '\n', trigger_query],
capture_output=True,
timeout=30
)
print(f'[*] Return code: {result.returncode}')
print(f'[*] stdout: {result.stdout.decode()[:500]}')
print(f'[*] stderr: {result.stderr.decode()[:1000]}')
Output is
[*] Return code: 1
[*] stdout:
Querying for the IPv4 endpoint 16777215.255.16777215.255 of a 6to4 IPv6 address.
No whois server is known for this kind of object.
[*] stderr: ==25556== Memcheck, a memory error detector
==25556== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==25556== Using Valgrind-3.25.1 and LibVEX; rerun with -h for copyright info
==25556== Command: ./whois -h _ 2002:FFFFFFFF:FFFFFFFF:1
==25556==
==25556== Invalid write of size 1
==25556== at 0x4877733: memmove (vg_replace_strmem.c:1415)
==25556== by 0x4940177: memcpy (string_fortified.h:29)
==25556== by 0x4940177: __printf_buffer_write (Xprintf_buffer_write.c:39)
==25556== by 0x49499E1: __printf_buffer (vfprintf-process-arg.c:240)
==25556== by 0x4967636: __vsprintf_internal (iovsprintf.c:62)
==25556== by 0x4945730: sprintf (sprintf.c:30)
==25556== by 0x401282D: convert_6to4 (whois.c:1423)
==25556== by 0x4013A12: handle_query (whois.c:378)
==25556== by 0x4014409: main (whois.c:315)
==25556== Address 0x4cca3d0 is 0 bytes after a block of size 16 alloc'd
==25556== at 0x4869818: malloc (vg_replace_malloc.c:446)
==25556== by 0x40127EB: conv
Fix
diff --git a/whois.c b/whois.c
index 60063d7..c8d6f99 100644
--- a/whois.c
+++ b/whois.c
@@ -1419,6 +1419,9 @@ char *convert_6to4(const char *s)
b = 0;
}
+ if (a > 0xFFFF || b > 0xFFFF)
+ return strdup("0.0.0.0");
+
new = malloc(sizeof("255.255.255.255"));
sprintf(new, "%u.%u.%u.%u", a >> 8, a & 0xff, b >> 8, b & 0xff);
Similar problem exists for convert_teredo(). Reproduce with
import subprocess
# convert_teredo() dispatch byte: 0x0B = \x0b (formfeed)
# Trigger: 2001:0:0:0:0:0:FFFFFFFF:FFFFFFFF
# sscanf %%x reads FFFFFFFF into both a and b → a = b = 0xFFFFFFFF
# a ^= 0xFFFF → 0xFFFFFF00, a >> 8 = 16776960 (8 digits)
# sprintf writes "16776960.0.16776960.0" (28 bytes) into 16-byte buffer
trigger_query = '2001:0:0:0:0:0:FFFFFFFF:FFFFFFFF'
result = subprocess.run(
['valgrind', '--tool=memcheck', './whois', '-h', '\x0b', trigger_query],
capture_output=True,
timeout=30
)
print(f'[*] Return code: {result.returncode}')
print(f'[*] stdout: {result.stdout.decode()[:500]}')
print(f'[*] stderr: {result.stderr.decode()[:1000]}')
On Linux (Debian testing here), demonstrate the buffer overflow with
Output is
Fix
Similar problem exists for
convert_teredo(). Reproduce with