简体   繁体   中英

Access token validation in Azure AD authentication

I was able to request a token in Azure AD authentication. but the problem is whenever I change the last character in access_token, it still successfully request in my API. I just follow this https://mehmetkut.com/2017/05/protect-aspnetcore-webapi-resources-with-azure-active-directory-en/ is there a way that it can validate the token? it only occurs when I change at least 1 of the last character.

https://mehmetkut.com/2017/05/protect-aspnetcore-webapi-resources-with-azure-active-directory-en/

Token is still valid even I changed the last character.

Funnily enough we also hit this in a security audit.

As it turns out, the last 4 bits of the signature are just padding and are not part of the signature. So certain characters will be accepted as the last character, not all. You aren't actually modifying the signature data in that case, only the padding.

Here's an explanation from someone smarter than me:

This is a side effect of base64 decoding, the fact that the decoded signature is 256 bytes long, and the fact that 256 leaves a remained of 1 when divided by 3. 😊

The RS256 alg value corresponds to the “RSASSA-PKCS1-v1_5 using SHA-256” algorithm, which results in a signature which is 256 bytes long that is then base64url-encoded to when constructing the JWT, resulting in 342 characters after the second '.'. The first 255 bytes of the unencoded signature all “fit” nicely into 340 characters in base64 (every 6 bits of input result in 1 encoded character). From the last byte of the signature, the first 6 bits give the 341st character of the encoded signature. Now we have just two bits left to encode. Since we need 6 bits to obtain a base64-coded character, we append four 0s giving us 6 bits, and encode as normal.

When decoding, we start from the left, convert each character to its base64 index in binary (eg “A” is 000000, “B” is 000001, “C” is 000010, etc.), and grab groups of 8 bits to make a byte of the decoded input. From the first 340 characters of base64-encoded data, we get the first 255 bytes of the original data (the signature bytes). This leaves us with 12 bits still. We grab 8 bits to form the 256th byte of the original input, and since there are no longer enough bits to form a full byte, we just discard the last 4 bits (remember that these four were the 0s we “filled in” when encoding).

Since the last 4 bits are simply discarded (they don't form part of the encoded signature, they're just there for padding), these 4 bits can actually be anything at all. Only the first two of the last 6 bits are actually part of the original message.

This is really hard to explain in text, but it's really obvious if you try it out for yourself: Just encode a single byte to Base64 manually, then decode it.

To take your example, if the last base64 character is “A”, this is the base64 index is 0 (000000). The characters “B” through “P “ correspond to eh the base64 indexes 1 (000001) through 15 (001111). In all of these, the first two bits are always 00. Since the last four (are going to be discarded), you can choose anything from A to P, and you won't have any effect on the two bits that actually matter. If you go to “Q”, with index 16 (010000), now you've changed one of those two bits from the message, and the signature is no longer valid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM