TL;DR
Last time, I posted about 1-day vulnerability CVE-2017-5123, waitid() arbitrary R/W with null-deref on LK v4.13.x/~v4.14.0-rc4. It just happened because there's no any sanity check whether input space (*infop exactly) is kernel-land or user-land.
Also, you can find other good payloads that include sandbox-bypass like chrome-sandbox (actually, it's kinda different vulnerability, but...), fully-chained sth, etc...
Anyway, recently, I've been spending some time fuzzing network and fs-related Linux kernel interfaces with syzkaller and hand :).
Actually, I didn't have enough time to fully analyze vulnerabilities & complete fully-working payloads. So, this post describes how the bug was discovered and suggesting a possible way to exploit for EoP or leak info.
Founds
Overally, there're some bugs at (DCCP, XDP, SCTP)-socket, (ext4, 9p)-fs, mm stuffs. Information Disclosure which can lead to KASLR bypass at dccp_feat_xxx and hugetlb stuff, xdp_umem_create, p9_client_rpc, etc... And ext4_xattr_set_entry [CVE-2018-10879] (6/25/2018, found by syzkaller), etc...
Targets
Most of the bugs can be worked on LK v4.16.x ~ v4.18.x-rc5 (latest).
1-day bug
Most of the bugs found by syzkaller and already patched by other people :).
ext4_xattr_set_entry
Currently, it was reported by Laura Pardo
on 6/29/2018. CVE-2018-10879.
When renaming a file in a crafted ext4 image, UAF triggered (dangling last is accessed). It just fixed by checking last & ext4 magic number whether it is valid.
file /fs/ext4/xattr.c L1598
Before
// LK v4.17.0+ // Fixed at LK v4.17.6
for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) {
if (!last->e_value_inum && last->e_value_size) {
size_t offs = le16_to_cpu(last->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
}
After
// LK v4.18.0-rc5
for (; !IS_LAST_ENTRY(last); last = next) {
next = EXT4_XATTR_NEXT(last);
if ((void *)next >= s->end) {
EXT4_ERROR_INODE(inode, "corrupted xattr entries");
ret = -EFSCORRUPTED;
goto out;
}
if (!last->e_value_inum && last->e_value_size) {
size_t offs = le16_to_cpu(last->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
}
file /fs/ext4/xattr.c L230
Before
if (buffer_verified(bh))
return 0;
if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
BHDR(bh)->h_blocks != cpu_to_le32(1))
goto errout;
After
if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) ||
BHDR(bh)->h_blocks != cpu_to_le32(1))
goto errout;
if (buffer_verified(bh))
return 0;
Syzkaller found this bug on 6/25/2018. Here's my syzkaller's report.
BUG: KASAN: use-after-free in ext4_xattr_set_entry+0x34fc/0x3a30 fs/ext4/xattr.c:1598
Read of size 4 at addr ffff88002f02b046 by task syz-executor14/14011
CPU: 0 PID: 14011 Comm: syz-executor14 Not tainted 4.17.0+ #9
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
Call Trace:
The buggy address belongs to the page:
page:ffffea0000bc0ac0 count:0 mapcount:-128 mapping:0000000000000000 index:0x1
flags: 0x100000000000000()
raw: 0100000000000000 ffffea0001174ec8 ffffea0001561e08 0000000000000000
raw: 0000000000000001 0000000000000000 00000000ffffff7f 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88002f02af00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff88002f02af80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff88002f02b000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff88002f02b080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff88002f02b100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
p9_client_rpc
syz-bot reported this bug on 7/11/2018. Bug type is an uninitialized variable.
In short, we need to validate p9pdu_readf
return-value before assigning -ecode to err. Because if p9pdu_readf
returns -EFAULT
, then err remains uninitalized.
file /net/9p/client.c L560
Before
...
// LK v4.17.8
} else {
err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
err = -ecode;
p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
}
...
After
I think it's not fixed yet but reported.
Here's my syzkaller report.
[ 155.012783] kmemleak: 8 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
BUG: memory leak
ferenced object 0xffff88006695ad80 (size 96):
comm "syz-executor15", pid 11123, jiffies 4294812752 (age 17.158s)
hex dump (first 32 bytes):
00 00 00 00 ad 4e ad de ff ff ff ff 00 00 00 00 .....N..........
ff ff ff ff ff ff ff ff a0 14 ba a1 ff ff ff ff ................
backtrace:
[<00000000d71df12d>] p9_client_prepare_req net/9p/client.c:757 [inline]
[<00000000d71df12d>] p9_client_rpc+0x1bd/0x1410 net/9p/client.c:757
[<0000000062b42e0d>] p9_client_version net/9p/client.c:976 [inline]
[<0000000062b42e0d>] p9_client_create+0xd0b/0x16ce net/9p/client.c:1069
[<000000006460f58e>] v9fs_session_init+0x21a/0x1960 fs/9p/v9fs.c:400
[<00000000066f7e92>] v9fs_mount+0x79/0x860 fs/9p/vfs_super.c:135
[<0000000057fd6665>] mount_fs+0xa7/0x323 fs/super.c:1277
[<0000000008124149>] vfs_kern_mount.part.33+0xc9/0x4c0 fs/namespace.c:1037
[<00000000110ad253>] vfs_kern_mount fs/namespace.c:1027 [inline]
[<00000000110ad253>] do_new_mount fs/namespace.c:2518 [inline]
[<00000000110ad253>] do_mount+0x552/0x2ee0 fs/namespace.c:2848
[<000000005eddec36>] ksys_mount+0x125/0x140 fs/namespace.c:3064
[<00000000d4c47900>] __do_sys_mount fs/namespace.c:3078 [inline]
[<00000000d4c47900>] __se_sys_mount fs/namespace.c:3075 [inline]
[<00000000d4c47900>] __x64_sys_mount+0xba/0x150 fs/namespace.c:3075
[<0000000052f04bfc>] do_syscall_64+0x165/0x670 arch/x86/entry/common.c:290
[<000000005d846763>] entry_SYSCALL_64_after_hwframe+0x49/0xbe
[<000000005c780d9d>] 0xffffffffffffffff
mm stuff
These bugs are what I found on LK v4.16.x. Here's my post.
I dunno whether it was patched :). But, as I remembered, it's not a perfectly reliable bug, and there's kinda restriction. So, I'll skip this bug :).
Console Demo
zero@zer0day:/tmp$ uname -a
Linux zer0day 4.16.0-rc5+ #19 SMP Sun Mar 18 20:44:40 KST 2018 x86_64 GNU/Linux
zero@zer0day:/tmp$ ./leak
zero@zer0day:/tmp$ ./leak 1
[+] Found Kernel Base Address!
[+] kbase : 0xffffffff89e00000
zero@zer0day:/tmp$ su
root@zer0day:/tmp# cat /proc/kallsyms | grep _text | head -n 1
ffffffff89e00000 T _text
root@zer0day:/tmp#
zero@zer0day:/tmp$ ./leak
...
zero@zer0day:/tmp$ ./leak 1
[+] Found Kernel Base Address!
[+] kbase : 0xffffffffb2600000
zero@zer0day:/tmp$ ls
leak leak.c
zero@zer0day:/tmp$ su
root@zer0day:/tmp# cat /proc/kallsyms | grep _text | head -n 1
ffffffffb2600000 T _text
root@zer0day:/tmp# uname -a
Linux zer0day 4.16.0-rc7+ #22 SMP Thu Mar 29 16:46:52 KST 2018 x86_64 GNU/Linux
Anyway, successfully got kernel base address :)
0-day bug
In this chapter, I gonna show information disclosure which can lead to KASLR bypass. This feature is used on many Linux distributions, So, maybe it is reliable on many Linux systems :| (i didn't test all of them, yet)
Bugs
This bug is slab-out-of-bounds
Read. By using this, kernel-land addresses (heap) can be leaked. Found on LK ~v.4.18.x-rc5.
Hint for the vulnerability is fs
. There're no any validations for specific variable and it leads to OOB.
syslog
[ 421.466496] ==================================================================
[ 421.467034] BUG: KASAN: slab-out-of-bounds in xxx
[ 421.467350] Read of size 48059 at addr ffff88006bb9002d by task poc/2823
[ 421.467704]
[ 421.467795] CPU: 1 PID: 2823 Comm: poc Not tainted 4.18.0-rc5+ #23
[ 421.468128] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[ 421.468626] Call Trace:
...
[ 421.484432] RIP: 0033:0x7fc9130f2afa
[ 421.484623] Code: ...
[ 421.485702] RSP: 002b:0000000000700c18 EFLAGS: 00000206 ORIG_RAX: 00000000000000a5
[ 421.486100] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007fc9130f2afa
[ 421.486469] RDX: 0000000000700d30 RSI: 0000000000700d40 RDI: 0000000000000000
[ 421.486838] RBP: 0000000000700d90 R08: 0000000000700c30 R09: 0000000000000001
[ 421.487205] R10: 0000000000000000 R11: 0000000000000206 R12: 00000000004005d0
[ 421.487571] R13: 00007ffcd7f02910 R14: 0000000000000000 R15: 0000000000000000
[ 421.487945]
[ 421.488030] The buggy address belongs to the page:
[ 421.488284] page:ffffea0001aee400 count:1 mapcount:0 mapping:0000000000000000 index:0x0 compound_mapcount: 0
[ 421.488789] flags: 0x100000000008000(head)
[ 421.489013] raw: 0100000000008000 dead000000000100 dead000000000200 0000000000000000
[ 421.489411] raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
[ 421.489810] page dumped because: kasan: bad access detected
[ 421.490099]
[ 421.490183] Memory state around the buggy address:
[ 421.490436] ffff88006bb91f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 421.490815] ffff88006bb91f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 421.491188] >ffff88006bb92000: 00 00 00 00 fe fe fe fe fe fe fe fe fe fe fe fe
[ 421.491558] ^
[ 421.491786] ffff88006bb92080: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
[ 421.492163] ffff88006bb92100: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
[ 421.492530] ==================================================================
...
[ 1316.744978] kmemleak: 314 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
[ 1939.198134] kmemleak: 12219 new suspected memory leaks (see /sys/kernel/debug/kmemleak)
file /sys/kernel/debug/kmemleak
unreferenced object 0xffff88005bfec000 (size 14280):
comm "poc", pid 3256, jiffies 4295094805 (age 1984.122s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 88 51 10 6b 00 88 ff ff .........Q.k....
00 80 2c 6a 00 88 ff ff 00 c0 2c 6a 00 88 ff ff ..,j......,j....
...
unreferenced object 0xffff88006b105188 (size 96):
comm "poc", pid 3256, jiffies 4295094805 (age 1984.122s)
hex dump (first 32 bytes):
00 00 00 00 ad 4e ad de ff ff ff ff 6b 6b 6b 6b .....N......kkkk
ff ff ff ff ff ff ff ff a0 14 7a 98 ff ff ff ff ..........z.....
Demo
I roughly make a PoC code, So, currently, it should be run by root
privilege. But, maybe it can also be run by normal user
privilege after a few fixes.
root@zer0day:/tmp# uname -a
Linux zer0day 4.18.0-rc5+ #23 SMP Tue Jul 17 22:48:05 KST 2018 x86_64 GNU/Linux
root@zer0day:/tmp# ls -al
total 24
drwxrwxrwt 2 root root 4096 Jul 20 09:51 .
drwxr-xr-x 24 root root 4096 Jul 17 14:19 ..
-rwxr-xr-x 1 zero zero 8307 Jul 20 09:18 poc
-rw-r--r-- 1 zero zero 1222 Jul 20 09:18 poc.c
root@zer0day:/tmp# ./poc
...
[lots of kaddr leaks...]
Hmm... not cool stuff :(
Conclusion
There're more bugs that I and fuzzer found like UAFs, OOBs, etc... But, some of them can't be reproducible :( or can run under some conditions...
Anyway, the latest LK version is v4.18.0-rc5 (7/20/2018). And i think the Linux kernel still has a lot of security issues and they're just exposed to unprivileged users. It means many interfaces need to be tested and some features should be restricted by default.