再探MS-SAMR協(xié)議
作者:Loong716@
0x00 前言
在前一篇《利用MS-SAMR協(xié)議修改用戶密碼》中介紹了利用MS-SAMR修改用戶密碼并還原的技巧。在本篇文章中,我們繼續(xù)介紹MS-SAMR協(xié)議的一些其它利用。
0x01 利用
1. 添加本地用戶
在滲透測(cè)試過(guò)程中,我們經(jīng)常會(huì)遇到在目標(biāo)機(jī)器添加賬戶但被殺軟攔截掉的情況。現(xiàn)在較為通用的繞過(guò)方法是通過(guò)調(diào)用NetUserAdd()
等API來(lái)添加用戶

我們同樣也可以利用MS-SAMR協(xié)議中的SamrCreateUser2InDomain()
來(lái)添加用戶(其實(shí)調(diào)用MS-SAMR是NetUserAdd()
等API的底層實(shí)現(xiàn))
需要注意的有兩點(diǎn),一點(diǎn)是Windows操作系統(tǒng)(域控除外)中的“域”分為內(nèi)置域(Builtin Domain)和賬戶域(Account Domain)
內(nèi)置域(Builtin Domain):包含在安裝操作系統(tǒng)時(shí)建立的默認(rèn)本地組,例如管理員組和用戶組
賬戶域(Account Domain):包含用戶、組和本地組帳戶。管理員帳戶在此域中。在工作站或成員服務(wù)器的帳戶域中定義的帳戶僅限于訪問(wèn)位于該帳戶所在物理計(jì)算機(jī)上的資源
因此我們需要在賬戶域中添加普通用戶,然后在內(nèi)置域中找到Administrators組,再將該用戶添加到內(nèi)置域中的Administrators中
第二個(gè)需要注意的是,利用SamrCreateUser2InDomain()
添加的賬戶默認(rèn)是禁用狀態(tài),因此我們需要調(diào)用SamrSetInformationUser()
在用戶的userAccountControl中清除禁用標(biāo)志位:
// Clear the UF_ACCOUNTDISABLE to enable account
userAllInfo.UserAccountControl &= 0xFFFFFFFE;
userAllInfo.UserAccountControl |= USER_NORMAL_ACCOUNT;
userAllInfo.WhichFields |= USER_ALL_USERACCOUNTCONTROL;
RtlInitUnicodeString(&userAllInfo.NtOwfPassword, password.Buffer);
// Set password and userAccountControl
status = SamSetInformationUser(hUserHandle, UserAllInformation, &userAllInfo);
在實(shí)現(xiàn)時(shí),如果直接調(diào)用MS-SAMR的話在設(shè)置用戶密碼時(shí)會(huì)非常復(fù)雜,涉及到加密算法并且可能需要SMB Session Key(用impacket很好實(shí)現(xiàn),但impacket不支持當(dāng)前用戶身份執(zhí)行)
但我們可以調(diào)用samlib.dll的導(dǎo)出函數(shù),在上一篇文章中提到過(guò)這些導(dǎo)出函數(shù)其實(shí)是封裝了協(xié)議的調(diào)用,實(shí)現(xiàn)會(huì)更簡(jiǎn)單一些,代碼Demo:https://github.com/loong716/CPPPractice/tree/master/AddUserBypass_SAMR

2. 解決密碼過(guò)期限制
假設(shè)在滲透測(cè)試過(guò)程中,我們收集到一臺(tái)服務(wù)器的用戶賬戶,但當(dāng)想要訪問(wèn)目標(biāo)SMB資源時(shí),發(fā)現(xiàn)該賬戶密碼已過(guò)期。此處以psexec橫向?yàn)槔繕?biāo)顯示STATUS_PASSWORD_MUST_CHANGE錯(cuò)誤:

此時(shí)我們可以利用samba中的smbpasswd來(lái)修改該用戶的密碼

修改之后使用新密碼就可以正常訪問(wèn)目標(biāo)的SMB資源了:
實(shí)際上smbpasswd調(diào)用的是MS-SAMR的SamrUnicodeChangePasswordUser2()
,該方法不需要上下文句柄,并且支持SMB空會(huì)話(Null Session)調(diào)用
https://github.com/samba-team/samba/blob/e742661bd2507d39dfa47e40531dc1dca636cbbe/source3/libsmb/passchange.c#L192
另外impacket之前也更新了該方法的example,并且該腳本支持hash傳遞:
https://github.com/SecureAuthCorp/impacket/blob/master/examples/smbpasswd.py
3. 信息收集/修改
MS-SAMR協(xié)議在信息收集/修改方面能做的事情很多,如枚舉/修改對(duì)象的ACL、用戶&組信息、枚舉密碼策略等。此處以枚舉本地管理員組賬戶為例
通常進(jìn)行本地管理員組賬戶的枚舉會(huì)調(diào)用NetLocalGroupGetMembers()
這一API,前面提到過(guò)這類API底層也是調(diào)用MS-SAMR協(xié)議,先來(lái)看一下正常調(diào)用的過(guò)程:
SamrConnect:獲取Server對(duì)象的句柄
SamrOpenDomain:打開(kāi)目標(biāo)內(nèi)置域的句柄
SamrLookupNamesInDomain:在內(nèi)置域中搜索Administrators的RID
SamrOpenAlias:根據(jù)Administrators的RID打開(kāi)別名句柄
SamrGetMembersInAlias:枚舉別名對(duì)象中的成員SID
此時(shí)我們?nèi)绻胍_(kāi)發(fā)自動(dòng)化的信息收集工具(如SharpHound),那么我們需要考慮工具的通用性,比如在第3步調(diào)用SamrLookupNamesInDomain()
時(shí),我們需要傳入"Administrators",但在某些系統(tǒng)中管理員組的名字可能有差異,如部分非英文操作系統(tǒng)中該組名為"Administradors",或者運(yùn)維修改了本地管理員組名稱,這樣我們直接調(diào)用NetLocalGroupGetMembers()
便不合適了
此時(shí)我們可以考慮優(yōu)化這一操作,我們可以注意到本地管理員組在不同Windows系統(tǒng)上的RID始終為544
那么我們可以這樣調(diào)用:
SamrConnect:獲取Server對(duì)象的句柄
SamrOpenDomain:打開(kāi)目標(biāo)內(nèi)置域的句柄
SamrOpenAlias:打開(kāi)RID為544對(duì)象的別名句柄
SamrGetMembersInAlias:枚舉該別名對(duì)象中的成員SID
按此思路,我們可以將MS-SAMR的API利用到我們自己工具的武器化or優(yōu)化上
4. 添加域內(nèi)機(jī)器賬戶
調(diào)用SamCreateUser2InDomain()
時(shí)指定AccountType為USER_WORKSTATION_TRUST_ACCOUNT可以在域內(nèi)添加機(jī)器賬戶
// Create computer in domain
status = SamCreateUser2InDomain(hDomainHandle, &computerName, USER_WORKSTATION_TRUST_ACCOUNT, USER_ALL_ACCESS | DELETE | WRITE_DAC, &hUserHandle, &grantAccess, &relativeId);
impacket的addcomputer.py包含了該方法,因?yàn)長(zhǎng)DAPS需要證書的不穩(wěn)定所以添加了SAMR(SAMR是Windows GUI環(huán)境添加機(jī)器使用的協(xié)議)
這個(gè)地方感覺(jué)還是有一些誤區(qū)的,通過(guò)LDAP修改unicodePwd
確實(shí)需要在加密的連接中操作,但LDAPS并不是必須的,像powermad.ps1在加密LDAP中添加機(jī)器賬戶同樣可以成功,并且非常穩(wěn)定
我們實(shí)戰(zhàn)中大多數(shù)情況下添加機(jī)器賬戶都是在利用基于資源約束委派時(shí),為了拿到一個(gè)有SPN的賬戶所以才選擇添加機(jī)器賬戶。但我實(shí)際測(cè)試中發(fā)現(xiàn)該方法并不會(huì)自動(dòng)為機(jī)器賬戶添加SPN,而通過(guò)LDAP或其他RPC為機(jī)器賬戶添加SPN又感覺(jué)有些畫蛇添足,只能先作為一種添加機(jī)器賬戶的實(shí)現(xiàn)方法,如果其他方法不成功時(shí)可以嘗試
0x02 參考
https://docs.microsoft.com/zh-cn/openspecs/windows_protocols/ms-samr/4df07fab-1bbc-452f-8e92-7853a3c7e380
https://github.com/SecureAuthCorp/impacket/
https://snovvcrash.rocks/2020/10/31/pretending-to-be-smbpasswd-with-impacket.html
https://blog.cptjesus.com/posts/sharphoundtechnical