Article

    Cyber News / Article / OMIGOD: Critical Vulnerabilities in OMI Affecting Countless Azure Customers

    OMIGOD: Critical Vulnerabilities in OMI Affecting Countless Azure Customers
    Ni
    Nir Ohfeld-2021-09-14

    OMIGOD: Critical Vulnerabilities in OMI Affecting Countless Azure Customers

    Wiz Research recently found 4 critical vulnerabilities in OMI, which is one of Azure's most ubiquitous yet least known software agents and is deployed on a large portion of Linux VMs in Azure.

    The Wiz Research Team recently found four critical vulnerabilities in OMI, which is one of Azure's most ubiquitous yet least known software agents and is deployed on a large portion of Linux VMs in Azure.The vulnerabilities are very easy to exploit, allowing attackers to remotely execute arbitrary code within the network with asingle requestand escalate to root privileges.

    CVE-2021-38647– Unauthenticated RCE as root

    CVE-2021-38648– Privilege Escalation vulnerability

    CVE-2021-38645– Privilege Escalation vulnerability

    CVE-2021-38649– Privilege Escalation vulnerability

    Many different services in Azure are affected, includingAzure Log Analytics,Azure DiagnosticsandAzure Security Center, as Microsoft uses OMI extensively behind the scenes as a common component for many of its management services for VMs. In a survey, Wiz found that over 65% of sampled Azure customers were exposed to these vulnerabilities andunknowingly at-risk. Although widely used, OMI’s functions within Azure VMs arealmost completely undocumentedand there areno clear guidelinesfor customers regarding how to check and/or upgrade existing OMI versions. For a high-level overview of the vulnerability and updates regarding mitigations,visit our OMIGOD blog. For our guidance on identifying and remediating OMIGOD in your environment,download our checklist.

    In this post we describe the full technical details of the vulnerabilities we found with the following sections:

    What is OMI

    Who is Vulnerable

    The OMI Attack Surface

    Technical Overview of Selected Vulnerabilities

    Key Takeaways

    Disclosure Timeline

    Appendix: Full Technical Details

    Note that this is only apartial list.Let us knowif you are aware of more Azure services silently deploying OMI.

    The OMI agent runs as root with high privileges.Any user can communicate with it using a UNIX socket or sometimes using an HTTP API when configured to allow external usage. As a result, OMI represents a possible attack surface where a vulnerability allows external users or low privileged users to remotely execute code on target machines or escalate privileges.

    Some Azure products, such as Configuration Management, expose an HTTPS port for interacting with OMI (port 5986 also known as WinRM port). This configuration enables the RCE vulnerability (CVE-2021-38647). It’s important to mention that most Azure services that use OMI deploy it without exposing the HTTPS port.

    Note that in the scenarios where the OMI ports (5986/5985/1270) are accessible to the internet to allow for remote management, this vulnerability can be also used by attackers to obtain initial access to a target Azure environment and then move laterally within it. Thus, an exposed HTTPS port is a holy grail for malicious attackers. As depicted in the diagram below,with one simple exploit they can get access to new targets, execute commands at the highest privileges and possibly spread to new target machines.

    The other three vulnerabilities are classified asprivilege escalation vulnerabilities, and they can enable attackers to gain the highest privileges on a machine with OMI installed. Attackers often use such vulnerabilities as part of sophisticated attack chains, after gaining initial low privileged access to their targets.

    This is a textbook RCE vulnerability, straight from the 90’s but happening in 2021 and affecting millions of endpoints. With a single packet, an attacker can become root on a remote machine by simply removing the authentication header. How can it be so simple?

    Thanks to the combination of a simple conditional statement coding mistake and an uninitialized authentication struct, any request without an Authorization header has its privileges default touid=0,gid=0, which is root.O-MI-GOD!

    This vulnerability allows for remote takeover when OMI exposes the HTTPS management port externally (5986/5985/1270). This is in fact the default configuration when installed standalone and in Azure Configuration Management or System Center Operations Manager (SCOM). Fortunately, other Azure services (such as Log Analytics) do not expose this port and thus the scope is limited to local privilege escalation.

    The diagram below illustrates the unexpected behavior of OMI when a command execution request is issued with no Authorization header.

    Normal flow with valid password in the Authentication header- The omicli issues an HTTP request to the remote OMI instance, passing the login information in the Authorization header.

    Authorization failure when passing an invalid Authentication header- As expected, if omicli passes an invalid header it fails.

    Exploit flow when passing a command without Authentication header- The OMI server trusts the request even without an Authentication header and enables the perfect RCE: single-request-to-rule-them-all.

    Here is the most minimal patch needed: from the OMI GitHub repo, simply initialize to an invalid value…

    Another disturbing issue we found was that this commit has been available in the OMI GitHub repo for anyone to see for over a month! This means that threat actors could have started exploiting these vulnerabilities over a month ago without any prior customer notifications.

    The following vulnerability affects all installations of OMI prior to version 1.6.8-1.This vulnerability is a Local Privilege Escalation and is remarkably similar to the above Remote Command Execution (CVE-2021-38647). The exploitation process is similar as well: record a legitimate command execution request from the omicli, omit the authentication part and reissue the command execution request. The command will be executed as root, regardless of the current user permissions. This might sound like the same vulnerability as the Remote Command Execution, but the root cause analysis shows that it’s an entirely different flaw.

    OMI has a frontend-backend architecture. The user doesn’t communicate directly with theomiserver. Instead. the server runs as root while a lower privileged frontend process calledomiengineruns asomiuser.

    The only way for a low privileged user to communicate withomiserveris through its frontend processomiengine.

    This architecture makes it particularly challenging for theomiserverto identify the user communicating on the other side of the communication. Theomiservermust trust theomiengineon the identity of the user. Therefore, each message theomiengineforwards to theomiserveris accompanied with theAuthInfostruct, which contains the user’suidandgid.

    As mentioned in the RCE vulnerability overview, theAuthInfostruct is initialized with bothuidandgidequal to zero, theuidandgidof the root user. As a result, if an attacker manages to issue a request that is forwarded to theomiserverbefore any authentication process takes place, the request will be processed by theomiserveras if it was issued by the root user.

    Theomienginehas a very problematic request handling logic. There is a set of message types (e.g. authentication requests) for which theomienginerequires special processing before forwarding them to the server. For requests with no special handling, theomienginesimply forwards them to the server, without any validation, alongside theAuthInfo,regardless of the client’s authentication state. For example - specific provider requests such as theSCX providerwhich is capable of creating arbitrary UNIX processes.

    The diagram below illustrates the communication that occurs when issuing a command execution request usingomicli:

    Messages with no special handling (such as theexecute /bin/idrequest), are forwarded to server. This means that if we issue the command execution request ourselves, without relying onomicli, the new process will be spawned under the default privileges inside theAuthInfostruct, which areuid=0,gid=0– root privileges!

    All an attacker has to do in order to exploit this vulnerability is to intercept the communication between theomicliand theomiengine, omit the authentication handshake and the command will be executed as root.

    You can find a more in-depth technical analysis of CVE-2021-38647, CVE-2021-38648 and CVE-2021-38645 in thetechnical appendix.

    Even though we researched a small part of Open Management Infrastructure, we managed to find several high/critical severity vulnerabilities affecting multiple Azure products. The ease of exploitation and the simplicity of the vulnerabilities makes you wonder if the OMI project is mature enough to be used so widely within Azure.

    OMI is an example of pre-installed software agents that cloud providers build into VMs running in their cloud. Problematically, this “secret” agent is both widely used (because it is open source) and completely invisible to customers as its usage within Azure is completely undocumented.

    There is no easy way for customers to know which of their VMs are running OMI, since Azure doesn’t mention OMI anywhere on the Azure Portal, which impairs customers’ risk assessment capabilities. This issue highlights a gap in the famousshared responsibility model. An agent that is under the cloud provider’s responsibility can easily be used by attackers to gain high privileges remotely on their target, and the true tragedy is that customers can’t even know whether they are open to this attack.

    Furthermore, it’s unclear who is responsible for patching vulnerabilities like this. Is it the user who isn’t aware the agents exist? Is it the cloud provider that shouldn’t have admin rights on the machine?

    We hope to raise awareness of the risks that come with “secret" agents running with high privileges in cloud environments, particularly among Azure customers who are currently at risk until they update to the latest version of OMI. We urge the research community to continue to audit the Open Management Infrastructure to ensure Azure users stay safe.

    To learn more about identifying and remediating OMIGOD, with step-by-step guidance,download our checklist.

    Anyone who is tracking OMI’s GitHub commit logs would notice that a strange “Enhanced Security”commitwas introduced on August 12th 2021. By doing a trivial patch-diff, a determined attacker could have developed an exploit for these vulnerabilities. This is especially concerning as Microsoft’s official patch (v1.6.8-1) was only released on September 8th 2021, leaving affected users with nothing they could do to prevent exploitation for almost a month after giving attackers a “silent” hint about the bugs.

    June 01, 2021- Wiz Research Team reported all 4 OMI vulnerabilities to MSRC.

    July 12, 2021- MSRC Confirmed one of the local privilege escalation vulnerabilities (CVE-2021-38648).

    July 16, 2021- MSRC Confirmed one of the local privilege escalation vulnerabilities (CVE-2021-38645).

    July 16, 2021- MSRC Confirmed the remote command execution vulnerability (CVE-2021-38647).

    July 23, 2021- MSRC Confirmed one of the local privilege escalation vulnerabilities (CVE-2021-38649).

    August 12, 2021- Wiz Research Team observed an “Enhanced Security” commit fixing all 4 reported vulnerabilities.

    September 8, 2021– Official patch released.

    September 14, 2021- All 4 vulnerabilities published on September’s Patch Tuesday.

    First let’s examine a legitimate example of remote OMI usage. We will execute the following command:

    And the following output will be displayed:

    Seems straightforward. Any user, in our caseazureuser, can execute an arbitrary command which will be executed with the user’s privileges, provided the correct password is supplied. By using Burp Suite and examining the traffic, we can see the protocol is very basic:

    The user’s supplied credentials are passed in the Authorization header, using Basic authentication(1). The user’s command is passed inside the SOAP/XML body(2). This is the response for the request above:

    If we try passing the wrong credentials inside the Authorization header:

    we receive a 401 response as expected:

    What would you expect to happen if we issued the same HTTP request without the Authorization header? We would expect to receive the same 401 Unauthorized response, similar to the one we got when we supplied bogus credentials.

    We definitely did not expect to receive the following response:

    The command executes! On top of that, it executes with root privileges! As we previously mentioned, we think that this is some extremely unexpected behavior. Let's understand the root cause of this bug by inspecting the source code.

    There are two important structs to keep in mind:Http_SR_SocketDataandAuthInfo.

    When a new user connects to the server, the_ListenerCallbackfunction is invoked. This function creates a newHttp_SR_SocketData(memset’ed to 0) and initializes some of its fields.

    The important part of the snippet above is that theh->authFailedfield is initialized toFALSE(1). Another important function is_ReadData, which also handles part of the authentication. This is the function that contains the critical logical bug:

    Can you spot the bug? Let’s think about how the function processes our request when we do not supply the Authorization header. The first condition(1)evaluates tofalse, and we end up inside the else statement, where the second condition(2)also evaluates tofalse(as we didn’t initiate any authentication procedure, therefore theauthFailedfield is set tofalse). We then continue to the Process_Authorized_Message function, whichhandles our request as an authenticated one. But with what permissions? Because the entire struct was previouslymemset’ed to 0, theAuthInfostruct containsuid=0,gid=0, meaning our request will be handled as if we wereauthenticated as root!

    To understand the next two vulnerabilities, we need to have a closer look at OMI’s architecture. OMI has a frontend-backend architecture. The user doesn’t communicate directly with theomiserver. Instead of theserverwhich runs as root, has a lower privileged frontend process calledomienginethat runs asomiuser. The only way to communicate withomiserveris through the UNIX sockets found in the/etc/opt/omi/conf/sockets/directory, which is only accessible to theomiuser, meaning that only processes under theomiuser can communicate withomiserver. Any local user can communicate with theomienginethrough the/var/opt/omi/run/omiserver.sockUNIX socket, which has full RWX permissions.

    This architecture makes it particularly challenging for theomiserverto identify the user communicating on the other side of the UNIX socket.Theomiservermust trust theomiengineon the identity of the useron the other end of the UNIX socket.

    To illustrate, here is a diagram of the communication that occurs when a user usesomito execute the/bin/idbinary:

    Which yields the following output:

    When no user credentials are provided,omipreforms implicit authentication as the user on the other side of the UNIX socket.

    Each connection between theomicliandomiengineis defined in a ProtocolSocket struct. Here’s the underlying structure, omitting irrelevant fields:

    One of the most important fields that is worth keeping in mind is the authInfo field, of typeAuthInfo, which has the following definition:

    When a user establishes a new connection to theomienginethrough the/var/opt/omi/run/omiserver.socka new ProtocolSocket is allocated, specifically, callocated. This means that all the fields are initialized to 0, including the connected user’suidandgid.

    After the connection is initialized, each user message in handled by the_ProcessReceivedMessagefunction.

    You can view the_ProcessReceivedMessageas aswitchstatement acting on themsg->tagfield, where thedefaultcase is to forward the message directly to the server, regardless of the user’s authentication state.

    The authentication messages fall under theBinProtocolNotificationTagclause, while the command execution request itself doesn’t match any of theif-elseclauses and is handled by thedefaultprocedure, so the message will be forwarded to the server, regardless of the user authentication state. That’s some interesting behavior, because theomiservertrusts theomiengineto handle the user’s authentication state and identity. Let’s think about what will happen if the user doesn’t perform the authentication negotiation before sending the execute command request: instead, once the user connects to theomiengine, she immediately issues the execute command request. As mentioned before, the message will be forwarded to the server. Theomiserverrelies on theomiengineto provide the user’suidandgidas part of message metadata. If the user did not initiate the authentication process, theuidandgidremain untouched, and as mentioned before, theAuthInfostruct ismemset'ed to 0, meaning that theuidandgidare both equal to 0, theuidandgidof the root user. The proof-of-concept of such a vulnerability is quite straight forward. We first need to record the communication between theomicliand theomiengine, omit the first authentication request, and only send the command execution request and gain root command execution.

    As mentioned earlier, OMI has a frontend-backend architecture, meaning that theomienginereceives the authentication request from the client,omicli, issues a new authentication request to theomiserver, saves the authentication result information, such as the user’suidandgidand forwards the response back to the user.

    Look at the authentication logic inside the_ProcessReceivedMessagefunction:

    Let’s review the logic,(1)first theomienginesaves the client’s socket in a connection hash map, using the connection number as the key.(2)Then theomiengineestablishes a new connection with theomiserver,(3)and saves it in the same tracker hash map.(4)Then the authentication request is sent to the server for validation.

    Now let’s look at how the same function handles the server response:

    Before we dive into this code snippet, there is something that needs to be emphasized. The_ProcessReceivedMessagefunction processes an incoming request from the client and the server thesameway,withoutany server validation.(1.1)The client’s socket id is fetched from the response and(1.2)fetched from the hash-map; if the socket is not found inside the hash-map, the authentication process fails.(2)Then the authentication response is parsed, and the authentication info is set accordingly. From now on, every command coming out of this client socket is executed with thosebinMsg->uidandbinMsg->gid, then(3)the server socket is fetched from the hash-map; if it does not exist the authentication process fails.

    Now let’s consider the following scenario: wheremalserveris a malicious client impersonating a server, which returns the authentication response beforeomiserverreturns its response. There are a few challenges to themalserverto successfully authenticate the user as root. First, it needs to know the user’s socket id(1.2), but from our experience, it is usually < 10 and can be guessed easily. If successfully guessed, the client’sauthInfo->uidandauthInfo->gidcan be both set to 0. Next, we need to bypass the(3)check, where theomienginechecks if ourmalserversocket is in its tracker hash-map, which it is not. We can bypass it by issuing an authentication request from themalserverto theomienginewhich will add its socket id to the hash-map, and immediately send an authentication success response for theomiclisocket id withuid=0,gid=0.

    The exploitation is quite complex and statistical due to a different bug (a use-after-free error that occurs in this code path) that keeps crashing theomiengine(which we’ve also reported to Microsoft), so instead of using theomicli, we created a Python script that sends the messages directly through theomiengineUNIX socket.

    The exploitation flow is straightforward:

    Main thread:

    Send an authentication request with bogus credentials

    Start another thread

    Send theid >> /tmp/wincommand

    Second thread:

    Send an authentication request

    Send authentication success response withuid=0,gid=0for the authentication request initiated in the main thread

    After a certain number of iterations, the race condition will be successfully exploited and we our code will execute as root.

    Wiz Research recently discovered a series of alarming vulnerabilities that highlight the supply chain risk of open source code, particularly for customers of cloud computing services.

    The first half of 2021 has been incredible for Wiz. Fueled by an additional $250M in funding ($350M total) from Sequoia, Index Ventures, Insight, Salesforce, Blackstone, Advent, Greenoaks, and Aglaé Wiz has grown at a blistering pace, going from 25 employees at the start of the year to 120 today.

    Wiz Research found an unprecedented critical vulnerability in Azure Cosmos DB. The vulnerability gives any Azure user full admin access (read, write, delete) to another customers Cosmos DB instances without authorization.

    Get a personalized demo

    ©2026Wiz, Inc.

    StatusPrivacy PolicyTerms of UseModern Slavery StatementCookie Settings

    Original source