Blog Post

Microsoft Defender Vulnerability Management Blog
7 MIN READ

Guidance for handling “regreSSHion” (CVE-2024-6387) using Microsoft Security capabilities

BrjannBrekkan's avatar
BrjannBrekkan
Icon for Microsoft rankMicrosoft
Jul 08, 2024

Investigating and assessing vulnerabilities within the software inventory is crucial, especially in light of high-severity vulnerabilities like the recent OpenSSH regreSSHion vulnerability. Such security risks are becoming increasingly common, often exploiting software dependencies and third-party services. The notoriety of incidents like the TeamViewer breach and the XZ Utils backdoor underscores the urgency for comprehensive vulnerability management and strategies to minimize the attack surface. In this blog post, we delve into the methodology for probing such incidents. We will demonstrate how organizations can harness the capabilities of Attack Path analysis together with Microsoft Defender suite of products to pinpoint and neutralize threats arising from such events. Our examination will center on: mapping vulnerabilities, evaluating affected assets, gauging potential impact via blast radius analysis, and implementing efficacious mitigations. 

 

Mapping Vulnerabilities and Impacted Assets 

The first step in managing an incident is to map affected software within your organization’s assets. Defender Vulnerability Management solution provides a comprehensive vulnerability assessment across all your devices.

 

Example: Mapping the regreSSHion vulnerability 

To map the presence of the regreSSHion vulnerability (CVE-2024-6387) in your environment, you can use the following KQL query in Advanced Hunting in Microsoft Defender portal:

 

 

DeviceTvmSoftwareVulnerabilities
| where CveId == "CVE-2024-6387"
| summarize by DeviceName, DeviceId, strcat(OSPlatform, " ", OSVersion), SoftwareName, SoftwareVersion

 

 

This query searches software vulnerabilities related to the specified CVE and summarizes them by device name and id, you can use this link to open the query in your environment.

 

Example: Mapping devices with vulnerable OpenSSH version installed 

Utilizing software inventory to map devices is advisable even when a CVE hasn’t been officially published or when there’s a specific requirement to upgrade a particular package and version.

 

DeviceTvmSoftwareInventory 
| where SoftwareName has "openssh"
| extend ParsedSoftwareVersion = extract(@"(\b(\d\.\d)|(\b\d\.\d))", 0, SoftwareVersion) // extract version number (e.g. "1:8.9p1-3ubuntu0.5" > "8.9")
| where 
    // filter for potentially vulnerable versions only
    toreal(ParsedSoftwareVersion) < 4.4 or 
    toreal(ParsedSoftwareVersion) >= 8.5 and toreal(ParsedSoftwareVersion) < 9.8
| project DeviceId, DeviceName, SoftwareName, SoftwareVersion, ParsedSoftwareVersion, SoftwareVendor

 

This query searches for devices that have the vulnerable OpenSSH versions installed, you can use this link to open the query in your environment.

Understanding Potential Impact: Attack Path Analysis 

Understanding the blast radius of impacted devices is critical for assessing the potential impact on your organization. Microsoft Security offers attack path analysis to visualize possible lateral movement steps an adversary might take. 

 

Leveraging Microsoft Defender for Cloud 

Defender for Cloud (MDC) discovers all cloud resources affected by the vulnerability which are also exposed to the internet through SSH ports. MDC highlights them in the ‘attack path analysis’ tool: 

 

Using attack path analysis, you can easily find all your exposed machines that are also potentially accessible for attackers. Use the following attack path title to filter the view only for exposed machines:  

  • Internet exposed Azure VM with OpenSSH regreSSHion vulnerability (CVE-2024-6387) 
  • Internet exposed AKS pod is running a container with OpenSSH regreSSHion vulnerability (CVE-2024-6387) 
  • Internet exposed EKS pod is running a container with OpenSSH regreSSHion vulnerability (CVE-2024-6387) 

Note: These attack path updates are rolling out and should be available for all customers shortly.

 

Using Cloud Security Explorer 

You can use the Cloud Security Explorer feature within Defender for Cloud to perform queries related to your posture across Azure, AWS, GCP, and code repositories. This allows you to investigate the specific CVE, identify affected machines, and understand the associated risks. 

We have created specific queries for this CVE that help you to easily get an initial assessment of the threat this vulnerability creates for your organization, with choices for customization: 

 

 

 

Advanced Hunting: Analyzing Attack Paths Across the Organization with Microsoft Security Exposure Management

To analyze the blast radius (i.e. the potential impact of a compromised device) of the regreSSHion vulnerability across different environments and assets, you can use the powerful `graph-match` KQL command under Advanced Hunting to identify other critical assets that might be at risk. 

The following query (wrapped in the BlastRadiusAttackPathMapping function for easier repeated usage) maps and returns possible attack paths an adversary can take.  
The function receives as an input: 

  • sourceTypes: filter for type of device that can be considered as entry points (e.g. virtual machine, endpoint device) 
  • sourceProperties: filter for properties the above devices must have (e.g. high severity vulnerabilities) 
  • sourceCveIDs: filter for specific vulnerabilities (CVE IDs) the above devices must have 
  • targetTypes: filter for type of device that are considered as the target of the path (e.g. storage account, privileged user, virtual machine, endpoint device) 
  • targetProperties: filter for properties the target devices must have (e.g. critical assets) 
  • maxPathLength: maximum hops for each attack path 
  • resultCountLimit: maximum amount of attack paths calculated 

 

 

let BlastRadiusAttackPathMapping = (sourceTypes: dynamic, sourceProperties: dynamic, sourceCveIDs: dynamic 
    , targetTypes: dynamic, targetProperties: dynamic 
    , maxPathLength: long = 6, resultCountLimit: long = 10000)  
{ 
    let edgeTypes               = pack_array
                              (
                                  'has permissions to',
                                  'contains',
                                  'can authenticate as',
                                  'can authenticate to',
                                  'can remote interactive logon to' 
        ,
                                  'can interactive logon to',
                                  'can logon over the network to',
                                  'contains',
                                  'has role on',
                                  'member of'
                              ); 
    let sourceNodePropertiesFormatted = strcat('(', strcat_array(sourceProperties, '|'), ')'); 
    let targetNodePropertiesFormatted = strcat('(', strcat_array(targetProperties, '|'), ')'); 
    let nodes = ( 
        ExposureGraphNodes 
        | project
            NodeId,
            NodeName,
            NodeLabel 
            ,
            SourcePropertiesExtracted = iff(sourceProperties != "[\"\"]", extract_all(sourceNodePropertiesFormatted, tostring(NodeProperties)), pack_array('')) 
            ,
            TargetPropertiesExtracted = iff(targetProperties != "[\"\"]", extract_all(targetNodePropertiesFormatted, tostring(NodeProperties)), pack_array('')) 
            ,
            criticalityLevel = toint(NodeProperties.rawData.criticalityLevel.criticalityLevel) 
        | mv-apply SourcePropertiesExtracted, TargetPropertiesExtracted on ( 
            summarize
                SourcePropertiesExtracted = make_set_if(SourcePropertiesExtracted, isnotempty(SourcePropertiesExtracted)) 
                ,
                TargetPropertiesExtracted = make_set_if(TargetPropertiesExtracted, isnotempty(TargetPropertiesExtracted)) 
            ) 
        | extend
            CountSourceProperties = coalesce(array_length(SourcePropertiesExtracted), 0) 
            ,
            CountTargetProperties = coalesce(array_length(TargetPropertiesExtracted), 0) 
        | extend
            SourceRelevancyByLabel = iff(NodeLabel in (sourceTypes) or sourceTypes == "[\"\"]", 1, 0) 
            ,
            TargetRelevancyByLabel = iff(NodeLabel in (targetTypes) or targetTypes == "[\"\"]", 1, 0) 
            ,
            SourceRelevancyByProperties = iff(CountSourceProperties > 0 or sourceProperties == "[\"\"]", 1, 0) 
            ,
            TargetRelevancyByProperties = iff(CountTargetProperties > 0 or targetProperties == "[\"\"]", 1, 0) 
        | extend
            SourceRelevancy = iff(SourceRelevancyByLabel == 1 and SourceRelevancyByProperties == 1, 1, 0) 
            ,
            TargetRelevancy = iff(TargetRelevancyByLabel == 1 and TargetRelevancyByProperties == 1, 1, 0) 
        ); 
    let edges = ( 
        ExposureGraphEdges 
        | where EdgeLabel in (edgeTypes) 
        | project
            EdgeId,
            EdgeLabel,
            SourceNodeId,
            SourceNodeName,
            SourceNodeLabel,
            TargetNodeId,
            TargetNodeName,
            TargetNodeLabel 
        ); 
    let vulnerableDevices = ( 
        ExposureGraphEdges 
        | where iif(sourceCveIDs == "[\"\"]", true, (SourceNodeName in (sourceCveIDs)) and (EdgeLabel == "affecting")) // filter for CVEs only if listed, otherwise return all nodes 
        | project NodeId=TargetNodeId 
        | distinct NodeId 
        ); 
    let paths = ( 
        edges 
        // Build the graph from all the nodes and edges and enrich it with node data (properties) 
        | make-graph SourceNodeId --> TargetNodeId with nodes on NodeId 
        // Look for existing paths between source nodes and target nodes with up to predefined number of hops 
        | graph-match cycles=none (s)-[e*1 .. maxPathLength]->(t) 
            // Filter only by paths with relevant sources and targets - filtered by node types and properties 
            where (s.SourceRelevancy == 1 and t.TargetRelevancy == 1) and s.NodeId in (vulnerableDevices) 
            project SourceName                = s.NodeName 
            , SourceType                = s.NodeLabel 
            , SourceId                  = s.NodeId 
            , SourceProperties          = s.SourcePropertiesExtracted 
            , CountSourceProperties     = s.CountSourceProperties 
            , SourceRelevancy           = s.SourceRelevancy 
            , TargetName                = t.NodeName 
            , TargetType                = t.NodeLabel 
            , TargetId                  = t.NodeId 
            , TargetProperties          = t.TargetPropertiesExtracted 
            , CountTargetProperties     = t.CountTargetProperties 
            , TargetRelevancy           = t.TargetRelevancy 
            , EdgeLabels                = e.EdgeLabel 
            , EdgeIds                   = e.EdgeId 
            , EdgeAllTargetIds          = e.TargetNodeId 
            , EdgeAllTargetNames        = e.TargetNodeId 
            , EdgeAllTargetTypes        = e.TargetNodeLabel 
        | extend
            PathLength                    = array_length(EdgeIds) + 1 
            ,
            PathId                        = hash_md5(strcat(SourceId, strcat(EdgeIds), TargetId)) 
        ); 
    let relevantPaths = ( 
        paths 
        | extend
            NodesInPath = array_concat(pack_array(SourceId), EdgeAllTargetIds),
            NodeLabelsInPath = array_concat(pack_array(SourceType), EdgeAllTargetTypes) 
        | extend NodesInPathList = NodesInPath 
        // Wrap the path into meaningful format (can be tweaked as needed) 
        | mv-expand with_itemindex = SortIndex
            EdgeIds to typeof(string),
            EdgeLabels to typeof(string) 
            ,
            NodesInPath to typeof(string),
            NodeLabelsInPath to typeof(string) 
        | sort by PathId, SortIndex asc 
        | extend step = strcat
                ( 
                    iff(isnotempty(NodesInPath), strcat('(', NodeLabelsInPath, ' ', SourceName, ':', NodesInPath, ')'), '') 
            ,
                    iff(CountSourceProperties > 0 and NodesInPath == SourceId, SourceProperties, '') 
            ,
                    iff(CountTargetProperties > 0 and NodesInPath == TargetId, TargetProperties, '') 
            ,
                    iff(isnotempty(EdgeLabels), strcat('-', EdgeLabels, '->'), '')
                ) 
        | summarize Path = make_list(step), take_any(*) by PathId 
        // Project relevant fields 
        | project
            SourceName,
            SourceType,
            SourceId,
            SourceProperties,
            CountSourceProperties,
            SourceRelevancy 
            ,
            TargetName,
            TargetType,
            TargetId,
            TargetProperties,
            CountTargetProperties,
            TargetRelevancy 
            ,
            PathId,
            PathLength,
            Path 
        | top resultCountLimit by PathLength asc 
        ); 
    relevantPaths 
}; 
// Calling the function starts here  
let sourceTypes         = pack_array('microsoft.compute/virtualmachines', 'compute.instances', 'ec2.instance', 'device', 'container-image', 'microsoft.hybridcompute/machines'); 
let sourceProperties    = pack_array('hasHighOrCritical'); // filter for assets with severe vulnerabilities 
let sourceCveIDs        = pack_array('CVE-2024-6387'); // filter for entry points with regSSHion CVE 
let targetTypes         = pack_array('');  
let targetProperties    = pack_array('criticalityLevel'); // filter for paths that ends with critical assets 
BlastRadiusAttackPathMapping(sourceTypes, sourceProperties, sourceCveIDs, targetTypes, targetProperties) 
| project-reorder SourceType, SourceName, TargetType, TargetName, Path 
| project-keep SourceType, SourceName, TargetType, TargetName, Path 

 

 

 

 

For our purposes we are filtering for “compute” devices (such as servers, VMs, endpoints) with high severity vulnerabilities, specifically the regSSHion CVE ID that can be utilized by adversaries to serve as an entry point for an attack. 
We’re also looking to map paths only to devices that have a critical role in the environment (such as a Domain Controller, user with privileged role, etc.) 

 

An example for such query results: 

 

The function can be easily reused, the only part that should be modified is the parameters and the function calling, right below
Line 177 
// Calling the function starts here:“

 

Recommendations for Mitigation and Best Practices 

Mitigating risks associated with vulnerabilities requires a combination of proactive measures and real-time defenses. Here are some recommendations: 

  • Apply Patches and Updates: Regularly update and patch all software to address known vulnerabilities. Use Defender Vulnerability Management to monitor and enforce patch compliance. 
  • Application Blocking: Once CVE is assigned, utilize Defender Vulnerability Management's application blocking capability to prevent the execution of vulnerable or malicious software. This feature is available in premium plans only (learn more). 
  • Remediate vulnerabilities: Use Defender for Cloud ‘remediate vulnerabilities’ recommendations to remediate affected VMs and containers across your multi-cloud environment. (learn more) 
  • Exposure Management: Keep monitoring your environment using attack path analysis to block possible attack routes, using either the visualization tool under Exposure Management in Security.microsoft.com portal or the ‘graph-match’ KQL command (learn more). 
  • Secure Management ports Use Defender for Cloud ‘Secure management ports’ recommendation to ensure the SSH ports on your machines are closed, or at least protected with just-in-time access control (learn more). 
  • Network Segmentation: Implement network segmentation to limit the spread of an attack and protect critical assets. 
  • Advanced Hunting: Continuously monitor your environment using advanced hunting queries to detect unusual activities and potential exploitation attempts 

 

Conclusion 

By following these guidelines and utilizing end-to-end integrated Microsoft Security products, organizations can better prepare for, prevent and respond to attacks, ensuring a more secure and resilient environment. 

While the above process provides a comprehensive approach to protecting your organization, continual monitoring, updating, and adapting to new threats are essential for maintaining robust security. 

Updated Jul 25, 2024
Version 3.0
  • 2vack's avatar
    2vack
    Copper Contributor

    Opening a ticket will have a Microsoft tech lead you here. The document discusses blocking the ssh server app, blocking ssh traffic, or securing port 22.  In other words, do not use win32-SSH if it cannot be secured as we don't have a fix.  :facepalm:

  • utpalmondal's avatar
    utpalmondal
    Copper Contributor

    This feels more like marketing of MS defender. What if we are not using MS defender? I have raised ticket and escalated since the CVE got released, and since then no answer. This is extremely un-acceptable a company like MS is completely silent when there is an inbuild OS SSH version falling under this impacted version.