Very High
SolarWinds Orion Platform Unauthenticated RCE (CVE-2021-25274)
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Add References:
SolarWinds Orion Platform Unauthenticated RCE (CVE-2021-25274)
MITRE ATT&CK
Collection
Command and Control
Credential Access
Defense Evasion
Discovery
Execution
Exfiltration
Impact
Initial Access
Lateral Movement
Persistence
Privilege Escalation
Topic Tags
Description
The Collector Service in SolarWinds Orion Platform before 2020.2.4 uses MSMQ (Microsoft Message Queue) and doesn’t set permissions on its private queues. As a result, remote unauthenticated clients can send messages to TCP port 1801 that the Collector Service will process. Additionally, upon processing of such messages, the service deserializes them in insecure manner, allowing remote arbitrary code execution as LocalSystem.
Add Assessment
Ratings
-
Attacker ValueVery High
-
ExploitabilityHigh
Technical Analysis
Please see the Rapid7 analysis.
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportCVSS V3 Severity and Metrics
General Information
Vendors
- solarwinds
Products
- orion platform
References
Additional Info
Technical Analysis
Description
On February 3, 2021, Trustwave security researcher Martin Rakhmanov published a blog post detailing vulnerabilities they discovered in the SolarWinds Orion Platform and Serv-U FTP Server products. These vulnerabilities are tracked as CVE-2021-25274, CVE-2021-25275, and CVE-2021-25276.
Of particular significance is CVE-2021-25274, an unauthenticated remote code execution (RCE) vulnerability in SolarWinds Orion Platform versions prior to 2020.2.4. The vulnerability stems from unauthenticated Microsoft Message Queuing (MSMQ) queues exposed on TCP port 1801. Data sent to these queues is deserialized by the SolarWinds Collector, leading to RCE as the LocalSystem account. Trustwave stated that they intend to release a proof-of-concept (PoC) on February 9, 2021.
SolarWinds has released Orion Platform 2020.2.4 to patch CVE-2021-25274. Rapid7 urges SolarWinds customers to update immediately, as CVE-2021-25274 is considered an impending threat due to ease of exploitation.
Affected products
- SolarWinds Orion Platform versions prior to 2020.2.4
Rapid7 analysis
The following code snippets are from patched version 2020.2.4. According to Rakhmanov:
After the patch is applied, there is a digital signature validation step performed on arrived messages so that messages having no signature or not signed with a per-installation certificate are not further processed.
This behavior can be seen in the decompiled .NET code.
Exhibit A: SolarWinds.Collector.Queue.MsmqQueueController
The MsmqQueueController
class controls MSMQ queues with prefix .\\Private$\\SolarWinds/Collector/ProcessingQueue/
. Its OpenQueue()
method sets CompressedMessageFormatter
as the formatter for serialization and deserialization operations.
[snip] private MessageQueue OpenQueue() { if (queue != null) { return queue; } lock (SyncRoot) { if (queue != null) { return queue; } if (!MessageQueue.Exists(QueueName)) { log.DebugFormat("Creating MSMQ [{0}]", QueueName); MessageQueue val = MessageQueue.Create(QueueName); try { ConfigureUsers(val); } finally { ((IDisposable)val)?.Dispose(); } } log.DebugFormat("Opening MSMQ [{0}]", QueueName); MessageQueue val2 = null; try { bool messageSigningEnabled = CollectorSettings.Instance.MessageSigningEnabled; val2 = new MessageQueue(QueueName); val2.set_Formatter((IMessageFormatter)(object)new CompressedMessageFormatter((IMessageFormatter)new BinaryMessageFormatter(), messageSigningEnabled ? new DataSignature() : null)); val2.get_MessageReadPropertyFilter().set_ArrivedTime(true); if (messageSigningEnabled) { val2.get_MessageReadPropertyFilter().set_Extension(true); } if (val2.get_MaximumQueueSize() != maximumQueueSize) { val2.set_MaximumQueueSize(maximumQueueSize); } queue = val2; } catch (Exception exception) { log.Error("Failed to initialize queue " + QueueName, exception); if (val2 != null) { ((Component)val2).Dispose(); } throw; } return val2; } } [snip]
CompressedMessageFormatter
itself uses BinaryMessageFormatter
as its formatter. Message signing is optionally enabled in the patched version.
Exhibit B: SolarWinds.Collector.Queue.CompressedMessageFormatter
CompressedMessageFormatter.Read()
calls baseFormatter.Read()
, where baseFormatter
is an instance of BinaryMessageFormatter
.
[snip] public object Read(Message message) { if (message == null) { throw new ArgumentNullException("message"); } if (dataSignature != null) { message.get_BodyStream().Position = 0L; if (!dataSignature.VerifyData(message.get_BodyStream(), message.get_Extension())) { throw new VerificationException("Invalid data signature"); } } byte[] array = new byte[compressHeader.Length]; message.get_BodyStream().Position = 0L; message.get_BodyStream().Read(array, 0, array.Length); if (compressHeader.SequenceEqual(array)) { message.get_BodyStream().Seek(array.LongLength, SeekOrigin.Begin); DeflateStream val = new DeflateStream(message.get_BodyStream(), (CompressionMode)0); try { Message val2 = new Message(); val2.set_BodyType(message.get_BodyType()); ((Stream)(object)val).CopyTo(val2.get_BodyStream()); message.set_BodyStream(val2.get_BodyStream()); } finally { ((IDisposable)val)?.Dispose(); } } message.get_BodyStream().Position = 0L; return baseFormatter.Read(message); } [snip]
Data signature verification is performed in the patched version. Presumably, this behavior does not exist in unpatched versions.
Exhibit C: System.Messaging.BinaryMessageFormatter
The following code snippet is from Microsoft’s reference source.
[snip] /// <include file='doc\BinaryMessageFormatter.uex' path='docs/doc[@for="BinaryMessageFormatter.Read"]/*' /> /// <devdoc> /// This method is used to read the contents from the given message /// and create an object. /// </devdoc> public object Read(Message message) { if (message == null) throw new ArgumentNullException("message"); int variantType = message.BodyType; if (variantType == VT_BINARY_OBJECT) { Stream stream = message.BodyStream; return formatter.Deserialize(stream); } throw new InvalidOperationException(Res.GetString(Res.InvalidTypeDeserialization)); } [snip]
Finally, BinaryMessageFormatter.Read()
directly deserializes its input stream. In a vulnerable version, RCE should be as straightforward as sending a .NET gadget chain over the MSMQ protocol to TCP port 1801. An independent security researcher has verified this.
Guidance
SolarWinds Orion Platform customers should update to version 2020.2.4 immediately. Furthermore, it is advised to limit access to TCP port 1801 on the Orion Platform host, as the patch leaves the MSMQ queues unauthenticated.
References
Report as Emergent Threat Response
Report as Exploited in the Wild
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below: