今天要介紹的是 Distributed Component Object Model (DCOM),也就是將透過 RPC 讓 COM object 也可以被 remote process 使用。另外,在介紹一些結構時,會特別說明一些重要欄位在 Windows Potatoes 中的意義。
Local Server Activation
根據 James Forshaw 的 COM in Sixty Seconds,在 DCOM 的架構中,有 System Activator (RPC Server) 擔任 Process 之間傳遞 COM object 的角色。
DEFINE_GUID(IID_ISystemActivator, "000001a0-0000-c000-000000000046")
struct ISystemActivator : public IUnknown {
HRESULT GetClassObject(
IActivationPropertiesIn *pActProperties,
IActivationPropertiesOut *ppActProperties
);
HRESULT CreateInstance(
IUnknown *pUnkOuter,
IActivationPropertiesIn *pActProperties,
IActivationPropertiesOut *ppActProperties
);
}
並且 COM Object 以 marshalling 的方式傳遞,這裡提到了兩個結構 IActivationPropertiesIn
和 IActivationPropertiesOut
。
struct PropsOutInfo {
DWORD cifs;
IID *piid;
HRESULT *phresults;
MInterfacePointer **ppIntfData;
}
struct MInterfacePointer {
unsigned long ulCntData;
byte abData[]; // <-- **OBJREF**
}
在 IActivationPropertiesOut
會有被 marshalling 的 COM Object ,其中最重要的結構就是 OBJREF。
以下是關於 OBJREF 的一些說明:
OBJREF
- signature (4 bytes): This MUST be set to the value 0x574f454d (MEOW).
- flags (4 bytes): This MUST be set to ONE of the following values
-
OBJREF_STANDARD
-
OBJREF_HANDLER
-
OBJREF_CUSTOM
-
OBJREF_EXTENDED
後面 u_objref
的部分會是 flags
指定的結構
OBJREF_STANDARD
- std (40 bytes): This MUST be an STDOBJREF.
- saResAddr (variable): A DUALSTRINGARRAY that MUST contain the network and security bindings for the object resolver service on the server.
STDOBJREF
- flags (4 bytes): This can be one of the following values. Any other value MUST be ignored by the client.
- cPublicRefs (4 bytes): The number of public references on the server object, which MUST be released later.
- oxid (8 bytes): This MUST be an OXID identifying the object exporter that contains the object.
- oid (8 bytes): This MUST be an OID identifying the object.
- ipid (16 bytes): This MUST be an IPID identifying a specific interface on the object.
正常狀況下, oxid
, oid
, ipid
的值會有特定的作用,但是在 Potatoes 中,client 會跟攻擊者偽冒的 OXID Resolver 溝通,攻擊者只要能成功讓偽冒的 OXID Resolver 回傳 RPC binding string 就好,因此這幾個欄位可以填入隨機值。
DUALSTRINGARRAY
- wNumEntries (2 bytes): The number of unsigned shorts from the first entry in the StringBinding array to the end of the buffer.
- wSecurityOffset (2 bytes): The number of unsigned shorts from the first entry in the StringBinding array to the first entry in the SecBinding array.
- StringBinding (variable): An array of one or more STRINGBINDING structures that SHOULD be ordered in decreasing order of preference by the object server.
- SecBinding (variable): An array of one or more SECURITYBINDING structures that SHOULD be ordered in decreasing order of preference by the object server.
其中這個 StringBinding 會指定 OXID resolver 的位址。
RemotePotato0
Windows Potatoes 是 Windows 中常見的提權工具的一種。不過 Potatoes 定義沒有那麼明確,但是大部分使用的提權核心技術是 NTLM Relay,並且也出現了不少搭配 DCOM 的方法。
而 RemotePotato0 就是其中一個最複雜的 Windows Potato,並且使用情境是在 Active Directory。
以下是 RemotePotato0 的步驟:
- 在一開始 Attacker 會取得在 session 0 的低權限的 Domain User 的執行權限,而且 Domain Admin 必須登入在 session 1。
- RemotePotato0 偽造 IStorage COM Object (OBJREF) 並以脆弱的 CLSID (會 impersonate user 的 service) 呼叫
CoGetInstanceFromStorage
觸發 DCOM Server 執行 unmarshal 偽造的 OBJREF。
- DCOM Server 會根據偽造的 OBJREF 向指定的 TCP Server 發出 OXID Request
- TCP Server 只限定在 Remote IP,因此使用 socat 重新導向 OXID Request 到 RemotePotato0 註冊的 RPC Server,也就是 OXID Resolver
- OXID Resolver 會負責回傳 DCOM Server 要連接的 RPC Server。雖然
IObjectExporter::ResolveOxid2
可以要求 DCOM Server 向 OXID Resolver 發起 NTLM Authentication,但是這邊的 RPC Authentication Level 是 RPC_C_AUTHN_LEVEL_PKT
,因此會校驗完整性,沒辦法直接 NTLM Relay
- DCOM Server 向 OXID Response 得到的 RPC Server 連接。 RemotePotato0 偽冒的 RPC Server 要求 DCOM Server 發起 NTLM Authentication
- RemotePotato0 將 NTLM Authentication 轉給 ntlmrelayx ,並且通過受害 Server 的 HTTP Authentication
如果專注在 DCOM Client 和 DCOM Server 的互動,在 RemotePotato0 中會是以下流程
綜觀 Windows Potatoes 的實作,可以發現利用手法越來越複雜,都是利用多種元件達成攻擊。
References