探索基于http.sys实现权限维持

admin 2022年7月6日08:31:35评论101 views字数 3182阅读10分36秒阅读模式

前言

在通常WEB应用中,一个应用只能绑定一个端口,若同时绑定一个端口,必然会抛出端口占用异常信息,微软在IIS 5.0以后版本提供了一种机制,Net. Port Sharing,即端口共享。它允许对应用同时使用一个端口只需要各自注册的url前缀不一样即可。

这种机制被封装在http.sys驱动中,驱动监听HTTP流量,然后根据URL注册的情况去分发到当前URL对应的应用。

winrm服务端口复用

实际上,winrm服务就是基于http.sys驱动上注册了wsman后缀,Windows Server 2008默认关闭WinRM服务,Windows Server 2012默认开启

测试环境:192.168.1.201 系统版本:Windows Server 2008 R2

在命令行下开启服务,防火墙会自动添加例外规则,系统默认监听端口5985。

winrm quickconfig –q

探索基于http.sys实现权限维持

此时使用netsh http show servicestate

可以查看到http.sys新注册了一条url前缀:

探索基于http.sys实现权限维持

由于系统原本没有开启5985端口,为了增加后门的隐蔽性,故通过以下命令将winrm服务端口修改至80端口,达到端口复用的效果。

winrm set winrm/config/Listener?Address=*+Transport=HTTP @{Port="80"}

探索基于http.sys实现权限维持

默认客户端连接则会提示Winrs error:WinRM 客户端无法处理该请求。如果身份验证方案与 Kerberos 不同,或者客户端计算机…,因为WinRM只允许当前域用户或者处于本机TrustedHosts列表中的远程主机进行访问,则需在客户端添加一个TrustedHost表,*代表信任远程任意主机:

Set-Item WSMan:localhostclienttrustedhosts -value *

然后使用winrs命令连接远程web服务端口获得交互式SHELL,

探索基于http.sys实现权限维持

使用python实现一款支持NTLM hash的客户端,需要注意的是:

windows 2008是LM-HASH:NTLM-HASH的方式,使用32个0替代。
windows 2012以及之后只能抓到NTLM的Hash,直接使用即可。

最终实现的代码已上传至github,地址如下:

https://github.com/c1y2m3/python-tools/blob/master/WinrmAttack.py

探索基于http.sys实现权限维持

HTTP ServerAPI端口复用

微软对外开放了如何调用这种http.sys驱动机制的API接口,也就是HTTP Server API。HTTP Server API 运行在用户模式中,也就是说任意用户都可以调用该API实现一个HttpListener,与 IIS 共享端口,但是前提是你必须拥有管理员权限。

探索基于http.sys实现权限维持

上图整个过程描述如下:

(1)第一步,IIS 或者是自己写的程序(HttpListener)调用API ,向内核的Http.sys注册一个URL前缀,这相当于向路由器添加一条路由规则,Http.sys就是这个路由器。

(2)第二步,Http.sys捕获到一个http请求,它将会根据自身的“路由表”找到该http请求的前缀所对应的应用,然后把请求分发给该应用。

(3)第三步,HttpListener接收到Http.sys转发来的请求,对其进行回应。

1.示例代码测试

微软官方有一个基于HTTP Server API 1.0版本的demo:

https://docs.microsoft.com/zh-cn/windows/win32/http/http-server-sample-application

笔者对其demo进行了简单的修改,进行如下演示:

探索基于http.sys实现权限维持

通过pReq->CookedUrl.pQueryString 能够读取url中的参数,去除参数后的问号对字符串拼接,

获取客户端输入的内容,C++ 代码如下:

*QueryString = new WCHAR[pReq->CookedUrl.QueryStringLength - 1];

wcsncpy_s(QueryString, wcslen(QueryString), pReq->CookedUrl.pQueryString + 5, wcslen(QueryString) - 1);

wprintf(L"[*] QueryStringDecode:%wsn", QueryString);
探索基于http.sys实现权限维持

后门功能设计

基于该demo进行修改,设计命令执行后门,通过GET请求发送要执行的cmd命令,格式为?,对传来的http请求进行身份验证,验证成功时进行回应,

例如: http://127.0.0.1/a?png=whoami,要执行的命令为whoami,通过处理http请求内容,执行系统命令并通过SendHttpResponse回显到客户端页面。

使用管道读取命令并执行,回传结果,参考代码如下:

https://github.com/3gstudent/Homework-of-C-Language/blob/master/UsePipeToExeCmd.cpp

探索基于http.sys实现权限维持
探索基于http.sys实现权限维持

在测试过程中发现当传入特殊字符时,例如空格,单双,引号等字符会被编码,导致某些命令无法解析执行 ,如图所示:

探索基于http.sys实现权限维持

这里笔者对命令使用了base64解码处理,解决以上问题且可以对流量进行简单加密,以及对回传的结果作格式转换。

并使用#pragma comment( linker, "/subsystem:"windows" /entry:"wmainCRTStartup"" ),屏蔽控制台应用程序的窗口,修改测试代码如下图:

探索基于http.sys实现权限维持

效果演示

可以看到,未注册/a/前缀时,因为此时只有iis使用了端口共享机制,http.sys把访问/a/的请求交给了iis处理,iis返回了404页面。

探索基于http.sys实现权限维持

随后我们用自己的程序把/a/前缀注册到http.sys,此时访问/a/路径,http.sys于是把请求交了我们的后门程序并回显系统命令。

探索基于http.sys实现权限维持

奇思异想

Windows Server 2008 R2及更高版本的系统默认无法获得明文密码,但是可以利用SSP即 Security Support Provider,通俗理解就是一个用于身份验证的 dll,系统在启动时 SSP 会被加载到 lsass.exe 进程中,由于 lsa 可扩展,导致在系统启动时我们完全可以加载一个自定义的 dll来记录明文账号密码。

mimilib从lsass进程中提取明文凭据的实现代码:

https://github.com/gentilkiwi/mimikatz/blob/master/mimilib/kssp.c

自动武器化实现思路:

1、将动态库或是驱动文件打包进一个可执行文件中,再由需要使用的时候,再临时释放和加载。

探索基于http.sys实现权限维持

2、将释放的dll文件复制到c:windowssystem32下,这里编译的时候需要注意的是程序是32位的,在64位系统下,所有对system32的操作都会被转向syswow64,修改系统注册表Security Packages的值为要加载dll的名称。

探索基于http.sys实现权限维持

3、通过调用 AddSecurityPackage API函数可以使 lsass.exe 进程加载指定的SSP / AP,无需重启,此时管理员输入了新的凭据,将会生成文件kiwissp.log,实战中,可配合上述的HTTP ServerAPI端口复用实时获取凭证,如有需求也可以自行改进。

效果演示:

探索基于http.sys实现权限维持

Reference

http://www.mamicode.com/info-detail-2638519.html

https://www.4hou.com/posts/y6jW

https://blog.csdn.net/ayang1986/article/details/83351842


原文始发于微信公众号(零队):探索基于http.sys实现权限维持

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年7月6日08:31:35
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   探索基于http.sys实现权限维持http://cn-sec.com/archives/922258.html

发表评论

匿名网友 填写信息