March 10, 2021
In our last post we covered the basics of the Covenant Command and Control (C2) framework: what it is, Covenant specific terminology and concepts, and basic features and functionality. For a refresher or some more baseline knowledge before moving forward, check out our Intro to Covenant C2.
Today, we’re taking a look at using Covenant C2 for Red Teaming. We’ll be exploring a few common scenarios teams are likely to encounter on a red team engagement and how to handle them with the Covenant framework. To accomplish this we’re using one of our featured Snap Labs environments, Spark Studio, which has everything we’ll need to test out the framework in a realistic simulated corporate network with Active Directory, simulated users, and vulnerabilities. For existing Snap Labs customers, spin up a Spark Studio lab and follow along! For teams looking to get a test environment spun up quickly, Contact Us about a free trial.
Depending on the type of Red Team engagement we’re performing, there may be a requirement to gain access to the target environment through an initial access vector. Typically, we’d perform reconnaissance on the target’s external network presence and identify exploitable weaknesses in externally facing applications that might allow us to achieve code execution. Alternatively, we might run one or more phishing campaigns with the goal of capturing Active Directory credentials or deploying a payload.
Covenant doesn’t have tools for scanning and exploiting a target’s external network, however it comes with several Launchers that can be used to generate payloads for phishing campaigns. Delivering payloads directly through the email in a campaign can be tricky, so we find it more successful to host deliver a document with embedded links/instructions for downloading our desired payloads. Through Covenant’s Launchers menu we can select an appropriate launcher/payload type, customize the payload to bypass AV and EDR tools, generate the payload then host it on our Covenant server for download.
Another common scenario for Red Team engagements is to skip the initial access portion of the testing and jump straight into internal network activities and validating the Blue Team’s detections and response processes. In this case, we typically are provided access in the form of Active Directory credentials or a collaborative user to run our payloads from within the organization.
In either case, the first step in our Red Team operation will be establishing this initial Grunt:
Once we’ve established our initial Grunt, the first thing we’ll typically do is to get a sense for our surroundings. What type of AV/EDR is the compromised host running (if any)? Are there other interesting process running? Who are the local administrators of this system? Answering these types of questions provides us with better situational awareness and allows us to make smart, deliberate operating decisions. This is especially important at the beginning of the engagement when our access is tenuous.
One great tool we can run natively through Covenant to help us better understand our current environment is the Seatbelt utility, part of the GhostPack project. For more details on the tool check out it’s GitHub page here: GhostPack/Seatbelt.
Seatbelt can run numerous modules individually, or check for everything in it’s set of capabilities. We can access this capability by interacting with our initial access Grunt or assigning it a Task.
Take the time to read carefully through the output of these Seatbelt modules. They can provide extremely insightful information that inform our decisions throughout the Red Team engagement.
We also find it helpful to list the running processes for a quick glance at other users that may be logged onto the system. These users are potential targets for impersonation and lateral movement.
After doing all our initial reconnaissance and situational awareness tasks, the typical next step is for us to start to branch out and compromise additional systems. These systems should somehow move us towards the end goal of our Red Team engagement. Whether the target system has users logged on we need to compromise, contains our target data, or is representative of the type of system an emulated adversary might target, these decisions should be deliberate and informed.
To move to our target system we’ll impersonate a process with our desired logon credentials, create a new Grunt with those permissions, then use that Grunt to move laterally and compromise the new system.
Impersonating the Target User/Process
We’ll require SYSTEM level privileges in order to impersonate our target process in many cases. Assuming our Grunt is currently running in a high integrity process, this is most easily accomplished through the built-in GetSystem command. Once we have the necessary permissions we can impersonate our target process with the ImpersonateProcess <pid> task.
We’ve now assumed the logon session permissions of our target process with PID 2624 (SPARKDM\omullin’s explorer.exe process).
Creating a New Grunt
Next, we’ll typically need to create a new Grunt to utilize for our lateral movement. The specifics behind why are a bit out of the scope of this post, but we’ve seen this as the most reliable method to ensure our Grunt has the permissions we expect it to when executing remote commands for lateral movement.
Covenant has a number of built in lateral movement capabilities. We can execute remote commands for lateral movement via PowerShell Remoting, WMI, or DCOM with built in Grunt commands. These methods also work well for creating our new local Grunt. During this post we’ll use WMI as our preferred remote command execution method. The following command can be used to execute our PowerShell launcher via WMI on the localhost, which should result in a new Grunt with the privileges of our current token.
WMIGrunt localhost powershell
Once we’ve established a Grunt as our target user (SPARKDMZ\omullins), we’re ready to move laterally to the new target system. We can use the same WMIGrunt command to execute PowerShell launcher, but this time we’ll specify a remote system as the target.
We should now have three separate Grunts active in the Covenant platform: our initial access Grunt, the localhost Grunt as our target user, and Grunt running as our target user on the remote system.
With this new access, we can repeat some of the steps we’ve previously taken to increase our situational awareness even further and identify additional hosts and users to compromise. Now that we have some additional access, we’ll also want to consider things like how many Grunts are actively communicating outbound with our Covenant server. The more Grunts that communicate directly over HTTP from their target hosts, the more likely it may be that the blue team will identify our activity and be able to successfully lock us out of the environment. To combat this, a common approach is to have only a few Grunts communicating directly to the Covenant server over HTTP while the rest use SMB and named pipes to leverage the existing outbound communication channels.
Covenant comes with several Grunt templates by default, one of which is an SMB template, GruntSMB. The GruntSMB template creates a named pipe to listen for commands from other Grunts. The major difference with between this Grunt template and the default GruntHTTP template (besides the protocol) is that it is a bind template. This means that we’ll need to reach out and connect to the SMB Grunt after it has been established using our desired launcher. To walk through this scenario, we can first configure our PowerShell launcher to use the GruntSMB template and optionally set a specific SMBPipeName value (this is highly recommended for real engagements!).
After generating our new SMB based PowerShell launcher, we can run it on the secondary target host with our existing Grunt or via another remote execution method. Once the SMB Grunt process is running, it will listen for connections to the “gruntsvc” named pipe. We can connect to it from our initial access Grunt with the following command:
Connect namesrv053.sparkdmz.lab gruntsvc
We now have an additional Grunt process running on the secondary target host, NAMESRV053, which is communicating through our initial access Grunt over SMB. Any tasks we send to this new Grunt will first be sent over HTTP through the initial access Grunt, then chained to the new Grunt over SMB. This is an extremely useful technique for proliferating our access across an environment in a stealthy way.
Covenant also provides a handy Graph feature with helps us visualize chained SMB connections.
This image shows that our SMB Grunt (in green), is communicating back to another HTTP Grunt, then to the original HTTP listener we configured. This type of data can be especially useful when debriefing the Blue Team on our activities.
Along with the Graph functionality, Covenant provides a Data tab that collects a bunch of relevant information from Grunt output as well as higher level Covenant info. We’ve found the Indicators tab of the Data page to be particularly relevant in helping to explain our activities, compromised hosts and users, and how we’ve communicated out of the target environment back to our Covenant server.
Covenant is a powerful open source tool for Red Teamers to conduct effective adversary emulations, targeted engagements, or purple team exercises. In our opinion, it’s one of the most effective solutions that doesn’t come with a commercial price tag.
To get started with the Covenant C2 framework in a realistic test environment, reach out to us about a free trial of the Snap Labs platform here: https://www.snaplabs.io/contact.