亚洲日本免费-啊轻点灬太粗太长了三男一女-麻豆av电影在线观看-日韩一级片毛片|www.grbbt.com

NtApphelpCacheControl漏洞分析

  起因:

  Google Project Zero團(tuán)隊(duì)的新晉成員James Forshaw在9月30日向微軟提交了名為“Windows: Elevation of Privilege inahcache.sys/NtApphelpCacheControl”的安全問題,并且在Google的漏洞公開期限(90天)后,也就是2014年12月29日(北京時間的12月30日)公開了此問題的細(xì)節(jié)。

  針對這個漏洞的爭論很多,很多觀眾在爭論微軟和Google對待安全漏洞的做法,90天公開策略是否合情合理等等,也有很多技術(shù)人員在爭論這個安全問題是否是嚴(yán)格意義上的權(quán)限提升漏洞。后者的一個主要原因是James Forshaw在演示這個漏洞時,是通過此漏洞來劫持UAC默認(rèn)級別下自動提權(quán)的ComputerDefaults程序,從而實(shí)現(xiàn)在默認(rèn)UAC設(shè)置下靜默從中完整性級別啟動高完整性級別的程序。

  通常來說,微軟安全響應(yīng)中心(MSRC)不認(rèn)為UAC默認(rèn)級別下中完整性級別到高完整性級別的提示繞過屬于安全漏洞的。

  但是,最近MSRC也將一些可以穿透InternetExplorer保護(hù)模式(PM)或增強(qiáng)保護(hù)模式(EPM)沙箱的安全問題(實(shí)際上是從低完整性級別穿透至中完整性級別的問題)作為安全漏洞來修補(bǔ)(例如CVE-2014-6349)。所以我們先擱置是否安全漏洞的這個爭議,深入分析下這個漏洞涉及的原理和問題。

  漏洞分析、成因與利用

  這個漏洞的基本原因,Google的這篇簡單說明里已經(jīng)講得比較準(zhǔn)確了,簡單來說,就是NtApphelpCacheControl這個系統(tǒng)調(diào)用,在調(diào)用者模擬System權(quán)限時,沒有正確識別調(diào)用者的Token,導(dǎo)致其本來僅提供給管理員和系統(tǒng)程序調(diào)用的接口,可以被低權(quán)限程序誤用,并借助該調(diào)用的相關(guān)機(jī)制,劫持高權(quán)限程序,實(shí)現(xiàn)權(quán)限提升。

  看完這個原因后,你可能會有疑問,這個系統(tǒng)調(diào)用是做什么的?什么是Apphelp?Token的判斷具體哪里有問題?Apphelp的哪項(xiàng)機(jī)制如何能被利用、以及是如何劫持高權(quán)限進(jìn)程的?接下來筆者就將深入地介紹這些內(nèi)容,詳細(xì)地解答這些問題。

  1. Apphelp與NtApphelpCacheControl

  在Windows 8.1 系統(tǒng)上,NtApphelpCacheControl這個系統(tǒng)調(diào)用,顧名思義,可以控制系統(tǒng)中Apphelp規(guī)則的快速緩存數(shù)據(jù)。

  Apphelp是微軟從WindowsXP操作系統(tǒng)開始引入的一項(xiàng)兼容性解決方案,官方的名字是”Application Compatibility Database”(應(yīng)用程序兼容性數(shù)據(jù)庫)。這套解決方案的目的是減少操作系統(tǒng)的向下兼容成本,不是在操作系統(tǒng)層面,而是通過這套兼容數(shù)據(jù)庫引擎提供包括Shim(Hook)在內(nèi)的大量控制功能,來做到實(shí)時地識別和修改特定存在兼容性問題的流行軟件程序,使其能夠兼容新的操作系統(tǒng)。

  關(guān)于這套機(jī)制,微軟官方從Windows7開始, 有一些功能性的介紹文檔,也可以通過官方的”Microsoft Application Compatibility Toolkit”(ACT),在Windows7以上的操作系統(tǒng)上方便里查看、修改和添加本地的兼容性數(shù)據(jù)庫。在此之前,Alex ionescu和一些其他的國內(nèi)外研究者也深入地研究過兼容性數(shù)據(jù)庫和Shim機(jī)制。

  微軟操作系統(tǒng)的各個版本積累了針對應(yīng)用程序的大量兼容性修改的方法和基礎(chǔ)數(shù)據(jù),使這些應(yīng)用程序可以流暢地運(yùn)行在新的操作系統(tǒng)中,這為微軟的操作系統(tǒng)在世界范圍內(nèi)的復(fù)雜環(huán)境中廣泛運(yùn)行和推廣起到了重要的作用。在Windows Vista發(fā)布后,它帶來的海量革新的同時,也導(dǎo)致大量應(yīng)用程序出現(xiàn)兼容性問題,成為該系統(tǒng)被人詬病的原因之一。為此,在其后的Windows7操作系統(tǒng)開發(fā)過程中,微軟加大了對應(yīng)用程序兼容性修復(fù)方面的重視和投入,不僅更廣泛地收集和編制應(yīng)用程序兼容性修復(fù)規(guī)則,也對這套兼容性機(jī)制做了升級換代。

  本次出現(xiàn)問題的NtApphelpCacheControl也是支持這套機(jī)制的一個新的接口。這已經(jīng)不是該函數(shù)第一次出現(xiàn)安全漏洞, 在j00ru Syscan2013上的關(guān)于Bochspwn的議題上,就公開了一個涉及NtApphelpCacheControl處理緩存代碼中存在的競爭條件漏洞(CVE-2013-1278)。閱讀下面的內(nèi)容的同時,建議讀者能看一看這個slides中NtApphelpCacheControl相關(guān)的內(nèi)容(75~94頁。

  為什么Apphelp需要這個接口呢?這還需要從XP系統(tǒng)說起,應(yīng)用程序兼容性的主數(shù)據(jù)庫實(shí)際存儲是在Windows安裝目錄下的AppPatchsysmain.sdb文件中的,但是每次進(jìn)程啟動、模塊加載時都去檢查這個數(shù)據(jù)文件顯然開銷太大。為了能快速處理針對這些可執(zhí)行程序的兼容性規(guī)則,就需要在內(nèi)存中緩存這個數(shù)據(jù)庫的機(jī)制。在Windows XP時代, Apphelp使用一塊名為ShimSharedMemory的全局共享Section來在不同進(jìn)程之間共享識別、修改可執(zhí)行程序的兼容性數(shù)據(jù)內(nèi)存。

  從Windows 2003開始,NtApphelpCacheControl函數(shù)被引入系統(tǒng)調(diào)用中,作為apphelp的內(nèi)核入口,在內(nèi)核中提供了整套新的應(yīng)用程序兼容性數(shù)據(jù)庫檢索、緩存的功能,使得應(yīng)用程序可以跨Session、跨隔離,并且快速查詢、應(yīng)用兼容性數(shù)據(jù)庫中的規(guī)則和處理方案,其緩存功能也實(shí)現(xiàn)了在盡量減少性能消耗的同時,快速地針對系統(tǒng)內(nèi)已知的存在兼容問題的程序進(jìn)行更快速地修復(fù)。

  在Windows2003,Windows Vista,Windows7和Windows8操作系統(tǒng)上,NtApphelpCacheControl是實(shí)現(xiàn)在系統(tǒng)內(nèi)核ntoskrnl內(nèi)部的,從Windows8.1操作系統(tǒng)開始,為了能夠減少升級成本,內(nèi)核將該系統(tǒng)調(diào)用的絕大部分最終實(shí)現(xiàn)在了一個新的內(nèi)核模式驅(qū)動程序ahcache.sys內(nèi)部,系統(tǒng)內(nèi)核通過發(fā)送設(shè)備控制命令給該驅(qū)動來實(shí)現(xiàn)該接口的絕大部分功能,在Windows10技術(shù)預(yù)覽版上,我們看到這個驅(qū)動又進(jìn)行了一次比較大的更新。

  NtApphelpCacheControl的原型為:

  NTSTATUS NtApphelpCacheControl(APPHELPCOMMAND Command , PVOID CommandData);

  這個Command提供了針對應(yīng)用程序兼容性數(shù)據(jù)庫緩存的查看、添加、刪除等等一系列功能。其中Command的枚舉功能和CommandData的數(shù)據(jù)結(jié)構(gòu),J00ru的議題和James的源碼中都提供了一些,但都不全面也有不少錯誤,通過IDA查看實(shí)現(xiàn)代碼很容易就可以看清楚,這里我將這些功能的Command id、對應(yīng)的控制碼(適用于 Windows8.1)和對應(yīng)實(shí)現(xiàn)的功能整理匯總后列出:

  enum APPHELPCOMMAND

  {

  AppHelpCahceLookup, // IoControlCode: 0x220003*

  AppHelpCahceRemove, // IoControlCode: 0x220007*

  AppHelpCahceUpdate, // IoControlCode: 0x22000B*

  AppHelpCacheFlush // IoControlCode: 0x22000F*

  AppHelpCacheDump, // IoControlCode: 0x220013

  AppHelpCacheNotifyStart , // IoControlCode: 0x220017

  AppHelpCacheNotifyStop, // IoControlCode: 0x22001B

  AppHelpCahceForward, // IoControlCode: 0x22001F

  AppHelpCacheQuery, // IoControlCode: 0x220023

  AppHelpQueryModule, // IoControlCode: 0x220027

  AppHelpRefresh, // IoControlCode: 0x22002B

  AppHelpCheckForChange, // IoControlCode: 0x22002F

  AppHelpQueryHwId,

  };

  James在源碼中定義了相關(guān)結(jié)構(gòu),不過看上去對這個結(jié)構(gòu)的了解也不是很深入。*:James的POC源碼中,對這四個控制碼少了一個0

  AppHelpCacheLookup:在Apphelp cache中尋找匹配的、需要處理的記錄。

  AppHelpCacheRemove: 刪除匹配的Apphelp Cache記錄

  AppHelpCahceUpdate:插入記錄到Apphelp Cache

  AppHelpCacheFlush:Flush AppHelp cache,將AppHelpCache的緩存數(shù)據(jù)清空(根據(jù)Flush的標(biāo)志不同,不一定真的刪除內(nèi)存中的數(shù)據(jù),只是去掉某些標(biāo)記),并刷新到磁盤(注冊表)上。

  James源碼中認(rèn)為這個命令是沒用處的AppHelpEnum。這是錯誤的 ,apphelp!ShimFlushAppcompatCache->kernelbase!BaseFlushAppcompatCache->kernel32!BaseFlushAppcompatCacheWorker 還在使用這個來清空shim的兼容數(shù)據(jù)數(shù)據(jù)。他應(yīng)該是將AppHelCacheFlush看漏了,源碼里對于NotifyStartEnum等后面的幾個都差了一個數(shù)。

  AppHelpCacheDump:這才是一個“沒用”的功能, AppHelp會枚舉緩存中的數(shù)據(jù),針對枚舉的項(xiàng)目并不做操作。筆者猜測這個命令之所以叫“Dump”,可能是一個調(diào)試功能。于是筆者從WDK中找了個checked build的內(nèi)核來看了下。果然在checked build內(nèi)核中,會枚舉緩存中的元素,并逐個打印出記錄要去匹配的文件名記錄。在Free build中,對應(yīng)的代碼被去掉了,所以成了一個看似無用的命令,實(shí)際在checked build,微軟的開發(fā)人員可能是有對應(yīng)的工具去通過這個接口方便地觀察緩存中都有那些記錄。

  AppHelpCacheNotifyStart/AppHelpCacheNotifyStop:這兩個命令主要用于同AppHelp的服務(wù)通訊,AppHelp內(nèi)核會通過AhcPort這個ALPC Port同Application Experience服務(wù)通訊。這兩個命令用于重連/停止 同服務(wù)的LPC通訊。

  AppHelpCacheForward: 用于將緩存可執(zhí)行程序的信息排隊(duì),然后轉(zhuǎn)發(fā)給Application Experience服務(wù)處理

  AppHelpCacheQuery: 用于獲取Shim Cache中的數(shù)據(jù)內(nèi)容、ShimCache的相關(guān)統(tǒng)計(jì)和隊(duì)列。

  AppHelpQueryModule/AppHelpCacheRefresh/AppHelpCheckForChange/AppHelpQueryHwId:這些是Windows8.1新增的命令,和這里就不詳細(xì)介紹了。

  下面介紹這個調(diào)用中重要的數(shù)據(jù)CommandBuffer的結(jié)構(gòu),這個結(jié)構(gòu)的數(shù)據(jù)驅(qū)動了Lookup/Remove/Update/Forward等大部分基本命令。

  這個CommandBuffer的結(jié)構(gòu)(我這里稱為APPHELP_COMMANDDATA),是由三個結(jié)構(gòu)體組成的:

  其中第一個結(jié)構(gòu)體用于存儲整個shim緩存和統(tǒng)計(jì)內(nèi)容,被AppHelpCacheQuery命令使用;

  第二個結(jié)構(gòu)體用于在AppHelpCacheLookup/AppHelpCacheRemove/AppHelpCacheUpdate這三個命令時來告訴接口檢索、刪除和添加的項(xiàng)目內(nèi)容;

  第三部分則用于AppHelpCacheForward命令,提供forward,用于提供轉(zhuǎn)發(fā)給服務(wù)的相關(guān)數(shù)據(jù)。

  無論是哪個命令,CommandBuffer都同時包含著三個結(jié)構(gòu)體,這也是為什么J00ru的議題和James的源碼里都提到提交的緩存結(jié)構(gòu)前面有大量無用的0數(shù)據(jù)的原因。

  下面給出這個結(jié)構(gòu)的定義:

  typedef struct APPHELP_COMMANDDATA{

  APPHELP_CACHE_QUERY QueryData; //Query full data

  APPHELP_CACHE_ENTRY EntryData ; //Lookup/Remove/Update entry

  APPHELP_CACHE_FORWARD ForwardData; //Data for forward

  } APPHELP_COMMANDDATA, *PAPPHELP_COMMANDDATA;

  其中APPHELP_CACHE_QUERY/APPHELP_CACHE_FORWARD的結(jié)構(gòu)和本次漏洞無關(guān),就留給感興趣的讀者去研究了。

  需要注意的是,QueryData的數(shù)據(jù)長度會影響后面的EntryData(這個長度在Win7Win8上不相同),Win7上是0×90,Win8.1上James已經(jīng)提供了是0×98(這也是為什么Win7上這個POC無法工作的原因之一)。這點(diǎn)看一看ApphelpCacheControlValidateParameters或AhcValidateAndGetParameters就可以了解了。

  這里提供一下APPHELP_CACHE_ENTRY的數(shù)據(jù)結(jié)構(gòu):

  typedef struct APPHELP_CACHE_ENTRY{

  DWORD Flags ;

  ULONG CacheReturnFlags ;

  HANDLE FileHandle;

  HANDLE ProcessHandle ;

  //Only in Win8/Win8.1UNICODE_STRING FileName;

  UNICODE_STRING PackageFullName;

  //only in Win8/Win8.1DWORD DataBufferSize;

  PVOID DataBuffer;

  } APPHELP_CACHE_ENTRY, *PAPPHELP_CACHE_ENTRY;

  FileHandle/FileName是對應(yīng)要進(jìn)行處理的可執(zhí)行程序(包括模塊)的對應(yīng)句柄和文件名,之所以要提供文件句柄,是因?yàn)閮?nèi)核使用一個AVL Table來存儲Entry數(shù)據(jù),使用文件句柄的FileTime來做其中平衡樹的索引。其中 Flags/CacheReturnFlags分別指明了這條Cache的功能和作用,尤其是對于DataBufferSize/DataBuffer是否有效的控制,是否在關(guān)機(jī)時保存到注冊表中等。

  DataBufferSize和DataBuffer描述了Entry相關(guān)的規(guī)則數(shù)據(jù)的內(nèi)容。

  ProcessHandle和PackageFullName僅在Windows8及以后的操作系統(tǒng)上使用。

  DataBuffer可以保存由RING3存儲的數(shù)據(jù)結(jié)構(gòu),一般來說由APPHELP_CACHEUPDATE更新到內(nèi)核緩存中,APPHELP_CACHELOOKUP獲取后使用,Shim引擎使用的數(shù)據(jù)結(jié)構(gòu),我稱為APPHELP_LOOKUP_RESULT(即James源碼中的APPHELP_QUERY結(jié)構(gòu)),如下:

  #define MAX_EXE_TAGS 16

  #define MAX_LAYER_TAGS 8

  typedef struct APPHELP_LOOKUP_RESULT

  {

  DWORD ExeTags[MAX_EXE_TAGS];

  DWORD ExeFlags[MAX_EXE_TAGS];

  DWORD LayerTags[MAX_LAYER_TAGS];

  DWORD LayerFlags;

  DWORD AppHelpTag;

  DWORD ExeTagsCount ;

  DWORD LayerTagsCount;

  GUID ExeGuid;

  DWORD Flags2;

  DWORD Unknown;

  DWORD Unknown2;

  GUID Guid2[16];

  };

  如James源碼中所使用的, 其中ExeTags指明了在sdb數(shù)據(jù)中的修復(fù)方案的tag id,ExeTagsCount是tag的數(shù)量,最多16個, LayerTags是Layer規(guī)則的數(shù)據(jù)。

  通過這些命令和數(shù)據(jù)結(jié)構(gòu),我們大概了解了NtAppHelpCacheControl提供的能力,那么RING3是如何使用它的呢?

  簡單地說,Ring3的Module Loader等模塊在模塊加載、進(jìn)程啟動等事件觸發(fā)時,會調(diào)用apphelp.dll中的相關(guān)接口, apphelp.dll再調(diào)用kernel32/kernelbase內(nèi)BasepShim*相關(guān)的API,通過NtAppHelpCacheControl中的CacheLookup功能查詢模塊的可執(zhí)行文件是否在緩存的數(shù)據(jù)中,如果存在就按照規(guī)則數(shù)據(jù)庫中對應(yīng)的規(guī)則處理,相關(guān)的數(shù)據(jù)通過CacheForward發(fā)送到服務(wù)進(jìn)程后,會調(diào)用CacheUpdate功能緩存被使用的數(shù)據(jù),加快二次查詢的速度。

  Token相關(guān)的問題

  了解了AppHelpCache的接口和基本工作原理后,我們很容易可以明白,如果可以低權(quán)限的程序可以調(diào)用AppHelpCacheUpdate命令添加緩存,那么可以劫持任意高權(quán)限程序,利用shim規(guī)則對其進(jìn)行修改,實(shí)現(xiàn)權(quán)限提升。

  那么我們回來看看這個漏洞的成因,如James在說明里提到的,這個漏洞的原因是因?yàn)橛糜隍?yàn)證AppHelpCacheUpdate是否運(yùn)行被調(diào)用的AhcVerifyAdminContext函數(shù),驗(yàn)證Token存在問題,這個函數(shù)很簡單,我們使用Hex-rays decomplier得到偽代碼:

  NTSTATUS AhcVerifyAdminContext()

  {

  retstatus = STATUS_ACCESS_DENIED;

  CurrentThread = KeGetCurrentThread();

  CurrentProcess = PsGetCurrentProcess();

  TokenType = 0;

  TokenObj = PsReferenceImpersonationToken(CurrentThread, &CopyOnOpen, &EffectiveOnly, &ImpersonationLevel);

  if ( TokenObj || (TokenObj = PsReferencePrimaryToken(CurrentProcess), TokenType = 1, TokenObj) )

  {

  if ( SeQueryInformationToken(TokenObj, 1, &TokenUserInformation) >= 0 )

  {

  if ( RtlEqualSid(_SeExports->SeLocalSystemSid, TokenUserInformation->User.Sid) || SeTokenIsAdmin(TokenObj) )

  {

  retstatus = STATUS_SUCCESS;

  }

  ExFreePoolWithTag(TokenUserInformation, 0);

  }

  else

  {

  AhcTracePrintf(0, "AhcVerifyAdminContext", 937, "Failed to query token information.
", v5);

  }

  if ( TokenObj )

  {

  if ( TokenType == 1 )

  {

  PsDereferencePrimaryToken(TokenObj);

  }

  else

  {

  PsDereferenceImpersonationToken(TokenObj);

  }

  }

  }

  else

  {

  AhcTracePrintf(0, "AhcVerifyAdminContext", 929, "Failed to get effective token", v5);

  }

  return retstatus;

  }

  函數(shù)的功能很簡單,首先試圖獲取線程模擬的token,如果線程的模擬token不存在,就獲取當(dāng)前進(jìn)程的主token對象,獲取token對象后, 通過SeQueryInformationToken(TokenUser)獲得Token的用戶信息。

  接著,對比如果下面token對象符合下面兩種情況的任一種,就返回STATUS_SUCCESS允許AppHelpCacheUpdate操作,否則就返回STATUS_ACCESS_DEIND拒絕操作:

  1.Token的用戶SID匹配LocalSystem的SID??2.Token通過SeTokenIsAdmin的驗(yàn)證,也就是token用戶組內(nèi)有啟用的Adminsitrator組。

  那么這個對比就是James所說的驗(yàn)證Token有問題的部分,有問題的原因就如James所說, 是因?yàn)闆]有去判斷ImpersonationLevel。

  這是因?yàn)楸荒M的Token的SID并不能決定Token就真的擁有對應(yīng)SID的權(quán)利,可以參考微軟關(guān)于SECURITY_IMPERSONATION_LEVEL的MSDN解釋。

  低于SecurityImpersonation的模擬token其實(shí)并不是以被模擬的Client的安全上下文運(yùn)行的,所以僅僅通過SID來判斷調(diào)用者是否具備LocalSystem的權(quán)限是不夠,類似的問題其實(shí)是Windows的內(nèi)核、內(nèi)核模式驅(qū)動程序中還有不少地方存在,感興趣的讀者可以再進(jìn)行一些挖掘。

  以James源碼的方法為例,通過Bits服務(wù)的BackgroundCopyManager接口創(chuàng)建一個下載任務(wù)后,代碼將自己的Notify對象設(shè)置為任務(wù)的通知接口。

  此時服務(wù)在下載通知時會調(diào)用對應(yīng)的對象,接著combase通過LPC回調(diào)試圖調(diào)用對象的接口函數(shù),而在調(diào)用前,就會使用RpcImpersonateClient->NtAlpcImpersonateClientOfPort,由AlpcpImpersonateMessage來為執(zhí)行回調(diào)接口準(zhǔn)備Alpc port指定的安全上下文。

  由于Bits的OLE Port指定的允許的SecurityQos->ImpersonationLevel級別的模擬,模擬完成后調(diào)用到James的處理代碼,他的代碼打開并保存了線程的token句柄,由此獲得了一個SecurityIdentification級別的Token句柄 ,Token是來自Bits服務(wù)的安全上下文,因此Token的SID自然也就是NT AUTHORITYSYSTEM(LocalSystem)

  這里Bits服務(wù)本身是沒有安全問題的,因?yàn)锳LPC獲得和模擬的token只是SecurityIdentification級別,即使模擬這個token(就如James的代碼后面所做的),也無法以System權(quán)限上下文工作,在訪問對象ACL時,會被拒絕訪問(可以參考SeAccessCheck中的實(shí)現(xiàn)和判斷),也不會被識別為admin/system(可以參考SeTokenIsAdmin在Windows7以上操作系統(tǒng)的實(shí)現(xiàn)),但是NtAppHelpCacheControl這里只判斷Token SID的方式,就導(dǎo)致了安全檢查被繞過,也是這個漏洞的根本原因。

  漏洞的利用

  James提供的POC針對這個漏洞利用的方法是劫持一個UAC默認(rèn)級別下會不區(qū)分命令行,無提示自動提權(quán)的程序ComputerDefaults.exe,找到regsv32修復(fù)的的sdb tag(通過替換模塊鏡像為regsvr32來進(jìn)行兼容修復(fù)),并將其設(shè)置到apphelp緩存中,這樣,在啟動ComputerDefaults.exe的時候,實(shí)際啟動的可執(zhí)行程序的鏡像就被Apphelp替換成了regsvr32.exe ,而啟動的時候命令行上加上想要注入高權(quán)限進(jìn)程的dll文件,就會使得regsvr32.exe在高完整性級別上加載我們想要加載的DLL,James的DLL代碼里實(shí)現(xiàn)的是啟動一個計(jì)算器程序。

  這個利用方法引來了一些爭議,很多人認(rèn)為這樣只證明可以繞過UAC默認(rèn)級別下中完整性級別到高完整性級別的彈框,通常來說不能說是安全漏洞,而且實(shí)際之前也有很多公開的技巧可以繞過UAC提示。

  但就如James自己說的,UAC的繞過僅僅只是個方便的演示方式,想一想測一測就能發(fā)現(xiàn),這個漏洞還有更多的利用方式。

  以IE11 的沙箱(PM)為例,這個漏洞需要的相關(guān)功能(包括BITS Token的獲取、NtAppHelpCacheControl的調(diào)用、sdb Tag的獲取等等)都是可以在IE11沙箱的低完整性級別下執(zhí)行的,那么惡意代碼一旦進(jìn)入沙箱,就可以利用這個漏洞劫持一個常用的中完整性級別程序(甚至系統(tǒng)中經(jīng)常被啟動的高完整性、系統(tǒng)完整性級別程序),就可能通過這個漏洞穿透沙箱,在沙箱外執(zhí)行惡意代碼。使用icacls.exe /setintegritylevel 給測試程序設(shè)置Low完整性級別后,可以很容易證實(shí)這點(diǎn)。

  即使是在通過Users用戶組的賬戶登錄的情況下,如果同時或之后有管理員賬戶登錄,由于這個AppHelp Cache是全局跨Session的,因此管理員運(yùn)行的程序也會可能受到劫持的影響,發(fā)生權(quán)限提升。

  這些都是通過James的測試程序就能完成的攻擊,但是這個攻擊的一個缺點(diǎn)是必須要有高權(quán)限的程序去啟動, 那么還有更好的利用方式么?

  肯定是有的,大家看到剛才我們介紹的AppHelpCacheFlush功能了吧,這個接口的調(diào)用者驗(yàn)證也存在和 AppHelpCacheUpdate同樣的問題,那么通過這個接口就可以直接將內(nèi)存中已經(jīng)添加的AppHelpCache刷入注冊表中(HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession ManagerAppCompatCache下AppCompatCache),這樣下次開機(jī)時就會加載并應(yīng)用添加的規(guī)則,這樣重新啟動后就可以更方便的劫持想要劫持的程序。

  同時,通過調(diào)用低完整性級別/低權(quán)限賬戶或AppContainer完整性級別下允許調(diào)用的某些服務(wù)LPC/COM接口,也可以使其啟動特定的高權(quán)限程序,并可能進(jìn)行劫持。

  這些技術(shù)含量不高,已經(jīng)提供了這么多Tips,再具體的方式就需要大家發(fā)揮想象力了,最后再提點(diǎn)細(xì)節(jié):AppHelp規(guī)則不僅能應(yīng)用于EXE進(jìn)程創(chuàng)建,也可以應(yīng)用在指定的任意模塊加載時。

  Windows7的問題

  James在說明里提到了Windows7的問題,在Windows7上, AppHelpCacheUpdate這條指令專門被一個特別的ApphelpCacheVerifyContext檢查所保護(hù)(對于其他被保護(hù)接口使用的是ApphelpCacheVerifyAdminContext,和Windows8/8.1一樣存在這個安全漏洞),這個檢查更嚴(yán)格,僅在主TOKEN具備TCB特權(quán)時才可以通過,代碼如下:

  NTSTATUS ApphelpCacheVerifyContext()

  {

  status = STATUS_SUCCESS;

  if ( PsGetCurrentThreadPreviousMode() && SeSinglePrivilegeCheck(SeTcbPrivilege, UserMode) == FALSE)

  status = STATUS_ACCESS_DENIED;

  return status;

  }

  看上去這個檢查函數(shù)是無法繞過了,James同時提到,這個檢查是在CommandBuffer中的某些Flags匹配時,才會進(jìn)行,也許可以繞過,那么實(shí)際如何呢?

  我們逆向NtAppHelpCacheControl在Win7上的相關(guān)實(shí)現(xiàn)可以得知,在CommandBuffer->Flags的Bit 2,3為1時,是不進(jìn)行這個檢查的,這樣的Entry是可以通過AppHelpCacheUpdate的檢查,加入緩存中的。

  但是,我們再來看AppHelpCacheLookup的相關(guān)實(shí)現(xiàn)就不難發(fā)現(xiàn), 僅當(dāng)entry->Flags的bit 0為1時,Lookup才為調(diào)用者返回CommandBuffer->DataBuffer和DataBufferSize,而就像在第一節(jié)里提到的,這兩個域描述了APPHELP_LOOKUP_RESULT數(shù)據(jù)結(jié)構(gòu),沒有這個數(shù)據(jù)我們無法指定要應(yīng)用的規(guī)則。

  所以至少通過目前的分析來看,通過修改Flags的方法,是無法將達(dá)成我們的劫持?jǐn)?shù)據(jù)加入緩存并生效的目的的,暫時可以認(rèn)為這個漏洞難以在Windows7上實(shí)現(xiàn)利用。

 

上一篇:智能無懼挑戰(zhàn) 山石網(wǎng)科轟動RSA2015

下一篇:中國頂級黑客的生意 在商業(yè)利益與社會責(zé)任間兩難抉擇