[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug-inetutils] Telnet client command parsing bugs

From: Peter Kasza
Subject: [bug-inetutils] Telnet client command parsing bugs
Date: Mon, 5 Jun 2017 20:49:30 +0200
User-agent: Mutt/ (2016-04-01)

Hi all,

I've been playing around with afl-fuzz[1] over the weekend and I've
discovered several bugs in the command parsing routine of the telnet
client. I've evaluated these from a security standpoint since the
telnet client is present in many appliances that disallow the user to
directly execute shell commands on the system.

None of the discovered issues are exploitable; however the analysis
below should provide enough information to fix them.

I've attached the input files that can be used to trigger the issues.

* Obtained crashes
  - inetutils-1.9.4/telnet/commands.c:162:      *argp++ = cp; // XXX CRASH 
  - inetutils-1.9.4/telnet/commands.c:201:  *argp++ = 0; // XXX CRASH HERE: 
BUFFER-OVERFLOW; testdata/crashes/id:000002,sig:06,src:000182,op:havoc,rep:8
  - inetutils-1.9.4/telnet/commands.c:1225:       *(ct->charp) = 
  - inetutils-1.9.4/telnet/commands.c:3052:     printf ("%s\n", c->help); // 

** Segmentation faults
Telnet seems to crash at [commands.c:1225] and [commands.c:3052] with a
segmentation fault. None of the addresses seem to be controllable by
an attacker, so no potential security vulnerabilities.

  - The first crash seems to read the charp field from the last element of
  the *Setlist* array which is the guard element and is set to zero in the

  - The second crash is very similar, however it crashes trying to access
  the guard element of the *cmdtab2* array.

** Buffer overflows
Both identified buffer overflows occur in the *makeargv* function at
[commands.c:162] and [commands.c:201]. From these, the first crash
seems to contain an out of bounds write that could be exploitable. The
other one just writes out a zero to the memory address.

   Breakpoint 1, makeargv () at commands.c:162
   162           *argp++ = cp; // XXX CRASH HERE: BUFFER-OVERFLOW; 
   (gdb) bt
   #0  makeargv () at commands.c:162
   #1  0x0804c8cb in command (top=1, tbuf=0x0, cnt=0) at commands.c:2981
   #2  0x08049d77 in main (argc=0, argv=0xbffff668) at main.c:414

The *makeargv* subroutine is called from the *command* function that
reads in commands from stdin and stores it in the *line* buffer. The
lines are read using fgets, and the proper buffer length is passed in.

   commands.c:2969: if (fgets (line, sizeof (line), stdin) == NULL)

Since the line buffer is 256 elements in size, we cannot pass in
longer commands than 255 bytes.

   commands.c:135: static char line[256];
   commands.c:136: static char saveline[256];
   commands.c:137: static int margc;
   commands.c:138: static char *margv[20];

However if we specify one character arguments we can pass in at most
128 elements. The *makeargv* function tokenizes the command and stores
the arguments in *margv*. We can overflow *margv* by (128 - 20) * 4,
which overwrites *margc*, *saveline* and part of the original line

This doesn't seem to result in a security vulnerability currently, but
it can become a serious issue if the *margv* and *margc* values are
ever moved in to the *makeargv* function as stack variables.

The current code allows an attacker to leak out the memory address
taken up by the arguments by prefixing a command with "!" and
overwriting the *saveline* buffer. Telnet will copy the line buffer to
the *saveline* array and then overwrite it in *makeargs* due to the
buffer overflow. When it tries to execute the command from *saveline*,
the memory address will be passed in as the program name.

   % perl -e 'print "!" . " A"x128' > test
   % cat test | telnet
   zsh:1: command not found: \M-ca
   telnet> telnet> ?Invalid command

[1]: http://lcamtuf.coredump.cx/afl/

Best Regards,
Peter Kasza


()  ascii ribbon campaign - against html e-mail
/\  www.asciiribbon.org   - against proprietary attachments

Attachment: crashes.tgz
Description: GNU Unix tar archive

reply via email to

[Prev in Thread] Current Thread [Next in Thread]