In our first file system attack, we found places where we’re likely to get good data with the credentials we’ve been able to steal. Our second attack let us focus in on only the data that is worth the time to steal so we can lessen the chances of getting caught – or at least get the best stuff before we do. The final stage in these attacks is typically persistence. Finding a way to stay in the systems even after we get caught and tossed out the first time. With credential attacks, that is a clear-cut exercise. You lose access with one credential but you use another or a side door you created to the same one to get back in. For the file system, we will say persistence means we’ve snuck in our trade craft to hunt and steal data and we need to get it back in after it gets discovered and deleted. Or, better yet, we hide it so it never gets deleted in the first place.
How to Hide Bad Things in a File System
If we wanted to talk about all the ways to hide data in a file system, this would be a book and not a blog post. So we’re going to limit the topic to NTFS file systems, and we’re only going to dive deeply into one of the two most used ways – the less common one. The most commonly used hiding spot in the NTFS file system is the Alternate Data Streams (ADS), which can live in any file on NTFS. This is something that is well explored by malware vendors. In brief, the data of a file lives in one attribute of that file as NTFS tracks it (creatively called the $DATA attribute). Data can live in other places, too. Those are the Alternate Data Streams. Because these are so well known most of the malware and other prevention vendors are scanning for these and removing them as a matter of course. Where the bad guys can slip them in and use them until they are discovered they can still be dangerous.
The other place in an NTFS file system data can be hidden is in NTFS Extended Attributes. Unlike the Alternate Data Streams, Extended Attributes are not either well known or widely used. So most systems aren’t scanning for them. If you ran off to Google “NTFS Extended Attributes,” you would see Microsoft (quite uncharacteristically) does not have a hit in the top 5. Even sites that do appear near the top are talking about how to attack these, and don’t give a lot of detail. This lack of clarity around the extended attributes is one reason they aren’t being used often. The other reason is that, unlike ADS that can be as large as they like, Extended Attributes are capped in size – with that cap varying on FAT, HPFS, and NTFS. Finding that cap is near impossible, but, if we can believe the folks who wrote NTFS for Linux, it is 65536 bytes. That is just enough space to store a script, small properties file, or other piece of a toolkit that can be used for mischief.
Using NTFS Extended Attributes for Persistence
If you want to dive very deeply (to a code level) on how this all works, then the best resource is over at Spector Ops by Jared Atkinson. In fact, the PowerShell code we’ll use here is based on what he wrote for that post with a few modifications. If you decide to dive in and play with this, you should know two things. First, this is dangerous stuff. There are no well-published and tested means to play with Extended Attributes (EAs) and that means you are in precarious territory when you mess with them. I did it in a lab where I knew it didn’t matter if I had to start all over from scratch. Second, you will need to get your hands dirty to even get off the starting blocks. Part of that is because there aren’t really good tools to use (though if you find some – let me know!). The other part is that is we are not going to share the code we wrote to mess with the EAs because we think it is a bit too far to go. In this series we have explored a lot of trade craft that is already out there. But we have yet to put out any of our own and we aim to keep it that way for now. If you would really like the PowerShell our very own MVP wrote, reach out and perhaps we can release it for someone with the right needs.
We start by taking a look at what, if any, EAs are already out there on the File System:
You can see what happens if I run Jared’s code on the whole C: drive (which is the default) in Figure 1. This will take a good amount of time depending on the number of files and the resources on your host. It’s also normal to get a couple access errors even when running as Admin thanks to temp files and other quirks. In this run, I only got one error so I went with that for this screen shot. The last two EAs you see are going to be common to nearly all Windows Server machines running 2012 or better. The others are EAs I added through the two mechanisms I found to add them. One method I found was a utility called FileTest. Before you run off to check it out, I’ll warn that I know nothing about this except that it came up in a NetApp Community post about EAs and the source looked clean so I built it to play around with. But I can’t say more than it worked for me and there was no malware in the source, YMMV. You can grab FileTest from the Ladislav Zezula’s site. The “NtCreateFile” screen was the one where I was able to create new files with EAs.
With a little help from our MVP Adam, I was able to get much more granular with manipulating EAs in PowerShell. When I looked at Jared’s code, I realized he was using PSReflect to call Ntdll.dll functions to get the EAs. So we could extend that to the set functions if we wired up the right structures in the script. C++ being beyond the magic that I’m able to do, I called in the cavalry and the result was a new function based on Jared’s base.
In Figure 2, we can now set and get EAs on arbitrary files with arbitrary names. Our only limit is the length restriction. If I was the bad guy, I could now use this to stuff data all over the place that would go undetected by the vast majority of scanning. If the size limits gets me down, I could also put things in places piece by piece and reassemble them. I could imagine building a routine where I hide an assembly script in a place well known to me that keeps and index of all the places where other pieces is – building out my attack scripts from pieces the same way you assemble a stack. In other words, I have a way to hide just about anything of any size in places where it will be very hard to find it.
How to Protect Yourself
It is a long road to get to the point where the bad guy is stuffing bits of badness in your file Extended Attributes. They need to get credentials. They need to find out there are places those credentials can grab data, and that there is data worth having in those spots. If they do get to this point, there are some things you can do:
There are special permissions for reading and writing NTFS Extended Attributes. So one path to mitigation may be to control these permissions. However, and this can’t be stressed enough, there is little known about how that may affect normal operations. Since the majority of EAs seem to be used by Microsoft themselves deep in the OS, playing with these permissions may have unintended consequences. That said, there is little reason we can find for allowing *write* privileges to these very widely. Proceed with caution, but this is the most direct control.
Watch for first time access activity. If a user has had access to a share for years and never touched it, the first time they do may be suspicious. It’s possible they finally got around to the project that was the reason they were given the access to start with. Or it may be that their credentials have been hijacked and now someone is using the methods above to scan for access to data they may want to steal.
Look for installations of the tools of the trade. Did Python suddenly appear on one of your servers? Has someone put the PowerSploit module onto a system? This may be your security team trying to probe and lock down vulnerable configurations, but it may also be a sign the bad guys are at work.
Hi Jonathan Congratulations for the post really usefull. Just one doubt I tried to execute the code from Jared and keeps giving error reading the same file a lot of times, as the script was not able to go through the error, this was normal? Thanks again for the article series Regards Diego
In my lab, I had to adjust some of the looping logic, too. Unfortunately, I broke that lab down a while back and don’t have the code anymore. From what I recall, it was a matter of changing the logic near the top about how it chooses what files to evaluate. I can say I recall not posting that fix as a sort of intelligence test. I never like leaving dangerous code around for the kiddies to simply copy and paste. It’s good when it takes at least a bit of skill to run with scissors without getting hurt.