Command & Control

Command & control (C2) is vital in modern collaborative hacking environments, perhaps even in individual hacking endeavors. The advanced capability embedded allows hackers to run pretty sophisticated techniques in short bursts, allowing them to bypass EDR and maintain access on machines over long extended periods of time. One of the most famous, and early C2 frameworks is Cobalt Strike (CS), owing its creation to the famous Raphael Mudge. CS has evolved over the years to expand its customization capability providing hackers with more freedom and creativity when engaging targets. CS itself is an expensive tool requiring a yearly subscription, but we got access to it from a learning environment (CRTO).

The following is a very basic exploration of a simulated engagement into an enterprise network containing servers such as web, SQL, FS, workstations, DC, and others. This is by no means a comprehensive showcase of CS or possible attack techniques; rather only a showcase.

Setup

Modifications to bypass AV and EDR is typically the first step prior to any engagement. Testing your current toolkits capabilities, making sure everything works and doesn't trigger AV or EDR is hugely important and may take a tremendous amount of time. Here are some examples of what can be done with CS.

Possible modifications to bypass AV within C2 profiles

CS contains profiles that determine how it's beacons operate and communicate back to the server. Some basic improvements over the default are: Setting DLLs to RW/RX instead of RWX. Cleanup to remove memory of the reflective loader after it being loaded. Obfuscate to remove the DLL headers in memory. Spawning post-ex processes as DLLHOST instead of the normal RunDLL32, which instantly is caught by AVs.

Running ThreatCheck against artifacts to check for static AV signatures

Checking for static signatures in the default artifacts are important, otherwise moving laterally through the network becomes impossible. This provides the ability to drop binaries on disk such as psexec for hopping machines. ThreatCheck does not however check in-memory, meaning the running operations still need to be validated to bypass AV.

Common script manager loaded CNA files

CS provides the ability to load custom CNA compiled scripts that change many of the default utilities. After using ThreatCheck, we can upload the script manager, generate stageless listeners and test manually whether they bypass the host machines AV or not.


Domain reconnaisance

Once on a machine, first is host and domain recon. Focusing on domain recon, here we list common PowerView commands that can be executed under powerpick if under Constrained Language Mode. Similar to powershell, CS has a powershell-import command to load powershell scripts.

Find the domain controller and filter for some properties

Listing the domain trust

Discovering the layout of the entire domain, one of the most important targets in some engagements is the DC. Get-DomainController filtering for properties can be used to do just that. Listing inbound and outbound domain trusts provides the entire scope for forest hopping. Get-DomainTrust lists all domain trusts with the trust direction, source and target names and attributes.

Organizational Units enumeration

Finding all available users in a domain

Listing all the OUs in a domain is good recon to scope out the entire possible attack surface. Commonly OUs can be misconfigured and given more privileges than they should leading to finding a path for impersonation and lateral movement. Along with the OUs, good recon means enumerating all users, groups and ACLs allocated to each. PowerView makes this easy with Get-DomainUser. Enumerating users also sets the pace for whether we can target service accounts, and what services may be implemented in the network, such as MS SQL.

Enumerate groups of individual users

Allocated groups to individual members generally is a hotspot for misconfigurations. Users are commonly given more privileges over time, known as privilege creep, or perhaps in testing environments admins forget to remove certain groups allocated to users.

Enumerate all groups

Get members of a specific group

Besides finding individual groups of members, we can list the entire groups created in a domain. Note this also outputs the default groups that exist in most AD environments too. Going back and forth between finding an interesting group, and listing all users under that group is common and can be done using Get-DomainGroupMember.

Enumerate local admin privileges allocated to certain groups

A powerful search is Get-DomainGPOUserLocalGroupMapping passing in Administrators to find users that have local admin privileges in certain machines due to their allocated groups.


Privilege escalation

If privilege escalation is within scope of an engagement, running .NET tools like SharpUp and Seatbelt can automate some vectors that are commonly found. Some service and token escalation examples are shown here.

SharpUp auditing services

Listing user groups

SharpUp is able to check for unquoted services, modifiable paths or binaries themselves. These vectors are easy to abuse if we can drop binaries on the system. Checking for over privileged users as administrators often give too much privileges to users, or never remove allocated privileges during testing.

Seatbelt user privilege enumeration

Seatbelt can also find privileges among other vectors. This is an example of SeImpersonate privileges often found on NT Service accounts.


Credentials

Common next step after gaining local administrator access is to look for tickets or hashes that can be used to traverse the domain. Here are some examples of Mimikatz and Rubeus. Note however, mimikatz usually is heavily signatured and found easily. Caution should be taken when thinking of running this tool, as beacons and parent beacons may be killed.

Mimikatz

Mimikatz dumping hashes

Hashes aren't usually used very much, and can be easily signatured using EDRs. Mimikatz can still dump hashes that may be crackable offline for use later.

Mimikatz dumping kerberos keys

More useful are Kerberos keys that can be dumped using mimikatz.

Mimikatz dumping SAM database

SAM database can be dumped using mimikatz and taken offline for further investigation.

Rubeus

List all cached tickets

Listing all tickets using rubeus to check for sessions available and their services in use. Much better opsec than dumping and using hashes, as tickets are used excessively in AD.

Dump a users service ticket using Rubeus

Specifying a LUID and the service to be dumped, rubeus can provide the ticket. Dumped tickets can then be added to CS credentials tab manually for further use. Good example to save in credentials are golden and diamond tickets or domain admin TGTs.


User impersonation

Having access to credentials, tickets and certificates at hand the next step is to usually impersonate these users. Impersonation is needed to hop between computers or check perform more reconnaisance on the host or remote systems. Notice the cyclical procedure of hacking an enterprise network, finding users, impersonating, hopping and perform reconnaisance. Rinse and repeat.

Pass the hash

Create new session using hash

Hashes can be passed to create new sessions, here is an example using mimikatz. Easily signatured and caught by EDRs however. The output reveals the PID that can be stolen later.

Pass the ticket

Pass a ticket into new session

Better opsec is to use Rubeus passing in a ticket to create a new session. Rubeus reveals the LUID and PID created using the ticket. Triage will also then show a new entry of that LUID.

Overpass the hash

Use AES256 hash for creating a TGT

Using Rubeus, we can use AES256 hashes gained to request a TGT. Using RC4 is a common way of getting caught easily, using more secure AES256 we may be able to bypass EDR. These TGTs can then be used in pass-the-ticket.

Token impersonations

List all running processes as SYSTEM

If we are already SYSTEM on the host parsing running processes that are running under the context of another user, we can easily steal its token and impersonate.

Steal process token and impersonate

CS provides a wonderful ability to steal token using token-store steal. These tokens are stored in the beacon session, and can be using using token-store use. These tokens are only stored on the current beacon, and are not accessible in other beacons.


Lateral Movement

Naturally after impersonating a user, hopping onto another machine for further reconnaisance is a good idea. CS provides many easy and configurable methods of jumping.

Jump

Jump machines using Psexec

Jump is a command available in CS with defaults of psexec, psexec64, psexec_psh (powershell one liner), winrm and winrm64. New methods can be added such as dcom. Another reason why C2s are good in enterprise environments.

Remote-exec

Execute beacon dropped on remote machine

Another method of jumping onto a system, is to execute a service binary already dropped on the system. Depending on applocker, be mindful of where binaries can be uploaded and executed. Registry policy contains policies of applocker which state which directories are given the ability to execute such beacons, otherwise they will not be executed and risk our beacons getting killed. After executing beacons using remote-exec, connect or link can be used to create a new session in CS.

DCOM

Spawn MMC20 on remote machine

Using Invoke-DCOM we can spawn a new session with MMC20 process.


DPAPI stored credentials

Stored credential blobs are stored on systems and can be enumerated and dumped using tools like Seatbelt and mimikatz.

Enumerate all vaults

Vaultcmd can be used to enumerate existing vaults and their GUIDS.

List credentials of 'Windows Credentials'

Vaults contain credentials which are encrypted and require a masterkey to decrypt. Master keys are also encrypted and need decrypting, which requires SYSTEM privileges to do so.

Using seatbelt, list credentials

Grab masterkey using Mimikatz DPAPI dump

Seatbelt can also be used to enumerate these credential blobs. DPAPI requires decrypting a masterkey to obtain the encryption key used to encrypt individual blobs. Here we show listing masterkeys using mimikatz.

List masterkey using MS-BKRP

Another method is to use MS-BKRP.

Decrypt credential blobs using gained masterkey & mimikatz

Mimikatz is used with the master key, and credential file specified to decrypt such blobs.


DPAPI scheduled task credentials

Along with stored credentials, DPAPI also stores scheduled tasks credentials. Similarly we can decrypt these blobs using mimikatz.

Enumerate service credential blobs on host system

Enumerating blobs by listing them on the host system. Note the difference in file path between the previous method, we are enumerating within System32.

Dump service credential blobs using masterkey and mimikatz

Similar to previous method we can use the masterkey gained using mimikatz, the credential path and mimikatz to dump the stored credential.


Kerberos

One of the greatest protocols to laterally move in a domain. C2s make abusing Kerberos easier due to access to spawning sessions easily, and having a storage for all NTLMs, AES256 hashes and tickets. No more saving tickets in text files.

Kerberoasting

ADSearch for users that are kerberoastable

ADSearch to look for users that can be kerberoastable. This is good opsec, as EDRs can easily catch if we try to dump all cached. Good for staying under the radar.

Rubeus kerberoast a specified user

Kerberoasting a specified user, using rubeus. These need to be cracked later to reveal the password, which may be hit of miss.

ASREP roasting

If users do not have Kerberos pre-authentication enabled, the AS-REP can be requested and the reply can be cracked offline to recover passwords.

ADSearch for users that are ASREP roastable

Again, look for users using ADSearch that are ASREP roastable instead of doing for all cached tickets. Good opsec and fly under the EDR radar.

Rubeus asreproast a specified user

Rubeus again for asreproasting, good idea to save these tickets if needed later in credentials tab of CS. But for service tickets and other credentials that have time limit make sure to specify as such under notes when adding manually.

Unconstrained delegations

When users or machines are given access to act of behalf of other users and services. Especially found when front-end services need access to backend ones. TGTs are cached and can be dumped. This is an older method, Windows have released newer versions due to it being insecure.

Search for computers that have unconstrained delegations

SharpSystemTrigger a call from DC to WEB system to get machine TGT

ADSearch can find unconstrained delegations, enumerating for both computer and users. Note that the DC will always show up in result, and can be skipped over. Using Rubeus we can monitor on the host that has unconstrained delegation. Using SharpSpoolTrigger, we can trigger authentication from other hosts to this one to steal their TGTs.

constrained delegations

To solve unconstrained delegation issues, constrained delegation was created. Instead of TGTs cached, a user will have to request and use a TGS of another user using their own TGT.

ADSearch for computers with constrained delegation privileges

S4U2Self and S4U2Proxy with Rubeus to get CIFS access

Enumerate machines or users that have this privilege, and to what service they are privileged to. In this case SQL-2 has privileges to another under the CIFS service. Using SQL-2's TGT we can perform an S4U2Self and S4U2Proxy using Rubeus s4u command specifying the msdsspn we are privileged to (CIFS). We can grab this newly created ticket and pass into a createnetonly.

Alternative service

Altservice in Rubeus allows us to not only have access to the msdsspn allocated to us, but any service we want. Meaning even if we are allocated CIFS only as previously shown above, we can instead request for LDAP service. Note this is allowed for both constrained and unconstrained delegation, resulting in access to any service (preferrably CIFS or LDAP) for the specified object.

Use altservice when running s4u with Rubeus to get LDAP ticket

Similar output to before, the only difference being the 'Final ticket will be for ...' output.

S4U2Self

Using TGT of a machine, we can S4U2Self to obtain a TGS as a user we know is local admin. Machines are not allowed remote local administrator access to themselves, S4U2Self solves this.

Clocked machine TGT when running SharpSpoolTrigger

Machine TGTs can be dumped using Rubeus Monitor and SharpSpoolTrigger as previously shown. Notice the DC-2$ which is a machine, and does not have admin access to itself normally. Meaning if we did a createnetonly to impersonate using this ticket, we could not list \\dc-2...\c$ or other directories.

S4U2Self to get TGS of admin user using machine TGT

Using Rubeus to s4u passing in the altservice, impersonated user and self flag. This new TGS can be passed into a createnetonly for local admin access to the machine.


Active Directory Certificate Services

Build and manage PKI. Abuse due to templates, misconfigurations allowing privilege escalation and persistence. Tools like Certify and Seatbelt can enumerate quickly and abuse.

Find vulnerabel CAs

Certify finds vulnerable certificate templates. ENROLLEE_SUPPLIESS_SUBJECT allows requestor to provide any subject alternative name. Users who can abuse this are under Enrollment rights.

Request certificate of a domain admin

Using Certify we can request a certificate for any domain user, preferably a domain admin. The output RSA private key and certificate can be used to create a ticket using OPENSSL. This can be used to request a TGT with the `certificate` flag in Rubeus.


Group Policy

Group policy objects are configurations applied to OUs which are normally only allocated to Domain Admins. But these rights are commonly delegated to other users validating this path for possible abuse.

Modify existing GPOs

Enumerating all GPOs and checking ACLs for CreateChild, WriteProperty or GenericWrite. This is the easiest method of abusing GPOs if found to be misconfigured.

Enumerate GPs for abuseable rights

Reveal GPO name from ObjectDN

As before, Get-DomainGPO and Get-DomainObjectACL can be used to enumerate for these misconfigurations. Passing in the ObjectDN into Get-DomainGPO can reveal the GPO name. Convert SID here tells you the groups that can modify this GPO.

Find OUs vulnerable GPOs are applied to

The OUs can then be found which the specific GPO is applied to, consequently each machine in the OU. Parsing SYSVOL or using SharpGPOAbuse can trigger a beacon and such.

Create GPOs

Besides modifying existing GPOs, we can also check if users have the ability to create GPOs. These are obviously abusable and allow us to spawn beacons to OUs that get allocated our created GPOs.

Find users with rights to create and link GPOs

Create new Evil GPO

Again with Get-DomainObjectAcl we can find which group can create and link GPOs (both are required). A simple New-GPO can be used to create a GPO.

New RegKey to run beacon using Evil GPO

Apply GPO to specified OUs

Another method is to use Set-GPPrefRegistryValue directory creating a RegKey in HKLM with a specified name and value. Again, can be beacon or anything else. GPO creation needs then to be applied to a specific OU using New-GPLink.


MSSQL

SQL Databases are commonly found in many enterprise networks. These are difficult to configure, and have a large attack surface. In some instances external databases are also connected creating a sort of interconnected spider of databases that can be enumerated and potentially abused.

Recon

Performing recon in a domain for an SQL server may prove to be difficult depending on how its been configured.

Find SPNs with MSSQL*

Check access to found SQL server

Get-SQLInstanceDomain searches for SPNs with 'MSSQL*' in the name. It won't catch a server without this in its name. Check if a server is accessible to us using Get-SQLConnectionTest.

Parse SQL server information

Lastly parse the servers information using Get-SQLServerInfo. Note these commands can be chained together is many SQL servers are found.

Impersonate

Assume the permissions of another user, potentially one with privileges. Commonly seen in testing environments. These are explicitly configured.

SQLRecon impersonate user with privileges to SQL server

Using SQLRecon with `m:i` flag and the impersonated user. SQLRecon also parses the users permissions nicely for us too. Notice the sysadmin role given.

Command execution

SQLRecon enable XP_CMDSHELL allowing command execution

Enabling this option allows for execution of any system command, even beacons using `powershell -w hidden -enc ...` as normally done. The m:xpcmd and c: flags are needed to pass in the commands. Port forwarding is easily granted in CS through the rportfwd command making sure to create a firewall rule beforehand to prevent administrator request popup.

Lateral movement

Databases may have 'links' that allow access to other external databases. These are normally in other domains, forests or even the cloud.

Enumerate all SQL links

Enumerating links using SQLRecon with m:links flag. We can also check for command execution by listing xp_cmdshell value and trying to set to 1. Links may have other links, going deeper and can be enumerated using Get-SQLServerLinkCrawl.

Privilege escalation

Spawned beacons from previous commands are low privileged MSSQLSERVICE accounts under NT Service.

NT Service accounts often have SeImpersonatePrivileges

These types of accounts often have SeImpersonatePrivilege required for normal operation which can be abused for privilege escalation on the low privilege session. Potato variants may be used.


Microsoft Configuration Manager

Also known as Systems Management Server (SMS), Systems Center Configuration Manager (SCCM), Endpoint Configuration Manager (MECM). Helsp deployment and management across many physical sites. Abusing this can grant access to all connected sites.

Enumeration

First to understand the landscape, who is connected, which accounts are admins. Enumeration is commonly done using SharpSCCM.

Find management point and links

SharpSCCM enumerate for collections

We can list management points using SharpSCCM, and their links. For example SMS:S01 here. We can parse for ACL and collections we can get ahold of using SharpSCCM. Note different users have access to different collections. It's a good idea to run this under different contexts to get a better picture.

Non domain joined computers

Abuse cached credentials in DPAPI for non-domain joined computers. All machines need to authenticate to SCCM Software Distribution Points using their account credentials even non-domain joined machines, but these machines credentials are stored locally and can be abused.

Find cached credentials of non domain joined machines

Using SharpSCCM, parse with local naa -m wmi. Credentials can be used easily with token-store or make_token. Note however make_token does not store the token leading to bad opsec if many srev2self and make_tokens are needed.

Lateral movement

If we are privileged enough, we can execute anything to any machine connected to SCCM. This allows lateral movement to any and all machines.

Execute beacon on all machines connected to SCCM

SharpSCCM can execute a beacon on all connected machines if we drop a binary somewhere.

Local administrator password solution

A solution for managing all administrator passwords across the enterprise. Especially useful when golden images are used for creating machines. Passwords need to change every set amount of time defined in the password policy, but LAPS does so automatically which is useful is large computer enterprises.

Find machines with LAPS enabled

Find ms-Mcs-AdmPwdExpirationTime not null

Enumerate if LAPS is present on the system. Can also be enumerated using Get-DomainGPO. Find where ms-Mcs-AdmPwdExpirationTime is not null using Get-DomainComputer.

Find machine registry policies

LAPSToolkit to find OUs that can read ms-Mcs-AdminPwd

After finding the GPO, we can parse its Registry.pol directly for LAPS config. Use LAPSToolkit to find OUs and their groups which can read ms-Mcs-AdminPwd. We can then Get-DomainComputer with the right property to dump the LapsAdmin password, and steal its token.


Domain Trust

Relationship of domains. Allows hopping between domains/forests depending on configuration. Children of domains typically are transitive meaning users can hop down the chain. Can be configured inbound and outbound, one-way or two-way, transitive and non-transitive.

List domain trust

One-way inbound

Easily abuseable. Principles in current domain can hop to across easily.

Find groups outside domain

Enumerate groups that have users outside its domain.

Request TGT of user using Rubeus

If its a user we have access to, we can request its TGT first using Rubeus. Or if we have a TGT stored, use that.

Request referral ticket from DC to foreign object

Then use the TGT to request referral ticket to foreign domain. This sends a request to the DC for a referral ticket.

Request TGS to foregin domain

Finally request a TGS for foreign domain. After stealing token we should be able to hop across. It's important to select the correct domain which the TGS should be created for, for example, the user may not be permitted access to the DC but a common mistake is to create a TGS for the foregin trust DC.

One-way outbound

A low privileged user can be accessed if the directory is one-way outbound. Both domains store a shared password in a Trusted Domain Object (TDO). These objects can be read using LDAP.

ADSearch for TDOs available

Parse Trusted Domain Objects using ADSearch.

Grab TDO guid

Obtain the TDOs guid and dump using mimikatz `lsadump::dcsync` with relevant domain and guid. Use dumped creds to request TGT for trust account user.


Persistence

After gaining access to a machine, its smart to maintain persistence. C2s make this easy using the generated listeners, we can create registry keys, autoruns, startups, etc. This is one example each for user and system persistence.

User

Drop a binary and create an HKCU registry key using SharPersist. Many other methods exist, this is only an example.

SharPersist a new HKCU key to execute beacon hidden on system

Binary needs to exist in applocker whitelist directory, and a directory we have access to as a user. ProgramData may be possible.

System

We can drop a binary anywhere, usually anywhere inside Windows is suitable enough of a hiding place however make sure applocker policies allow running executable out of that directory.

SharPersist a dropped beacon in C:\Windows directory for SYSTEM persistence

SharPersist can simply create a new serviec and execute on next boot.


Domain Dominance

Enough privileges gained can result in dominance over an entire domain. Tickets and certificates are a great way to gain access over long periods of time.

silver tickets

Forged service tickets for any user and any service. Short term persistence as these typically are changed every 30 days.

Create Silver ticket using Rubeus, access to services

Rubeus can be used to create silver tickets.

Golden tickets

A forged TGT signed by the domains KRBTGT account. Access to any user, on any machine, any service. Never changed.

Create Golden ticket using Rubeus, access to anything on system

Can be requested and loaded into C2 using Rubeus.

Diamond tickets

Similar to golden tickets but under the radar. The TGT is decrypted, modified, re-encrypted and loaded into a session.

Create Diamond tickets using Rubeus, better EDR evasion

Rubeus can be used to create diamond tickets.