ASP.NET Cookie是怎么生成的(推荐)

2020-02-01 09:26:42丽君

文中的Constants.SecurityDataProtectionProvider,刚好就被定义为"security.DataProtectionProvider"。

我们翻阅MachineKeyDataProtector的源代码,刚好看到它依赖于MachineKey:

internal class MachineKeyDataProtector
{
 private readonly string[] _purposes;

 public MachineKeyDataProtector(params string[] purposes)
 {
 _purposes = purposes;
 }

 public virtual byte[] Protect(byte[] userData)
 {
 return MachineKey.Protect(userData, _purposes);
 }

 public virtual byte[] Unprotect(byte[] protectedData)
 {
 return MachineKey.Unprotect(protectedData, _purposes);
 }
}

最终到了我们的老朋友MachineKey。

逆推过程,破解Cookie
首先总结一下这个过程,对一个请求在Mvc中的流程来说,这些代码集中在ASP.NET Identity中,它会经过:

AccountController SignInManager AuthenticationManager

设置AuthenticatinResponseGrant

然后进入CookieAuthentication的流程,这些代码集中在Owin中,它会经过:

CookieAuthenticationMiddleware(读取AuthenticationResponseGrant)
ISecureDataFormat(实现类:SecureDataFormat<T>)
IDataSerializer(实现类:TicketSerializer)
IDataProtector(实现类:MachineKeyDataProtector)
ITextEncoder(实现类:Base64UrlTextEncoder)

这些过程,结果上文中找到的所有参数的值,我总结出的“祖传破解代码”如下:

string cookie = "nZBqV1M-Az7yJezhb6dUzS_urj1urB0GDufSvDJSa0pv27CnDsLHRzMDdpU039j6ApL-VNfrJULfE85yU9RFzGV_aAGXHVkGckYqkCRJUKWV8SqPEjNJ5ciVzW--uxsCBNlG9jOhJI1FJIByRzYJvidjTYABWFQnSSd7XpQRjY4lb082nDZ5lwJVK3gaC_zt6H5Z1k0lUFZRb6afF52laMc___7BdZ0mZSA2kRxTk1QY8h2gQh07HqlR_p0uwTFNKi0vW9NxkplbB8zfKbfzDj7usep3zAeDEnwofyJERtboXgV9gIS21fLjc58O-4rR362IcCi2pYjaKHwZoO4LKWe1bS4r1tyzW0Ms-39Njtiyp7lRTN4HUHMUi9PxacRNgVzkfK3msTA6LkCJA3VwRm_UUeC448Lx5pkcCPCB3lGat_5ttGRjKD_lllI-YE4esXHB5eJilJDIZlEcHLv9jYhTl17H0Jl_H3FqXyPQJR-ylQfh";
var bytes = TextEncodings.Base64Url.Decode(cookie);
var decrypted = MachineKey.Unprotect(bytes,
 "Microsoft.Owin.Security.Cookies.CookieAuthenticationMiddleware",
 "ApplicationCookie",
 "v1");
var serializer = new TicketSerializer();
var ticket = serializer.Deserialize(decrypted);
ticket.Dump(); // Dump为LINQPad专有函数,用于方便调试显示,此处可以用循环输出代替

运行前请设置好app.config/web.config中的machineKey节点,并安装NuGet包:Microsoft.Owin.Security,运行结果如下(完美破解):

总结

学习方式有很多种,其中看代码是我个人非常喜欢的一种方式,并非所有代码都会一马平川。像这个例子可能还需要有一定ASP.NET知识背景。

注意这个“祖传代码”是基于.NET Framework,由于其用到了MachineKey,因此无法在.NET Core中运行。我稍后将继续深入聊聊MachineKey这个类,看它底层代码是如何工作的,然后最终得以在.NET Core中直接破解ASP.NET Identity中的Cookie,敬请期待!