{"id":9130,"date":"2024-09-21T09:27:09","date_gmt":"2024-09-21T07:27:09","guid":{"rendered":"https:\/\/tajdini.net\/blog\/?p=9130"},"modified":"2024-09-21T09:43:32","modified_gmt":"2024-09-21T07:43:32","slug":"understanding-tokens-in-entra-ida-comprehensive-guide","status":"publish","type":"post","link":"https:\/\/tajdini.net\/blog\/identity-and-active-directory\/understanding-tokens-in-entra-ida-comprehensive-guide\/","title":{"rendered":"Understanding Tokens in Entra ID:A Comprehensive Guide"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.xintra.org\/\"><\/a>When you hear \u201ctokens\u201d in the world of Entra ID, what does it mean? There are different types of tokens with different utilities. Not all tokens are created equal either; there are more attractive tokens for an attacker to steal causing a world of confusion and pain for blue and red teamers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This blog aims to demystify the primary differences between the most common types of tokens you may encounter and the attacks they are susceptible to. We will cover the following topics:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Token Hierarchy \u2013 What token to steal?<\/li>\n\n\n\n<li>Different Types of Tokens\u00a0<\/li>\n\n\n\n<li>ID tokens<\/li>\n\n\n\n<li>Access Tokens<\/li>\n\n\n\n<li>Refresh Tokens<\/li>\n\n\n\n<li>Family of Refresh Tokens<\/li>\n\n\n\n<li>Primary Refresh tokens<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Token Hierachy: What Token to Steal?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">What token should you steal as an attacker? This depends on the attacker\u2019s actions on objectives and the utility (usage) of the token. The token hierarchy list below is placed in order of attractiveness to an attacker based on access duration, bypasses, and lateral movement\/privilege escalation opportunities. The blog post expands further into each type of token but this section is the TL;DR for the entire blog post.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"904\" height=\"370\" src=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token1.png\" alt=\"\" class=\"wp-image-9133\" srcset=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token1.png 904w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token1-300x123.png 300w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token1-768x314.png 768w\" sizes=\"auto, (max-width: 904px) 100vw, 904px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/storagepublic.xintra.org\/public\/i\/20240731-032929\/Token1.png\" target=\"_blank\" rel=\"noreferrer noopener\"><\/a>Most organisations rely on Conditional Access policies as one of their primary protection methods against cloud attacks. However, if an attacker steals a Primary Refresh Token \u2013 conditional access policies are\u00a0<a href=\"https:\/\/learn.microsoft.com\/en-us\/entra\/identity\/devices\/concept-primary-refresh-token\" target=\"_blank\" rel=\"noreferrer noopener\">not evaluated or applied to the issued PRT<\/a>. This means the conditional access policies are not the most effective mitigation technique for PRT (there are others, but we won\u2019t go into mitigations in this blog post).<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"904\" height=\"214\" src=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token2.png\" alt=\"\" class=\"wp-image-9134\" srcset=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token2.png 904w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token2-300x71.png 300w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token2-768x182.png 768w\" sizes=\"auto, (max-width: 904px) 100vw, 904px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/storagepublic.xintra.org\/public\/i\/20240731-032937\/Token2.png\" target=\"_blank\" rel=\"noreferrer noopener\"><\/a>The second best (or tying for first place) token to steal are tokens that grant 90-day access and allow opportunities for an attacker to perform lateral movement and privilege escalation. Naturally this would be the undocumented Family of Refresh Tokens (FRT). These group of refresh tokens allow an attacker the ability to mint access tokens for\u00a0<em>other<\/em>\u00a0applications within the \u201cfamily\u201d.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The third would be a refresh token that grants an attacker persistent access to a specific resource for up to 90 days. The final contenders would be an access token or a SAML token with a lifetime of 1 hour each. The ranking for a SAML token would be higher if a Golden SAML attack has taken place.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Different Types of Tokens<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Tokens grant access to one or more resources in the cloud. There are several different \u201ctypes\u201d of tokens that exist \u2013 for example, access tokens and SAML tokens. These different types of tokens&nbsp;<em>supposed<\/em>&nbsp;to follow varying protocol references such as the OAuth 2.0, ODIC and SAML. However, Microsoft does not&nbsp;<em>strictly<\/em>&nbsp;adhere to these guidelines&nbsp;<a href=\"https:\/\/github.com\/secureworks\/family-of-client-ids-research\" target=\"_blank\" rel=\"noreferrer noopener\">as outlined by this fantastic writeup from Secureworks<\/a>&nbsp;where the OAuth 2.0 standard isn\u2019t abided by.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the world of tokens abiding by OAuth 2.0, there is a concept of a \u201cbearer token\u201d. You may see or be familiar with this when you perform a \u201cpass the token\u201d attack and paste your token in the request after the word \u201cbearer\u201d. Bearer tokens are a security token where&nbsp;<a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/rfc6750#section-1.2\" target=\"_blank\" rel=\"noreferrer noopener\">\u201cany party in possession of the token (a \u201cbearer\u201d) can use the token in any way that any other party in possession of it can\u201d<\/a>. This naturally leads to the assumption that if stolen, bearer tokens can be maliciously abused by an attacker to perform their actions on objectives. This may be a concept you\u2019re familiar with if you\u2019ve stolen a token and noted that they start with \u201ceyJ\u201d or \u201c0.AU\u201d. Bearer tokens typically are represented by a JSON Web Token (JWT) which can be decoded using something like \u201cjwt.io\u201d.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"904\" height=\"214\" src=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token3.png\" alt=\"\" class=\"wp-image-9135\" srcset=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token3.png 904w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token3-300x71.png 300w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token3-768x182.png 768w\" sizes=\"auto, (max-width: 904px) 100vw, 904px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/storagepublic.xintra.org\/public\/i\/20240731-032942\/Token3.png\" target=\"_blank\" rel=\"noreferrer noopener\"><\/a>Below is an image of a token being \u201cdecoded\u201d \u2013 and as you can see this bearer token contains a refresh token within it.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"754\" height=\"316\" src=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token4.png\" alt=\"\" class=\"wp-image-9136\" srcset=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token4.png 754w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token4-300x126.png 300w\" sizes=\"auto, (max-width: 754px) 100vw, 754px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Now, the next logical question would be what types of tokens can be a bearer token? The answer to this question would be 3 \u2013 there are three different types of bearer tokens and they are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><em>ID Token<\/em><\/strong>\u00a0Lifetime:\u00a0 1 hour<br>Used for authentication and contains information about the resources, owner, UPN etc<\/li>\n\n\n\n<li><strong><em>Access Token<\/em><\/strong>\u00a0Lifetime: 1 hour<br>Used for authorization and are credentials that are used to access an application\/resource<\/li>\n\n\n\n<li><strong><em>Refresh Token<\/em><\/strong>\u00a0Lifetime: 90 days<br>Used to obtain new tokens that have expired.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Now, aside from bearer tokens; Microsoft also issue SAML tokens to facilitate single sign-on (SSO). These tokens are valid for 1 hour and can be used by an attacker to impersonate a user\u2019s access to multiple different resources. In the absence of a Golden SAML attack (granting the attacker the ability to forge multiple SAML tokens), these tokens rank lower on our hierarchy list.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"904\" height=\"262\" src=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token5.png\" alt=\"\" class=\"wp-image-9137\" srcset=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token5.png 904w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token5-300x87.png 300w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token5-768x223.png 768w\" sizes=\"auto, (max-width: 904px) 100vw, 904px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>ID Tokens<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">These tokens are valid for 1 hour and prove authentication (that a user has authenticated to a resource\/application). The token contains information including verification details around who the user is. The primary difference between an ID token and an access token is that the ID token itself \u201cshould\u201d not be used to authorization purposes (which is what an access token is used for). Now with all things, \u201cshould not be used\u201d does not always mean \u201ccannot be used\u201d.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The image below is a decoded ID token, and as you can see it contains details around the user, the IP address, and further details around the user verification.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"802\" height=\"472\" src=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token6.png\" alt=\"\" class=\"wp-image-9138\" srcset=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token6.png 802w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token6-300x177.png 300w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token6-768x452.png 768w\" sizes=\"auto, (max-width: 802px) 100vw, 802px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Microsoft documentation on ID Tokens:\u00a0<a href=\"https:\/\/learn.microsoft.com\/en-us\/entra\/identity-platform\/id-tokens\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/learn.microsoft.com\/en-us\/entra\/identity-platform\/id-tokens<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Access Tokens<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Valid for 1 hour, these tokens grant access to resources and are used for authorization. These tokens embed information around who the user is and what specific resource the access is intended for. As you can see from the decoded access token below \u2013 the token has the scope\u00a0<a href=\"https:\/\/graph.microsoft.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">graph.microsoft.com<\/a>\u00a0via the client (application) Microsoft Office.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"630\" height=\"514\" src=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token7.png\" alt=\"\" class=\"wp-image-9139\" srcset=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token7.png 630w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token7-300x245.png 300w\" sizes=\"auto, (max-width: 630px) 100vw, 630px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Access tokens can be stolen and \u201cpassed\u201d to maliciously access the scope and application on behalf of the victim user.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Refresh Tokens (An Attacker\u2019s Buffet)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Refresh tokens are a type of bearer token that can be redeemed by an application to fetch a new set of \u201cbearer tokens\u201d. Since access tokens have a lifetime of 1 hour, this is where the utility of a refresh token comes in for the attacker. These tokens can be used continually within the lifetime of 90 days to obtain new access tokens. Given this power, refresh tokens are typically the primary target for attackers as it grants them up to 90 days of continual access to a specific resource \/ application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When decoding the bearer token, this is what a refresh token will look like:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"794\" height=\"224\" src=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token8.png\" alt=\"\" class=\"wp-image-9140\" srcset=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token8.png 794w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token8-300x85.png 300w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token8-768x217.png 768w\" sizes=\"auto, (max-width: 794px) 100vw, 794px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Here is where the nuance comes in, there are different TYPES of refresh tokens that exist (refresh tokens, Primary Refresh Tokens (PRT), and Family of Refresh Tokens (FRT)). With regards to these different types of refresh tokens, there are two key distinctions that they each fall into:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><em>Type 1<\/em><\/strong>: Refresh token that allows an attacker to obtain an access token to the SAME resource only<\/li>\n\n\n\n<li><strong><em>Type 2<\/em><\/strong>: Refresh tokens that allow an attacker to obtain access tokens for OTHER resources.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Family of Refresh Tokens (FRT)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There is a second type of refresh token known as Family Refresh Tokens (FRT) that are also valid for 90 days. This research was publicised by&nbsp;<a href=\"https:\/\/github.com\/secureworks\/family-of-client-ids-research\" target=\"_blank\" rel=\"noreferrer noopener\">Secureworks in this write-up about Family of Client IDs<\/a>. This \u201cFRT\u201d is undocumented by Microsoft. These tokens can be used by an attacker to mint tokens to ALL applications within \u201cthe family\u201d. Now this \u201cfamily\u201d is undocumented by Microsoft, but Secureworks keeps a non-exhaustive list of what these are&nbsp;<a href=\"https:\/\/github.com\/secureworks\/family-of-client-ids-research\/blob\/main\/known-foci-clients.csv\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This implementation of FRTs by Microsoft contradicts the OAuth 2.0 standard. As per the OAuth2.0 safeguards, bearer tokens are supposed to only be used to obtain tokens with identical or narrower scope and for the same client (application) it\u2019s issued for. This is not the case with FRTs.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What this means in layman terms is, if an attacker steals a refresh token for any application within this \u201cfamily\u201d \u2013 they can mint tokens to ALL the applications inside this family (allowing lateral movement). In terms of attacker hierarchy, the implication here is: depending on your attacker objective, aim to get a FRT over a typical refresh token as this allows you room for lateral movement and privilege escalation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Primary Refresh Tokens<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Valid for 14 days, these refresh tokens are used for single sign-in (SSO) across applications used on the device and contain two additional details embedded in them:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Device ID:<\/strong>\u00a0This field identifies the device where the PRT resides on<\/li>\n\n\n\n<li><strong><em>Session Key:<\/em><\/strong>\u00a0Acts as a proof of possession when the PRT obtains tokens for other applications<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Similar to FRT, these tokens can be used to access multiple different resources (not abiding by the OAuth 2.0 standard). As per Microsoft documentation,\u00a0<a href=\"https:\/\/learn.microsoft.com\/en-us\/entra\/identity\/devices\/concept-primary-refresh-token\" target=\"_blank\" rel=\"noreferrer noopener\">Conditional Access policies are not evaluated when PRTs are issued<\/a>.\u00a0 Therefore, if an attacker steals a PRT, it will automatically satisfy device-based conditional access policies.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"716\" height=\"318\" src=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token9.png\" alt=\"\" class=\"wp-image-9141\" srcset=\"https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token9.png 716w, https:\/\/tajdini.net\/blog\/wp-content\/uploads\/2024\/09\/Token9-300x133.png 300w\" sizes=\"auto, (max-width: 716px) 100vw, 716px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We tested this in our tenant and found that even when conditional access policies are applied which restrict geolocations, we were still able to successful perform \u201cPass the PRT\u201d and bypass these conditional access policies.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/github.com\/secureworks\/family-of-client-ids-research?tab=readme-ov-file#part-2&#8212;introducing-family-of-client-ids&#8211;family-refresh-tokens\n<\/div><\/figure>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/learn.microsoft.com\/en-us\/entra\/identity\/devices\/concept-primary-refresh-token\n<\/div><\/figure>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/learn.microsoft.com\/en-us\/entra\/identity-platform\/reference-saml-tokens\n<\/div><\/figure>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/learn.microsoft.com\/en-us\/entra\/identity-platform\/access-tokens\n<\/div><\/figure>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/learn.microsoft.com\/en-us\/entra\/identity-platform\/id-tokens\n<\/div><\/figure>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/learn.microsoft.com\/en-us\/entra\/identity-platform\/refresh-tokens\n<\/div><\/figure>\n\n\n\n<figure class=\"wp-block-embed\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/learn.microsoft.com\/en-us\/entra\/identity-platform\/configurable-token-lifetimes\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>When you hear \u201ctokens\u201d in the world of Entra ID, what does it mean? There are different types of tokens with different utilities. Not all tokens [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":9133,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[226,230],"tags":[125,248,230,198],"class_list":["post-9130","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-identity-and-active-directory","category-penetration-testing","tag-active-directory","tag-entra-id","tag-penetration-testing","tag-privilege-escalation"],"_links":{"self":[{"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/posts\/9130","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/comments?post=9130"}],"version-history":[{"count":2,"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/posts\/9130\/revisions"}],"predecessor-version":[{"id":9142,"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/posts\/9130\/revisions\/9142"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/media\/9133"}],"wp:attachment":[{"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/media?parent=9130"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/categories?post=9130"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tajdini.net\/blog\/wp-json\/wp\/v2\/tags?post=9130"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}