作者:
騰訊電腦管家
·
2015/03/05 15:54
0x00 前言
Win8開始,Windows引入了新的程式隔離機制AppContainer,MetroAPP以及開啟EPM的IE Tab程式都執行在AppContainer隔離環境,在最新的Win10Pre(9926)上,仍然如此。騰訊反病毒實驗室對AppContainer的工作機制做一深入解讀。
0x01 AppContainer帶來的變化
Vista以前的系統,如XP,用安全描述符(簡稱SD,下同)裡的DACL(discretionary access control list)來控制使用者和使用者組的訪問許可權。
Vista以後,增加了Integrity Mechanism,在SD的SACL(system access control list)裡增加一個mandatory label的ACE,擴充套件了Windows安全體系。預設的控制策略是No-Write-Up,允許較低完整性級別的程式讀訪問較高完整性級別的物件;禁止較低完整性級別的程式寫訪問較高完整性級別的物件。
Win8引入了AppContainer隔離機制,提供了更細粒度的許可權控制,能夠阻止對未授權物件的讀寫訪問。
以Win10PreX64(9926)開啟EPM的IE Tab程式為例,看看有哪些變化。
從Process Explorer裡可以看到,IE Tab程式的完整性級別不再是Low,而是變成了AppContainer:
圖1
在程式屬性的Security標籤可以看到,增加了標誌為AppContainer以及Capability的SID:
圖2
一個AppContainer程式可以訪問的物件,在SD的DACL裡增加了額外的ACE。以IE Tab程式的程式物件為例:
圖3
0x02 如何使用AppContainer隔離機制
這裡我們不討論MetroAPP,主要看看DesktopAPP如何使用AppContainer隔離機制。
仍然以Win10PreX64(9926)開啟EPM的IE Tab程式為例:在IE選項裡開啟EPM,下斷點nt!NtCreateLowBoxToken,然後新建IE Tab,命中斷點,擷取最上面的幾層呼叫棧:
圖4
可見,透過CreateProcess這個API就可以建立出AppContainer程式。
看看CreateAppContainerProcessStrW的邏輯片段,把PackageSID String(圖2裡標記為AppContainer的SID)和CapabilitySID(圖2裡標記為Capability的SID) string轉為SID後,傳給了CreateAppContainerProcessW:
圖5
看看CreateAppContainerProcessW的邏輯片段,把傳入的CapabilitySIDs和PackageSID加入到ProcThreadAttributes,然後透過STARTUPINFOEX結構把ProcThreadAttributes傳給了CreateProcessW。
圖6
圖7
圖8
搞清楚IE Tab程式的建立邏輯,我們就可以建立自己的AppContainer程式了。
直接複用IE的PackageSID和CapabilitySIDs來建立AppContainer程式。如果需要定義自己的PackageSID,可以參考MSDN上的CreateAppContainerProfile等API,這裡就不討論了。
成功的建立出了具有AppContainer隔離機制的記事本程式。32位和64位程式都可以。可以自由組合Capability,這裡我選擇了IE Tab 6個Capability裡的3個。
如果程式在設計時沒有考慮使用AppContainer隔離機制,依賴沒有授權給AppContainer的系統資源,比如系統根目錄,使用者根目錄等,使用AppContainer隔離機制啟動程式會失敗。
0x03 AppContainer的訪問許可權控制
為描述方便,AppContainer程式的AccessToken我們簡稱為LowBoxToken(下同)。
下面是一個LowBoxToken的部分資訊,可以看到TokenFlags的掩碼位0x4000是置位的,這表示該Token是一個LowBoxToken。我們還可以看到PackageSid、Capabilities等資訊(圖2裡標誌為AppContainer和Capability的SID)。
圖11
0x04 DACL
DACL的遍歷是在SepNormalAccessCheck/SepMaximumAccessCheck裡進行的。這裡我們以SepNormalAccessCheck為例,來看一看如何處理AppContianer相關的ACE。
一般來說,在遍歷DACL時,如果滿足以下3個條件中的任意一個,檢查停止。
有一個access-denied ACE明確拒絕了請求訪問許可權中的任意一個;
有一個或者多個access-allowed ACEs明確給予了所有的請求訪問許可權;
已經檢查完了所有的ACE,但是仍然至少有一個請求訪問許可權沒有被明確給予,這種情況下,訪問被拒絕。
從Windows Server 2003開始,DACL裡ACE的順序為:
Explicit ACE:Access Denied
Explicit ACE:Access Allowed
Inherited ACE:Access Denied
Inherited ACE:Access Allowed
這個遍歷規則和順序保證了明確拒絕優先於明確允許;明確指定的訪問控制優先於繼承的訪問控制。
以下的內容基於Win10PreX86( 9926)。
0x05 ACCESS_ALLOWED_ACE_TYPE
在遍歷型別為ACCESS_ALLOWED_ACE_TYPE的ACE時,如果ACE的SID字首為SePackagePrefixSid(S-1-15-2)或者SeCapabilityPrefixSid(S-1-15-3),則跳轉到處理AppContainer訪問許可權控制的邏輯:
圖12
如果ACE的SID字首為SePackagePrefixSid(S-1-15-2),會先看這個SID是否為ALL APPLICATION PACKAGES,這是一個Well known SID
圖13
如果是這個SID,認為匹配成功,不需要再精確比較SID了;否則和Token的PackageSID做精確匹配:
圖14
如果ACE的SID字首為SeCapabilityPrefixSid(S-1-15-3),會嘗試匹配Token的Capabilities:
圖15
PackageSID或者Capabilities匹配成功後,會透過a13記錄獲取到的許可權以及還剩下未獲取到的許可權。a13是上層呼叫傳進來的結構指標,上一層函式會根據這個結構的值,判斷AppContainer程式是否獲取到了請求的訪問許可權。
看看上一層函式SepAccessCheck的邏輯片段,var_AccessLowbox就是圖14/15裡的a13。如果PackageSID或者CapabilitieSID給予的許可權不能完全覆蓋使用者請求的許可權(var_Remaining != 0),則訪問失敗:
圖16
另外,對於No DACL的情況,也有額外的處理邏輯。AppContainer程式訪問No DACL的物件時,是無法獲得訪問許可權的:
圖17
所以在Win8及以上系統中,我們如果想要建立一個所有程式(包括開啟EPM的IE Tab )都能訪問的物件,對於該物件的SD,除了在SACL裡指定為低完整性級別外,還要考慮在DACL中顯示的給予everyone以及ALL APPLICATIONS PACKAGE對應的訪問許可權控制。
0x06 ACCESS_DENIED_ACE_TYPE
在遍歷型別為ACCESS_DENIED_ACE_TYPE的ACE時,處理邏輯裡並沒有區分ACE的SID是否為PackageSID或者CapabilitiesSID。而是簡單使用SepSidInTokenSidHash函式在Token的SidHash/RestrictedSidHash裡匹配。如果是PackageSID或者CapabilitiesSID,匹配會失敗,因此該ACE描述的拒絕訪問許可權控制不會生效:
圖18
做一個實驗驗證上面的結論,首先我們用AppContainer隔離機制啟動一個記事本,複用IE EPM的PackageSID以及部分Capabilities:
圖19
把C:\Users{當前使用者}\AppData\Local\Packages\windows_ie_ac_001\AC\Temp\test\1.txt設定為下面的許可權控制:
圖20
圖21
ACE[0]Mask為0x001F01FF,包含要請求的許可權0x00100080 雖然ACE[0]明確的拒絕了 S-1-15-2-1430448594-2639229838-973813799-439329657-1197984847-4069167804-1277922394 (圖19裡標誌為AppContainer的SID),記事本仍然能成功開啟1.txt(ACE1明確給予了ALL APPLICATION PACKAGES 0x001F01FF的訪問許可權)。
0x07 結束語
AppContainer提供了更細粒度的隔離機制,不僅能用於MetroAPP和 IE EPM,當應用程式需要訪問未知第三方內容時,也可以考慮使用AppContainer隔離機制,把對系統的潛在影響降到最低。
本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!