会话0的局限与新攻击思路
近期@decoder_it和@splinter_code披露了新型DCOM/RPC NTLM中继攻击技术:当用户在会话0(如PowerShell远程会话)登录时,调用CoGetInstanceFromIStorage
会使DCOM激活器在最低交互会话而非会话0创建对象。初始解组IStorage对象时,系统会使用对应会话的认证用户身份——若该用户是域管理员等特权账户,即可通过中继NTLM认证攻击远程服务器。
此技术的瓶颈在于必须处于会话0环境。虽然非管理员用户可能通过PowerShell远程登录,但相比终端服务器多用户场景,这种机会更罕见。理想方案是能自由选择对象创建会话。
会话标识符的隐藏潜力
系统其实存在跨会话激活机制:会话标识符(session moniker)可激活非会话0的跨会话对象(笔者曾多次利用此特性进行跨会话攻击[1][2][3])。微软始终未修复此非管理员也能使用的激活路径。
但根据文档,会话标识符无法与IStorage激活结合使用——COM API仅允许二选一。深入研究DCOM协议规范后发现,这两者在技术层面是独立的:
- 会话激活通过
SpecialPropertiesData
激活属性的dwSessionId
字段实现 - 编组IStorage对象可通过
InstanceInfoData
激活属性的ifdStg
字段传递
理论上可将这些属性打包发送至IRemoteSCMActivator
接口的RemoteGetClassObject
或RemoteCreateInstance
方法,但需验证可行性。
逆向系统原生激活机制
由于直接实现DCOM激活复杂度过高(需NDR编组激活属性且本地激活存在特殊限制),我们转向分析系统现有机制。关键突破口在于观察会话标识符的激活流程:
-
解析标识符字符串
MkParseDisplayName
函数调用链中,FindSessionMoniker
函数解析"Session:X"格式字符串,创建CSessionMoniker
实例:1 2 3 4 5 6 7
HRESULT FindSessionMoniker(LPBC pbc, LPCWSTR pszDisplayName, ULONG *pchEaten, LPMONIKER *ppmk) { if (wcsnicmp(pszDisplayName, L"Session:", 8)) return MK_E_UNAVAILABLE; // 解析会话ID或Console标识 *ppmk = new CSessionMoniker(dwSessionId, bConsole); }
-
构建复合标识符
示例字符串Session:3!clsid:0002DF02-...
会生成由会话标识符(会话3)和类标识符(浏览器代理CLSID)组成的复合标识符。 -
激活链调用
类标识符的BindToObject
方法调用左侧会话标识符的BindToObject
请求IClassActivator
接口,继而调用:1 2 3 4 5 6
HRESULT CSessionMoniker::GetClassObject(REFCLSID pClassID, ...) { CoCreateInstance(&CLSID_ComActivator, ..., IID_IStandardActivator, &pActivator); pActivator->QueryInterface(IID_ISpecialSystemProperties, &pSpecialProperties); pSpecialProperties->SetSessionId(m_sessionid, m_console, TRUE); return pActivator->StandardGetClassObject(...); }
实现IStorage混合激活
关键发现:IStandardActivator
接口存在未公开方法:
|
|
这证实了会话激活与IStorage激活可混合使用。笔者已用C#编写概念验证代码(详见GitHub),但尚未在实际漏洞场景中测试。
本文揭示了通过未文档化COM接口突破安全限制的技术本质,为防御复杂化的DCOM攻击提供了新视角。
参考文献
[1] 跨会话注入示例1
[2] 会话令牌操纵技术
[3] COM激活路径绕过案例