Skip to content

buffer overflow in convert_6to4() and convert_teredo() #207

Description

@rockdaboot

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]}')

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions