For the complete documentation index, see llms.txt. This page is also available as Markdown.

Disabled Kerberoasting

마이크로소프트 설계에 의하면 서비스 계정이 SPN을 삭제하지 않고 비활성화 되더라도 TGS-REQ의 sname 필드를 검증하여 비활성화 된 계정은 거부되도록 되어 있습니다.

하지만 커버로스 설계의 검증 로직 미흡으로 인해 AS-REQ 단계에서 sname 필드에 비활성화 된 계정을 요청한다면 검증을 통과하여 티켓을 발급받을 수 있습니다.

Abuse

# 비활성화 계정의 spn 열거 및 획득
python3 disabledKerberoast.py -u 'mick3y' -p 'Password123!' -d contoso.com -dc-ip 192.168.1.11
python3 disabledKerberoast.py -u 'mick3y' -p 'Password123!' -d contoso.com -dc-ip 192.168.1.11 --request-user Administrator

Root Cause

as-req

AS Requested Service Tickets에서 언급한 것과 같이 sname-string 필드는 cname과 동일한 구조체를 공유하기 때문에 spn을 소유한 계정이라면 spn을 모르더라도 계정 이름 자체로 서비스 티켓 발급이 가능합니다.

따라서 클라이언트가 커버로스 사전 인증 단계에서 요청하는 krbtgt/domain 형식은 spn을 소유한 krbtgt에 대한 서비스 티켓 요청입니다.

krbtgt spn

krbtgt는 서비스 티켓을 보유하고 있는 비활성 계정임에도 불구하고 클라이언트가 krbtgt에 대한 서비스 티켓을 요청할 수 있습니다.

kadmin/changepw TGS-REQ
kadmin/changepw TGS-REP

이론상 krbtgt 계정이 다른 서비스 계정과 동일하다면, spn을 삭제하지 않고 비활성화된 계정의 서비스 티켓을 발급하여 패스워드 크랙하는 것이 가능합니다.

가설을 검증하기 위해 disabled/spn을 서비스 계정에 할당한 채로 비활성화 한 뒤, tgs-req를 전송합니다.

disabled/spn TGS-REQ
disabled/spn TGS-REP

TGS-REP에서 확인할 수 있듯이 krbtgt는 일반 계정과 다른 특수한 계정이기 때문에 일반 비활성 서비스 계정에 대한 TGS-REQ는 거절당합니다. 원인은 kdcsvc.dll을 분석하여 확인 가능합니다.

kdcsvc.dll

FillExtendedError 함수는 커버로스 오류를 반환하는 함수입니다. 해당 함수는 4가지 조건이 모두 만족될 때 실행됩니다. 두 번째 조건에서 502 값인지를 검증하는데, 이 값은 krbtgt의 RID 값입니다.

krbtgt RID

이러한 조건문 때문에 krbtgt는 비활성 상태더라도 서비스 티켓이 정상적으로 발급되며, 일반 비활성 서비스 계정에 대한 티켓 요청은 거절되는 것입니다.

하지만 커버로스 오류를 반환하는 함수 FillExtendedError을 참조하는 함수를 보면 as-req에 관련된 것은 확인되지 않습니다.

xrefs to FillExtendedError by IDA

권한이 있는 계정으로부터 다음번 로그인 시 패스워드를 변경하도록 설정된 경우와, TGT 발급을 위해서 AS-REQ 과정에서도 서비스 티켓을 요청할 수 있다는 것은 이미 확인된 정보이기 때문에 AS-REQ를 통해 비활성화 된 서비스 티켓을 요청하면 커버로스 검증 로직을 우회하여 티켓 발급이 가능합니다.

실습을 위한 환경에서 disabledUser는 disabled/spn 서비스를 보유하고 있는 비활성 계정입니다.

disabledUser 정보
as-req
as-rep

발급된 티켓은 커버로스팅을 통해 얻는 서비스 티켓과 동일한 포맷을 갖기 때문에 해시캣 13100 모듈로 크랙이 가능합니다.

Last updated