This week's episode idea comes from Carlos "Dark0perator" Perez, one of the MetaSploit developers. He asked me about using PowerShell for post exploitation enumeration. For those you who don't know what that is, it is pillaging a compromised host for useful information. Oh, and don't call it PEE for short. This doesn't have to specific to attacking systems, this same information can be useful for Incident Response.
PowerShell supports all of the classic Windows shell commands and executables, so I won't reinvent the wheel in an attempt to create a PowerShell version of qwinsta, netstat, ipconfig, or the net commands (users, accounts, session,...). PowerShell is very useful for parsing the output of those commands, but our focus for this episode is the information, not parsing it.
Enumeration involves pulling information from the system. The PowerShell naming scheme is Verb-Noun where the Verbs are standardized. The standard verb for retrieving information is Get. In the default shell in PowerShell v2 there are approximately 50 cmdlets that use the Get verb. That is the base of what we have to work with to retrieve information that may be useful to us.
First, we need to know which version of PowerShell is running on the machine. This may make a difference later since some cmdlets have been added or changed in version 2. The Get-Host cmdlet is what we will use. The only output that is really useful is the version, so we will just look at that.
PS C:\> Get-Host | Select Version
Another potentially useful bit of information is the patches that are installed. We can use Get-HotFix to retrieve that information, but unfortunately, Get-HotFix is only available in v2.
PS C:\> Get-HotFix
Source Description HotFixID InstalledBy InstalledOn
------ ----------- -------- ----------- -----------
ROCKY7 Update KB958830 MYDOM\tim 10/27/2009 12:00:00 AM
ROCKY7 Security Update KB971468 NT AUTHORITY\SYSTEM 2/23/2010 12:00:00 AM
ROCKY7 Security Update KB973525 MYDOM\jmallen 10/15/2009 12:00:00 AM
ROCKY7 Update KB973874 MYDOM\jmallen 10/15/2009 12:00:00 AM
We know what patches were installed, by whom they were installed, and when they were installed. At first glance this might not seem very useful, but it is. We can see what patches were installed, but more importantly we could figure out what patches weren't installed. One could guess that if the patches weren't installed on this machine, they might not be installed on others, and that would could give you a good path for exploiting other systems.
This output also provides some juicy usernames. The users who do the patching need administrative rights. If we can get a hold of one of these users' credentials, hash, or tokens we likely will have be able to get elevated privileges elsewhere.
Finally, we can take a look at the installation date to determine the organization's deployment schedule. Microsoft pushes patches on the 2nd Tuesday of the month. From the output above we can see that KB971468 wasn't installed until two weeks later. If we looked at the full list of installation dates we might see a pattern and be able to confirm that the patch cycle is two weeks. You could probably assume that the patch cycle is the same across the entire organization and that gives you, the penetration tester, two weeks between when a vulnerability is announced and when the patch is applied to the system. That two week window can be a good time to compromise a bunch of machines.
The cmdlet also has a ServicePackInEffect property we can use to determine the service pack. Windows 7 and Windows 2008 R2, both come with PowerShell v2, but neither has a service pack (yet), so this isn't particularly useful on these platforms. I tested it on a few Windows 2003 boxes with PowerShell v2 and the results were really weird. It was as if the values were assigned to the wrong properties. The SerivePackInEffect property sometimes contained a KB# while the KB property was blank. The later entries were correct and it did show the service pack. It was rather odd, but it worked.
Users and Groups from ACLs
If you had access to a shared drive you could use the Acl to pull group and user names.
PS C:\> ls -r | Get-Acl | select -ExpandProperty Access | select IdentityReference -Unique
This next command is similar, but returns a smaller scope of users. It typically returns a subset of the above command but in rare cases it could contain additional users.
PS C:\> ls -r | Get-Acl | select Owner -Unique
These commands do a recursive directory listing, so be careful! It is noisy and painfully slow. Although, when it is done you do have a nice list of security principles.
Getting a list of available snap-ins lets you know what the machine is used for.
PS C:\> Get-PSSnapin -Registered
Name : Microsoft.Exchange.Management.PowerShell.Admin
PSVersion : 1.0
Description : Admin Tasks for the Exchange Server
Name : Microsoft.Exchange.Management.Powershell.Support
PSVersion : 1.0
Description : Support Tasks for the Exchange Server
Name : VMware.VimAutomation.Core
PSVersion : 2.0
Description : This Windows PowerShell snap-in contains Windows
PowerShell cmdlets used to manage vSphere.
A machine that has additional systems-admin PowerShell tools is probably allowed to talk through the firewall to some juicy servers. If the machine has the Exchange snap-ins, you can bet it is a mail server and is a box that an admin uses. It also means that you might be able to send mail, control mail flow, or get a list of *all* the users in the domain. If it has the VMWare snap-in you can use that as a launching point to pwn an entire virtual infrastructure. In short, additional snap-ins means additional cmdlets and additional fun, fun, fun!
Another important piece is the .NET framework. This is has the potential to be the most powerful tool in PowerShell. The .NET framework gives you access to the power of a full programming language. On some assessments, the rules of engagement may state that you are not allowed to install software or download thrid party executables, but it may be acceptable to use PowerShell so you can now run a sniffer.
Ok, I know I said I wasn't going to reinvent the wheel, but this wheel is Z-rated. While Get-WmiObject (alias gwmi) provides the same functionality as wmic, the implementation is much better. Instead of receiving weirdly formatted results you get nice object with nicely named properties. Gone are the days of parsing wide results and trying to figure out which property value goes with which heading.
Carlos' enumeration script for MetaSploit has 15 wmi commands it runs to pull information. Here are the PowerShell equivalents.
gwmi win32_logicaldisk | select description,filesystem,name,size
gwmi win32_networkloginprofile | select name,lastlogon,badpasswordcount
gwmi win32_networkconnection | select name,username,connectiontype,localname
gwmi win32_share | select name,path
gwmi win32_ntlogevent | select path,filename,writeable
gwmi win32_product | select name,version
gwmi win32_service list briefget-service gwmi win32_processget-process gwmi win32_rdtoggleno equivalent in PowerShell
The output of these commands can be rather long so I recommend piping the results into a csv file. It keeps all the property names and values and allows for easy sorting and parsing later.
PS C:\> gwmi win32_useraccount | Export-Csv C:\output\accounts.csv
And if you want to use the results you can use Import-Csv to read the file and get all the object properties.
While there aren't a lot of PowerShell specific commands here, Microsoft is continually shifting to PowerShell, and all of their server products are going to support it. Exchange can be entirely controlled with PowerShell, SQL and System Center are coming, and SharePoint 2010 supports it. PowerShell support isn't just limited to Microsoft -- Citrix and VMware are among the other companies adding support for PowerShell. Mastering PowerShell will be an essential skill for a network admins, security admins, or pen testers. While there isn't a wide breadth of cmdlets that are useful for obtaining this information, PowerShell is a handy thing to have in your tool belt. Worst case, it is a fancy way to call the classic Windows commands.
Now get ready for the Ninja's to do some serious fu.
3D (a name that is entirely in Hexadecimal, thank you very much) Responds:
Ahhhh…. Post Exploitation Enumeration. I love the topic. In fact, it’s the primary reason I’ve devoted so much of my time over the years to command line kung fu. In my penetration tests, I’d often find myself staring at a C:\> shell prompt on a successfully compromised Windows box. I decided to devote all of my spare time to maximizing my ability to manipulate a system from such a prompt so that I could really shine during a penetration test. Gaining shell access isn’t the end of your penetration test… it’s just when things start to get interesting. If you really want to express the true business risk associated with the vulnerabilities you’ve found, gaining shell access and performing solid post-exploitation analysis and pivoting is the way to do it. I’ve got a huge section in my SANS 560 course devoted to the art of using shells for successful pillaging in post-exploitation.
You know, this blog is in some way partly an offspring of my post-exploitation musings. I started to tweet about some of the commands I was using after exploiting a system, Hal started to respond to those tweets, and we opted to take our little spats into blog form. The rest, as they say, is history. Well, maybe “doskey /history” in this case, but you get my point.
One of the big things I like to do on a system after I’ve compromised it is to find out what other systems it has recently communicated with. I do this with a quick barrage of commands, starting with searching for established TCP connections:
C:\> netstat –na | find “EST”
Next, I look to see which machines on the same subnet we’ve talked with recently by dumping the ARP cache:
C:\> arp –a
Then, I look at the DNS cache, to see which names we’ve resolved recently:
C:\> ipconfig /displaydns
Also, I like to check out the current SMB connections made from this machine to file servers and related systems:
C:\> net use
And those made to this machine from Windows clients and such:
C:\> net sessions
Tim says he likes to get information about installed patches and software. I do too. To get a list of hotfixes, I simply run WMIC asking for Quick Fix Engineering information:
C:\> wmic qfe list full
That’ll show me the list of patches, their install date, and the effective Service Pack of the system (which is usually one more than the latest service pack Microsoft has released... Applying even one hotfix after a given Service Pack bumps up the effective Service Pack number for that hotfix by one).
Getting a list of installed software is pretty straightforward too. I usually start by checking where my system partition is:
C:\> echo %systemroot%
You see, a lot attackers just assume that the operating system is installed in C:\. If the sysadmin moved it to D:\ or elsewhere, they’ll get confused when their commands for pillaging don’t seem to find much stuff in C:\. Once I’ve checked that systemroot, I can then run:
C:\> dir “C:\Program Files” > inventory.txt
I’ll transfer the inventory.txt file back to my own machine for more detailed analysis, looking for vulnerable software installed on the machine that may be included on other systems I want to attack next, pivoting through my conquered host. I focus on vulnerable third-party apps, such as Adobe Reader, the Java Runtime Environment, the Office suite, and browsers. The nicest part here is that the output of my dir command will include last update dates of each of those files, so I can tell how far out of patch each program is.
For a list of users and groups defined on my local box, as well as members of the administrators group, I run:
C:\> net user
C:\> net localgroup
C:\> net localgroup administrators
To find installed administrative snap-ins and the things the given machine was used to administer, I often hunt for custom MSC files saved by administrators for quick access to various administrative functions in the GUI. Such admins often save their files in their own user directories, so I look inside of C:\Documents and Settings, or C:\Users, depending on the version of Windows I’ve gained access to. Note that I don’t particularly care about the “normal” msc files, such as lusrmgr.msc (for local user management) or eventvwr.msc (the Event Viewer), which are stored in system32. I want the custom msc files, because they’ll hold the additional installed snap-ins that I’m focused on:
C:\> dir /b /s C:\users\*.msc
Once I’ve found an msc file, I hunt for the string “String ID” in the file, which shows me the administrative snap-ins that msc file was used to administer:
C:\> type Console1.msc | find /i "String ID"
<string id="1" refs="1">Favorites</string>
<string id="2" refs="1">Event Viewer (Local)</string>
<string id="3" refs="2">Console Root</string>
<string id="4" refs="1">Local Computer Policy</string>
<string id="5" refs="1">IP Security Policies on Local Computer</string>
Nice… it looks like this administrator used this machine to configure the Local Computer Policy GPOs and the IP Security Policies.
For the WMI stuff, which is accessed at cmd.exe via the WMIC command, I’ve written gobs of articles over the years. There is so much chocolatey goodness in the WMIC command that I’ve already documented, I’ll just refer you to simple Google search of my work in that arena. On second thought, let’s do a Bing search, since that’s the same company that gave us the wonderful WMIC command:
These are simply some of the highlights of the things you may want to do in post-exploitation during a penetration test. I always try to keep an open and inquisitive mind once I gain access, looking for other items that are system-specific to the machine for plundering. But, remember… always stay within scope and follow your rules of engagement for the test!
4a1 Takes a Trip Down Memory Lane
As 3d points out, PEE is almost the raison d'etre for this blog. Long-time readers will recognize a lot of tips and tricks in this article that have cropped up in previous Episodes. But this article gives us a chance to consolidate a lot of those scattered tricks into one place, and of course we also get to add in Tim's tasty Powershell confections.
First it's probably useful to figure out what kind of machine you're on and what privilege level you currently have. "uname -a" and "id" are useful for this:
$ uname -a
Linux elk 2.6.31-20-generic #58-Ubuntu SMP Fri Mar 12 04:38:19 UTC 2010 x86_64 GNU/Linux
uid=1000(hal) gid=1000(hal) groups=4(adm),20(dialout),24(cdrom),46(plugdev),107(lpadmin),...
On Linux systems, "cat /etc/*-release" will usually produce additional output that describes the specific distro and version number you've cracked.
Now let's look at getting network-related information for the machine. First, "ifconfig -a" will dump out the current configuration of all network interfaces on the system, and "netstat -in" will give you some network interface statistics that will show you which interfaces are being used most heavily. You'll also probably want to look at the network routing table ("netstat -rn") and local DNS servers ("cat /etc/resolv.conf"). If you've happened to already broken root on the system you're exploiting, then using a command like "iptables -vnL" to dump the current firewall config on the system can be useful as well.
Similar to Windows, we can use "arp -an" to dump the current ARP cache on the system, which can give you some idea of systems that your pwned host has been talking to recently. But perhaps even more interesting is the kernel routing cache ("route -Cn"), which actually shows you the per-host routes taken by recent network traffic.
There's "netstat -an" for showing current network connections and services listening on network ports. Linux systems allow you to add the "-p" option to output process information associated with these network ports. Or, if you've already broken root, you can use "lsof -i" to dump much more detailed information about network connections and their associated processes.
Speaking of processes, there's the venerable "ps -ef" ("ps auxww" on BSD) command for listing currently running processes. Figuring out which services are configured to start at boot time is one of those crazy OS-specific issues-- every Unix-like OS seems to provide slightly different interfaces for figuring out this information. Episode #57 does a pretty good job of delving into this, so I won't repeat myself here.
If you're interested in understanding how the file systems on the machine are laid out and what network shares might be in use, just run the "mount" command with no arguments. There are some additional subtleties that you may run into here related to logical volume managers and encrypted file systems, so you might want to check out Episode #59 for more details.
If the machine you're attacking is a file server, you might also be interested in getting information about the the file systems that remote clients are mounting from the local server. On NFS servers, "showmount -a" will normally display this information ("showmount -e" should normally list all exported file systems, or you could just look at the /etc/exports file). If you're a Samba server for Windows clients, just run "smbstatus".
As far as enumerating users and groups goes, Episode #44 has this useful little tidbit for listing users and their group memberships:
$ for u in `cut -f1 -d: /etc/passwd`; do echo -n $u:; groups $u; done | sort
hal:hal adm dialout cdrom plugdev lpadmin admin sambashare
The tricks in Episode #34 for finding UID 0 accounts and accounts with null passwords can also be useful if you're looking for accounts to exploit.
Listing all installed software and the patch status of the machine is another one of those annoying distro-specific problems in Unix. For Red Hat derived systems, you're looking at "rpm -qa" to list all installed packages and their version numbers, and "yum list updates" to show pending updates that have yet to be applied ("yum list-security" may work on newer Red Hat releases to show only the security-related updates). On Debian systems, the corresponding commands are "dpkg --list" and "apt-show-versions -u".
Whew! That's a whole lot of fu! But it's also been a nice trip down memory lane with some of our more useful postings.