作者:御守實驗室
原文鏈接:https://mp.weixin.qq.com/s/eMXaerqdkrq4maHuzII9BA
相關閱讀:《從 mimikatz 學習 Windows 安全之訪問控制模型(二)》

0x00 前言

Mimikatz是法國安全研究員Benjamin Delpy開發的一款安全工具。滲透測試人員對mimikatz印象最深的肯定就是抓取Windows憑證,但作者對它的描述是“a tool I've made to learn C and make somes experiments with Windows security.”,其實它的功能不僅僅是抓取憑證,還包含了很多Windows安全相關的技術和知識

這里借用@daiker師傅的思維導圖,mimikatz的模塊大致可分為幾個部分:

圖片

因此文章也會大致分為windows 訪問控制模型,windows 憑據以及加解密,windows AD 安全,windows 進程以及服務,mimikatz 其他模塊五個小系列。之前自己一直想分析mimikatz的相關功能,主要是出于以下原因:

  • mimikatz中有許多功能利用了Windows的一些機制和特性,以changentlm為例,其利用MS-SAMR協議修改用戶的密碼,我們再根據MS-SAMR或RPC進行知識延伸,肯定也有不少收獲
  • mimikatz中涉及大量內存的操作,其中運用的內存Patch技術也被經常應用于一些安全機制的繞過(如繞過AMSI、Credential Guard等),于是自己想在分析過程中通過windbg學到一些調試的技巧
  • mimikatz在實戰中被殺的很厲害,了解相應原理可以自己實現相應功能
  • 學習/練習C語言 :D

mimikatz中與Windows訪問控制模型相關的有privilege、token、sid三個模塊,其分別對應特權、訪問令牌、安全標識符三個知識,本文主要分析token模塊,并簡要介紹Windows訪問控制模型

由于mimikatz代碼邏輯較為復雜,涉及大量回調,因此文中代碼都是經過簡化的。文章可能也會有一些技術上或者邏輯上的錯誤,還請師傅們指正

0x01 訪問控制模型簡介

Windows訪問控制模型有兩個基本組成部分:

  • 訪問令牌(Access Token):包含有關登錄用戶的信息
  • 安全描述符(Security Descriptor):包含用于保護安全對象的安全信息

1. 訪問令牌(Access Token)

訪問令牌(Access Token)被用來描述一個進程或線程的安全上下文,用戶每次登錄成功后,系統會為其創建訪問令牌,該用戶的所有進程也將擁有此訪問令牌的副本

當線程與安全對象進行交互或嘗試執行需要特權的系統任務時,系統使用訪問令牌來標識用戶。使用windbg查看進程的token,其包含信息如下圖所示:

圖片

圖片

圖片

2. 安全描述符(Security Descriptor)

安全描述符(Security Descriptor)包含與安全對象有關的安全信息,這些信息規定了哪些用戶/組可以對這個對象執行哪些操作,安全描述符主要由以下部分構成:

  • 所有者的SID
  • 組SID
  • 自主訪問控制列表(DACL),規定哪些用戶/組可以對這個對象執行哪些操作
  • 系統訪問控制列表(SACL),規定哪些用戶/組的哪些操作將被記錄到安全審計日志中

在windbg中查看一個安全對象的安全描述符,可以清晰的看到安全描述符的組成:

圖片

可以看到該安全描述符的DACL中有三條ACE,ACE的類型都是ACCESS_ALLOWED_ACE_TYPEMask是權限掩碼,用來指定對應的權限。以第一條ACE為例,其表示允許SID為S-1-5-32-544的對象能夠對該安全對象做0x001fffff對應的操作

3. 權限檢查的過程

當某個線程嘗試訪問一個安全對象時,系統根據安全對象的ACE對照線程的訪問令牌來判斷該線程是否能夠對該安全對象進行訪問。通常,系統使用請求訪問的線程的主訪問令牌。但是,如果線程正在模擬其他用戶,則系統會使用線程的模擬令牌

此時將在該安全對象的DACL中按順序檢查ACE,直到發生以下事件:

  • 某一條拒絕類型的ACE顯式拒絕令牌中某個受信者的所有訪問權限
  • 一條或多條允許類型的ACE允許令牌中列出的受信者的所有訪問權限
  • 檢查完所有ACE但沒有一個權限顯式允許,那么系統會隱式拒絕該訪問

我們以微軟文檔中的圖片為例,描述一下整個過程:

圖片

  1. 線程A請求訪問安全對象,系統讀取ACE1,發現拒絕Andrew用戶的所有訪問權限,而線程A的訪問令牌是Andrew,因此拒絕訪問,并不再檢查ACE2、ACE3
  2. 線程A請求訪問,系統按順序讀取ACE,ACE1不適用,讀取到ACE2發現適用,再讀取到ACE3也適用,因此最終該用戶擁有對該安全對象的讀、寫、執行權限

0x02 Mimikatz的Token模塊

Mimikatz的token模塊共有5個功能:

  • token::whoami:列出當前進程/線程的token信息
  • token::list:列出當前系統中存在的token
  • token::elevate:竊取其他用戶的token
  • token::run:利用某用戶權限運行指定程序
  • token::revert:恢復為原來的token

1. token::whoami

該功能用于列出當前進程/線程的token信息

圖片

只有一個可選參數/full,當指定該參數時會打印出當前token的組信息和特權信息:

圖片

該功能的原理大致如下:

  1. 通過OpenProcess()獲取當前進程/線程的句柄
  2. 調用GetTokenInformation()獲取token的各種信息并輸出

其核心為調用GetTokenInformation()來獲取token的各種信息,我們先來看這個API定義

圖片

其中第二個參數是一個TOKEN_INFORMATION_CLASS枚舉類型,我們可以通過指定它的值來獲取token指定的信息

圖片例如獲取token的SessionID并輸出,可以使用以下代碼:

圖片

2. token::list

該功能是獲取當前系統中所有的token,注意使用前需要先獲取SeDebugPrivilege,否則列出的token不全

圖片

該功能原理大致如下:

  1. 調用NtQuerySystemInformation()獲取系統進程信息(如進程PID等)
  2. 循環遍歷所有進程的PID,使用token::whoami功能中的方法對指定token信息進行輸出

NtQuerySystemInformation()用來檢索指定的系統信息:

圖片

其第一個參數是一個SYSTEM_INFORMATION_CLASS枚舉類型,我們同樣可以指定不同參數來獲取不同的系統信息

圖片

以獲取系統進程名和PID為例,代碼如下:

圖片

PS:按照該思路,理論上利用CreateToolhelp32Snapshot() + Process32First()遍歷進程PID也可以實現該功能

3. token::elevate

該模塊用于竊取指定用戶的token,共有7個可選參數,這些參數主要用來指定要竊取的token,如果不指定參數則默認竊取NT AUTHORITY\SYSTEM的token

  • /id:指定目標token的TokenID
  • /domainadmin:竊取域管的token
  • /enterpriseadmin:竊取企業管理員的token
  • /admin:竊取本地管理員的token
  • /localservice:竊取Local Service權限的token
  • /networkservice:竊取Network Service權限的token
  • /system:竊取SYSTEM權限的token

假設我們現在在目標機器上發現的域管權限的token

圖片

我們可以指定目標TokenID,或者使用/domainadmin來竊取域管的token,執行成功后可以看到當前線程已經擁有域管的模擬令牌:

圖片

然后我們就可以在當前mimikatz上下文中使用域管身份執行操作了,如DCSync

圖片

該功能大致過程如下:

  1. 通過OpenProcess()獲取當前進程/線程的句柄
  2. 調用OpenProcessToken()打開與進程相關的token句柄
  3. 使用DuplicateTokenEx()使用目標進程token創建一個新的模擬token
  4. 調用SetThreadToken()設置當前線程的token為上一步創建的新的模擬token

由于竊取token是Access Token利用的重點,該過程放在本文后面分析

4. token::run

該功能是使用指定的token來運行程序,也可以使用token::elevate中的幾個參數來指定運行程序的token,除此之外還有一個參數:

  • /process:指定要運行的程序,默認值為whoami.exe

圖片

其原理前三步與token::elevate大致相同,區別在于使用DuplicateTokenEx()竊取token后,該功能使用CreateProcessAsUser()來使用新的primary token創建一個進程

圖片

創建進程后,利用匿名管道做進程間通信,將新創建進程的標準輸出寫入到匿名管道的write端,從管道read端讀取數據進行回顯(在webshell等非交互場景下很有用)

圖片

5. token::revert

該模塊用來清除線程的模擬令牌:

圖片

原理很簡單,直接使用SetThreadToken(NULL, NULL)即可將當前線程的token清除

0x03 令牌竊取

在滲透測試中,竊取token是administrator -> system的常見手法之一,還經常被用于降權等用戶切換操作

1. 原理

竊取token主要涉及以下幾個API:

1.OpenProcess

圖片

該函數打開指定PID的進程的句柄,需要注意的是第一個參數dwDesiredAccess,主要會用到的是以下三個權限

  • PROCESS_ALL_ACCESS
  • PROCESS_QUERY_INFORMATION (0x0400)
  • PROCESS_QUERY_LIMITED_INFORMATION (0x1000)

我在編寫竊取Token的代碼時,發現對部分進程(如smss.exe、csrss.exe等)調用OpenProcess會出現拒絕訪問的情況,查閱網上資料后發現這些進程存在保護,需要使用PROCESS_QUERY_LIMITED_INFORMATION權限打開句柄,詳情請參考這篇文章

2.OpenProcessToken

圖片

該函數打開與進程相關聯的令牌的句柄,其中第二個參數DesiredAccess同樣用來指定令牌的訪問權限,需要以下幾個:

  • TOKEN_DUPLICATE:復制令牌需要的權限
  • TOKEN_QUERY:查詢令牌需要的權限

如果要調用DuplicateTokenEx需要指定TOKEN_DUPLICATE,如果調用ImpersonatedLoggedOnUser則需要指定TOKEN_DUPLICATE和TOKEN_QUERY

3.DuplicateTokenEx

圖片

DuplicateTokenEx用來復制現有的令牌來生成一張新令牌,該函數可以選擇生成主令牌還是模擬令牌

  • hExistingToken:指定現有的令牌句柄,可以使用OpenProcessToken獲得

  • dwDesiredAccess:用來指定令牌訪問權限,需要指定以下幾個來支持后面調用CreateProcessWithToken

    • TOKEN_DUPLICATE:需要復制訪問令牌
  • TOKEN_QUERY:需要查詢訪問令牌
  • TOKEN_ASSIGN_PRIMARY:將令牌附加到主進程的權限
  • TOKEN_ADJUST_DEFAULT:需要更改訪問令牌的默認所有者、主要組或 DACL
  • TOKEN_ADJUST_SESSIONID:需要調整訪問令牌的會話 ID,需要 SE_TCB_NAME 權限

  • lpTokenAttributes:指向SECURITY_ATTRIBUTES結構的指針,該 結構指定新令牌的安全描述符并確定子進程是否可以繼承該令牌

  • ImpersonationLevel:指定令牌的模擬級別,當進行復制令牌時,主令牌被復制為模擬令牌是始終被允許的,而模擬令牌復制為主令牌則需要模擬級別 >= Impersonate

  • TokenType:指定新令牌的類型,是主令牌(Primary Token)還是模擬令牌(Impersonate Token)

  • phNewToken:返回令牌句柄的地址

復制完一張新令牌后,我們就可以利用這張新令牌來運行我們指定的進程了

4.CreateProcessWithTokenW

圖片

該函數創建一個新進程及其主線程,新進程在指定令牌的安全上下文中運行。我們直接指定前面復制出來的新令牌,使用該令牌創建我們指定的進程即可

2. 利用

根據mimikatz的token模塊的原理,簡單實現了一個demo,也有許多token相關的工具如incognito等

當獲取管理員權限后,我們可以列出系統中進程對應的token:

圖片

然后竊取指定進程的token來運行我們的程序,如直接運行上線馬

圖片

如果想要拿回程序輸出的話,則可以通過管道等進程間通信的方法來回顯輸出

圖片

如果拿到一臺機器有域管的進程,那么我們可以直接竊取域管進程的token來進行DCSync攻擊

圖片

0x04 參考鏈接

https://docs.microsoft.com/

https://github.com/gentilkiwi/mimikatz/

https://www.ired.team/offensive-security/privilege-escalation/t1134-access-token-manipulation

https://www.slideshare.net/JustinBui5/understanding-windows-access-token-manipulation

https://posts.specterops.io/understanding-and-defending-against-access-token-theft-finding-alternatives-to-winlogon-exe-80696c8a73b


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1669/