Vulnerability Development mailing list archives

Re: Telnetd AYT overflow scanner and linux telnet 0.17


From: <zen-parse () gmx net>
Date: Fri, 3 Aug 2001 07:25:40 +1200 (NZST)

General notice Before I begin:

Please:
 Do not email me to ask for an exploit for this.
 Do not email me to ask to  teach you how to hack.
 Do not tell me about anything you have done that is illegal.

I was glancing through this list, as I occasionally do, and saw a post
that made me fear for the minds of people who are trying to learn.

The telnetd bug is not immediately exploitable through the initial
buffer overflow, yes you can smash the stack, but no you cant control
the data.

I'll come to the 2nd part of that in a moment.

Well, congratulations. You found the function that allows the expansion of
the input that causes the overflow, but unfortunately have failed to grasp
a few of the important facts you should understand when trying to develop
an exploit.

One: You can only 'smash the stack' if the buffer is on the stack. netobuf
is not. 'Smashing the stack' is usually taken to mean overwriting the
return address of a function. We cannot do that from here. Here is how you
can tell.

bash-2.04$ objdump -t /usr/sbin/in.telnetd|grep netobuf
080585a0 g     O .bss   00002040              netobuf

As you can see, netobuf is in the .bss segment. (NOT THE STACK)

(This copy is from telnet-0.17-7.src.rpm (netkit-telnet-0.17, one of the
'Not vulnerable' telnetds), which is that standard server for Redhat 7.0,
thatI have recompiled with debugging options (-g2 to the CCFLAGS in the
Makefile), and installed by hand, just moving the telnetd file to
/usr/sbin/in.telnetd and another copy to a working directory, and not
stripping it, as files generally are when they get installed. Again, I
didn't check if it would happen, so it might not.)


A good hint that something might be on the stack is the list of variables
declared in the function. Local variables are on the stack. For example.
len and maxsize are probably on the stack in this function...

void
netoprintf(const char *fmt, ...)
{
   int len, maxsize;
   va_list ap;
   int done=0;

...

(I say probably, because depending on optimizations in compiling, they may
be stored in registers, and not even [be able to be touched with / need
to be counted in calculatning the size of] a stack overflow.)

global.c:char   netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;

netobuf has been declared outside a function, so its not on the stack.

[ this is the current stack, we overflow netobuf ]
netobuf (8254)
pcc (30)
ptyobuf (8254)
ncc (30)
subbuffer (510)
envinit (30)
progname (30)
ptyibuf (???)

Tthis is not the stack.

netobuf is in fact declared (in global.c) as
char    netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;

Lets see what the buffer sizes are.

bash-2.04$ cpp global.c |grep netobuf
extern char netobuf[8192 +64], *nfrontp, *nbackp;
char netobuf[8192 +64], *nfrontp, *nbackp;

I think you maths is slightly out. 8192 + 64 = 8256 and its unlikely that
any form of optimization or rearrangement so its able to be traced more
efficienlty would result in a buffer that is 2 bytes smaller than it has
been declared.
(Multiples of 4 are also more likely to be the right length (More likely
only though.)) An int is length 4bytes. (I have no idea where you got 30
from.) You didn't give any addresses in the posting that I could use
to verify you knew what you were talking about when you said that gdb
might've been allocating 30 bytes per int, so I'm going to assume you
didn't.

A normal (4000 ayt's) only seems to get about halfway into subbuffer
before the program exits.

Could it be you were sending them in 'packets'? If the daemon does a
netflush() between parts then they start going back from the beginning of
the buffer.

The 2nd thing you said initially that made me write this email.
 You can't control the data.

You can control the data.
Can you show me the rule that says you are only allowed to use AYT to
explot this bug?

Have a look on the internet for RFCs (Request For Comments) dealing with
the TELNET protocol.

You will see there is a great deal of things you can do.

Also looking at the source (did you?) will should you there are more
replies that get put into the netobuf (via the variable nfrontp, which
I'm sure you would've noticed is initialized to be equal to netobuf.)
You also would've seen the send_will() send_wont() send_do() and send_dont()
functions, and noticed that they don't do any bounds checking either,
trusting that if you could send it in one message, it could be stored in a
buffer the same size. You would also notice that you can control the last
byte of each 3 byte cluster? And noticed that a \0 gets added to the end
of the buffer under most situations, either by the vsnprintf() or by
another function?

Read the RFCs there is even one quite funny one, if you look hard enough,
that should entertain you enough to continue looking through them enough
to work out how to do this properly.

(strlen(hostname) + 12) * ayt

Yoy! Something that is accurate!

Alright what do we have.  We can make a string which is

(strlen(hostname)+12) *N + 3 *M bytes long by sending a string that is
2 * N + 3 * N bytes long. Now, bear with me for a momement.

In an ideal world (which this isn't, but we will pretend it is)
two-thirds of computer names will not be a multiple of 3 letters long.

Huh? you go.

Well, if you are slightly lucky, and have a machine that returns a name
that is not a multiple of 3 bytes long, you can overflow ANY distance (up
2 the maximum imposed by the input length of course)  distance into the
heap.

'Huh?' you go.

(.bss segment is 'low heap', followed by the area that get malloc()ed for
things, the heap, proper.)

To exploit this, you would need to use the AYT overflow to overwrite one
of the internal stack variables (and create a secondary vulnerability),
                  ^^^^^ <- not stack!!!!!        ^^^ YAY
then exploit this newly created vulnerability to launch a shell. )
                                                            ^^^^^^<-no!!!!


In a few days, maybe a week, all will become clear.

-- zen-parse

-- 
-------------------------------------------------------------------------
The preceding information, unless directly posted by zen-parse () gmx net to
an open forum is confidential information and not to be distributed
(without explicit permission being given by zen-parse () gmx net). Legal
action may be taken to enforce this. If you are mum or dad, this probably
doesn't apply to you.



Current thread: