Take the next step
Talk to us today
This post discusses how we adapted the Blacklist3r tool to achieve authentication bypass on a web application implementing OWIN (Open Web Interface for .NET) OAuth 2.0 during a client pentest.
Authored by Michael Tsai
Published on
Blacklist3r is a project that collects pre-published secret keys such as the Machine Key used by a .NET application from various locations such as public Github repositories, blog posts and tutorials. These keys are sometimes reused in the production environment or were accidentally published by the developers. Blacklist3r also provides the AspDotNetWrapper
tool to brute-force encrypted material against this list of Machine Keys.
The types of encrypted data it supported are:
However, as the tool did not support decrypting OWIN OAuth Access Tokens by default, we needed to modify Blacklist3r to support this feature. This led to a successful decryption of the access token, which resulted in authentication bypass on the target application.
OWIN stands for “Open Web Interface for .NET”. It is a specification that aims to decouple the web application from the web server. For more information regarding OWIN and the Microsoft implementation Katana, please see the official documentation.
A classic implementation of OAuth 2.0 in ASP.NET 4.x is to use the OWIN OAuth middleware. This is based on the Microsoft.Owin.*
libraries provided by Katana. The OAuth architecture typically includes an Authorisation Server and a Resource Server. Upon successful authentication on the Authorisation Server, the client would be issued an access token for accessing the protected resources on the Resource Server.
In a since-removed article (archived on the Internet Wayback Machine), Microsoft describes an implementation to issue a Bearer Token in the context of Client Credentials Grant.
The Authentication Provider is set up as follows during start up:
The GrantClientCredentials
method is implemented as follows:
The token generation happens during context.Validated(identity)
. This relevant code is implemented in Microsoft.Owin.Security.OAuth/Provider/BaseValidatingTicketContext.cs
. The AuthenticationTicket
is created at this point based on the provided identity and properties.
Microsoft.Owin.Security.OAuth/Provider/BaseValidatingTicketContext.cs
As the Authentication Ticket is created, an access token is then issued to the client. This code flow is shown below:
Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerHandler.cs
Microsoft.Owin.Security/Infrastructure/AuthenticationTokenCreateContext.cs
Microsoft.Owin.Security/DataHandler/SecureDataFormat.cs
To understand the encryption process, we have to trace back how _serializer
, _protector
and _encoder
were defined.
_serializer
is a TicketSerializer
object whose Serialize()
function is simply performing Gzip compression_protector
is defined as follows:
Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerMiddleware.cs
_encoder
is Base64Url
encoding.The encryption part is defined by the Protect()
function, which eventually calls the standard MachineKey.Protect()
function defined in System.Web.Security
. The _purposes
string is also passed in along with the user data.
For testing purpose and to summarise the operation, we have also come up with the following sample code to create an access token.
// Create new ClaimsIdentity
var identity = new ClaimsIdentity("Bearer");
// Add some claims here
identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
// Set authentication properties
var props = new AuthenticationProperties();
props.IssuedUtc = new DateTime(2020, 12, 12);
props.ExpiresUtc = new DateTime(2222, 12, 12);
// Create a sample Authentication ticket
var sampleAuthTicket = new AuthenticationTicket(identity, props);
var newSerializer = new TicketSerializer();
var sampleTicket = newSerializer.Serialize(sampleAuthTicket);
// Encrypt the ticket
var enc = EncryptData(sampleTicket, machineKey, validationKey, "SHA1", "AES", emptyIV);
Console.WriteLine("Encrypted OAuth token: " + enc);
The EncryptData()
method is taken and adapted from Blacklist3r:
public static string EncryptData(
byte[] plaintext,
string machineKey,
string validationKey,
string validationAlgo,
string DecryptionAlgo,
byte[] encryptionIV
) {
AspNetCryptoServiceProvider obj = new AspNetCryptoServiceProvider(
validationKey, validationAlgo, machineKey, DecryptionAlgo
);
obj.SetEncryptionIV(encryptionIV);
Purpose purpose = Purpose.User_MachineKey_Protect.AppendSpecificPurposes(
new[] {
"Microsoft.Owin.Security.OAuth",
"Access_Token",
"v1"
}
);
ICryptoService cryptoService = obj.GetCryptoService(purpose);
var encrypted = cryptoService.Protect(plaintext);
return Convert.ToBase64String(encrypted).Replace('+', '-').Replace('/', '_').Replace("=", "");
}
Now knowing the context of how an access token is created and encrypted, we can customise Blacklist3r to brute force for OWIN OAuth tokens.
It is relatively easy to add OWIN OAuth support to Blacklist3r since it already supports OWIN auth cookies. If we compare the two implementations during the encryption process, we notice that the only difference is the purposes
string array that gets passed into the CreateDataProtector()
function:
Regarding the Blacklist3r project itself, the code inside the AspDotNetWrapper/Customization
directory is all we need to modify. We can see the existing purpose string for OWIN auth cookie is defined in DefinePurpose.cs
:
Instead of typeof(CookieAuthenticationMiddleware).FullName
which is Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware
, we would just need typeof(OAuthBearerAuthenticationMiddleware).Namespace
which evaluates to Microsoft.Owin.Security.OAuth
. Similarly, instead of ApplicationCookie
we would put Access_Token
. In addition to this main modification, there is only slight changes required for the other pieces of code that deal with handling command line arguments and decrypted output.
After the change, we can now successfully decrypt the target Bearer Token and obtain the machine key:
Blacklist3r is a highly useful tool to audit the target application for usage of pre-published machine keys. Successful brute-forcing of this information could often lead to authentication bypass or Remote Code Execution. In this post, we have shown our approach to modifying Blacklist3r to decrypt OWIN OAuth access tokens and that other encryption routines could also be added to Blacklist3r with ease.
Talk to us today