Re: Telnetd AYT overflow scanner and linux telnet 0.17

From: zen-parseat_private
Date: Thu Aug 02 2001 - 12:25:40 PDT

  • Next message: Haul: "RE: Suspicious joe.exe"

    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-parseat_private to
    an open forum is confidential information and not to be distributed
    (without explicit permission being given by zen-parseat_private). Legal
    action may be taken to enforce this. If you are mum or dad, this probably
    doesn't apply to you.
    



    This archive was generated by hypermail 2b30 : Thu Aug 02 2001 - 20:41:03 PDT