Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Apr 2000 17:30:46 +0200
From:      Graham Wheeler <gram@cequrux.com>
To:        hackers@FreeBSD.ORG
Subject:   Determining traffic on a socket - solution and security question
Message-ID:  <38F496A6.1DE73643@cequrux.com>
References:  <53045.955453206@axl.ops.uunet.co.za> <38F31395.68EFE3EF@cequrux.com> <38F44460.391BD4B9@cequrux.com> <38F46F1C.1115AEDE@cequrux.com>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------7FACD920DB1E44CD02E708A0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I have attached my final program which works on both FreeBSD 2.x and
FreeBSD 3.x (I don't have a FreeBSD 4.x box to test this on yet).

On FreeBSD 2.x one must be root to run this (to read /dev/kmem), but
on FreeBSD 3.x any user can run this.

I would argue that this is a potential security vulnerability. Some
clever user may be able to exploit this for some protocols to determine
the lengths of usernames and passwords (admittedly this is unlikely to
work with telnet unless in line mode). The sysctl calls that extract
things like TCP control blocks should require privileged access
(although the downside of this is that programs like netstat would have
to be setuid).


-- 
Dr Graham Wheeler                        E-mail: gram@cequrux.com
Director, Research and Development       WWW:    http://www.cequrux.com
CEQURUX Technologies                     Phone:  +27(21)423-6065
Firewalls/VPN Specialists                Fax:    +27(21)424-3656
--------------7FACD920DB1E44CD02E708A0
Content-Type: text/plain; charset=us-ascii;
 name="showtraf.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="showtraf.c"

#include <stdio.h>
#include <fcntl.h>
#include <kvm.h>
#include <nlist.h>

#include <sys/types.h>
#include <sys/socket.h>
#if (__FreeBSD__ > 2)
#include <sys/socketvar.h>
#endif

#include <net/route.h>

#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#define TCPSTATES
#include <netinet/tcp_fsm.h>
#define TCPTIMERS
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#if (__FreeBSD__ > 2)
#include <sys/sysctl.h>
#include <netinet/in_pcb.h>
#endif

//----------------------------------------------------------------

void Display(struct inpcb *inpcb, struct tcpcb *tcpcb)
{
    if (tcpcb->t_state >= TCPS_ESTABLISHED && tcpcb->t_state < TCP_NSTATES)
    {
    	printf("%17s:%-5d ", inet_ntoa(inpcb->inp_laddr.s_addr),
			ntohs(inpcb->inp_lport));
    	printf("%17s:%-5d ", inet_ntoa(inpcb->inp_faddr.s_addr), 
			ntohs(inpcb->inp_fport));
    	printf("[%10s] tx: %10lu rx: %10lu\n",
			tcpstates[tcpcb->t_state],
			(u_long)tcpcb->snd_nxt - (u_long)tcpcb->iss,
			(u_long)tcpcb->rcv_nxt - (u_long)tcpcb->irs);
    }
}

#if (__FreeBSD__ <= 2)

struct nlist nml[] = {
#define N_TCB		0
	{ "_tcb" },
	0
};

void Process_IP_CB(kvm_t *kmem, struct inpcb *inpcb)
{
    struct tcpcb tcpcb;
    if (kvm_read(kmem, (long)inpcb->inp_ppcb, (char*)&tcpcb, sizeof(tcpcb))>0)
	Display(inpcb, &tcpcb);
}

void Process_IP_CBs(kvm_t *kvm)
{
    struct inpcb in_pcb;
    long off = nml[N_TCB].n_value;
    if (kvm_read(kvm, off, (char *) &in_pcb, sizeof (struct inpcb))>0)
    {
        long prev = off;
        while (in_pcb.inp_list.le_next != (struct inpcb *)off)
        {
	    long next = (long)in_pcb.inp_list.le_next;
	    if (kvm_read(kvm, next, (char*)&in_pcb, sizeof(struct inpcb)) < 0 ||
		(long)in_pcb.inp_list.le_prev != prev) // lost sync
	    	    break;
	    Process_IP_CB(kvm, &in_pcb);
	    prev = next;
	}
    }
}
#endif

main(int argc, char **argv)
{
#if (__FreeBSD__ > 2)
    int len = 0;
    if (sysctlbyname("net.inet.tcp.pcblist", 0, &len, 0, 0)<0)
	perror("sysctlbyname");
    else
    {
	char *buf = (char*)malloc(len);
	if (buf == 0)
	    perror("malloc");
	else if (sysctlbyname("net.inet.tcp.pcblist", buf, &len, 0, 0)<0)
	    perror("sysctlbyname");
	else
	{
	    struct xinpgen *xig, *oxig;
	    oxig = xig = (struct xinpgen*)buf;
	    for (xig = (struct xinpgen*)(((char*)xig)+xig->xig_len) ;
		 xig->xig_len > sizeof(struct xinpgen);
	         xig = (struct xinpgen*)(((char*)xig)+xig->xig_len))
	    {
		struct tcpcb *tcpcb = & ((struct xtcpcb*)xig)->xt_tp;
		struct inpcb *inpcb = & ((struct xtcpcb*)xig)->xt_inp;

		if (inpcb->inp_gencnt <= oxig->xig_gen)
		    Display(inpcb, tcpcb);
	    }
	}
	if (buf) free(buf);
    }
#else
    kvm_t *kvm = kvm_open(0,0,0,0,0);
    if (kvm)
    {
        if (kvm_nlist(kvm, nml) < 0)
	    perror("kvm_nlist");
        else
        {
            Process_IP_CBs(kvm);
	    kvm_close(kvm);
        }
    }
    else perror("kvm_open");
#endif
}



--------------7FACD920DB1E44CD02E708A0--



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?38F496A6.1DE73643>